From 137fb8ea6af2789b3238b22bac31d80bced41dfe Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期三, 28 七月 2021 11:39:39 +0800 Subject: [PATCH] 2021-07-28 --- src/menu/components/form/formaction/index.scss | 5 src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx | 77 src/tabviews/custom/components/chart/antv-scatter/index.scss | 70 src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.scss | 11 src/mob/mobshell/index.jsx | 65 src/tabviews/scriptmanage/config.jsx | 2 src/views/menudesign/printmenuform/index.jsx | 100 src/locales/zh-CN/model.js | 2 src/tabviews/home/index.jsx | 33 src/templates/zshare/editTable/index.scss | 4 src/tabviews/zshare/actionList/changeuserbutton/index.jsx | 40 src/menu/datasource/verifycard/index.jsx | 109 src/assets/css/main.scss | 27 src/mob/components/navbar/normal-navbar/wrapsetting/index.jsx | 81 src/templates/formtabconfig/settingform/index.jsx | 4 src/menu/components/card/cardcellcomponent/index.jsx | 114 src/mob/searchconfig/searchdragelement/card.jsx | 132 src/menu/components/card/cardcomponent/index.jsx | 42 src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.jsx | 0 src/views/menudesign/index.scss | 2 src/menu/components/card/prop-card/index.jsx | 44 src/templates/zshare/customscript/index.jsx | 11 src/mob/components/navbar/normal-navbar/menusetting/index.jsx | 63 package-lock.json | 706 src/assets/css/viewstyle.scss | 17 src/menu/components/card/cardcomponent/settingform/index.jsx | 32 src/tabviews/zshare/topSearch/index.jsx | 765 src/assets/mobimg/navtop-mob.png | 0 src/api/index.js | 90 src/mob/components/formdragelement/index.scss | 245 config/webpack.config.js | 11 src/mob/searchconfig/groupform/index.jsx | 90 src/templates/sharecomponent/actioncomponent/index.scss | 2 src/menu/components/chart/antv-dashboard/index.scss | 50 src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss | 11 src/menu/components/chart/antv-dashboard/chartcompile/index.scss | 44 src/mob/components/menubar/normal-menubar/wrapsetting/index.scss | 7 src/mob/mobshell/card.jsx | 62 src/mob/mobshell/index.scss | 30 src/tabviews/custom/components/card/prop-card/index.scss | 22 src/tabviews/zshare/mutilform/mkNumberInput/index.scss | 27 src/menu/components/share/styleInput/index.scss | 11 src/pc/bgcontroller/index.jsx | 71 src/views/pcdesign/index.jsx | 540 src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss | 25 src/mob/components/formdragelement/index.jsx | 132 src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx | 7 src/menu/components/carousel/data-card/wrapsetting/settingform/index.jsx | 23 src/views/appmanage/transform/index.jsx | 89 src/views/appmanage/header/index.jsx | 31 src/pc/modulesource/option.jsx | 15 src/templates/zshare/editTable/index.jsx | 61 src/tabviews/zshare/normalTable/index.jsx | 55 src/menu/components/form/normal-form/groupform/index.jsx | 25 src/views/menudesign/homeform/index.jsx | 69 src/components/mkIcon/index.scss | 53 src/menu/datasource/index.jsx | 164 src/menu/components/chart/antv-bar/index.scss | 11 src/menu/components/tree/antd-tree/index.jsx | 188 src/menu/components/carousel/cardcomponent/index.jsx | 3 src/tabviews/zshare/actionList/normalbutton/index.jsx | 279 src/tabviews/custom/components/table/normal-table/index.scss | 28 src/menu/modulesource/option.jsx | 13 src/pc/transfer/index.scss | 0 src/views/appmanage/index.scss | 132 src/menu/components/card/balcony/wrapsetting/settingform/index.scss | 36 src/views/appmanage/transform/index.scss | 4 src/templates/sharecomponent/actioncomponent/actionform/index.jsx | 37 src/menu/pastecontroller/index.jsx | 26 src/views/interface/workspace/editTable/index.scss | 85 src/views/interface/workspace/index.scss | 52 src/mob/searchconfig/settingform/index.jsx | 222 src/mob/header/index.scss | 8 src/tabviews/zshare/topSearch/mkSelect/index.scss | 0 src/menu/components/share/searchcomponent/dragsearch/index.scss | 6 src/tabviews/zshare/mutilform/mkRadio/index.scss | 0 src/menu/datasource/verifycard/settingform/index.scss | 8 src/mob/searchconfig/searchdragelement/index.jsx | 123 src/tabviews/zshare/mutilform/mkInput/index.scss | 27 src/views/printTemplate/option.js | 8 src/menu/components/share/sourcecomponent/inputform/index.jsx | 20 src/components/header/index.jsx | 113 src/views/pcdesign/menuform/index.jsx | 4 src/templates/formtabconfig/index.jsx | 8 src/templates/zshare/verifycard/callbackcustomscript/index.jsx | 7 src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss | 8 src/views/appmanage/scriptform/index.jsx | 242 src/templates/sharecomponent/fieldscomponent/index.jsx | 13 src/menu/components/code/sandbox/index.jsx | 6 src/views/billprint/index.scss | 6 src/menu/components/tabs/tabcomponents/index.scss | 5 src/views/appmanage/header/index.scss | 57 src/menu/components/table/normal-table/columns/index.scss | 30 src/components/paste/index.jsx | 72 src/menu/bgcontroller/index.jsx | 50 src/tabviews/custom/components/share/normalheader/index.jsx | 2 src/templates/sharecomponent/settingcomponent/settingform/utils.jsx | 28 src/tabviews/zshare/mutilform/mkDatePicker/index.scss | 0 src/templates/sharecomponent/settingcomponent/settingform/datasource/index.scss | 3 src/views/menudesign/printmenuform/index.scss | 5 src/menu/components/chart/antv-pie/chartcompile/index.jsx | 8 src/templates/zshare/verifycard/index.jsx | 47 src/menu/components/share/sourcecomponent/index.jsx | 15 src/mob/components/navbar/normal-navbar/index.scss | 111 src/pc/createview/index.scss | 0 src/tabviews/zshare/topSearch/dategroup/yearpicker/index.scss | 0 config/webpackDevServer.config.js | 2 src/tabviews/zshare/actionList/printbutton/index.jsx | 119 src/tabviews/tabmanage/index.jsx | 6 package.json | 7 src/tabviews/zshare/topSearch/advanceform/index.jsx | 112 src/menu/replaceField/settingform/index.scss | 0 src/menu/components/chart/antv-bar/chartcompile/index.jsx | 181 src/tabviews/zshare/topSearch/mkDatePicker/index.scss | 0 src/mob/header/index.jsx | 16 src/mob/searchconfig/index.jsx | 574 config/modules.js | 2 src/mob/components/navbar/normal-navbar/menusetting/menutable/index.jsx | 198 src/menu/components/share/markcomponent/index.jsx | 40 src/tabviews/custom/components/form/normal-form/index.scss | 4 src/menu/components/card/cardcellcomponent/dragaction/action.jsx | 22 src/menu/components/card/cardcellcomponent/elementform/index.jsx | 2 src/tabviews/zshare/mutilform/mkSelect/index.scss | 0 src/menu/components/tabs/antv-tabs/index.scss | 79 src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.scss | 11 public/admin.html | 6 src/templates/menuconfig/editthdmenu/index.jsx | 21 src/tabviews/zshare/actionList/newpagebutton/index.jsx | 51 src/tabviews/commontable/index.jsx | 105 src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx | 18 src/menu/components/share/normalheader/index.scss | 20 src/tabviews/custom/components/card/cardcellList/index.jsx | 200 src/components/editor/index.jsx | 16 src/tabviews/custom/components/table/normal-table/index.jsx | 181 src/menu/components/group/groupsetting/settingform/index.jsx | 11 src/mob/modulesource/index.jsx | 1 src/components/mkIcon/index.jsx | 70 src/menu/components/group/groupcomponents/card.jsx | 21 src/tabviews/zshare/mutilform/index.jsx | 1605 - src/assets/img/rolemanage.jpg | 0 src/menu/components/share/actioncomponent/actionform/index.jsx | 90 src/mob/components/menubar/normal-menubar/index.scss | 62 src/menu/components/table/normal-table/columns/index.jsx | 84 src/menu/popview/index.jsx | 105 src/tabviews/zshare/mutilform/mkDatePicker/index.jsx | 71 src/tabviews/treepage/index.jsx | 20 src/menu/components/share/logcomponent/index.jsx | 7 src/pc/components/navbar/normal-navbar/index.jsx | 18 src/components/paste/index.scss | 0 src/tabviews/custom/components/chart/antv-scatter/index.jsx | 432 src/menu/components/chart/antv-dashboard/chartcompile/index.jsx | 333 src/views/printTemplate/index.jsx | 6 src/mob/components/navbar/normal-navbar/menusetting/menuform/index.jsx | 222 src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.scss | 0 src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx | 174 src/menu/components/card/balcony/index.scss | 77 config/pnpTs.js | 2 src/tabviews/subtable/index.jsx | 97 src/menu/components/group/normal-group/index.scss | 2 src/tabviews/custom/components/card/table-card/index.jsx | 61 src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx | 342 src/menu/components/share/actioncomponent/index.scss | 7 src/menu/components/chart/antv-scatter/index.scss | 72 src/templates/comtableconfig/source.jsx | 12 src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx | 26 src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx | 8 src/tabviews/zshare/mutilform/mkTextArea/index.scss | 0 src/menu/components/form/wrapsetting/settingform/index.scss | 3 src/menu/components/card/cardcomponent/pastecomponent/index.jsx | 77 src/mob/components/topbar/normal-navbar/index.jsx | 195 src/views/login/index.scss | 109 src/tabviews/zshare/topSearch/mkDatePicker/index.jsx | 93 src/pc/components/login/wrapsetting/index.jsx | 81 src/pc/components/login/normal-login/index.scss | 138 src/mob/searchconfig/groupdragelement/card.jsx | 61 src/tabviews/custom/components/code/sand-box/index.jsx | 18 src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx | 12 src/menu/components/card/table-card/index.jsx | 64 src/templates/modalconfig/settingform/index.scss | 5 src/pc/createview/settingform/index.scss | 11 src/menu/components/tree/antd-tree/wrapsetting/settingform/index.jsx | 262 src/mob/modulesource/option.jsx | 21 src/tabviews/custom/components/share/normalTable/index.scss | 34 src/templates/modalconfig/checkCard/index.scss | 14 src/tabviews/zshare/actionList/excelInbutton/index.jsx | 44 public/options.json | 10 src/templates/modalconfig/checkCard/index.jsx | 34 src/views/pcdesign/index.scss | 2 src/templates/calendarconfig/source.jsx | 6 src/views/mobdesign/index.jsx | 706 src/mob/searchconfig/groupdragelement/index.jsx | 64 src/mob/searchconfig/searchdragelement/index.scss | 149 src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx | 83 src/mob/colorsketch/index.jsx | 17 src/templates/zshare/modalform/datatable/index.jsx | 44 src/menu/components/share/actioncomponent/formconfig.jsx | 115 src/tabviews/custom/components/group/normal-group/index.jsx | 211 src/templates/menuconfig/editfirstmenu/index.jsx | 14 src/tabviews/custom/components/carousel/prop-card/index.jsx | 29 src/templates/zshare/modalform/datatable/index.scss | 6 src/templates/sharecomponent/searchcomponent/searchform/index.jsx | 296 src/mob/components/topbar/normal-navbar/wrapsetting/index.scss | 7 src/tabviews/custom/components/card/balcony/index.scss | 65 src/views/mobdesign/menuform/index.jsx | 4 src/menu/components/card/balcony/wrapsetting/index.scss | 7 src/templates/sharecomponent/searchcomponent/index.jsx | 32 src/menu/components/tree/antd-tree/wrapsetting/index.scss | 7 src/menu/components/share/mobPagination/index.jsx | 20 src/menu/components/card/table-card/cardcomponent/index.jsx | 13 src/tabviews/custom/components/share/normalheader/index.scss | 7 src/views/mobdesign/index.scss | 83 src/utils/utils.js | 406 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx | 73 src/index.js | 4 src/menu/components/search/main-search/dragsearch/index.jsx | 20 src/views/appmanage/scriptform/index.scss | 12 src/views/interface/workspace/request/index.scss | 162 src/tabviews/custom/components/share/tabtransfer/index.jsx | 208 src/menu/components/tabs/tablabelform/index.jsx | 28 src/menu/replaceField/index.jsx | 381 src/mob/modalconfig/controller.jsx | 64 src/menu/modalconfig/index.scss | 15 src/menu/modalconfig/index.jsx | 51 src/tabviews/custom/components/card/balcony/index.jsx | 301 src/views/rolemanage/header/index.scss | 58 src/tabviews/zshare/imgScale/index.jsx | 65 src/utils/option.js | 164 src/templates/zshare/modalform/index.jsx | 105 src/menu/components/table/normal-table/wrapsetting/index.jsx | 2 src/mob/components/topbar/normal-navbar/index.scss | 82 src/assets/mobimg/ratioboard.png | 0 src/tabviews/custom/components/editor/braft-editor/index.jsx | 18 src/menu/components/chart/antv-bar/chartcompile/index.scss | 3 src/menu/components/share/styleInput/index.jsx | 140 src/menu/components/chart/antv-scatter/chartcompile/index.jsx | 271 src/templates/zshare/verifycard/customscript/index.jsx | 7 src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx | 118 src/menu/components/chart/antv-scatter/index.jsx | 404 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx | 6 src/views/interface/workspace/index.jsx | 123 src/tabviews/zshare/mutilform/mkInput/index.jsx | 84 src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx | 233 src/tabviews/zshare/mutilform/mkNumberInput/index.jsx | 67 src/pc/components/login/wrapsetting/settingform/index.jsx | 270 src/menu/components/card/cardcomponent/pastecomponent/index.scss | 0 src/mob/searchconfig/groupdragelement/index.scss | 27 src/views/interface/header/index.jsx | 45 src/tabviews/zshare/mutilform/mkCheckCard/index.scss | 98 src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.jsx | 130 src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx | 20 src/pc/menushell/card.jsx | 46 src/menu/components/carousel/prop-card/index.jsx | 29 src/menu/components/search/main-search/dragsearch/card.jsx | 66 src/menu/components/chart/antv-pie/index.jsx | 384 src/menu/components/share/mobPagination/index.scss | 14 src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx | 62 src/tabviews/zshare/mutilform/mkCheckbox/index.scss | 0 src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx | 66 src/menu/components/tabs/tabcomponents/card.jsx | 15 src/tabviews/zshare/fileupload/index.scss | 15 src/templates/sharecomponent/treesettingcomponent/index.jsx | 11 src/templates/zshare/modalform/modaleditable/index.jsx | 5 src/assets/mobimg/scatter.png | 0 src/menu/modalconfig/controller.jsx | 6 src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx | 14 src/menu/datasource/verifycard/utils.jsx | 32 src/mob/searchconfig/groupform/index.scss | 18 src/tabviews/custom/components/chart/antv-bar-line/index.jsx | 1061 + src/tabviews/custom/components/chart/antv-dashboard/index.jsx | 618 src/views/login/loginform.jsx | 78 src/menu/components/card/balcony/wrapsetting/settingform/index.jsx | 415 src/tabviews/formtab/formgroup/index.jsx | 55 src/menu/components/share/actioncomponent/dragaction/card.jsx | 8 src/templates/comtableconfig/index.jsx | 2 src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx | 54 src/mob/searchconfig/pastecomponent/index.jsx | 57 src/menu/components/tabs/antv-tabs/dragabletabs.jsx | 16 src/views/printTemplate/print.js | 10 src/tabviews/zshare/topSearch/index.scss | 33 src/pc/transfer/settingform/index.jsx | 69 src/menu/sysinterface/settingform/baseform/index.jsx | 4 src/views/interface/workspace/request/index.jsx | 310 src/menu/components/group/groupcomponents/index.scss | 5 src/menu/datasource/verifycard/settingform/index.jsx | 39 src/menu/components/share/actioncomponent/index.jsx | 52 src/mob/searchconfig/source.jsx | 33 src/menu/picturecontroller/editform/index.jsx | 63 src/menu/popview/index.scss | 162 src/tabviews/zshare/mutilform/mkCheckbox/index.jsx | 39 src/pc/createview/settingform/index.jsx | 107 src/tabviews/zshare/imgScale/index.scss | 20 src/menu/stylecombcontrolbutton/index.scss | 10 src/tabviews/custom/components/tree/antd-tree/index.jsx | 452 src/tabviews/zshare/actionList/popupbutton/index.jsx | 60 src/tabviews/custom/components/tabs/antv-tabs/index.jsx | 4 src/menu/components/share/searchcomponent/index.jsx | 2 src/views/interface/index.scss | 6 src/templates/treepageconfig/index.jsx | 3 src/menu/components/form/formaction/index.jsx | 23 src/tabviews/custom/index.scss | 6 src/views/billprint/index.jsx | 40 src/tabviews/subtabtable/index.jsx | 93 src/menu/replaceField/index.scss | 9 src/views/menudesign/index.jsx | 113 src/tabviews/custom/components/card/data-card/index.jsx | 144 src/menu/replaceField/settingform/index.jsx | 78 src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx | 22 src/tabviews/verupmanage/config.jsx | 6 src/tabviews/zshare/mutilform/checkCard/index.jsx | 29 src/router/index.js | 39 src/menu/components/card/cardcomponent/settingform/index.scss | 5 src/menu/components/card/data-card/index.jsx | 116 src/menu/components/chart/antv-dashboard/index.jsx | 538 src/views/appmanage/index.jsx | 913 + src/menu/components/tabs/antv-tabs/index.jsx | 86 src/templates/sharecomponent/searchcomponent/index.scss | 10 src/menu/modulesource/index.jsx | 1 src/templates/sharecomponent/settingcomponent/index.jsx | 33 src/views/design/index.jsx | 5 src/mob/components/menubar/normal-menubar/menucomponent/index.scss | 0 src/templates/subtableconfig/source.jsx | 12 src/menu/components/tree/antd-tree/index.scss | 36 src/tabviews/custom/components/chart/antv-bar-line/index.scss | 48 src/views/interface/api/index.js | 175 src/mob/modalconfig/source.jsx | 104 src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx | 105 src/tabviews/calendar/index.jsx | 69 src/pc/quotecomponent/index.jsx | 2 src/templates/zshare/editcomponent/index.jsx | 82 src/views/rolemanage/index.jsx | 813 + src/tabviews/custom/components/carousel/data-card/index.jsx | 28 src/tabviews/zshare/mutilform/mkSelect/index.jsx | 179 src/templates/zshare/verifycard/customform/index.jsx | 7 src/tabviews/custom/components/tree/antd-tree/index.scss | 97 src/mob/modalconfig/pastecomponent/index.jsx | 76 src/templates/sharecomponent/settingcalcomponent/index.jsx | 11 src/views/interface/header/index.scss | 63 src/menu/components/card/balcony/index.jsx | 237 src/menu/components/tree/antd-tree/wrapsetting/settingform/index.scss | 15 src/tabviews/zshare/actionList/tabbutton/index.jsx | 49 src/menu/stylecontroller/index.jsx | 83 src/views/rolemanage/index.scss | 90 src/menu/components/card/cardcellcomponent/formconfig.jsx | 72 src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx | 302 src/pc/components/login/wrapsetting/index.scss | 7 src/menu/stylecombcontrolbutton/index.jsx | 8 src/tabviews/zshare/fileupload/index.jsx | 208 src/tabviews/zshare/topSearch/dategroup/index.scss | 0 src/menu/components/card/cardcellcomponent/index.scss | 7 src/mob/components/navbar/normal-navbar/menusetting/menuform/index.scss | 10 src/templates/modalconfig/index.jsx | 11 src/templates/sharecomponent/searchcomponent/searchform/index.scss | 15 src/templates/sharecomponent/tablecomponent/index.jsx | 1 src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx | 23 src/mob/modalconfig/index.jsx | 466 src/mob/modalconfig/index.scss | 321 src/views/interface/index.jsx | 28 src/menu/components/form/formaction/formconfig.jsx | 10 src/tabviews/custom/components/card/prop-card/index.jsx | 55 src/mob/components/topbar/normal-navbar/wrapsetting/index.jsx | 81 src/menu/components/tree/antd-tree/wrapsetting/index.jsx | 83 src/mob/components/menubar/normal-menubar/index.jsx | 265 src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx | 4 src/views/interface/history/index.scss | 113 src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx | 22 src/menu/components/chart/antv-pie/index.scss | 4 src/tabviews/zshare/topSearch/dategroup/yearpicker/index.jsx | 0 src/tabviews/custom/components/chart/antv-pie/index.jsx | 525 src/templates/subtableconfig/index.jsx | 2 src/tabviews/zshare/mutilform/checkCard/index.scss | 64 src/tabviews/zshare/topSearch/dategroup/index.jsx | 138 src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx | 12 src/menu/components/card/table-card/cardcomponent/settingform/index.jsx | 1 src/templates/zshare/modalform/index.scss | 8 src/tabviews/custom/index.jsx | 366 src/tabviews/zshare/mutilform/mkTextArea/index.jsx | 92 src/menu/components/card/data-card/wrapsetting/settingform/index.jsx | 58 src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx | 8 src/mob/searchconfig/pastecomponent/index.scss | 0 src/views/appmanage/submutilform/index.jsx | 144 src/tabviews/custom/components/chart/antv-dashboard/index.scss | 110 src/views/design/header/index.jsx | 7 src/assets/mobimg/login.png | 0 src/menu/components/group/groupcomponents/index.jsx | 55 src/templates/zshare/basetransferform/index.jsx | 4 src/menu/components/form/formaction/actionform/index.jsx | 4 src/assets/mobimg/dashboard.png | 0 src/tabviews/custom/components/carousel/data-card/index.scss | 1 src/menu/components/card/cardcellcomponent/dragaction/index.jsx | 7 src/menu/components/form/normal-form/index.jsx | 138 src/pc/menushell/index.jsx | 16 src/tabviews/zshare/actionList/exceloutbutton/index.jsx | 195 src/menu/components/card/cardcellcomponent/dragaction/card.jsx | 28 src/menu/components/chart/antv-bar/index.jsx | 658 src/pc/modulesource/index.jsx | 1 src/views/appmanage/submutilform/index.scss | 6 src/assets/mobimg/tree.png | 0 src/views/rolemanage/header/index.jsx | 32 src/menu/components/card/data-card/wrapsetting/index.jsx | 4 src/menu/components/carousel/data-card/index.jsx | 29 src/mob/components/navbar/normal-navbar/menusetting/index.scss | 11 src/mob/components/menubar/normal-menubar/menucomponent/index.jsx | 218 src/tabviews/zshare/mutilform/mkCheckCard/index.jsx | 140 src/menu/components/share/normalheader/index.jsx | 16 src/templates/modalconfig/settingform/index.jsx | 90 src/pc/components/login/normal-login/loginform.jsx | 139 src/menu/components/search/main-search/index.jsx | 43 src/tabviews/scriptmanage/index.jsx | 70 src/assets/mobimg/menubar.png | 0 src/menu/components/tabs/tabsetting/settingform/index.jsx | 22 src/mob/searchconfig/controller.jsx | 62 src/views/login/index.jsx | 12 src/pc/transfer/index.jsx | 132 src/tabviews/zshare/mutilform/mkRadio/index.jsx | 40 src/mob/components/navbar/normal-navbar/index.jsx | 187 src/utils/utils-datamanage.js | 179 src/menu/components/search/main-search/wrapsetting/settingform/index.jsx | 24 src/utils/utils-custom.js | 177 src/views/interface/workspace/editTable/index.jsx | 249 src/views/printTemplate/mutilform/index.scss | 14 config/env.js | 2 src/menu/components/share/searchcomponent/dragsearch/card.jsx | 2 src/tabviews/custom/components/carousel/prop-card/index.scss | 1 src/menu/components/tabs/tabcomponents/index.jsx | 12 src/menu/components/table/normal-table/columns/editColumn/index.jsx | 63 src/menu/components/card/data-card/index.scss | 19 src/menu/menushell/card.jsx | 12 src/mob/searchconfig/settingform/index.scss | 23 src/templates/sharecomponent/settingcomponent/settingform/index.jsx | 48 src/menu/components/chart/antv-scatter/chartcompile/index.scss | 41 src/templates/modalconfig/dragelement/card.jsx | 4 src/views/interface/history/index.jsx | 290 src/tabviews/zshare/mutilform/mkColor/index.scss | 41 src/mob/components/navbar/normal-navbar/menusetting/menutable/index.scss | 23 src/mob/modalconfig/pastecomponent/index.scss | 0 src/api/cacheutils.js | 31 src/views/printTemplate/mutilform/index.jsx | 83 src/views/design/sidemenu/config.jsx | 20 src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx | 155 src/menu/components/card/balcony/wrapsetting/index.jsx | 83 src/mob/colorsketch/index.scss | 18 src/tabviews/zshare/topSearch/advanceform/index.scss | 41 src/menu/components/table/normal-table/index.jsx | 31 src/menu/components/group/normal-group/index.jsx | 10 src/tabviews/zshare/actionList/asyncButtonComponent.jsx | 18 src/mob/components/navbar/normal-navbar/wrapsetting/index.scss | 7 src/components/tabview/index.jsx | 2 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx | 72 src/views/design/header/index.scss | 7 src/tabviews/zshare/mutilform/mkSwitch/index.jsx | 43 src/menu/datasource/verifycard/customscript/index.jsx | 10 src/pc/transfer/settingform/index.scss | 11 src/mob/searchconfig/index.scss | 365 src/pc/components/login/wrapsetting/settingform/index.scss | 11 src/tabviews/custom/components/chart/antv-pie/index.scss | 5 src/tabviews/zshare/topSearch/mkSelect/index.jsx | 121 config/paths.js | 2 src/tabviews/zshare/mutilform/mkColor/index.jsx | 60 src/tabviews/custom/components/share/normalTable/index.jsx | 30 src/templates/modalconfig/dragelement/index.jsx | 3 src/tabviews/custom/components/card/data-card/index.scss | 22 src/menu/components/search/main-search/index.scss | 44 src/menu/components/share/usercomponent/index.jsx | 1 src/assets/mobimg/nest.png | 0 src/menu/components/form/wrapsetting/settingform/index.jsx | 17 src/menu/components/share/pastecomponent/index.jsx | 51 src/templates/zshare/formconfig.jsx | 717 src/tabviews/zshare/mutilform/mkSwitch/index.scss | 0 src/pc/createview/index.jsx | 201 src/tabviews/custom/components/form/normal-form/index.jsx | 140 src/mob/components/formdragelement/card.jsx | 200 src/pc/components/login/normal-login/index.jsx | 170 src/tabviews/custom/components/chart/antv-scatter/asyncButtonComponent.jsx | 34 /dev/null | 88 src/templates/menuconfig/editsecmenu/index.jsx | 32 src/tabviews/custom/components/card/cardcellList/index.scss | 23 src/menu/menushell/index.jsx | 13 src/templates/sharecomponent/columncomponent/columnform/index.jsx | 3 478 files changed, 32,754 insertions(+), 7,141 deletions(-) diff --git a/config/env.js b/config/env.js index b0344c5..f8c5326 100644 --- a/config/env.js +++ b/config/env.js @@ -1,4 +1,4 @@ -'use strict'; +// 'use strict'; const fs = require('fs'); const path = require('path'); diff --git a/config/modules.js b/config/modules.js index 46d9c9e..10c4374 100644 --- a/config/modules.js +++ b/config/modules.js @@ -1,4 +1,4 @@ -'use strict'; +// 'use strict'; const fs = require('fs'); const path = require('path'); diff --git a/config/paths.js b/config/paths.js index f23c121..68fc8d7 100644 --- a/config/paths.js +++ b/config/paths.js @@ -1,4 +1,4 @@ -'use strict'; +// 'use strict'; const path = require('path'); const fs = require('fs'); diff --git a/config/pnpTs.js b/config/pnpTs.js index d1b0539..6a3b546 100644 --- a/config/pnpTs.js +++ b/config/pnpTs.js @@ -1,4 +1,4 @@ -'use strict'; +// 'use strict'; const { resolveModuleName } = require('ts-pnp'); diff --git a/config/webpack.config.js b/config/webpack.config.js index 54b9961..a793358 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -173,14 +173,16 @@ pathinfo: isEnvDevelopment, // There will be one main bundle, and one file per asynchronous chunk. // In development, it does not produce real files. + // contenthash => hash filename: isEnvProduction - ? 'static/js/[name].[contenthash:8].js' + ? 'static/js/[name].[hash:8].js' : isEnvDevelopment && 'static/js/bundle.js', // TODO: remove this when upgrading to webpack 5 futureEmitAssets: true, // There are also additional JS chunk files if you use code splitting. + // contenthash => hash chunkFilename: isEnvProduction - ? 'static/js/[name].[contenthash:8].chunk.js' + ? 'static/js/[name].[hash:8].chunk.js' : isEnvDevelopment && 'static/js/[name].chunk.js', // We inferred the "public path" (such as / or /my-project) from homepage. // We use "/" in development. @@ -565,8 +567,9 @@ new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional - filename: 'static/css/[name].[contenthash:8].css', - chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', + // contenthash => hash + filename: 'static/css/[name].[hash:8].css', + chunkFilename: 'static/css/[name].[hash:8].chunk.css', }), // Generate a manifest file which contains a mapping of all asset filenames // to their corresponding output file so that tools can pick it up without diff --git a/config/webpackDevServer.config.js b/config/webpackDevServer.config.js index 33ab8d3..a90fc24 100644 --- a/config/webpackDevServer.config.js +++ b/config/webpackDevServer.config.js @@ -1,4 +1,4 @@ -'use strict'; +// 'use strict'; const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware'); const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware'); diff --git a/package-lock.json b/package-lock.json index fd8ff65..2a72c49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,47 +60,74 @@ } }, "@antv/color-util": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.5.tgz", - "integrity": "sha512-eQktA9YDnWCj03rfjpg0ajvCfRkHXzBzsZa9z94pY6Jb7e3XtPUp7vDpB8KhaKm9GjPtGzQDneh+gnqkEK8mtQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.6.tgz", + "integrity": "sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==", "requires": { "@antv/util": "^2.0.9", - "tslib": "^1.10.0" + "tslib": "^2.0.3" }, "dependencies": { "@antv/util": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz", - "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz", + "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==", "requires": { - "tslib": "^1.10.0" + "tslib": "^2.0.3" } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" } } }, "@antv/component": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.2.tgz", - "integrity": "sha512-aU65T9jD85H+3WhhmgPz8kiuqxJGPuHFgRiBYmR+vQUnAA2nOW2bCafiNx/bSEAqmVgsr+8e+9IDQZ6PowIgtQ==", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.11.tgz", + "integrity": "sha512-7hl7IPPF/QmE25lrZhppEW8BYJzU3SE6IGq4/NhrvcDk79Xhm1L4KOcAAcZ0zYBRaOwQL3yMcraIL+/Z1UhLjw==", "requires": { "@antv/dom-util": "~2.0.1", - "@antv/g-base": "~0.5.0", + "@antv/g-base": "0.5.6", "@antv/matrix-util": "^3.1.0-beta.1", "@antv/path-util": "~2.0.7", "@antv/scale": "~0.3.1", "@antv/util": "~2.0.0", "fecha": "~4.2.0", - "tslib": "^1.10.0" + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } }, "@antv/coord": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.0.tgz", - "integrity": "sha512-lm5Ct+r62mFVqhziKoDFN3PQjnkNBMOoOG+kBsPq3M3GqlQt5Jc7euOHMFcYSZM9HJmsKkGcih6EWDVVliMEZg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.1.tgz", + "integrity": "sha512-rFE94C8Xzbx4xmZnHh2AnlB3Qm1n5x0VT3OROy257IH6Rm4cuzv1+tZaUBATviwZd99S+rOY9telw/+6C9GbRw==", "requires": { "@antv/matrix-util": "^3.1.0-beta.2", - "@antv/util": "~2.0.3", - "tslib": "^1.10.0" + "@antv/util": "~2.0.12", + "tslib": "^2.1.0" + }, + "dependencies": { + "@antv/util": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz", + "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==", + "requires": { + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } }, "@antv/data-set": { @@ -127,11 +154,18 @@ } }, "@antv/dom-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.2.tgz", - "integrity": "sha512-i/rh385casRd6OA4rbpbA2jyiwY/w7PtkA+74mH43PiBzOcLpDg1jEWR9dMO0tIqUzHQWWqKNNjmXVubl4GS6g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.3.tgz", + "integrity": "sha512-dUHsUT4U9X1T1/Y9bH3jRMe0MzvWJk2jSQm1vm3w9NX+Ra0ftq5VUBiGTNbthm3nFwG0fFFjip904rYjl50g4A==", "requires": { - "tslib": "^1.10.0" + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } }, "@antv/event-emitter": { @@ -140,81 +174,105 @@ "integrity": "sha512-6C6NJOdoNVptCr5y9BVOhKkCgW7LFs/SpcRyAExUeSjAm0zJqcqNkSIRGsXYhj4PJI+CZICHzGwwiSnIsE68Ug==" }, "@antv/g-base": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.1.tgz", - "integrity": "sha512-gbv+uz/SvzM4/p3PLjAiEZUp6kdzKkCbVWTCdBXB1cvNMttlEzWEB8MOFbEkcIAy7TtjQJJRv8ThI/ngFzU+fg==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.6.tgz", + "integrity": "sha512-szxqFQ/xdCnfaeSEEC2kVjXdKxJnvKKJNT0MvaOG3UXOfsjPDLgb3IKLr+bU3sLvTAQfPhsbtYh7mWb03+mGjA==", "requires": { "@antv/event-emitter": "^0.1.1", - "@antv/g-math": "^0.1.5", + "@antv/g-math": "^0.1.6", "@antv/matrix-util": "^3.1.0-beta.1", "@antv/path-util": "~2.0.5", "@antv/util": "~2.0.0", - "@types/d3-timer": "^1.0.9", + "@types/d3-timer": "^2.0.0", "d3-ease": "^1.0.5", "d3-interpolate": "^1.3.2", "d3-timer": "^1.0.9", - "detect-browser": "^5.1.0" + "detect-browser": "^5.1.0", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } }, "@antv/g-canvas": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.3.tgz", - "integrity": "sha512-80k1BbiY05heHKUm4o6IL6KVRZS+uAgzdIF2OaC9grQc6KxrJoK2dCxKpmna3NBHTU9Sm+/rsiGcL7lp7S+ecQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.6.tgz", + "integrity": "sha512-r6f6KqYuNZWunf2Vnf1ACopn8aic6TBFhaN3XuckenhQNqR+/PI/4Mft7z14zo7WH58X2Xs2Npq9awJXBEUzaw==", "requires": { - "@antv/g-base": "^0.5.1", - "@antv/g-math": "^0.1.5", + "@antv/g-base": "^0.5.3", + "@antv/g-math": "^0.1.6", "@antv/matrix-util": "^3.1.0-beta.1", "@antv/path-util": "~2.0.5", "@antv/util": "~2.0.0", - "gl-matrix": "^3.0.0" + "gl-matrix": "^3.0.0", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } }, "@antv/g-math": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.5.tgz", - "integrity": "sha512-29B3p33jzUPIyx1xYfNCexbp7jvahD6bD8FKKyWqfYZHQbvrFfV8ZNUu66RJLfDrl0KaKT6C5whfKs/WrVaflQ==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.7.tgz", + "integrity": "sha512-xGyXaloD1ynfp7gS4VuV+MjSptZIwHvLHr8ekXJSFAeWPYLu84yOW2wOZHDdp1bzDAIuRv6xDBW58YGHrWsFcA==", "requires": { "@antv/util": "~2.0.0", "gl-matrix": "^3.0.0" } }, "@antv/g-svg": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.2.tgz", - "integrity": "sha512-T0PYjIM+WX6zv3yUgSkyRcHFq4hlio0MeRGoJR60P5U5MNSdkZnblcu79cpU2i42Z7wBr404Kv1dplCGxC38PA==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.6.tgz", + "integrity": "sha512-Xve1EUGk4HMbl2nq4ozR4QLh6GyoZ8Xw/+9kHYI4B5P2lIUQU95MuRsaLFfW5NNpZDx85ZeH97tqEmC9L96E7A==", "requires": { - "@antv/g-base": "^0.5.1", - "@antv/g-math": "^0.1.5", + "@antv/g-base": "^0.5.3", + "@antv/g-math": "^0.1.6", "@antv/util": "~2.0.0", - "detect-browser": "^5.0.0" + "detect-browser": "^5.0.0", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } }, "@antv/g2": { - "version": "4.1.0-beta.18", - "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.1.0-beta.18.tgz", - "integrity": "sha512-RW3e95V2aUtys36guS7PNHbfgyYZgigu18OLSYPkgyRLF0pPABcSrIot+xnVGQ4Cx0ZDmhJVTvpXjU4QMa96kw==", + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.1.14.tgz", + "integrity": "sha512-JdU+0suxkDqjTZNyG915zQ7eM+bdT2fHV48VGc1LvCroUHzCncCnbx5HZ19aZhvuij2hM6eh52vb8mwIXIzMBw==", "requires": { "@antv/adjust": "^0.2.1", "@antv/attr": "^0.3.1", "@antv/color-util": "^2.0.2", - "@antv/component": "^0.8.0", + "@antv/component": "^0.8.7", "@antv/coord": "^0.3.0", "@antv/dom-util": "^2.0.2", "@antv/event-emitter": "~0.1.0", - "@antv/g-base": "^0.5.0", - "@antv/g-canvas": "^0.5.0", - "@antv/g-svg": "^0.5.0", + "@antv/g-base": "0.5.6", + "@antv/g-canvas": "0.5.6", + "@antv/g-svg": "0.5.6", "@antv/matrix-util": "^3.1.0-beta.1", "@antv/path-util": "^2.0.3", - "@antv/scale": "^0.3.1", + "@antv/scale": "^0.3.7", "@antv/util": "~2.0.5", "tslib": "^2.0.0" }, "dependencies": { "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" } } }, @@ -237,38 +295,50 @@ }, "dependencies": { "@antv/util": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz", - "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz", + "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==", "requires": { - "tslib": "^1.10.0" + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } } } }, "@antv/path-util": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.8.tgz", - "integrity": "sha512-g5gt12MY1oEzh/j5XfLNRCfJU7E+Us+2yM5Hqc0y8xeWhb5l013XG5BPV37KmOf6WAys9KNxklNniHCZ6SqCKw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.9.tgz", + "integrity": "sha512-kunEz4dNheQMVn4rVFsoBDx+n9Knfi3uRLvDk9SojZAqpninsjFhdoiYtbExwJGz1FYGtiV10Y6N1tp73kZFcg==", "requires": { "@antv/util": "^2.0.9", - "tslib": "^1.10.0" + "tslib": "^2.0.3" }, "dependencies": { "@antv/util": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz", - "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz", + "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==", "requires": { - "tslib": "^1.10.0" + "tslib": "^2.0.3" } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" } } }, "@antv/scale": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.4.tgz", - "integrity": "sha512-mZaf3MtMoQJtd+KAgTANVbvKpaXVpzLAFbKO/wSKaLFpnWO0bwMVDYzrs+5DZhfEfMbZpP/A7qUZ2/DLh0T3Tg==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.9.tgz", + "integrity": "sha512-m56Rs4Zta7XnuF+aNbJXMsgBqATO1M4kvu+dEmhzLYsPK5D3dHpJTOGh/Zy55eirekb9F7jiu29SJqPNnhxq+g==", "requires": { "@antv/util": "~2.0.3", "fecha": "~4.2.0", @@ -276,18 +346,25 @@ }, "dependencies": { "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" } } }, "@antv/util": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.8.tgz", - "integrity": "sha512-G9QRygQJ8UNGMi8L1dfMIa4SofbEO+jkXwvRY4ek/MLd04Q01UN0U28JeMFzw6FCKJdxiFu+2uwT/zjoFr3QoQ==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz", + "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==", "requires": { - "tslib": "^1.10.0" + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } } }, "@babel/code-frame": { @@ -1464,6 +1541,33 @@ "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-9.0.1.tgz", "integrity": "sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA==" }, + "@fast-csv/format": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", + "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==", + "requires": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isboolean": "^3.0.3", + "lodash.isequal": "^4.5.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0" + } + }, + "@fast-csv/parse": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", + "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", + "requires": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + } + }, "@hapi/address": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.1.tgz", @@ -2376,9 +2480,9 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, "@types/d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-ZnAbquVqy+4ZjdW0cY6URp+qF/AzTVNda2jYyOzpR2cPT35FTXl78s15Bomph9+ckOiI1TtkljnWkwbIGAb6rg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.0.tgz", + "integrity": "sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg==" }, "@types/eslint-visitor-keys": { "version": "1.0.0", @@ -2425,6 +2529,11 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==" + }, + "@types/node": { + "version": "14.14.44", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.44.tgz", + "integrity": "sha512-+gaugz6Oce6ZInfI/tK4Pq5wIIkJMEJUu92RB3Eu93mtj4wjjjz9EB5mLp5s1pSsLXdC/CPut/xF20ZzAQJbTA==" }, "@types/prop-types": { "version": "15.7.2", @@ -3151,6 +3260,61 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + } + } }, "are-we-there-yet": { "version": "1.1.5", @@ -4033,10 +4197,50 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } }, "block-stream": { "version": "0.0.9", @@ -4373,10 +4577,20 @@ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==" + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" }, "builtin-status-codes": { "version": "3.0.0", @@ -4550,6 +4764,21 @@ "commander": "^2.16.0", "crc-32": "~1.2.0", "printj": "~1.1.2" + } + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "requires": { + "traverse": ">=0.3.0 <0.4" + }, + "dependencies": { + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" + } } }, "chalk": { @@ -4875,6 +5104,34 @@ "arity-n": "^1.0.4" } }, + "compress-commons": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.0.tgz", + "integrity": "sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==", + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "compressible": { "version": "2.0.17", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", @@ -5088,6 +5345,27 @@ "requires": { "exit-on-epipe": "~1.0.1", "printj": "~1.1.0" + } + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "create-ecdh": { @@ -7166,6 +7444,14 @@ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "^2.0.2" + } + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -7966,6 +8252,63 @@ "safe-buffer": "^5.1.1" } }, + "exceljs": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.2.1.tgz", + "integrity": "sha512-EogoTdXH1X1PxqD9sV8caYd1RIfXN3PVlCV+mA/87CgdO2h4X5xAEbr7CaiP8tffz7L4aBFwsdMbjfMXi29NjA==", + "requires": { + "archiver": "^5.0.0", + "dayjs": "^1.8.34", + "fast-csv": "^4.3.1", + "jszip": "^3.5.0", + "readable-stream": "^3.6.0", + "saxes": "^5.0.1", + "tmp": "^0.2.0", + "unzipper": "^0.10.11", + "uuid": "^8.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "requires": { + "xmlchars": "^2.2.0" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "requires": { + "rimraf": "^3.0.0" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + } + } + }, "exec-sh": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", @@ -8301,6 +8644,15 @@ "time-stamp": "^1.0.0" } }, + "fast-csv": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz", + "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==", + "requires": { + "@fast-csv/format": "4.3.5", + "@fast-csv/parse": "4.3.6" + } + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -8435,9 +8787,9 @@ } }, "fecha": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", - "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", + "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" }, "figgy-pudding": { "version": "3.5.1", @@ -8700,6 +9052,11 @@ "inherits": "^2.0.1", "readable-stream": "^2.0.0" } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { "version": "7.0.1", @@ -9940,6 +10297,11 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" }, "immer": { "version": "1.10.0", @@ -11421,6 +11783,11 @@ "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==" }, + "js-table2excel": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/js-table2excel/-/js-table2excel-1.0.3.tgz", + "integrity": "sha512-ivzOdgYqOD3zqzJZfW0Nm35P9BWffxD0Unwr+2QBeEawV7hhRY9RHBVNcvO6A9PhGkMyqPVL/u4/NeufaTTTXw==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -11587,6 +11954,17 @@ "object.assign": "^4.1.0" } }, + "jszip": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz", + "integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==", + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -11634,6 +12012,14 @@ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -11660,6 +12046,19 @@ "prelude-ls": "~1.1.2", "type-check": "~0.3.2" } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "requires": { + "immediate": "~3.0.5" + } + }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=" }, "load-json-file": { "version": "1.1.0", @@ -11773,6 +12172,31 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" + }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -11782,6 +12206,36 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" }, "lodash.keys": { "version": "3.1.2", @@ -11829,6 +12283,11 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" }, "lodash.uniq": { "version": "4.5.0", @@ -17057,6 +17516,14 @@ } } }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "requires": { + "minimatch": "^3.0.4" + } + }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -17991,6 +18458,11 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" }, "set-value": { "version": "2.0.1", @@ -19022,6 +19494,30 @@ "inherits": "2" } }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", @@ -19778,6 +20274,30 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, + "unzipper": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + }, + "dependencies": { + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=" } } }, @@ -20736,6 +21256,28 @@ } } }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "zrender": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/zrender/-/zrender-4.1.2.tgz", diff --git a/package.json b/package.json index 5ca8645..aaef24f 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "private": true, "dependencies": { "@antv/data-set": "^0.11.4", - "@antv/g2": "^4.1.0-beta.18", + "@antv/g2": "^4.1.14", + "@antv/util": "^2.0.13", "@babel/core": "7.5.5", "@svgr/webpack": "4.3.2", "@typescript-eslint/eslint-plugin": "1.13.0", @@ -39,6 +40,7 @@ "eslint-plugin-jsx-a11y": "6.2.3", "eslint-plugin-react": "7.14.3", "eslint-plugin-react-hooks": "^1.6.1", + "exceljs": "^4.2.1", "file-loader": "3.0.1", "fs-extra": "7.0.1", "html-webpack-plugin": "4.0.0-beta.5", @@ -52,6 +54,7 @@ "jest-environment-jsdom-fourteen": "0.1.0", "jest-resolve": "24.8.0", "jest-watch-typeahead": "0.3.1", + "js-table2excel": "^1.0.3", "jsbarcode": "^3.11.3", "jssha": "^3.2.0", "md5": "^2.2.1", @@ -189,7 +192,7 @@ ] ] }, - "homepage": "./build", + "homepage": ".", "devDependencies": { "typescript": "^4.0.2" } diff --git a/public/admin.html b/public/admin.html index 1c43083..41254bc 100644 --- a/public/admin.html +++ b/public/admin.html @@ -24,10 +24,8 @@ var appPort = 'admin/index.html' if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) { appPort = 'mob/index.html' - } else { - if (config.defaultApp) { - appPort = 'pc/' - } + } else if (config.defaultApp) { + appPort = 'pc/index.html' } window.location.replace(url + appPort) } diff --git a/public/options.json b/public/options.json index 9e7abbb..e213888 100644 --- a/public/options.json +++ b/public/options.json @@ -1,13 +1,15 @@ { "appId": "20201221213901540C6BC419CE41E47FABA62", "appkey": "2020122121373692319E639E61B0E46A6BC2C", - "mainSystemApi": "http://cloud.positecgroup.com:8080/webapi/dostar", + "mainSystemApi": "https://cloud.positecgroup.com/webapi/dostars", "systemType": "", - "externalDatabase": "false", + "externalDatabase": "mkdata_kress_test", "lineColor": "", "filter": "false", "defaultApp": "", "defaultLang": "zh-CN", - "host": "http://qingqiumarket.cn", - "service": "mkwms/" + "WXAppID": "", + "debugger": false, + "host": "http://bms-test.kresstools.cn", + "service": "oc/" } \ No newline at end of file diff --git a/src/api/cacheutils.js b/src/api/cacheutils.js index 2aa5642..aa742fc 100644 --- a/src/api/cacheutils.js +++ b/src/api/cacheutils.js @@ -5,7 +5,7 @@ /** * @description 鎵撳紑websql */ - static openWebSql () { + static openWebSql (sysType) { let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : '' try { window.GLOB.WebSql = openDatabase(`mkdb${service}`, '1', 'mk-pc-database', 50 * 1024 * 1024) @@ -22,6 +22,15 @@ // eslint-disable-next-line throw 'CREATE TABLE ERROR' }) + + if (sysType === 'local' && window.GLOB.systemType === '') { + tx.executeSql('CREATE TABLE IF NOT EXISTS FUNCS (func_code varchar(50), key_sql text, CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50))', [], () => { + + }, () => { + // eslint-disable-next-line + throw 'CREATE TABLE ERROR' + }) + } }) // window.GLOB.WebSql.transaction(tx => { // tx.executeSql('DROP TABLE VERSIONS') @@ -42,16 +51,13 @@ } return new Promise((resolve, reject) => { window.GLOB.WebSql.transaction(tx => { - tx.executeSql('SELECT * FROM VERSIONS', [], (tx, results) => { + tx.executeSql("SELECT * FROM VERSIONS where CDefine1='LongParam'", [], (tx, results) => { if (results.rows.length === 0) { - tx.executeSql('DELETE FROM CONFIGS') - resolve({version: '', createDate: ''}) - } else if (results.rows.length === 1) { - resolve(results.rows[0]) - } else if (results.rows.length > 1) { tx.executeSql('DELETE FROM VERSIONS') tx.executeSql('DELETE FROM CONFIGS') resolve({version: '', createDate: ''}) + } else { + resolve(results.rows[0]) } }, (tx, results) => { window.GLOB.WebSql = null @@ -107,7 +113,7 @@ static updateWebSqlTime (curTime) { if (!window.GLOB.WebSql || !curTime) return window.GLOB.WebSql.transaction(tx => { - tx.executeSql(`UPDATE VERSIONS SET createDate='${curTime}'`, [], () => {}, () => { + tx.executeSql(`UPDATE VERSIONS SET createDate='${curTime}' where CDefine1='LongParam'`, [], () => {}, () => { window.GLOB.WebSql = null }) }) @@ -119,7 +125,7 @@ static updateWebSqlversion (version, curTime) { if (!window.GLOB.WebSql || !curTime || !version) return window.GLOB.WebSql.transaction(tx => { - tx.executeSql(`UPDATE VERSIONS SET version='${version}', createDate='${curTime}'`, [], () => {}, () => { + tx.executeSql(`UPDATE VERSIONS SET version='${version}', createDate='${curTime}' where CDefine1='LongParam'`, [], () => {}, () => { window.GLOB.WebSql = null }) }) @@ -131,7 +137,7 @@ static createWebSqlversion (version, curTime) { if (!window.GLOB.WebSql || !curTime || !version) return window.GLOB.WebSql.transaction(tx => { - tx.executeSql('INSERT INTO VERSIONS (version, createDate) VALUES (?, ?)', [version, curTime], () => {}, () => { + tx.executeSql('INSERT INTO VERSIONS (version, createDate, CDefine1) VALUES (?, ?, ?)', [version, curTime, 'LongParam'], () => {}, () => { window.GLOB.WebSql = null }) }) @@ -182,7 +188,7 @@ /** * @description 鎵撳紑IndexedDB */ - static openIndexDB () { + static openIndexDB (sysType) { let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : '' try { let request = window.indexedDB.open(`mkdb${service}`, 1) @@ -202,6 +208,9 @@ objectStore.createIndex('menuid', 'menuid', { unique: false }) objectStore.createIndex('userid', 'userid', { unique: false }) } + if (window.GLOB.systemType === '' && sysType === 'local' && !window.GLOB.IndexDB.objectStoreNames.contains('funcs')) { + window.GLOB.IndexDB.createObjectStore('funcs', { keyPath: 'id' }) + } } } catch (e) { console.warn('IndexedDB 鍒濆鍖栧け璐ワ紒') diff --git a/src/api/index.js b/src/api/index.js index ad91d61..c5f65d9 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -17,9 +17,9 @@ 1578479100252lfbp29v1kafk4s4q4ig,1577971621421tg4v0i1ur8873k7e0ob,1577929944419lgc5h3hepum765e2k7u,1588493493409k9guqp067d31lu7blsv` if (window.openDatabase) { - CacheUtils.openWebSql() + CacheUtils.openWebSql(options.sysType) } else if (window.indexedDB) { - CacheUtils.openIndexDB() + CacheUtils.openIndexDB(options.sysType) } axios.defaults.crossDomain = true @@ -255,15 +255,31 @@ login_id_address: ipAddress } + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + + let sys_datetime = sessionStorage.getItem('sys_datetime') + let app_datetime = sessionStorage.getItem('app_datetime') + if (sys_datetime && app_datetime) { + let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000) + param.timestamp = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss') + } + // Type: 'S' 鏃� let shaObj = new jsSHA('SHA-1', 'TEXT') - param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') shaObj.update(password) param.Password = shaObj.getHash('HEX').toUpperCase() param.Password = md5(username + param.Password + param.timestamp) + // Type: 'mk_' 鏃� + // param.Type = '鍏挜' + // let shaObj = new jsSHA('SHA-1', 'TEXT') + // shaObj.update(password) + // param.Password = shaObj.getHash('HEX').toUpperCase() + // param.Password = md5('绉侀挜' + username + param.Password + param.timestamp) + // Type: 'X' 鏃� // param.Password = Utils.formatOptions(password) + param.appkey = window.GLOB.appkey || '' let url = '/webapi/dologon' @@ -297,14 +313,26 @@ return Promise.reject() } + let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + let sys_datetime = sessionStorage.getItem('sys_datetime') + let app_datetime = sessionStorage.getItem('app_datetime') + if (sys_datetime && app_datetime) { + let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000) + curTime = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss') + '.000' + } + if (window.GLOB.WebSql) { return new Promise((resolve, reject) => { CacheUtils.getWebSqlVersion().then(msg => { appVersion.oldVersion = msg.version || '' - let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + let modifydate = msg.createDate || curTime + if (modifydate.indexOf('Invalid date') > -1) { + modifydate = curTime + } + let param = { func: 's_get_app_version', - modifydate: msg.createDate || curTime, + modifydate } this.getSystemConfig(param).then(res => { @@ -348,10 +376,13 @@ return new Promise((resolve, reject) => { CacheUtils.getIndexDBVersion().then(msg => { appVersion.oldVersion = msg.version || '' - let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + let modifydate = msg.createDate || curTime + if (modifydate.indexOf('Invalid date') > -1) { + modifydate = curTime + } let param = { func: 's_get_app_version', - modifydate: msg.createDate || curTime, + modifydate } this.getSystemConfig(param).then(res => { @@ -437,6 +468,30 @@ return axios({ url, + method: 'post', + data: param + }) + } + + /** + * @description 鑾峰彇鎴栦慨鏀圭郴缁熼厤缃紝澧炲姞appkey + */ + getSystemFuncs (time) { + let param = { + func: 's_get_func_base_sso', + update_date: time, + userid: sessionStorage.getItem('UserID') || '', + lang: sessionStorage.getItem('lang') || '', + SessionUid: localStorage.getItem('SessionUid') || '', + LoginUID: sessionStorage.getItem('LoginUID') || '', + appkey: window.GLOB.appkey + } + + let url = window.GLOB.mainSystemApi + param = this.encryptParam(param) + + return axios({ + url: `${url}/${param.func}`, method: 'post', data: param }) @@ -785,22 +840,17 @@ param = this.encryptParam(param) + let url = '/webapi/SaveBase64Image' if (param.rduri) { - let url = param.rduri.replace(/webapi(.*)$/, 'webapi/SaveBase64Image') + url = param.rduri.replace(/webapi(.*)$/, 'webapi/SaveBase64Image') delete param.rduri - - return axios({ - url, - method: 'post', - data: param - }) - } else { - return axios({ - url: '/webapi/SaveBase64Image', - method: 'post', - data: param - }) } + + return axios({ + url, + method: 'post', + data: param + }) } /** diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss index 3d90a6e..9c1486d 100644 --- a/src/assets/css/main.scss +++ b/src/assets/css/main.scss @@ -135,15 +135,15 @@ background: rgba(0, 0, 0, 0); } // 閲嶇疆妯℃�佹婊氬姩鏉� -.ant-modal-wrap::-webkit-scrollbar { +.ant-modal-wrap::-webkit-scrollbar, .ant-drawer-wrapper-body::-webkit-scrollbar { width: 7px; } -.ant-modal-wrap::-webkit-scrollbar-thumb { +.ant-modal-wrap::-webkit-scrollbar-thumb, .ant-drawer-wrapper-body::-webkit-scrollbar-thumb { border-radius: 5px; - box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); - background: rgba(0, 0, 0, 0.13); + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.1); + background: rgba(0, 0, 0, 0.1); } -.ant-modal-wrap::-webkit-scrollbar-track { +.ant-modal-wrap::-webkit-scrollbar-track, .ant-drawer-wrapper-body::-webkit-scrollbar-track { box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); border-radius: 3px; border: 1px solid rgba(0, 0, 0, 0.07); @@ -386,4 +386,21 @@ padding: 5px 20px; } } +} + +.ant-input[disabled] { + background-color: #fafafa!important; +} +.ant-btn[disabled] { + background-color: transparent!important; + border-color: rgba(0, 0, 0, 0.35)!important; + color: rgba(0, 0, 0, 0.35)!important; +} +.ant-btn.ant-btn-link { + border-width: 0; +} +.button-list { + .ant-btn.ant-btn-link { + border-width: 1px; + } } \ No newline at end of file diff --git a/src/assets/css/viewstyle.scss b/src/assets/css/viewstyle.scss index d1ca60c..e1f8bcc 100644 --- a/src/assets/css/viewstyle.scss +++ b/src/assets/css/viewstyle.scss @@ -33,11 +33,8 @@ button.vercode { color: $color6; } - .ant-tabs { - .ant-tabs-tab.ant-tabs-tab-active { - color: $color6; - } - .ant-tabs-tab:hover { + .login-way-wrap { + .login-way.active, .login-way:hover { color: $color6; } } @@ -208,7 +205,7 @@ .top-search { >.ant-row { .ant-col.search-button { - .ant-btn:not(.ant-btn-primary):active, .ant-btn:not(.ant-btn-primary).active, .ant-btn:not(.ant-btn-primary):hover, .ant-btn:not(.ant-btn-primary):focus { + .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link).active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):hover, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):focus { color: $color7; border-color: $color7; } @@ -216,6 +213,14 @@ background-color: $color6; border-color: $color6; } + .ant-btn-link { + color: $color6; + } + } + } + .advanced-list { + .advance-value { + color: $color6; } } } diff --git a/src/assets/img/rolemanage.jpg b/src/assets/img/rolemanage.jpg index 1b6c346..8fe80c3 100644 --- a/src/assets/img/rolemanage.jpg +++ b/src/assets/img/rolemanage.jpg Binary files differ diff --git a/src/assets/mobimg/dashboard.png b/src/assets/mobimg/dashboard.png new file mode 100644 index 0000000..9769128 --- /dev/null +++ b/src/assets/mobimg/dashboard.png Binary files differ diff --git a/src/assets/mobimg/login.png b/src/assets/mobimg/login.png new file mode 100644 index 0000000..13c10ee --- /dev/null +++ b/src/assets/mobimg/login.png Binary files differ diff --git a/src/assets/mobimg/menubar.png b/src/assets/mobimg/menubar.png new file mode 100644 index 0000000..2766d21 --- /dev/null +++ b/src/assets/mobimg/menubar.png Binary files differ diff --git a/src/assets/mobimg/navtop-mob.png b/src/assets/mobimg/navtop-mob.png new file mode 100644 index 0000000..829cd6b --- /dev/null +++ b/src/assets/mobimg/navtop-mob.png Binary files differ diff --git a/src/assets/mobimg/nest.png b/src/assets/mobimg/nest.png new file mode 100644 index 0000000..16c2158 --- /dev/null +++ b/src/assets/mobimg/nest.png Binary files differ diff --git a/src/assets/mobimg/ratioboard.png b/src/assets/mobimg/ratioboard.png new file mode 100644 index 0000000..53498da --- /dev/null +++ b/src/assets/mobimg/ratioboard.png Binary files differ diff --git a/src/assets/mobimg/scatter.png b/src/assets/mobimg/scatter.png new file mode 100644 index 0000000..dfeb28a --- /dev/null +++ b/src/assets/mobimg/scatter.png Binary files differ diff --git a/src/assets/mobimg/tree.png b/src/assets/mobimg/tree.png new file mode 100644 index 0000000..b26f993 --- /dev/null +++ b/src/assets/mobimg/tree.png Binary files differ diff --git a/src/components/editor/index.jsx b/src/components/editor/index.jsx index a94d12e..3cfc203 100644 --- a/src/components/editor/index.jsx +++ b/src/components/editor/index.jsx @@ -23,8 +23,8 @@ class NormalEditor extends Component { static propTpyes = { - Item: PropTypes.object, // 琛ㄥ崟鍏冪礌 - onChange: PropTypes.func, // 琛ㄥ崟鏇存柊 + config: PropTypes.object, + onChange: PropTypes.func } state = { @@ -33,16 +33,17 @@ } UNSAFE_componentWillMount () { + const { config, defaultValue } = this.props let initVal = null let encryption = 'false' - if (this.props['data-__meta']) { - initVal = this.props['data-__meta'].initialValue || null - } else if (this.props.defaultValue) { - initVal = this.props.defaultValue || null + if (config && config.initval) { + initVal = config.initval + } else if (defaultValue) { + initVal = defaultValue } - if (this.props.Item && this.props.Item.encryption === 'true') { + if (config && config.encryption === 'true') { encryption = 'true' if (initVal) { try { @@ -92,6 +93,7 @@ form.append('fileExt', params.file.fileType) form.append('shardingCnt', _param.chunks) form.append('shardingNo', _param.chunk) + form.append('LoginUID', sessionStorage.getItem('LoginUID') || '') Api.getLargeFileUpload(form).then(res => { if (res.status) { diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx index aa7b4d2..0fab405 100644 --- a/src/components/header/index.jsx +++ b/src/components/header/index.jsx @@ -143,7 +143,7 @@ edition_type: 'A', pro_sys: window.GLOB.systemType === 'production' ? 'Y' : '' }).then(result => { - let _permAction = {} // 鎸夐挳鏉冮檺 + let _permAction = {loaded: true} // 鎸夐挳鏉冮檺 if (result && result.status) { if (result.UserRoles_Menu) { @@ -214,7 +214,7 @@ this.props.modifyMenuTree(menulist) this.props.modifyMainMenu(mainMenu) - this.props.initMenuPermission(thdMenuList) + this.props.initMenuPermission([...thdMenuList, {MenuID: 'home_page_id', EasyCode: '', MenuName: 'home', type: 'CustomPage'}]) resolve(_menu) }) @@ -371,7 +371,7 @@ // 淇敼缂栬緫鐘舵�� let UserID = sessionStorage.getItem('CloudUserID') let LoginUID = sessionStorage.getItem('CloudLoginUID') - + if (!UserID || !LoginUID) { this.setState({ loginVisible: true @@ -408,12 +408,18 @@ sessionStorage.setItem('dataM', res.dataM ? 'true' : '') sessionStorage.setItem('isEditState', 'true') + this.setSystemFuncs() + this.props.modifyMenuTree([]) this.props.modifyMainMenu(null) this.props.modifyTabview([]) this.props.history.replace('/design') } else { + if (res.message.indexOf('瀵嗙爜閿欒') > -1) { + const input = document.getElementById('password') + input && input.select() + } this.setState({ loginLoading: false }) @@ -427,6 +433,107 @@ }) } + setSystemFuncs = () => { + if (!window.GLOB.WebSql && !window.GLOB.IndexDB) { + return + } + this.getfuncTime().then(res => { + Api.getSystemFuncs(res.createDate).then(result => { + if (!result.status) { + notification.error({ + top: 92, + message: result.message, + duration: 10 + }) + return + } else if (result.func_detail && result.func_detail.length > 0) { + this.writeFuncs(result.func_detail) + } + }) + }) + } + + writeFuncs = (funcs) => { + let timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + + let sys_datetime = sessionStorage.getItem('sys_datetime') + let app_datetime = sessionStorage.getItem('app_datetime') + if (sys_datetime && app_datetime) { + let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000) + timestamp = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss') + } + + if (window.GLOB.WebSql) { + window.GLOB.WebSql.transaction(tx => { + tx.executeSql('DELETE FROM FUNCS') + + funcs.forEach(item => { + if (!item.key_sql) return + tx.executeSql('INSERT INTO FUNCS (func_code, key_sql) VALUES (?, ?)', [item.func_code, item.key_sql]) + }) + tx.executeSql(`UPDATE VERSIONS SET createDate='${timestamp}' where CDefine1='funcs'`) + }) + } else { + let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs') + + objectStore.clear() + + funcs.forEach(item => { + if (!item.key_sql) return + item.id = item.func_code + objectStore.add(item) + }) + + let funcStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version') + funcStore.put({id: 'funcs', version: '1.0', createDate: timestamp}) + } + } + + getfuncTime = () => { + return new Promise((resolve, reject) => { + if (window.GLOB.WebSql) { + window.GLOB.WebSql.transaction(tx => { + tx.executeSql("SELECT * FROM VERSIONS where CDefine1='funcs'", [], (tx, results) => { + let rows = results.rows + if (rows.length === 0) { + tx.executeSql('DELETE FROM FUNCS') + tx.executeSql('INSERT INTO VERSIONS (version, createDate, CDefine1) VALUES (?, ?, ?)', ['1.0', '1970-01-01 14:59:09.000', 'funcs']) + resolve({createDate: '1970-01-01 14:59:09.000'}) + } else { + resolve(rows[0]) + } + }, (tx, results) => { + reject() + console.warn(results) + }) + }) + } else { + let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version') + let request = objectStore.get('funcs') + + request.onerror = (event) => { + console.warn(event) + reject() + } + + request.onsuccess = () => { + if (request.result) { + resolve(request.result) + } else { + let add = objectStore.add({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'}) + + add.onerror = () => { + reject() + } + add.onsuccess = () => { + resolve({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'}) + } + } + } + } + }) + } + changeSystem = (system) => { let url = system.LinkUrl1 diff --git a/src/components/mkIcon/index.jsx b/src/components/mkIcon/index.jsx new file mode 100644 index 0000000..583e170 --- /dev/null +++ b/src/components/mkIcon/index.jsx @@ -0,0 +1,70 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Modal, Icon, Row, Col, Button } from 'antd' + +import { minkeIconSystem } from '@/utils/option.js' +import './index.scss' + +class MkIcon extends Component { + static propTpyes = { + onChange: PropTypes.func + } + + state = { + selectIcon: '', + allowClear: false, + icons: [...minkeIconSystem.direction, ...minkeIconSystem.edit, ...minkeIconSystem.normal, ...minkeIconSystem.trademark, ...minkeIconSystem.data, ...minkeIconSystem.hint], + visible: false + } + + UNSAFE_componentWillMount () { + let val = '' + if (this.props['data-__meta']) { + val = this.props['data-__meta'].initialValue || '' + } + + this.setState({selectIcon: val, allowClear: this.props.allowClear === true}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + checkIcon = (val) => { + this.setState({selectIcon: val, visible: false}) + this.props.onChange(val) + } + + render() { + const { selectIcon, visible, icons, allowClear } = this.state + + return ( + <div className="mk-icon-box"> + {selectIcon ? <Icon type={selectIcon}/> : <Icon style={{opacity: 0}} type="plus"/>} + <Icon className="trigger" onClick={() => this.setState({visible: true})} type="swap"/> + {allowClear ? <Icon className="close" onClick={() => this.checkIcon('')} type="close"/> : null} + <Modal + wrapClassName="popview-modal mk-icon-wrap" + title={'鍥炬爣閫夋嫨'} + visible={visible} + width={800} + maskClosable={false} + onCancel={() => { this.setState({ visible: false }) }} + footer={[ + <Button key="close" onClick={() => { this.setState({ visible: false }) }}>鍏抽棴</Button> + ]} + destroyOnClose + > + <Row> + {icons.map(icon => <Col className={icon === selectIcon ? 'active' : ''} key={icon} span={4}> + <Icon onClick={() => this.checkIcon(icon)} type={icon} /> + </Col>)} + </Row> + </Modal> + </div> + ) + } +} + +export default MkIcon \ No newline at end of file diff --git a/src/components/mkIcon/index.scss b/src/components/mkIcon/index.scss new file mode 100644 index 0000000..4ba05ef --- /dev/null +++ b/src/components/mkIcon/index.scss @@ -0,0 +1,53 @@ +.mk-icon-box { + display: block; + height: 32px; + border: 1px solid #d9d9d9; + border-radius: 4px; + line-height: 32px; + padding: 0px 0px 0px 10px; + + .anticon.trigger { + float: right; + line-height: 32px; + padding: 0 10px; + border-left: 1px solid #d9d9d9; + } + .close.anticon { + float: right; + margin-top: 6px; + margin-right: 5px; + background: #efefef; + border-radius: 50%; + color: #757575; + padding: 3px; + font-size: 10px; + opacity: 0; + transition: opacity 0.3s; + } +} +.mk-icon-box:hover { + border-color: #1890ff; + .close.anticon { + opacity: 1; + } +} +.mk-icon-box::after { + content: ' '; + display: block; + clear: both; +} +.mk-icon-wrap { + .ant-col { + text-align: center; + line-height: 55px; + .anticon { + font-size: 30px; + cursor: pointer; + } + } + .active.ant-col { + .anticon { + color: #1890ff; + } + } +} diff --git a/src/components/paste/index.jsx b/src/components/paste/index.jsx new file mode 100644 index 0000000..4760c22 --- /dev/null +++ b/src/components/paste/index.jsx @@ -0,0 +1,72 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Icon, Modal, notification } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) + +class PasteController extends Component { + static propTpyes = { + options: PropTypes.array, + updateConfig: PropTypes.func + } + + state = { + visible: false + } + + handleMenuClick = () => { + this.setState({visible: true}) + } + + pasteSubmit = () => { + const { options } = this.props + this.pasteFormRef.handleConfirm().then(res => { + if (!options.includes(res.copyType)) { + notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', duration: 5 }) + return + } + this.props.updateConfig(res, (result) => { + if (result.status) { + notification.success({ + top: 92, + message: '绮樿创鎴愬姛锛�', + duration: 2 + }) + this.setState({visible: false}) + } else { + notification.success({ + top: 92, + message: result.message, + duration: 2 + }) + } + }) + }) + } + + render() { + const { visible } = this.state + + return ( + <div style={{display: 'inline-block'}}> + <Icon type="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} /> + <Modal + title="绮樿创" + visible={visible} + width={600} + maskClosable={false} + onOk={this.pasteSubmit} + onCancel={() => {this.setState({visible: false})}} + destroyOnClose + > + <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> + </Modal> + </div> + ) + } +} + +export default PasteController \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/components/paste/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/components/paste/index.scss diff --git a/src/components/tabview/index.jsx b/src/components/tabview/index.jsx index 980b810..a9ebd63 100644 --- a/src/components/tabview/index.jsx +++ b/src/components/tabview/index.jsx @@ -137,6 +137,8 @@ return (<TabManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) } else if (view.type === 'RolePermission') { return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) + } else if (view.type === 'appRolePermission') { + return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) } else if (view.type === 'FormTab') { return (<FormTab MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'iframe') { diff --git a/src/index.js b/src/index.js index 5e8a1c2..5c7b909 100644 --- a/src/index.js +++ b/src/index.js @@ -69,9 +69,9 @@ sessionStorage.setItem('role_id', sessionStorage.getItem('localRole_id') || '') sessionStorage.setItem('dataM', sessionStorage.getItem('localDataM') || '') -// 鏂扮郴缁熸枃浠剁疆浜巃dmin涓� ../options.json +// 鏂扮郴缁熸枃浠剁疆浜巃dmin涓� ../options.json , { cache: 'no-cache'} -fetch('./options.json') +fetch('../options.json') .then(response => response.json()) .catch(() => { document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">绯荤粺閰嶇疆淇℃伅鑾峰彇澶辫触锛岃鑱旂郴绠$悊鍛橈紒</div>' diff --git a/src/locales/zh-CN/model.js b/src/locales/zh-CN/model.js index c50cd3a..5a3a4cd 100644 --- a/src/locales/zh-CN/model.js +++ b/src/locales/zh-CN/model.js @@ -125,7 +125,7 @@ 'model.form.link': '鑱斿姩鑿滃崟', 'model.form.linkform': '鍏宠仈琛ㄥ崟', 'model.form.dateday': '鏃ユ湡锛堝ぉ锛�', - 'model.form.datetime': '鏃ユ湡锛堢锛�', + 'model.form.datetime': '鏃ユ湡锛堝垎/绉掞級', 'model.form.dateweek': '鏃ユ湡锛堝懆锛�', 'model.form.datemonth': '鏃ユ湡锛堟湀锛�', 'model.form.daterange': '鏃ユ湡锛堝尯闂达級', diff --git a/src/menu/bgcontroller/index.jsx b/src/menu/bgcontroller/index.jsx index 9dbdec5..7018a0c 100644 --- a/src/menu/bgcontroller/index.jsx +++ b/src/menu/bgcontroller/index.jsx @@ -1,7 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Form } from 'antd' +import { Form, Select } from 'antd' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' @@ -10,6 +10,7 @@ const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) +const { Option } = Select class MobController extends Component { static propTpyes = { @@ -21,6 +22,8 @@ dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, backgroundColor: '', backgroundImage: '', + backgroundSize: '', + backgroundRepeat: '', } UNSAFE_componentWillMount () { @@ -35,7 +38,9 @@ this.setState({ backgroundColor: config.style.backgroundColor, - backgroundImage: bgImg + backgroundImage: bgImg, + backgroundSize: config.style.backgroundSize || '100%', + backgroundRepeat: config.style.backgroundRepeat || 'repeat', }) } @@ -72,8 +77,30 @@ this.props.updateConfig(config) } + backgroundSizeChange = (val) => { + this.setState({ + backgroundSize: val + }) + + let config = fromJS(this.props.config).toJS() + config.style.backgroundSize = val + + this.props.updateConfig(config) + } + + backgroundRepeatChange = (val) => { + this.setState({ + backgroundRepeat: val + }) + + let config = fromJS(this.props.config).toJS() + config.style.backgroundRepeat = val + + this.props.updateConfig(config) + } + render () { - const { backgroundColor, backgroundImage } = this.state + const { backgroundColor, backgroundImage, backgroundSize, backgroundRepeat } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -94,6 +121,23 @@ <Form.Item colon={false} label="鍥剧墖"> <SourceComponent value={backgroundImage} type="" placement="right" onChange={this.imgChange}/> </Form.Item> + <Form.Item colon={false} label="姣斾緥"> + <Select defaultValue={backgroundSize} onChange={this.backgroundSizeChange}> + <Option value="100%">100%</Option> + <Option value="100% 100%">100% 100%</Option> + <Option value="auto 100%">auto 100%</Option> + <Option value="contain">contain</Option> + <Option value="cover">cover</Option> + </Select> + </Form.Item> + <Form.Item colon={false} label="閲嶅"> + <Select defaultValue={backgroundRepeat} onChange={this.backgroundRepeatChange}> + <Option value="repeat">repeat</Option> + <Option value="no-repeat">no-repeat</Option> + <Option value="repeat-x">repeat-x</Option> + <Option value="repeat-y">repeat-y</Option> + </Select> + </Form.Item> </Form> </div> ) diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx new file mode 100644 index 0000000..0fc02d5 --- /dev/null +++ b/src/menu/components/card/balcony/index.jsx @@ -0,0 +1,237 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' +import { resetStyle } from '@/utils/utils-custom.js' +import MKEmitter from '@/utils/events.js' +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import './index.scss' + +const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) +const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) +const CardCellComponent = asyncComponent(() => import('../cardcellcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/components/paste')) +const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) +const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) + +class BalconyEditComponent extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + back: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + tabId: card.tabId || '', + parentId: card.parentId || '', + format: 'object', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 + pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� + switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + dataName: card.dataName || '', + width: card.width || 24, + name: card.name, + subtype: card.subtype, + setting: { interType: 'system' }, + wrap: { name: card.name, width: card.width || 24, linkType: 'static', position: 'relative', datatype: 'static' }, + style: { marginLeft: '0px', marginRight: '0px', marginTop: '0px', marginBottom: '0px' }, + columns: [], + scripts: [], + elements: [], + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.wrap.name = card.name + _card.style = config.style + + _card.elements = _card.elements.map(elem => { + elem.uuid = Utils.getuuid() + return elem + }) + } + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (component) => { + this.setState({ + card: component + }) + + component.width = component.wrap.width + component.name = component.wrap.name + + this.props.updateConfig(component) + } + + updateCard = (elements) => { + const { card } = this.state + + let _card = {...card, elements: elements} + + this.setState({ + card: _card, + }) + + this.props.updateConfig(_card) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds.length !== 1 || comIds[0] !== card.uuid) return + + let _card = {...card, style} + + this.setState({ + card: _card + }) + + this.props.updateConfig(_card) + } + + addElement = () => { + const { card } = this.state + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.eleType = 'text' + newcard.datatype = 'dynamic' + newcard.height = 1 + + // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌 + MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], newcard) + } + + addButton = () => { + const { card } = this.state + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.eleType = 'button' + newcard.label = 'button' + newcard.sqlType = '' + newcard.Ot = 'requiredSgl' + newcard.OpenType = 'prompt' + newcard.icon = '' + newcard.class = 'primary' + newcard.intertype = 'system' + newcard.execSuccess = 'grid' + newcard.execError = 'never' + newcard.popClose = 'never' + newcard.errorTime = 10 + newcard.verify = null + newcard.show = 'link' + + // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌 + MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], newcard) + } + + pasteComponent = (res, resolve) => { + const { card } = this.state + + let type = res.copyType + delete res.copyType + + res.uuid = Utils.getuuid() + res.focus = true + + if (type === 'customCardElement') { + MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], res) + } else { + res.eleType = 'button' + MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], res) + } + resolve({status: true}) + } + + render() { + const { card } = this.state + + let _style = resetStyle(card.style) + + return ( + <div className="menu-balcony-edit-box" style={_style} id={card.uuid}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="plus" title="娣诲姞鍏冪礌" onClick={this.addElement} type="plus" /> + <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="balcony" card={card}/> + <PasteComponent options={['action', 'customCardElement']} updateConfig={this.pasteComponent} /> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <ClockComponent config={card} updateConfig={this.updateComponent}/> + <UserComponent config={card}/> + <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null} + {card.wrap.datatype === 'static' ? <Icon style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/> : null} + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + <CardCellComponent cards={card} cardCell={card} elements={card.elements} updateElement={this.updateCard}/> + </div> + ) + } +} + +export default BalconyEditComponent \ No newline at end of file diff --git a/src/menu/components/card/balcony/index.scss b/src/menu/components/card/balcony/index.scss new file mode 100644 index 0000000..1e071bd --- /dev/null +++ b/src/menu/components/card/balcony/index.scss @@ -0,0 +1,77 @@ +.menu-balcony-edit-box { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 30px; + + .card-control { + position: absolute; + top: 0px; + left: 0px; + .anticon-tool { + right: auto; + left: 1px; + padding: 1px; + } + } + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + + .card-item { + overflow: hidden; + position: relative; + background-color: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 20px; + } + + .card-item:hover { + box-shadow: 0px 0px 2px #1890ff; + } + + .model-menu-card-cell-list .card-detail-row > .anticon-plus { + position: absolute; + right: -30px; + font-size: 16px; + } + .model-menu-action-list { + line-height: 40px; + .ant-row > .anticon-plus { + position: absolute; + right: -30px; + font-size: 16px; + } + } + .card-add-button { + text-align: right; + clear: left; + .anticon-plus { + font-size: 20px; + color: #26C281; + padding: 5px; + margin-right: 10px; + } + } +} +.menu-balcony-edit-box::after { + display: block; + content: ' '; + clear: both; +} +.menu-balcony-edit-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/menu/components/card/balcony/wrapsetting/index.jsx b/src/menu/components/card/balcony/wrapsetting/index.jsx new file mode 100644 index 0000000..a8332db --- /dev/null +++ b/src/menu/components/card/balcony/wrapsetting/index.jsx @@ -0,0 +1,83 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import './index.scss' + +class BalconyWrapSetting extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + wrap: null + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({wrap: fromJS(config.wrap).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + editDataSource = () => { + this.setState({ + visible: true + }) + } + + verifySubmit = () => { + const { config } = this.props + + this.verifyRef.handleConfirm().then(res => { + + this.setState({ + wrap: res, + visible: false + }) + this.props.updateConfig({...config, wrap: res}) + }) + } + + render () { + const { config } = this.props + const { visible, dict, wrap } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} /> + <Modal + wrapClassName="popview-modal" + title="鍗$墖璁剧疆" + visible={visible} + width={800} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + wrap={wrap} + config={config} + inputSubmit={this.verifySubmit} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default BalconyWrapSetting \ No newline at end of file diff --git a/src/menu/components/card/balcony/wrapsetting/index.scss b/src/menu/components/card/balcony/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/menu/components/card/balcony/wrapsetting/index.scss @@ -0,0 +1,7 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx b/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..d0124d5 --- /dev/null +++ b/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx @@ -0,0 +1,415 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select, Cascader } from 'antd' + +import MenuUtils from '@/utils/utils-custom.js' +import StyleInput from '@/menu/components/share/styleInput' +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, + config: PropTypes.object, + wrap: PropTypes.object, + inputSubmit: PropTypes.func + } + + state = { + roleList: [], + modules: [], + supmodules: [], + appType: sessionStorage.getItem('appType'), + linkType: this.props.wrap.linkType, + position: this.props.wrap.position, + } + + UNSAFE_componentWillMount () { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + let menu = fromJS(window.GLOB.customMenu).toJS() + + let modules = MenuUtils.getLinkModules(menu.components) + if (!modules) { + modules = [] + } + + let _menu = fromJS(window.GLOB.customMenu).toJS() + + let supmodules = MenuUtils.getSupModules(_menu.components, '') + if (!supmodules) { + supmodules = [] + } + + this.setState({roleList, modules, supmodules}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + chose = (val) => { + let values = {} + if (val === 'top') { + values = { + top: '0px', + left: '50%', + right: '', + bottom: '', + transform: 'translateX(-50%)' + } + } else if (val === 'top-left') { + values = { + top: '0px', + left: '0px', + right: '', + bottom: '', + transform: '' + } + } else if (val === 'top-right') { + values = { + top: '0px', + left: '', + right: '0px', + bottom: '', + transform: '' + } + } else if (val === 'left-middle') { + values = { + top: '50%', + left: '0px', + right: '', + bottom: '', + transform: 'translateY(-50%)' + } + } else if (val === 'right-middle') { + values = { + top: '50%', + left: '', + right: '0px', + bottom: '', + transform: 'translateY(-50%)' + } + } else if (val === 'bottom-left') { + values = { + top: '', + left: '0px', + right: '', + bottom: '0px', + transform: '' + } + } else if (val === 'bottom-right') { + values = { + top: '', + left: '', + right: '0px', + bottom: '0px', + transform: '' + } + } else if (val === 'bottom') { + values = { + top: '', + left: '50%', + right: '', + bottom: '0px', + transform: 'translateX(-50%)' + } + } else if (val === 'middle') { + values = { + top: '50%', + left: '50%', + right: '', + bottom: '', + transform: 'translate(-50%, -50%)' + } + } + this.props.form.setFieldsValue(values) + } + + render() { + const { wrap } = this.props + const { getFieldDecorator } = this.props.form + const { roleList, modules, supmodules, linkType, position } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�"> + <Icon type="question-circle" /> + 缁勪欢鍚嶇О + </Tooltip> + }> + {getFieldDecorator('name', { + initialValue: wrap.name, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��"> + <Icon type="question-circle" /> + 瀹藉害 + </Tooltip> + }> + {getFieldDecorator('width', { + initialValue: wrap.width || 24, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '瀹藉害!' + } + ] + })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��"> + <Icon type="question-circle" /> + 鏁版嵁鏉ユ簮 + </Tooltip> + }> + {getFieldDecorator('datatype', { + initialValue: wrap.datatype + })( + <Radio.Group> + <Radio value="dynamic">鍔ㄦ��</Radio> + <Radio value="static">闈欐��</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="缁勪欢涓庡叾浠栫粍浠朵箣闂寸殑鎺у埗绫诲瀷锛岀嫭绔嬭〃绀轰笌鍏朵粬娌℃湁鍏宠仈銆�"> + <Icon type="question-circle" /> + 鍙楁帶绫诲瀷 + </Tooltip> + }> + {getFieldDecorator('linkType', { + initialValue: wrap.linkType || 'static' + })( + <Radio.Group onChange={(e) => this.setState({linkType: e.target.value})}> + <Radio value="static">鐙珛</Radio> + <Radio value="sync">鍚屾</Radio> + <Radio value="sup">涓婄骇</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {linkType === 'sup' ? <Col span={12}> + <Form.Item label="涓婄骇缁勪欢"> + {getFieldDecorator('supModule', { + initialValue: wrap.supModule, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '涓婄骇缁勪欢!' + } + ] + })( + <Cascader options={supmodules} expandTrigger="hover" placeholder="" /> + )} + </Form.Item> + </Col> : null} + {linkType === 'sup' ? <Col span={12}> + <Form.Item label="鏄剧ず鎺у埗"> + {getFieldDecorator('supControl', { + initialValue: wrap.supControl || 'show' + })( + <Radio.Group> + <Radio key="hidden" value="hidden"> 閫夎鏄剧ず </Radio> + <Radio key="show" value="show"> 濮嬬粓鏄剧ず </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {linkType === 'sync' ? <Col span={12}> + <Form.Item label="鍚屾缁勪欢"> + {getFieldDecorator('syncModule', { + initialValue: wrap.syncModule, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鍚屾缁勪欢!' + } + ] + })( + <Cascader options={modules} expandTrigger="hover" placeholder="" /> + )} + </Form.Item> + </Col> : null} + {linkType === 'sync' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="褰撳悓姝ョ粍浠跺彲澶氶�夋椂锛岃缃叏閫夋湁鏁堛��"> + <Icon type="question-circle" /> + 鍏ㄩ�� + </Tooltip> + }> + {getFieldDecorator('checkAll', { + initialValue: wrap.checkAll || 'hidden' + })( + <Radio.Group> + <Radio key="hidden" value="hidden"> 闅愯棌 </Radio> + <Radio key="show" value="show"> 鏄剧ず </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="浣跨敤鍥哄畾瀹氫綅鏃讹紝璇峰湪娴嬭瘯鐜涓煡鐪嬪畾浣嶆晥鏋溿��"> + <Icon type="question-circle" /> + 浣嶇疆 + </Tooltip> + }> + {getFieldDecorator('position', { + initialValue: wrap.position || 'relative' + })( + <Radio.Group onChange={(e) => this.setState({position: e.target.value})}> + <Radio value="relative">鐩稿瀹氫綅</Radio> + <Radio value="fixed">鍥哄畾瀹氫綅</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {position === 'fixed' ? <Col span={12}> + <Form.Item label="蹇嵎閫夋嫨"> + <Select onSelect={this.chose}> + <Select.Option key='1' value={'top'}>涓�</Select.Option> + <Select.Option key='2' value={'top-left'}>宸︿笂</Select.Option> + <Select.Option key='3' value={'top-right'}>鍙充笂</Select.Option> + <Select.Option key='4' value={'left-middle'}>宸︿腑</Select.Option> + <Select.Option key='5' value={'right-middle'}>鍙充腑</Select.Option> + <Select.Option key='6' value={'bottom-left'}>宸︿笅</Select.Option> + <Select.Option key='7' value={'bottom-right'}>鍙充笅</Select.Option> + <Select.Option key='8' value={'bottom'}>涓�</Select.Option> + <Select.Option key='9' value={'middle'}>涓棿</Select.Option> + </Select> + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濅笂"> + {getFieldDecorator('top', { + initialValue: wrap.top || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濆彸"> + {getFieldDecorator('right', { + initialValue: wrap.right || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濅笅"> + {getFieldDecorator('bottom', { + initialValue: wrap.bottom || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濆乏"> + {getFieldDecorator('left', { + initialValue: wrap.left || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="瀹為檯瀹藉害"> + {getFieldDecorator('realwidth', { + initialValue: wrap.realwidth || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="鍙樻崲"> + {getFieldDecorator('transform', { + initialValue: wrap.transform || '' + })( + <Select> + <Select.Option key='1' value={''}>鏃�</Select.Option> + <Select.Option key='2' value={'translateY(-50%)'}>涓婄Щ50%</Select.Option> + <Select.Option key='3' value={'translateY(50%)'}>涓嬬Щ50%</Select.Option> + <Select.Option key='4' value={'translateX(-50%)'}>宸︾Щ50%</Select.Option> + <Select.Option key='5' value={'translateX(50%)'}>鍙崇Щ50%</Select.Option> + <Select.Option key='6' value={'translate(-50%, -50%)'}>宸︿笂绉�50%</Select.Option> + <Select.Option key='7' value={'translate(-50%, 50%)'}>宸︿笅绉�50%</Select.Option> + <Select.Option key='8' value={'translate(50%, -50%)'}>鍙充笂绉�50%</Select.Option> + <Select.Option key='9' value={'translate(50%, 50%)'}>鍙充笅绉�50%</Select.Option> + </Select> + )} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label="榛戝悕鍗�"> + {getFieldDecorator('blacklist', { + initialValue: wrap.blacklist || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {roleList.map(option => + <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/menu/components/card/balcony/wrapsetting/settingform/index.scss b/src/menu/components/card/balcony/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..9644e12 --- /dev/null +++ b/src/menu/components/card/balcony/wrapsetting/settingform/index.scss @@ -0,0 +1,36 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } + .css { + padding-top: 10px; + .css-class { + position: absolute; + right: 13px; + top: -15px; + z-index: 1; + button { + height: 25px; + } + } + .ant-form-item { + margin-bottom: 0; + } + .ant-form-item-label { + width: 16%; + } + .ant-form-item-control-wrapper { + width: 84%; + .code-mirror-wrap .code-mirror-area .CodeMirror { + height: 100px; + min-height: 100px; + } + } + } +} \ No newline at end of file diff --git a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx index 7bdc28b..4ce1876 100644 --- a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx +++ b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx @@ -1,9 +1,11 @@ import React from 'react' import { useDrag, useDrop } from 'react-dnd' import { Icon, Popover, Button } from 'antd' + +import { resetStyle } from '@/utils/utils-custom.js' import './index.scss' -const Card = ({ id, card, moveCard, findCard, editCard, delCard, profileCard, changeStyle, doubleClickCard }) => { +const Card = ({ id, card, moveCard, findCard, editCard, copyCard, delCard, profileCard, changeStyle, doubleClickCard }) => { const originalIndex = findCard(id).index const [{ isDragging }, drag] = useDrag({ item: { type: 'action', id, originalIndex }, @@ -25,12 +27,6 @@ }, }) - let _style = {opacity: isDragging ? 0 : 1} - - if (card.style) { - _style = {...card.style, opacity: isDragging ? 0 : 1} - } - let hasProfile = false if (['pop', 'prompt', 'exec'].includes(card.OpenType)) { hasProfile = true @@ -41,25 +37,27 @@ } let btnElement = null + let _style = resetStyle(card.style) if (card.show === 'icon') { - btnElement = (<Button style={card.btnstyle} type="link"><Icon type={card.icon}/></Button>) + btnElement = (<Button style={_style} type="link"><Icon type={card.icon}/></Button>) } else if (card.show === 'link') { - btnElement = (<Button style={card.btnstyle} type="link">{card.label}{card.icon ? <Icon type={card.icon}/> : null}</Button>) + btnElement = (<Button style={_style} type="link">{card.icon ? <Icon type={card.icon}/> : null}{card.label}</Button>) } else { - btnElement = (<Button icon={card.icon} style={card.btnstyle}> {card.label} </Button>) + btnElement = (<Button style={_style}> {card.label}{card.icon ? <Icon type={card.icon}/> : null} </Button>) } return ( <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <Icon className="edit" title="缂栬緫" type="edit" onClick={() => editCard(id)} /> + <Icon className="copy" title="澶嶅埗" type="copy" onClick={() => copyCard(id)} /> <Icon className="close" title="鍒犻櫎" type="close" onClick={() => delCard(id)} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)} type="font-colors" /> {hasProfile ? <Icon className="profile" title="setting" type="profile" onClick={() => profileCard(id)} /> : null} </div> } trigger="hover"> - <div ref={node => drag(drop(node))} className={'ant-col card-button-cell ant-col-' + card.width} onDoubleClick={() => doubleClickCard(id)}> - <div style={_style}> + <div ref={node => drag(drop(node))} className={'ant-col card-button-cell ant-col-' + card.width} onDoubleClick={(e) => {e.stopPropagation(); doubleClickCard(id)}}> + <div style={{opacity: isDragging ? 0 : 1}}> {btnElement} </div> </div> diff --git a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx index 96b6549..9ee5976 100644 --- a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx +++ b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx @@ -11,13 +11,18 @@ import MKEmitter from '@/utils/events.js' import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import './index.scss' const BarCode = asyncComponent(() => import('@/components/barcode')) const QrCode = asyncComponent(() => import('@/components/qrcode')) const Video = asyncComponent(() => import('@/components/video')) const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent')) +const PicRadio = { + '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%', + '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%', + '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%' +} const Card = ({ id, parent, fields, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, updateMarks, doubleClickCard }) => { const originalIndex = findCard(id).index @@ -45,6 +50,17 @@ if (card.style) { _style = {...card.style, opacity: isDragging ? 0 : 1} + _style = resetStyle(_style) + } + if (card.eleType === 'picture' && card.maxWidth) { + _style.maxWidth = card.maxWidth + let left = _style.marginLeft && _style.marginLeft !== '0px' ? _style.marginLeft : 'auto' + let right = _style.marginRight && _style.marginRight !== '0px' ? _style.marginRight : 'auto' + _style.margin = (_style.marginTop || 0) + ' ' + right + ' ' + (_style.marginBottom || 0) + ' ' + left + delete _style.marginLeft + delete _style.marginRight + delete _style.marginTop + delete _style.marginBottom } const getContent = () => { @@ -85,12 +101,8 @@ _imagestyle.borderRadius = card.style.borderRadius } - if (card.lenWidRadio === '16:9') { - _imagestyle.paddingTop = '56.25%' - } else if (card.lenWidRadio === '3:2') { - _imagestyle.paddingTop = '66.67%' - } else if (card.lenWidRadio === '4:3') { - _imagestyle.paddingTop = '75%' + if (PicRadio[card.lenWidRadio]) { + _imagestyle.paddingTop = PicRadio[card.lenWidRadio] } else { _imagestyle.paddingTop = '100%' } @@ -146,7 +158,7 @@ <Icon className="copy" title="澶嶅埗" type="copy" onClick={() => copyCard(id)} /> <Icon className="close" title="鍒犻櫎" type="close" onClick={() => delCard(id)} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)} type="font-colors" /> - {['text', 'number', 'slider'].includes(card.eleType) ? <MarkColumn columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null } + {['text', 'number', 'slider', 'sequence'].includes(card.eleType) ? <MarkColumn columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null } </div> } trigger="hover"> <div ref={node => drag(drop(node))} className={'ant-col card-cell ant-col-' + card.width}> diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx index eda8cc2..96eea80 100644 --- a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx +++ b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx @@ -38,7 +38,11 @@ let copycard = fromJS(card).toJS() let _cards = fromJS(cards).toJS() - copycard.copyType = 'customCardElement' + if (card.eleType === 'button') { + copycard.copyType = 'action' + } else { + copycard.copyType = 'customCardElement' + } copycard.focus = true let _val = fromJS(copycard).toJS() @@ -112,6 +116,7 @@ key={card.uuid} card={card} parent={parent} + copyCard={copyCard} moveCard={moveCard} editCard={editCard} changeStyle={changeStyle} diff --git a/src/menu/components/card/cardcellcomponent/elementform/index.jsx b/src/menu/components/card/cardcellcomponent/elementform/index.jsx index 2f0f75c..38de87f 100644 --- a/src/menu/components/card/cardcellcomponent/elementform/index.jsx +++ b/src/menu/components/card/cardcellcomponent/elementform/index.jsx @@ -15,7 +15,7 @@ sequence: ['eleType', 'width'], text: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix', 'link'], number: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix'], - picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'link'], + picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'maxWidth', 'link'], video: ['eleType', 'datatype', 'width', 'aspectRatio', 'autoPlay', 'loop'], icon: ['eleType', 'icon', 'datatype', 'width'], slider: ['eleType', 'datatype', 'width', 'color', 'maxValue'], diff --git a/src/menu/components/card/cardcellcomponent/formconfig.jsx b/src/menu/components/card/cardcellcomponent/formconfig.jsx index b81da36..ac0423d 100644 --- a/src/menu/components/card/cardcellcomponent/formconfig.jsx +++ b/src/menu/components/card/cardcellcomponent/formconfig.jsx @@ -4,11 +4,11 @@ const Formdict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS /** - * @description 鑾峰彇鎸夐挳琛ㄥ崟閰嶇疆淇℃伅 - * @param {*} card 缂栬緫鎸夐挳 - * @param {*} type 鎸夐挳绫诲瀷锛岀敤浜庡尯鍒嗗彲閫夌殑鎵撳紑鏂瑰紡 + * @description 鑾峰彇鍏冪礌閰嶇疆淇℃伅 + * @param {*} card + * @param {*} type */ -export function getCardCellForm (card, type) { +export function getCardCellForm (card, type, subtype, cardCell) { let _options = [ { value: 'text', text: '鏂囨湰'}, { value: 'number', text: '鏁板��'}, @@ -22,7 +22,7 @@ { value: 'currentDate', text: '褰撳墠鏃堕棿'}, ] - if (type === 'table') { + if (type === 'table' || (type === 'card' && subtype === 'datacard')) { _options.push({value: 'sequence', text: '搴忓彿'}) } let appMenus = [] @@ -40,6 +40,17 @@ } else { appMenus = [] } + } + + let dataTypes = [ + { value: 'dynamic', text: '鍔ㄦ��' }, + { value: 'static', text: '闈欐��' } + ] + if (cardCell.$cardType === 'extendCard') { + card.datatype = 'static' + dataTypes = [ + { value: 'static', text: '闈欐��' } + ] } let forms = [ @@ -98,10 +109,7 @@ label: '鏁版嵁绫诲瀷', initVal: card.datatype || 'static', required: true, - options: [ - { value: 'dynamic', text: '鍔ㄦ��' }, - { value: 'static', text: '闈欐��' } - ] + options: dataTypes }, { type: 'select', @@ -293,10 +301,32 @@ required: true, options: [ { value: '1:1', text: '1:1' }, - { value: '3:2', text: '3:2' }, { value: '4:3', text: '4:3' }, - { value: '16:9', text: '16:9' } + { value: '3:2', text: '3:2' }, + { value: '16:9', text: '16:9' }, + { value: '2:1', text: '2:1' }, + { value: '3:1', text: '3:1' }, + { value: '4:1', text: '4:1' }, + { value: '5:1', text: '5:1' }, + { value: '6:1', text: '6:1' }, + { value: '7:1', text: '7:1' }, + { value: '8:1', text: '8:1' }, + { value: '9:1', text: '9:1' }, + { value: '10:1', text: '10:1' }, + { value: '3:4', text: '3:4' }, + { value: '2:3', text: '2:3' }, + { value: '9:16', text: '9:16' }, ] + }, + { + type: 'number', + key: 'maxWidth', + min: 10, + max: 2000, + label: '鏈�澶у搴�', + initVal: card.maxWidth || '', + tooltip: '鍥剧墖瀹藉害鐨勬渶澶у�笺��', + required: false, }, { type: 'select', @@ -332,7 +362,7 @@ forbid: !isApp, options: [ { value: '', text: '鏃�' }, - { value: 'page', text: '鑿滃崟' }, + // { value: 'page', text: '鑿滃崟' }, { value: 'linkpage', text: '鍏宠仈鑿滃崟' }, { value: 'custom', text: '閾炬帴' } ] @@ -358,15 +388,15 @@ { value: 'self', text: '褰撳墠椤甸潰' } ] }, - { - type: 'select', - key: 'copyMenuId', - label: '澶嶅埗鑿滃崟', - initVal: card.copyMenuId || '', - required: false, - forbid: !isApp, - options: appMenus - }, + // { + // type: 'select', + // key: 'copyMenuId', + // label: '澶嶅埗鑿滃崟', + // initVal: card.copyMenuId || '', + // required: false, + // forbid: !isApp, + // options: appMenus + // }, { type: 'radio', key: 'joint', diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx index 58deb61..e46935d 100644 --- a/src/menu/components/card/cardcellcomponent/index.jsx +++ b/src/menu/components/card/cardcellcomponent/index.jsx @@ -34,6 +34,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, // 缂栬緫涓厓绱� formlist: null, // 琛ㄥ崟淇℃伅 elements: null, // 鎸夐挳缁� @@ -47,16 +48,25 @@ */ UNSAFE_componentWillMount () { const { elements } = this.props + let _elements = fromJS(elements).toJS() this.setState({ - elements: fromJS(elements).toJS() + elements: _elements.map(item => { + if (item.btnstyle) { // 鍏煎 + item.style = item.style || {} + item.style = {...item.style, ...item.btnstyle} + delete item.btnstyle + } + + return item + }) }) } componentDidMount () { - MKEmitter.addListener('cardAddElement', this.cardAddElement) MKEmitter.addListener('submitStyle', this.getStyle) MKEmitter.addListener('submitModal', this.handleSave) + MKEmitter.addListener('cardAddElement', this.cardAddElement) MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) } @@ -83,9 +93,9 @@ this.setState = () => { return } - MKEmitter.removeListener('cardAddElement', this.cardAddElement) MKEmitter.removeListener('submitStyle', this.getStyle) MKEmitter.removeListener('submitModal', this.handleSave) + MKEmitter.removeListener('cardAddElement', this.cardAddElement) MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) } @@ -126,12 +136,10 @@ const { cards, cardCell } = this.props let _style = element.style ? fromJS(element.style).toJS() : {} - let options = ['font', 'border', 'padding', 'margin', 'backgroundColor'] + let options = ['font', 'border', 'padding', 'margin', 'background'] if (element.eleType === 'button') { - if (element.btnstyle) { - _style = {..._style, ...element.btnstyle} - } + options.push('width', 'float') } else if (element.eleType === 'picture') { options = ['border', 'margin'] } else if (element.eleType === 'slider') { @@ -187,6 +195,17 @@ if (line) { _card.innerHeight = fontSize * lineHeight * line } + } else if (_card.eleType === 'sequence') { + _card.style = style + + let fontSize = 14 + let lineHeight = 1.5 + + if (_card.style.fontSize) { + fontSize = parseInt(_card.style.fontSize) + } + + _card.innerHeight = fontSize * lineHeight } else if (_card.eleType === 'barcode') { _card.style = style @@ -198,47 +217,7 @@ _card.innerHeight = _card.barHeight + (_card.displayValue === 'true' ? fontSize + 2 : 0) } else if (_card.eleType === 'button') { // 鎷嗗垎style - let _style = fromJS(style).toJS() - _card.style = {} - - if (_style.marginTop) { - _card.style.marginTop = _style.marginTop - delete _style.marginTop - } - if (_style.marginBottom) { - _card.style.marginBottom = _style.marginBottom - delete _style.marginBottom - } - if (_style.marginLeft) { - _card.style.marginLeft = _style.marginLeft - delete _style.marginLeft - } - if (_style.marginRight) { - _card.style.marginRight = _style.marginRight - delete _style.marginRight - } - if (_style.paddingTop) { - _card.style.paddingTop = _style.paddingTop - delete _style.paddingTop - } - if (_style.paddingBottom) { - _card.style.paddingBottom = _style.paddingBottom - delete _style.paddingBottom - } - if (_style.paddingLeft) { - _card.style.paddingLeft = _style.paddingLeft - delete _style.paddingLeft - } - if (_style.paddingRight) { - _card.style.paddingRight = _style.paddingRight - delete _style.paddingRight - } - if (_style.textAlign) { - _card.style.textAlign = _style.textAlign - delete _style.textAlign - } - - _card.btnstyle = _style + _card.style = style } else { _card.style = style } @@ -259,7 +238,7 @@ * @description 鍏冪礌缂栬緫锛岃幏鍙栧厓绱犺〃鍗曚俊鎭� */ handleElement = (card) => { - const { cards } = this.props + const { cards, cardCell } = this.props if (card.eleType === 'button') { this.handleAction(card) @@ -267,7 +246,7 @@ this.setState({ visible: true, card: card, - formlist: getCardCellForm(card, cards.type) + formlist: getCardCellForm(card, cards.type, cards.subtype, cardCell) }) } } @@ -310,7 +289,7 @@ this.setState({ actvisible: true, card: card, - formlist: getActionForm(card, functip, cards.setting, usefulFields, 'card', menulist, modules) + formlist: getActionForm(card, functip, cards, usefulFields, 'card', menulist, modules) }) } @@ -404,18 +383,18 @@ if (cell.uuid === res.uuid) { res = {...cell, ...res} delete res.focus - let btnstyle = {} + let style = {} - if (res.class !== cell.class || res.show !== cell.show || !res.btnstyle) { + if (res.class !== cell.class || res.show !== cell.show || !res.style) { if (res.show === 'link' || res.show === 'icon') { - btnstyle.color = color[res.class] - btnstyle.backgroundColor = 'transparent' + style.color = color[res.class] + style.backgroundColor = 'transparent' } else { - btnstyle.color = '#ffffff' - btnstyle.backgroundColor = color[res.class] + style.color = '#ffffff' + style.backgroundColor = color[res.class] } } - res.btnstyle = {...res.btnstyle, ...btnstyle} + res.style = {...res.style, ...style} return res } @@ -436,17 +415,14 @@ */ deleteElement = (card) => { const { cards, cardCell, side } = this.props - const { dict, elements } = this.state + const { dict, elements, appType } = this.state let _this = this confirm({ content: dict['model.confirm'] + dict['model.delete'] + '鍏冪礌鍚楋紵', onOk() { let _elements = elements.filter(item => item.uuid !== card.uuid) - - if (card.eleType === 'button') { - MKEmitter.emit('delButtons', [card.uuid]) - } + if (card.OpenType === 'popview' || card.verify || card.modal) { card.$parentId = cardCell.uuid card.$side = side || '' @@ -459,6 +435,11 @@ }, () => { _this.props.updateElement(_elements) }) + + if (card.eleType !== 'button') return + if (appType === 'mob' || (appType === 'pc' && card.OpenType !== 'popview')) return + + MKEmitter.emit('delButtons', [card.uuid]) }, onCancel() {} }) @@ -500,15 +481,16 @@ handleSubConfig = (item) => { const { cards } = this.props + const { appType } = this.state let btn = fromJS(item).toJS() - if ((sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') !== 'false')) return + if ((sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') === 'true')) return if (btn.eleType === 'button') { if (btn.OpenType === 'pop') { if (!btn.modal) { btn.modal = { - setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, + setting: { title: btn.label, width: appType === 'mob' ? 100 : 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, tables: [], groups: [], fields: [] @@ -647,7 +629,7 @@ > <ActionForm dict={dict} - type="card" + type={cards.type === 'balcony' ? '' : 'card'} card={card} formlist={this.state.formlist} inputSubmit={this.handleActionSubmit} diff --git a/src/menu/components/card/cardcellcomponent/index.scss b/src/menu/components/card/cardcellcomponent/index.scss index 2fd0ecb..6ad726c 100644 --- a/src/menu/components/card/cardcellcomponent/index.scss +++ b/src/menu/components/card/cardcellcomponent/index.scss @@ -16,16 +16,23 @@ cursor: pointer; } + .ant-btn { + padding: 0; + } + .card-button-cell { float: left; button { + width: 100%; background-size: cover; background-position: center center; height: auto; min-height: 32px; + text-align: center; span { font-style: inherit; text-decoration: inherit; + font-weight: inherit; } } } diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx index f32968a..af376d8 100644 --- a/src/menu/components/card/cardcomponent/index.jsx +++ b/src/menu/components/card/cardcomponent/index.jsx @@ -8,13 +8,14 @@ import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' import SettingForm from './settingform' - +import { resetStyle } from '@/utils/utils-custom.js' import Utils from '@/utils/utils.js' import MKEmitter from '@/utils/events.js' import './index.scss' const CardCellComponent = asyncComponent(() => import('../cardcellcomponent')) const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('./pastecomponent')) class CardBoxComponent extends Component { static propTpyes = { @@ -88,7 +89,7 @@ this.props.updateElement(_card) } - updateCard = (elements) => { + updateCard = (elements, type) => { const { card, side } = this.state let _card = {} @@ -99,9 +100,16 @@ _card = {...card, elements: elements} } - this.setState({ - card: _card - }) + if (type === 'paste') { + this.setState({ + card: _card, + elements: fromJS(elements).toJS() + }) + } else { + this.setState({ + card: _card + }) + } this.props.updateElement(_card) } @@ -213,6 +221,14 @@ } } + doubleClickCard = () => { + const { card } = this.state + + if (card.setting.click === 'menu' && card.setting.menu) { + MKEmitter.emit('changeEditMenu', {MenuID: card.setting.menu}) + } + } + render() { const { cards, offset } = this.props const { card, elements, side, settingVisible, dict } = this.state @@ -233,10 +249,11 @@ marginTop: card.style.marginTop } } + _style = resetStyle(_style) return ( <Col span={card.setting.width || 6} offset={offset || 0}> - <div className="card-item" style={_style} onClick={this.clickComponent} id={card.uuid}> + <div className="card-item" style={_style} onClick={this.clickComponent} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard()}} id={card.uuid}> <CardCellComponent cards={cards} cardCell={card} side={side} elements={elements} updateElement={this.updateCard}/> <div className="card-control"> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ @@ -245,16 +262,17 @@ <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> <Icon className="edit" title="缂栬緫" type="edit" onClick={() => this.setState({settingVisible: true})} /> <CopyComponent type="cardcell" card={card}/> + <PasteComponent elements={elements} options={['action', 'customCardElement']} updateConfig={(list) => this.updateCard(list, 'paste')} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> - {cards.subtype === 'propcard' ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> - <Icon className="plus" title="宸︾Щ" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> - <Icon className="close" title="鍙崇Щ" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> + <Icon className="plus" title="鍓嶇Щ" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> + <Icon className="close" title="鍚庣Щ" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> </div> } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}> <Icon type="swap" id={card.uuid + 'swap'}/> - </Popover> : null} - {cards.subtype === 'propcard' ? <Icon className="close" title="鍒犻櫎鍗$墖" type="delete" onClick={() => this.props.deleteElement(card)} /> : null} + </Popover> + {cards.subtype === 'propcard' || card.$cardType === 'extendCard' ? <Icon className="close" title="鍒犻櫎鍗$墖" type="delete" onClick={() => this.props.deleteElement(card)} /> : null} {card.setting.type === 'multi' ? <Switch size="small" onClick={this.changeSide} defaultChecked /> : null} </div> } trigger="hover"> @@ -266,7 +284,7 @@ wrapClassName="popview-modal" title={'鍗$墖璁剧疆'} visible={settingVisible} - width={700} + width={800} maskClosable={false} okText={dict['model.submit']} onOk={this.settingSubmit} diff --git a/src/menu/components/card/cardcomponent/pastecomponent/index.jsx b/src/menu/components/card/cardcomponent/pastecomponent/index.jsx new file mode 100644 index 0000000..bc98b34 --- /dev/null +++ b/src/menu/components/card/cardcomponent/pastecomponent/index.jsx @@ -0,0 +1,77 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Icon, Modal, notification } from 'antd' + +import Utils from '@/utils/utils.js' +import MKEmitter from '@/utils/events.js' +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) + +class PasteController extends Component { + static propTpyes = { + config: PropTypes.object, // 缁勪欢閰嶇疆 + updateConfig: PropTypes.func + } + + state = { + visible: false + } + + handleMenuClick = () => { + this.setState({visible: true}) + } + + pasteSubmit = () => { + const { options, elements } = this.props + this.pasteFormRef.handleConfirm().then(res => { + if (!options.includes(res.copyType)) { + notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', duration: 5 }) + return + } + + let _uuid = Utils.getuuid() + if (res.copyType === 'action' && res.OpenType === 'popview') { + let _cell = fromJS(res).toJS() + _cell.$originUuid = res.uuid + _cell.uuid = _uuid + MKEmitter.emit('copyButtons', [_cell]) + } + res.uuid = _uuid + + this.props.updateConfig([...elements, res]) + this.setState({visible: false}) + + notification.success({ + top: 92, + message: '绮樿创鎴愬姛锛�', + duration: 2 + }) + }) + } + + render() { + const { visible } = this.state + + return ( + <div style={{display: 'inline-block'}}> + <Icon type="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} /> + <Modal + title="绮樿创" + visible={visible} + width={600} + maskClosable={false} + onOk={this.pasteSubmit} + onCancel={() => {this.setState({visible: false})}} + destroyOnClose + > + <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> + </Modal> + </div> + ) + } +} + +export default PasteController \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/menu/components/card/cardcomponent/pastecomponent/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/menu/components/card/cardcomponent/pastecomponent/index.scss diff --git a/src/menu/components/card/cardcomponent/settingform/index.jsx b/src/menu/components/card/cardcomponent/settingform/index.jsx index 738bd50..6424977 100644 --- a/src/menu/components/card/cardcomponent/settingform/index.jsx +++ b/src/menu/components/card/cardcomponent/settingform/index.jsx @@ -17,15 +17,15 @@ state = { type: this.props.setting.type || 'simple', click: this.props.setting.click || '', - isApp: sessionStorage.getItem('appType') === 'pc', + appType: sessionStorage.getItem('appType'), menulist: [] } UNSAFE_componentWillMount() { - const { isApp } = this.state + const { appType } = this.state let menulist = null - if (isApp) { + if (appType) { menulist = sessionStorage.getItem('appMenus') } else { menulist = sessionStorage.getItem('fstMenuList') @@ -67,7 +67,7 @@ render() { const { setting, cards } = this.props const { getFieldDecorator } = this.props.form - const { menulist, click, isApp } = this.state + const { menulist, click, appType } = this.state const formItemLayout = { labelCol: { @@ -81,7 +81,7 @@ } return ( - <div className="model-menu-setting-form"> + <div className="model-menu-card-setting-form"> <Form {...formItemLayout}> <Row gutter={24}> <Col span={12}> @@ -102,7 +102,7 @@ })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} </Form.Item> </Col> - <Col span={12}> + {appType !== 'mob' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="閫夋嫨澶嶅紡鍗℃椂锛屽彲閰嶇疆榧犳爣鎮诞鏃剁殑鏄剧ず淇℃伅銆�"> <Icon type="question-circle" /> @@ -118,7 +118,7 @@ </Radio.Group> )} </Form.Item> - </Col> + </Col> : null} {this.state.type === 'multi' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="澶嶅紡鍗$墖榧犳爣鎮诞淇℃伅鐨勫姩鐢绘晥鏋溿��"> @@ -155,19 +155,25 @@ </Form.Item> </Col> : null} <Col span={12}> - <Form.Item label="鐐瑰嚮浜嬩欢"> + <Form.Item label={ + <Tooltip placement="topLeft" title="褰撻�夋嫨瑙﹀彂鎸夐挳鏃讹紝鍙湁褰撳崱鐗囦腑鍙瓨鍦ㄤ竴涓寜閽椂鏈夋晥銆�"> + <Icon type="question-circle" /> + 鐐瑰嚮浜嬩欢 + </Tooltip> + }> {getFieldDecorator('click', { initialValue: click })( - <Radio.Group onChange={(e) => this.setState({click: e.target.value})}> + <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({click: e.target.value})}> <Radio value="">鏃�</Radio> <Radio value="menu">鑿滃崟</Radio> <Radio value="link">閾炬帴</Radio> + <Radio value="button">鎸夐挳</Radio> </Radio.Group> )} </Form.Item> </Col> - {!isApp && click === 'menu' ? <Col span={12}> + {!appType && click === 'menu' ? <Col span={12}> <Form.Item label="鑿滃崟"> {getFieldDecorator('menu', { initialValue: setting.menu || [], @@ -182,7 +188,7 @@ )} </Form.Item> </Col> : null} - {isApp && click === 'menu' ? <Col span={12}> + {appType && click === 'menu' ? <Col span={12}> <Form.Item label="鍏宠仈鑿滃崟"> {getFieldDecorator('menu', { initialValue: setting.menu || '', @@ -217,7 +223,7 @@ })( <TextArea rows={2}/> )} </Form.Item> </Col> : null} - {isApp ? <Col span={12}> + {appType === 'pc' && click !== '' && click !== 'button' ? <Col span={12}> <Form.Item label="鎵撳紑鏂瑰紡"> {getFieldDecorator('open', { initialValue: setting.open || 'blank' @@ -229,7 +235,7 @@ )} </Form.Item> </Col> : null} - {click !== '' ? <Col span={12}> + {click !== '' && click !== 'button' ? <Col span={12}> <Form.Item label="鍙傛暟鎷兼帴"> {getFieldDecorator('joint', { initialValue: setting.joint || 'true' diff --git a/src/menu/components/card/cardcomponent/settingform/index.scss b/src/menu/components/card/cardcomponent/settingform/index.scss index 8898344..36d76eb 100644 --- a/src/menu/components/card/cardcomponent/settingform/index.scss +++ b/src/menu/components/card/cardcomponent/settingform/index.scss @@ -1,4 +1,4 @@ -.model-menu-setting-form { +.model-menu-card-setting-form { position: relative; .anticon-question-circle { @@ -16,4 +16,7 @@ width: 84%; } } + .ant-radio-wrapper { + margin-right: 3px; + } } \ No newline at end of file diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx index 7b12967..5c85b95 100644 --- a/src/menu/components/card/data-card/index.jsx +++ b/src/menu/components/card/data-card/index.jsx @@ -5,7 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' @@ -15,6 +15,7 @@ const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) const CardComponent = asyncComponent(() => import('../cardcomponent')) +const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) @@ -34,14 +35,15 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, card: null, + appType: sessionStorage.getItem('appType'), back: false } UNSAFE_componentWillMount () { const { card } = this.props + const { appType } = this.state if (card.isNew) { - let ismob = sessionStorage.getItem('appType') === 'mob' let _card = { uuid: card.uuid, type: card.type, @@ -56,7 +58,7 @@ name: card.name, subtype: card.subtype, setting: { interType: 'system' }, - wrap: { name: card.name, width: card.width || 24, title: '', pagestyle: 'page', switch: 'false' }, + wrap: { name: card.name, width: card.width || 24, title: '', pagestyle: 'page', switch: 'false', cardType: '' }, style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, columns: [], @@ -66,7 +68,7 @@ btnlog: [], subcards: [{ uuid: Utils.getuuid(), - setting: { width: ismob ? 24 : 6, type: 'simple'}, + setting: { width: appType === 'mob' ? 24 : 6, type: 'simple'}, style: { borderWidth: '1px', borderColor: '#e8e8e8', paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', @@ -192,6 +194,7 @@ * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 */ deleteCard = (cell) => { + const { appType } = this.state let card = fromJS(this.state.card).toJS() let _this = this @@ -200,25 +203,31 @@ onOk() { card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) - let uuids = [] - cell.elements && cell.elements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - cell.backElements && cell.backElements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - MKEmitter.emit('delButtons', uuids) - if (card.btnlog) { card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) } _this.setState({card}) _this.props.updateConfig(card) + + if (appType === 'mob') return + + let uuids = [] + + cell.elements && cell.elements.forEach(c => { + if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return + + uuids.push(c.uuid) + }) + cell.backElements && cell.backElements.forEach(c => { + if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return + + uuids.push(c.uuid) + }) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -285,27 +294,27 @@ newcard.execError = 'never' newcard.verify = null newcard.show = 'button' - newcard.btnstyle = {marginRight: '15px'} + newcard.style = {marginRight: '15px'} // 娉ㄥ唽浜嬩欢-娣诲姞鎸夐挳 MKEmitter.emit('addButton', card.uuid, newcard) } setSubConfig = (item) => { - const { card } = this.state + const { card, appType } = this.state let btn = fromJS(item).toJS() if (btn.OpenType === 'pop' || btn.execMode === 'pop') { if (!btn.modal) { btn.modal = { - setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, + setting: { title: btn.label, width: appType === 'mob' ? 100 : 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, tables: [], groups: [], fields: [] } } MKEmitter.emit('changeModal', card, btn) - } else if (btn.OpenType === 'popview') { + } else if (btn.OpenType === 'popview' && appType !== 'mob') { MKEmitter.emit('changePopview', card, btn) } } @@ -374,6 +383,54 @@ } } + addCard = () => { + let card = fromJS(this.state.card).toJS() + let height = card.subcards[0].style.height + if (height === 'auto') { + height = '100px' + } + + let newcard = { + uuid: Utils.getuuid(), + $cardType: 'extendCard', + setting: { width: 6, type: 'simple', click: 'button'}, + style: { + height, + borderWidth: '1px', borderColor: '#e8e8e8', + paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', + marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' + }, + backStyle: {}, + elements: [], + backElements: [] + } + + card.subcards.push(newcard) + + this.setState({card}) + this.props.updateConfig(card) + } + + move = (item, direction) => { + let card = fromJS(this.state.card).toJS() + + let dragIndex = card.subcards.findIndex(c => c.uuid === item.uuid) + let hoverIndex = null + + if (direction === 'left') { + hoverIndex = dragIndex - 1 + } else { + hoverIndex = dragIndex + 1 + } + + if (hoverIndex === -1 || hoverIndex === card.subcards.length) return + + card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1)) + + this.setState({card}) + this.props.updateConfig(card) + } + clickComponent = (e) => { if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { e.stopPropagation() @@ -382,7 +439,7 @@ } render() { - const { card } = this.state + const { card, appType } = this.state let offset = 0 if (card.wrap.cardFloat && card.wrap.cardFloat !== 'left') { @@ -395,17 +452,19 @@ offset = Math.floor(offset / 2) } } + let _style = resetStyle(card.style) return ( - <div className="menu-data-card-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> + <div className={'menu-data-card-edit-box ' + appType} style={_style} onClick={this.clickComponent} id={card.uuid}> <NormalHeader defaultshow="hidden" config={card} updateComponent={this.updateComponent}/> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> - <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鍗$墖" onClick={this.addCard} type="plus" /> : null} + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null} <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> <WrapComponent config={card} updateConfig={this.updateComponent} /> <CopyComponent type="datacard" card={card}/> - <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} /> + <PasteComponent config={card} options={['action', 'search', 'form', 'cardcell']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <UserComponent config={card}/> @@ -415,10 +474,11 @@ } trigger="hover"> <Icon type="tool" /> </Popover> - <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/> - {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} offset={!index ? offset : 0} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} + <ActionComponent config={card} type="datacard" setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/> + {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} offset={!index ? offset : 0} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} <div style={{clear: 'both'}}></div> - {card.wrap.pagestyle !== 'switch' && card.setting.laypage === 'true' ? <Pagination total={85} size="small" showTotal={total => `鍏� ${total} 鏉} pageSize={20} defaultCurrent={1}/> : null} + {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType !== 'mob' ? <Pagination total={85} size="small" showTotal={total => `鍏� ${total} 鏉} pageSize={20} defaultCurrent={1}/> : null} + {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType === 'mob' ? <MobPagination /> : null} </div> ) } diff --git a/src/menu/components/card/data-card/index.scss b/src/menu/components/card/data-card/index.scss index 6346310..71b6f6e 100644 --- a/src/menu/components/card/data-card/index.scss +++ b/src/menu/components/card/data-card/index.scss @@ -75,12 +75,31 @@ line-height: 55px; } } + .normal-pagination { + .am-button::before { + display: none; + } + .am-button { + border: none; + font-size: 16px; + } + } } .menu-data-card-edit-box::after { display: block; content: ' '; clear: both; } +.menu-data-card-edit-box.mob { + .model-menu-action-list { + position: absolute; + top: 5px; + right: 0px; + .page-card { + line-height: 40px; + } + } +} .menu-data-card-edit-box:hover { z-index: 1; box-shadow: 0px 0px 4px #1890ff; diff --git a/src/menu/components/card/data-card/wrapsetting/index.jsx b/src/menu/components/card/data-card/wrapsetting/index.jsx index 81346a6..8877617 100644 --- a/src/menu/components/card/data-card/wrapsetting/index.jsx +++ b/src/menu/components/card/data-card/wrapsetting/index.jsx @@ -8,7 +8,7 @@ import SettingForm from './settingform' import './index.scss' -class DataSource extends Component { +class CardWrapSetting extends Component { static propTpyes = { config: PropTypes.any, updateConfig: PropTypes.func @@ -80,4 +80,4 @@ } } -export default DataSource \ No newline at end of file +export default CardWrapSetting \ No newline at end of file diff --git a/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx b/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx index 08b58e2..d1c8eb0 100644 --- a/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx +++ b/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx @@ -6,14 +6,17 @@ class SettingForm extends Component { static propTpyes = { - dict: PropTypes.object, // 瀛楀吀椤� - config: PropTypes.object, // 鍗$墖琛屼俊鎭� - wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� - inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + dict: PropTypes.object, + config: PropTypes.object, + wrap: PropTypes.object, + inputSubmit: PropTypes.func } state = { - roleList: [] + roleList: [], + appType: sessionStorage.getItem('appType'), + cardType: this.props.wrap.cardType, + MenuType: '' } UNSAFE_componentWillMount () { @@ -28,7 +31,13 @@ roleList = [] } - this.setState({roleList}) + let MenuType = '' + + if (window.GLOB.customMenu && window.GLOB.customMenu.parentId === 'BillPrintTemp') { + MenuType = 'billPrint' + } + + this.setState({roleList, MenuType}) } handleConfirm = () => { @@ -55,7 +64,7 @@ render() { const { wrap, config } = this.props const { getFieldDecorator } = this.props.form - const { roleList } = this.state + const { roleList, MenuType, appType, cardType } = this.state const formItemLayout = { labelCol: { @@ -132,7 +141,7 @@ )} </Form.Item> </Col> : null} - {config.subtype === 'datacard' ? <Col span={12}> + {config.subtype === 'datacard' || (config.subtype === 'tablecard' && appType === 'mob') ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="鏁版嵁婧愪腑閫夋嫨鍒嗛〉鏃舵湁鏁堛��"> <Icon type="question-circle" /> @@ -144,7 +153,8 @@ })( <Radio.Group> <Radio value="page">椤电爜</Radio> - <Radio value="switch">宸﹀彸鍒囨崲</Radio> + {appType !== 'mob' ? <Radio value="switch">宸﹀彸鍒囨崲</Radio> : null} + {appType === 'mob' ? <Radio value="slide">婊戝姩鍔犺浇</Radio> : null} </Radio.Group> )} </Form.Item> @@ -154,10 +164,22 @@ {getFieldDecorator('cardType', { initialValue: wrap.cardType || '' })( - <Radio.Group style={{whiteSpace: 'nowrap'}}> + <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({cardType: e.target.value})}> <Radio key="" value=""> 涓嶅彲閫� </Radio> <Radio key="radio" value={'radio'}> 鍗曢�� </Radio> {config.subtype !== 'propcard' ? <Radio key="checkbox" value={'checkbox'}> 澶氶�� </Radio> : null} + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {config.subtype === 'datacard' && appType === 'mob' && cardType === 'checkbox' ? <Col span={12}> + <Form.Item label="鍏ㄩ��"> + {getFieldDecorator('checkAll', { + initialValue: wrap.checkAll || 'hidden' + })( + <Radio.Group> + <Radio key="hidden" value="hidden"> 闅愯棌 </Radio> + <Radio key="show" value="show"> 鏄剧ず </Radio> </Radio.Group> )} </Form.Item> @@ -180,7 +202,7 @@ )} </Form.Item> </Col> : null} - {config.subtype !== 'tablecard' ? <Col span={12}> + {config.subtype !== 'tablecard' && appType !== 'mob' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="榧犳爣鎮诞浜庡崱鐗囦笂鏂规椂锛屽崱鐗囨斁澶�1.05鍊嶃��"> <Icon type="question-circle" /> @@ -197,19 +219,7 @@ )} </Form.Item> </Col> : null} - {config.subtype === 'tablecard' ? <Col span={12}> - <Form.Item label={ - <Tooltip placement="topLeft" title="琛ㄦ牸楂樺害锛岃秴鍑烘椂婊氬姩锛岄珮搴︿负绌烘椂鏍规嵁鍐呭鑷�傚簲銆�"> - <Icon type="question-circle" /> - 楂樺害 - </Tooltip> - }> - {getFieldDecorator('height', { - initialValue: wrap.height - })(<InputNumber min={100} max={2000} precision={0} onPressEnter={this.handleSubmit} />)} - </Form.Item> - </Col> : null} - {config.subtype === 'propcard' ? <Col span={12}> + {config.subtype === 'propcard' && MenuType === 'billPrint' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="閫夋嫨绫诲瀷涓恒�婇〉鐪�/椤佃剼銆嬫椂锛屾墦鍗扮殑姣忛〉閲岄兘浼氬甫鏈夎缁勪欢銆�"> <Icon type="question-circle" /> diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx index 8cac50c..e132a91 100644 --- a/src/menu/components/card/prop-card/index.jsx +++ b/src/menu/components/card/prop-card/index.jsx @@ -5,7 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' @@ -33,15 +33,16 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, back: false } UNSAFE_componentWillMount () { const { card } = this.props + const { appType } = this.state if (card.isNew) { - let ismob = sessionStorage.getItem('appType') === 'mob' let _card = { uuid: card.uuid, type: card.type, @@ -63,7 +64,7 @@ scripts: [], subcards: [{ uuid: Utils.getuuid(), - setting: { width: ismob ? 24 : 6, type: 'simple'}, + setting: { width: appType === 'mob' ? 24 : 6, type: 'simple'}, style: { borderWidth: '1px', borderColor: '#e8e8e8', paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', @@ -195,6 +196,7 @@ * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 */ deleteCard = (cell) => { + const { appType } = this.state let card = fromJS(this.state.card).toJS() let _this = this @@ -202,19 +204,6 @@ content: '纭畾鍒犻櫎鍗$墖鍚楋紵', onOk() { card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) - - let uuids = [] - cell.elements && cell.elements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - cell.backElements && cell.backElements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - MKEmitter.emit('delButtons', uuids) if (card.btnlog) { card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) @@ -222,6 +211,25 @@ _this.setState({card}) _this.props.updateConfig(card) + + if (appType === 'mob') return + + let uuids = [] + + cell.elements && cell.elements.forEach(c => { + if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return + + uuids.push(c.uuid) + }) + cell.backElements && cell.backElements.forEach(c => { + if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return + + uuids.push(c.uuid) + }) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -373,8 +381,10 @@ } } + let _style = resetStyle(card.style) + return ( - <div className="menu-prop-card-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-prop-card-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <NormalHeader defaultshow="hidden" config={card} updateComponent={this.updateComponent}/> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> diff --git a/src/menu/components/card/table-card/cardcomponent/index.jsx b/src/menu/components/card/table-card/cardcomponent/index.jsx index e3d9ac7..a46143b 100644 --- a/src/menu/components/card/table-card/cardcomponent/index.jsx +++ b/src/menu/components/card/table-card/cardcomponent/index.jsx @@ -8,7 +8,7 @@ import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' import SettingForm from './settingform' - +import { resetStyle } from '@/utils/utils-custom.js' import Utils from '@/utils/utils.js' import MKEmitter from '@/utils/events.js' import './index.scss' @@ -163,10 +163,11 @@ render() { const { cards } = this.props const { card, elements, settingVisible, dict } = this.state + let _style = resetStyle(card.style) return ( <div className="ant-col ant-col-24"> - <div className="card-item" style={card.style}> + <div className="card-item" style={_style}> <CardCellComponent cards={cards} cardCell={card} elements={elements} updateElement={this.updateCard}/> <div className="card-control"> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ @@ -176,6 +177,14 @@ <Icon className="edit" title="缂栬緫" type="edit" onClick={() => this.setState({settingVisible: true})} /> <CopyComponent type="cardcell" card={card}/> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="plus" title="鍓嶇Щ" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> + <Icon className="close" title="鍚庣Щ" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> + </div> + } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}> + <Icon type="swap" id={card.uuid + 'swap'}/> + </Popover> <Icon className="close" title="鍒犻櫎鍗$墖" type="delete" onClick={() => this.props.deleteElement(card)} /> </div> } trigger="hover"> diff --git a/src/menu/components/card/table-card/cardcomponent/settingform/index.jsx b/src/menu/components/card/table-card/cardcomponent/settingform/index.jsx index ba0dcf4..c4054ef 100644 --- a/src/menu/components/card/table-card/cardcomponent/settingform/index.jsx +++ b/src/menu/components/card/table-card/cardcomponent/settingform/index.jsx @@ -90,6 +90,7 @@ {option.label} </Select.Option> )} + <Select.Option key={'index'} value={'$Index'}>搴忓彿锛堝墠绔級</Select.Option> </Select> )} </Form.Item> diff --git a/src/menu/components/card/table-card/index.jsx b/src/menu/components/card/table-card/index.jsx index cc8ddff..a7d5efe 100644 --- a/src/menu/components/card/table-card/index.jsx +++ b/src/menu/components/card/table-card/index.jsx @@ -5,7 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' @@ -15,6 +15,7 @@ const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const WrapComponent = asyncIconComponent(() => import('../data-card/wrapsetting')) const CardComponent = asyncComponent(() => import('./cardcomponent')) +const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination')) const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) @@ -33,6 +34,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, card: null, + appType: sessionStorage.getItem('appType'), back: false } @@ -171,6 +173,7 @@ * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 */ deleteCard = (cell) => { + const { appType } = this.state let card = fromJS(this.state.card).toJS() let _this = this @@ -178,15 +181,6 @@ content: '纭畾鍒犻櫎鍗$墖鍚楋紵', onOk() { card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) - - let uuids = [] - cell.elements && cell.elements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - - MKEmitter.emit('delButtons', uuids) if (card.btnlog) { card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) @@ -194,6 +188,20 @@ _this.setState({card}) _this.props.updateConfig(card) + + if (appType === 'mob') return + + let uuids = [] + + cell.elements && cell.elements.forEach(c => { + if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return + + uuids.push(c.uuid) + }) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -202,7 +210,7 @@ changeStyle = () => { const { card } = this.state - MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) + MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) } getStyle = (comIds, style) => { @@ -314,6 +322,26 @@ } } + move = (item, direction) => { + let card = fromJS(this.state.card).toJS() + + let dragIndex = card.subcards.findIndex(c => c.uuid === item.uuid) + let hoverIndex = null + + if (direction === 'left') { + hoverIndex = dragIndex - 1 + } else { + hoverIndex = dragIndex + 1 + } + + if (hoverIndex === -1 || hoverIndex === card.subcards.length) return + + card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1)) + + this.setState({card}) + this.props.updateConfig(card) + } + clickComponent = (e) => { if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { e.stopPropagation() @@ -322,15 +350,16 @@ } render() { - const { card } = this.state + const { card, appType } = this.state + let _style = resetStyle(card.style) return ( - <div className="menu-table-card-edit-box" style={{...card.style, height: card.wrap.height}} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-table-card-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <NormalHeader config={card} updateComponent={this.updateComponent}/> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞鍗$墖" onClick={this.addCard} type="plus" /> - <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null} <WrapComponent config={card} updateConfig={this.updateComponent} /> <CopyComponent type="tablecard" card={card}/> <PasteComponent config={card} options={['cardcell', 'search', 'form']} updateConfig={this.updateComponent} /> @@ -343,10 +372,11 @@ } trigger="hover"> <Icon type="tool" /> </Popover> - <div style={{minHeight: card.wrap.height - 90}}> - {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} + <div style={{minHeight: 'calc(100% - 90px)'}}> + {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} updateElement={this.updateCard} move={this.move} deleteElement={this.deleteCard}/>))} </div> - {card.setting.laypage === 'true' ? <Pagination size="small" total={50} /> : null} + {card.setting.laypage === 'true' && card.wrap.pagestyle !== 'slide' && appType !== 'mob' ? <Pagination size="small" total={50} /> : null} + {card.setting.laypage === 'true' && card.wrap.pagestyle !== 'slide' && appType === 'mob' ? <MobPagination /> : null} </div> ) } diff --git a/src/menu/components/carousel/cardcomponent/index.jsx b/src/menu/components/carousel/cardcomponent/index.jsx index 5a3909e..1519f58 100644 --- a/src/menu/components/carousel/cardcomponent/index.jsx +++ b/src/menu/components/carousel/cardcomponent/index.jsx @@ -8,7 +8,7 @@ import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' import SettingForm from './settingform' - +import { resetStyle } from '@/utils/utils-custom.js' import Utils from '@/utils/utils.js' import MKEmitter from '@/utils/events.js' import './index.scss' @@ -176,6 +176,7 @@ _style.boxShadow = '0 0 4px ' + _style.shadow } _style.height = cards.style.height + _style = resetStyle(_style) return ( <div className="card-item" style={_style} onClick={this.clickComponent} id={card.uuid}> diff --git a/src/menu/components/carousel/data-card/index.jsx b/src/menu/components/carousel/data-card/index.jsx index df2cf25..9a3ab4f 100644 --- a/src/menu/components/carousel/data-card/index.jsx +++ b/src/menu/components/carousel/data-card/index.jsx @@ -5,7 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' @@ -30,6 +30,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, back: false } @@ -163,6 +164,7 @@ * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 */ deleteCard = (cell) => { + const { appType } = this.state let card = fromJS(this.state.card).toJS() let _this = this @@ -171,20 +173,26 @@ onOk() { card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) - let uuids = [] - cell.elements && cell.elements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - MKEmitter.emit('delButtons', uuids) - if (card.btnlog) { card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) } _this.setState({card}) _this.props.updateConfig(card) + + if (appType === 'mob') return + + let uuids = [] + + cell.elements && cell.elements.forEach(c => { + if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return + + uuids.push(c.uuid) + }) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -251,9 +259,10 @@ render() { const { card } = this.state + let _style = resetStyle(card.style) return ( - <div className="menu-data-carousel-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-data-carousel-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <WrapComponent config={card} updateConfig={this.updateComponent}/> diff --git a/src/menu/components/carousel/data-card/wrapsetting/settingform/index.jsx b/src/menu/components/carousel/data-card/wrapsetting/settingform/index.jsx index 0007143..21fec41 100644 --- a/src/menu/components/carousel/data-card/wrapsetting/settingform/index.jsx +++ b/src/menu/components/carousel/data-card/wrapsetting/settingform/index.jsx @@ -13,6 +13,7 @@ } state = { + appType: sessionStorage.getItem('appType'), roleList: [] } @@ -55,7 +56,7 @@ render() { const { wrap, config } = this.props const { getFieldDecorator } = this.props.form - const { roleList } = this.state + const { roleList, appType } = this.state const formItemLayout = { labelCol: { @@ -161,7 +162,19 @@ )} </Form.Item> </Col> - <Col span={12}> + {appType === 'mob' ? <Col span={12}> + <Form.Item label="鍨傜洿鏄剧ず"> + {getFieldDecorator('vertical', { + initialValue: wrap.vertical || 'false' + })( + <Radio.Group> + <Radio value="true">鏄�</Radio> + <Radio value="false">鍚�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {appType !== 'mob' ? <Col span={12}> <Form.Item label="鎸囩ず鐐逛綅缃�"> {getFieldDecorator('dotPosition', { initialValue: wrap.dotPosition || 'bottom' @@ -174,8 +187,8 @@ </Radio.Group> )} </Form.Item> - </Col> - <Col span={12}> + </Col> : null} + {appType !== 'mob' ? <Col span={12}> <Form.Item label="鍔ㄧ敾鏁堟灉"> {getFieldDecorator('effect', { initialValue: wrap.effect || 'scrollx' @@ -186,7 +199,7 @@ </Radio.Group> )} </Form.Item> - </Col> + </Col> : null} <Col span={12}> <Form.Item label="榛戝悕鍗�"> {getFieldDecorator('blacklist', { diff --git a/src/menu/components/carousel/prop-card/index.jsx b/src/menu/components/carousel/prop-card/index.jsx index b1f7abf..404d434 100644 --- a/src/menu/components/carousel/prop-card/index.jsx +++ b/src/menu/components/carousel/prop-card/index.jsx @@ -5,7 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' @@ -31,6 +31,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, back: false } @@ -180,6 +181,7 @@ * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 */ deleteCard = (cell) => { + const { appType } = this.state let card = fromJS(this.state.card).toJS() let _this = this @@ -187,14 +189,6 @@ content: '纭畾鍒犻櫎鍗$墖鍚楋紵', onOk() { card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) - - let uuids = [] - cell.elements && cell.elements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - MKEmitter.emit('delButtons', uuids) if (card.btnlog) { card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) @@ -202,6 +196,20 @@ _this.setState({card}) _this.props.updateConfig(card) + + if (appType === 'mob') return + + let uuids = [] + + cell.elements && cell.elements.forEach(c => { + if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return + + uuids.push(c.uuid) + }) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -328,9 +336,10 @@ render() { const { card } = this.state + let _style = resetStyle(card.style) return ( - <div className="menu-prop-carousel-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-prop-carousel-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞鍗$墖" onClick={this.addCard} type="plus" /> diff --git a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx index 29d0d30..42099ee 100644 --- a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx +++ b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx @@ -8,31 +8,34 @@ * @param {object} card // 鍥捐〃瀵硅薄 */ export function getBaseForm (card) { - let isApp = sessionStorage.getItem('appType') === 'pc' - let menulist = null + // let appType = sessionStorage.getItem('appType') + // let menulist = null - if (isApp) { - menulist = sessionStorage.getItem('appMenus') - } else { - menulist = sessionStorage.getItem('fstMenuList') - } + // if (appType === 'pc') { + // menulist = sessionStorage.getItem('appMenus') + // if (Array.isArray(card.linkmenu)) { + // card.linkmenu = '' + // } + // } else { + // menulist = sessionStorage.getItem('fstMenuList') + // } - if (menulist) { - try { - menulist = JSON.parse(menulist) - if (isApp) { - menulist = menulist.map(item => { - item.value = item.MenuID - item.text = item.MenuName - return item - }) - } - } catch { - menulist = [] - } - } else { - menulist = [] - } + // if (menulist) { + // try { + // menulist = JSON.parse(menulist) + // if (appType === 'pc') { + // menulist = menulist.map(item => { + // item.value = item.MenuID + // item.text = item.MenuName + // return item + // }) + // } + // } catch { + // menulist = [] + // } + // } else { + // menulist = [] + // } let roleList = sessionStorage.getItem('sysRoles') if (roleList) { @@ -91,38 +94,38 @@ required: false, options: roleList }, - { - type: 'cascader', - key: 'linkmenu', - label: '鍏宠仈鑿滃崟', - initVal: card.linkmenu || [], - tooltip: '鍦ㄤ娇鐢ㄦ煴褰㈠浘涓旀湭鍚敤鑷畾涔夎缃椂鏈夋晥銆�', - required: false, - forbid: isApp, - options: menulist - }, - { - type: 'select', - key: 'linkmenu', - label: '鍏宠仈鑿滃崟', - initVal: card.linkmenu || '', - tooltip: '鍙屽嚮楗煎浘锛屼細鎵撳紑鍏宠仈鐨勮彍鍗曘��', - required: false, - forbid: !isApp, - options: menulist - }, - { - type: 'radio', - key: 'open', - label: '鎵撳紑鏂瑰紡', - initVal: card.open || 'blank', - required: false, - forbid: !isApp, - options: [ - { value: 'blank', text: '鏂扮獥鍙�' }, - { value: 'self', text: '褰撳墠绐楀彛' } - ] - } + // { + // type: 'cascader', + // key: 'linkmenu', + // label: '鍏宠仈鑿滃崟', + // initVal: card.linkmenu || [], + // tooltip: '鍦ㄤ娇鐢ㄦ煴褰㈠浘涓旀湭鍚敤鑷畾涔夎缃椂鏈夋晥銆�', + // required: false, + // forbid: appType === 'pc' || appType === 'mob', + // options: menulist + // }, + // { + // type: 'select', + // key: 'linkmenu', + // label: '鍏宠仈鑿滃崟', + // initVal: card.linkmenu || '', + // tooltip: '鍙屽嚮鏌辩姸鍥撅紝浼氭墦寮�鍏宠仈鐨勮彍鍗曘��', + // required: false, + // forbid: appType !== 'pc', + // options: menulist + // }, + // { + // type: 'radio', + // key: 'open', + // label: '鎵撳紑鏂瑰紡', + // initVal: card.open || 'blank', + // required: false, + // forbid: appType !== 'pc', + // options: [ + // { value: 'blank', text: '鏂扮獥鍙�' }, + // { value: 'self', text: '褰撳墠绐楀彛' } + // ] + // } ] } @@ -132,6 +135,7 @@ * @param {Array} columns // 鏄剧ず鍒� */ export function getOptionForm (card, columns) { + let appType = sessionStorage.getItem('appType') let shapes = [] if (card.chartType === 'line') { @@ -159,28 +163,48 @@ let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) + let labelOptions = [{ + value: 'false', + text: '闅愯棌' + }, { + value: 'true', + text: '鏄剧ず' + }] + + if (card.chartType === 'bar') { + labelOptions[1].text = '澶栭儴' + labelOptions.push(...[{ + value: 'top', + text: '椤堕儴' + }, { + value: 'middle', + text: '涓棿' + }, { + value: 'bottom', + text: '搴曢儴' + }]) + } + return [ { type: 'radio', key: 'datatype', label: '鏁版嵁绫诲瀷', initVal: card.datatype || 'query', - tooltip: '缁熻鍥捐〃閫傜敤浜庤〃鏍间笉鍒嗛〉锛屼笖鏁版嵁闇�瑕佽浆鎹�', + tooltip: '缁熻鍥捐〃閫傜敤浜庡睍绀烘暟鎹被鍨嬩负鍔ㄦ�佸�笺��', required: false, options: [ { value: 'query', text: Formdict['header.form.query'] }, { value: 'statistics', text: Formdict['header.form.statistics'] } ] - }, - { + }, { type: 'select', key: 'Xaxis', label: 'X-杞�', initVal: card.Xaxis || '', required: true, options: xfields - }, - { + }, { type: 'select', key: 'InfoType', label: '绫诲瀷', @@ -188,8 +212,7 @@ hidden: card.datatype !== 'statistics', required: true, options: xfields - }, - { + }, { type: 'select', key: 'InfoValue', label: '鍊�', @@ -197,8 +220,7 @@ hidden: card.datatype !== 'statistics', required: true, options: yfields - }, - { + }, { type: 'select', key: 'legend', label: '鍥句緥浣嶇疆', @@ -219,8 +241,7 @@ { field: 'left-bottom', label: '宸︿笅' }, { field: 'hidden', label: '闅愯棌' } ] - }, - { + }, { type: 'select', key: 'Yaxis', label: 'Y-杞�', @@ -229,16 +250,14 @@ hidden: card.datatype === 'statistics', required: true, options: yfields - }, - { + }, { type: 'select', key: 'shape', label: '褰㈢姸', initVal: card.shape || (shapes[0] && shapes[0].field), required: false, options: shapes - }, - { + }, { type: 'radio', key: 'tooltip', label: '鎮诞鎻愮ず', @@ -251,8 +270,7 @@ value: 'false', text: '闅愯棌' }] - }, - { + }, { type: 'radio', key: 'point', label: '鐐瑰浘', @@ -266,8 +284,7 @@ value: 'false', text: '闅愯棌' }] - }, - { + }, { type: 'radio', key: 'transpose', label: '鍙樻崲', @@ -281,8 +298,7 @@ value: 'false', text: Formdict['model.false'] }] - }, - { + }, { type: 'radio', key: 'show', label: '鏍煎紡鍖�', @@ -295,20 +311,41 @@ value: 'percent', text: '鐧惧垎姣�' }] - }, - { - type: 'radio', + }, { + type: labelOptions.length > 20 ? 'select' : 'radio', key: 'label', - label: '鏍囨敞鍊�', + label: '鏍囩', initVal: card.label || 'false', required: false, + options: labelOptions + }, { + type: 'radio', + key: 'labelColor', + label: '鏍囩棰滆壊', + initVal: card.labelColor || 'system', + tooltip: '浣跨敤绯荤粺鑹叉椂锛屼娇鐢ㄨ壊绯婚�夐」璁剧疆鐨勭郴缁熼鑹诧紝浣跨敤鑷畾涔変负棰滆壊璁剧疆涓畾涔夌殑鍥惧舰棰滆壊銆�', + required: false, options: [{ - value: 'true', - text: '鏄剧ず' + value: 'system', + text: '绯荤粺' }, { - value: 'false', - text: '闅愯棌' + value: 'custom', + text: '鑷畾涔�' }] + // }, { + // type: 'radio', + // key: 'offset', + // label: '鏍囨敞浣嶇疆', + // initVal: card.offset || 'outer', + // required: false, + // options: [{ + // value: 'outer', + // text: '澶栭儴' + // }, { + // value: 'inner', + // text: '鍐呴儴' + // }], + // forbid: card.chartType !== 'bar' }, { type: 'radio', key: 'adjust', @@ -322,6 +359,21 @@ }, { value: 'stack', text: '鍫嗗彔' + }] + }, { + type: 'radio', + key: 'area', + label: '闈㈢Н鍥�', + initVal: card.area || 'false', + // tooltip: '浠呭湪褰㈢姸涓簊mooth鏃舵湁鏁堛��', + required: false, + forbid: ['bar'].includes(card.chartType), + options: [{ + value: 'true', + text: '鏄剧ず' + }, { + value: 'false', + text: '涓嶆樉绀�' }] }, { type: 'radio', @@ -353,16 +405,32 @@ text: '鏋佸潗鏍�' }] }, { - type: 'number', - key: 'InfoDefNumber', - label: '灞曠ず鏁�', - tooltip: '榛樿鏄剧ず绫诲瀷鏁伴噺', - min: 1, - max: 50, - decimal: 0, - initVal: card.InfoDefNumber || 5, - hidden: card.datatype !== 'statistics', - required: true + type: 'radio', + key: 'grid', + label: '缃戞牸绾�', + initVal: card.grid || 'show', + required: false, + options: [{ + value: 'show', + text: '鏄剧ず' + }, { + value: 'hidden', + text: '闅愯棌' + }] + }, { + type: 'radio', + key: 'y_line', + label: 'y杞磋竟绾�', + initVal: card.y_line || 'hidden', + tooltip: '鍥惧舰宸︿晶鎴栧彸渚х殑杈圭嚎銆�', + required: false, + options: [{ + value: 'show', + text: '鏄剧ず' + }, { + value: 'hidden', + text: '闅愯棌' + }] }, { type: 'number', key: 'barSize', @@ -375,19 +443,87 @@ forbid: !['bar'].includes(card.chartType), required: false }, { + type: 'number', + key: 'barRadius', + label: '鏌卞舰鍦嗚', + tooltip: '鏌卞舰鍥句笂绔渾瑙掋��', + min: 0, + max: 200, + decimal: 0, + initVal: card.barRadius || 0, + forbid: !['bar'].includes(card.chartType), + required: false + }, { + type: 'number', + key: 'min', + label: '鏈�灏忓��', + tooltip: 'y杞存渶灏忓�硷紝涓虹┖鏃惰嚜閫傚簲銆�', + initVal: card.min, + required: false + }, { + type: 'number', + key: 'max', + label: '鏈�澶у��', + tooltip: 'y杞存渶澶у�硷紝涓虹┖鏃惰嚜閫傚簲銆�', + initVal: card.max, + required: false + }, { type: 'color', key: 'color', label: '鑹茬郴', - initVal: card.color || 'rgba(0, 0, 0, 0.85)', - tooltip: '鍧愭爣杞村強绀轰緥绛夋彁绀烘枃瀛椾娇鐢ㄧ殑棰滆壊銆�', + initVal: card.color || 'rgba(0, 0, 0, 0.65)', + tooltip: '鍧愭爣杞存彁绀烘枃瀛楀強绀轰緥鐨勯鑹层��', + required: false + }, { + type: 'color', + key: 'lineColor', + label: '杞寸嚎棰滆壊', + initVal: card.lineColor, + tooltip: '鍧愭爣杞寸嚎鐨勯鑹诧紝鍖呮嫭x杞淬�亂杞村強缃戞牸绾裤��', + allowClear: true, + required: false + }, { + type: 'color', + key: 'selectColor', + label: '閫変腑棰滆壊', + initVal: card.selectColor || '', + tooltip: '閫変腑鏌卞舰鍥剧殑棰滆壊锛屽湪浜や簰鏁堟灉銆婂厓绱犻�変腑锛堝閫夛級銆嬪拰銆婂厓绱犻�変腑锛堝崟閫夛級銆嬩腑鏈夋晥锛岃嚜瀹氫箟璁剧疆涓棤鏁堛��', + forbid: !['bar'].includes(card.chartType), + allowClear: true, + required: false + }, { + type: 'number', + key: 'rotate', + label: '鏃嬭浆', + tooltip: '鍧愭爣杞存爣娉ㄦ枃鏈殑鏃嬭浆瑙掑害銆�', + min: 0, + max: 360, + decimal: 0, + initVal: card.rotate, + forbid: appType !== 'mob', + required: false + }, { + type: 'select', + key: 'interaction', + label: '浜や簰鏁堟灉', + initVal: card.interaction || [], + multi: true, required: false, - options: [{ - value: 'black', - text: '榛戣壊' - }, { - value: 'white', - text: '鐧借壊' - }] + forbid: appType === 'mob', + options: [ + { value: 'element-active', label: '鍏冪礌鑱氱劍' }, + { value: 'element-selected', label: '鍏冪礌閫変腑锛堝閫夛級' }, + { value: 'element-single-selected', label: '鍏冪礌閫変腑锛堝崟閫夛級' }, + { value: 'active-region', label: '鑳屾櫙妗�' }, + { value: 'view-zoom', label: '瑙嗗浘缂╂斁' }, + { value: 'element-highlight', label: '鍏冪礌楂樹寒' }, + { value: 'element-highlight-by-color', label: '鍚岃壊鍏冪礌楂樹寒' }, + { value: 'element-highlight-by-x', label: '鍚孹杞村厓绱犻珮浜�' }, + { value: 'legend-filter', label: '鍥句緥杩囨护' }, + { value: 'legend-active', label: '鍥句緥鑱氱劍' }, + { value: 'legend-highlight', label: '鍥句緥楂樹寒' }, + { value: 'brush', label: '閫夋杩囨护' }, + ] } ] } diff --git a/src/menu/components/chart/antv-bar/chartcompile/index.jsx b/src/menu/components/chart/antv-bar/chartcompile/index.jsx index db034f3..3f31823 100644 --- a/src/menu/components/chart/antv-bar/chartcompile/index.jsx +++ b/src/menu/components/chart/antv-bar/chartcompile/index.jsx @@ -24,6 +24,7 @@ state = { view: 'normal', + ramp: 'false', visible: false, datatype: '', plot: null, @@ -48,6 +49,34 @@ } }, ], + rampColorColumns: [ + { + title: '鎸囨爣', + dataIndex: 'label', + editable: false, + width: '20%' + }, + { + title: '棰滆壊1', + dataIndex: 'color', + inputType: 'color', + editable: true, + width: '30%', + render: (text, record) => { + return (<div style={{width: '80px', height: '23px', background: text}}></div>) + } + }, + { + title: '棰滆壊2', + dataIndex: 'color1', + inputType: 'color', + editable: true, + width: '30%', + render: (text, record) => { + return (<div style={{width: '80px', height: '23px', background: text}}></div>) + } + }, + ], statColorColumns: [ { title: '鎸囨爣', @@ -67,19 +96,48 @@ } }, ], + rampStatColorColumns: [ + { + title: '鎸囨爣', + dataIndex: 'type', + inputType: 'input', + editable: true, + width: '20%' + }, + { + title: '棰滆壊1', + dataIndex: 'color', + inputType: 'color', + editable: true, + width: '30%', + render: (text, record) => { + return (<div style={{width: '80px', height: '23px', background: text}}></div>) + } + }, + { + title: '棰滆壊2', + dataIndex: 'color1', + inputType: 'color', + editable: true, + width: '30%', + render: (text, record) => { + return (<div style={{width: '80px', height: '23px', background: text}}></div>) + } + }, + ], cusColumns: [ { title: '鎸囨爣', dataIndex: 'name', editable: false, - width: '20%' + width: '14%' }, { title: '褰㈢姸', dataIndex: 'shape', inputType: 'cascader', editable: true, - width: '20%', + width: '12%', render: (text, record) => { return text.join(' / ').replace('line', '鎶樼嚎').replace('bar', '鏌卞舰') }, @@ -117,7 +175,7 @@ dataIndex: 'axis', inputType: 'select', editable: true, - width: '20%', + width: '12%', options: [ { value: 'true', text: '鏄剧ず'}, { value: 'false', text: '闅愯棌'} @@ -132,7 +190,7 @@ dataIndex: 'label', inputType: 'select', editable: true, - width: '20%', + width: '12%', options: [ { value: 'true', text: '鏄剧ず'}, { value: 'false', text: '闅愯棌'} @@ -141,6 +199,37 @@ let trans = {'true': '鏄剧ず', 'false': '闅愯棌'} return trans[text] || '闅愯棌' } + }, + { + title: '鏍囬', + dataIndex: 'title', + inputType: 'select', + editable: true, + width: '12%', + options: [ + { value: 'true', text: '鏄剧ず'}, + { value: 'false', text: '闅愯棌'} + ], + render: (text, record) => { + let trans = {'true': '鏄剧ず', 'false': '闅愯棌'} + return trans[text] || '鏄剧ず' + } + }, + { + title: '鏈�灏忓��', + dataIndex: 'min', + inputType: 'number', + editable: true, + required: false, + width: '12%' + }, + { + title: '鏈�澶у��', + dataIndex: 'max', + inputType: 'number', + editable: true, + required: false, + width: '12%' }, ] } @@ -163,6 +252,7 @@ this.setState({ visible: true, view: 'normal', + ramp: config.plot.ramp || 'false', datatype: config.plot.datatype || 'query', fieldName: fieldName, plot: fromJS(config.plot).toJS(), @@ -181,7 +271,7 @@ formlist: formlist.map(item => { if (['Yaxis'].includes(item.key)) { item.hidden = val === 'statistics' - } else if (['InfoType', 'InfoValue', 'InfoDefNumber'].includes(item.key)) { + } else if (['InfoType', 'InfoValue'].includes(item.key)) { item.hidden = val !== 'statistics' } return item @@ -291,7 +381,7 @@ } ] })( - <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> + <Radio.Group style={{whiteSpace: 'nowrap'}} disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> {item.options.map(option => { return ( <Radio key={option.value} value={option.value}>{option.text}</Radio> @@ -314,7 +404,7 @@ {getFieldDecorator(item.key, { initialValue: item.initVal })( - <ColorSketch /> + <ColorSketch allowClear={item.allowClear} /> )} </Form.Item> </Col> @@ -329,6 +419,35 @@ let val = e.target.value this.setState({plot: {...plot, enabled: val}}) + } + + mutilBarChange = (e) => { + const { plot } = this.state + let val = e.target.value + + this.setState({plot: {...plot, mutilBar: val}}) + } + + rampChange = (e) => { + const { plot } = this.state + let val = e.target.value + let colors = plot.colors || [] + + if (val === 'true') { + colors = colors.map(item => { + item.color1 = item.color1 || item.color + return item + }) + } + + this.setState({plot: {...plot, colors, ramp: val}, ramp: val}) + } + + rampDirectionChange = (e) => { + const { plot } = this.state + let val = e.target.value + + this.setState({plot: {...plot, rampDirection: val}}) } onSubmit = () => { @@ -411,6 +530,7 @@ name: labels[item] || item, axis: i === 0 ? 'true' : 'false', label: 'false', + title: 'true', shape: _plot.chartType === 'bar' && i === 0 ? ['bar', 'rect'] : ['line', 'smooth'] } }) @@ -425,7 +545,8 @@ uuid: Utils.getuuid(), type: item, label: labels[item] || item, - color: chartColors[i % limit] + color: chartColors[i % limit], + color1: chartColors[i % limit] } }) } @@ -459,7 +580,8 @@ plot.colors.push({ uuid: Utils.getuuid(), type: `鎸囨爣${plot.colors.length}`, - color: 'rgb(91, 143, 249)' + color: 'rgb(91, 143, 249)', + color1: 'rgb(91, 143, 249)' }) this.setState({plot}) @@ -478,7 +600,7 @@ } render() { - const { view, visible, datatype, plot, colorColumns, statColorColumns, cusColumns, baseFormlist } = this.state + const { view, visible, datatype, plot, ramp, colorColumns, rampColorColumns, statColorColumns, rampStatColorColumns, cusColumns, baseFormlist } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -497,7 +619,7 @@ wrapClassName="popview-modal menu-chart-edit-modal" title="鍥捐〃缂栬緫" visible={visible} - width={850} + width={950} maskClosable={false} onOk={this.onSubmit} onCancel={() => { this.setState({ visible: false }) }} @@ -514,9 +636,29 @@ </TabPane> {plot ? <TabPane tab="棰滆壊璁剧疆" key="color"> <div> + <Col span={8} style={{height: '40px', top: '-5px', zIndex: 1}}> + <Form {...formItemLayout}> + <Form.Item label="娓愬彉鑹�" style={{marginBottom: 10}}> + <Radio.Group value={plot.ramp || 'false'} onChange={this.rampChange}> + <Radio value="false">涓嶄娇鐢�</Radio> + <Radio value="true">浣跨敤</Radio> + </Radio.Group> + </Form.Item> + </Form> + </Col> + {plot.chartType === 'line' ? <Col span={8} style={{height: '40px', top: '-5px', zIndex: 1}}> + <Form {...formItemLayout}> + <Form.Item label="娓愬彉鏂瑰悜" style={{marginBottom: 10}}> + <Radio.Group value={plot.rampDirection || 'horizontal'} onChange={this.rampDirectionChange}> + <Radio value="horizontal">姘村钩</Radio> + <Radio value="vertical">鍨傜洿</Radio> + </Radio.Group> + </Form.Item> + </Form> + </Col> : null} {datatype === 'statistics' ? <Button className="color-add mk-green" onClick={this.addColor}>{this.props.dict['model.add']}</Button> : null} - {datatype === 'statistics' ? <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={statColorColumns} onChange={this.changeColor}/> : null} - {datatype !== 'statistics' ? <EditTable actions={['edit']} data={plot.colors || []} columns={colorColumns} onChange={this.changeColor}/> : null} + {datatype === 'statistics' ? <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={ramp ==='true' ? rampStatColorColumns : statColorColumns} onChange={this.changeColor}/> : null} + {datatype !== 'statistics' ? <EditTable actions={['edit']} data={plot.colors || []} columns={ramp ==='true' ? rampColorColumns : colorColumns} onChange={this.changeColor}/> : null} </div> </TabPane> : null} {plot ? <TabPane tab="鑷畾涔夎缃�" disabled={datatype === 'statistics'} key="custom"> @@ -530,7 +672,18 @@ </Form.Item> </Form> </Col> - <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>娉細浣跨敤鑷畾涔夎缃椂锛屾樉绀虹殑鍧愭爣杞寸涓�涓湪宸︿晶锛岀浜屼釜鍦ㄥ彸渚э紝澶氫綑鐨勪笉鐢熸晥锛涙煴褰㈠浘鍙彲浠ユ坊鍔犱竴涓紙璁剧疆澶氫釜鏃讹紝绗竴涓敓鏁堬級銆�</Col> + <Col span={12}> + <Form {...formItemLayout}> + <Form.Item label="澶氭煴鎺掑垪" style={{marginBottom: 10}}> + <Radio.Group value={plot.mutilBar || 'dodge'} onChange={this.mutilBarChange}> + <Radio value="dodge">鍒嗙粍</Radio> + <Radio value="stack">鍫嗗彔</Radio> + <Radio value="overlap">閲嶅彔</Radio> + </Radio.Group> + </Form.Item> + </Form> + </Col> + <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>娉細浣跨敤鑷畾涔夎缃椂锛屾樉绀虹殑鍧愭爣杞寸涓�涓湪宸︿晶锛岀浜屼釜鍦ㄥ彸渚э紝澶氫綑鐨勪笉鐢熸晥銆�</Col> <EditTable actions={['edit', 'move']} data={plot.customs || []} columns={cusColumns} onChange={this.changeCustom}/> </TabPane> : null} </Tabs> diff --git a/src/menu/components/chart/antv-bar/chartcompile/index.scss b/src/menu/components/chart/antv-bar/chartcompile/index.scss index 5928db8..244c6aa 100644 --- a/src/menu/components/chart/antv-bar/chartcompile/index.scss +++ b/src/menu/components/chart/antv-bar/chartcompile/index.scss @@ -20,6 +20,9 @@ .ant-input-number { width: 100%; } + .ant-radio-wrapper { + margin-right: 5px; + } .ant-tabs-nav-wrap { text-align: center; } diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx index 40cfcf1..19cd40e 100644 --- a/src/menu/components/chart/antv-bar/index.jsx +++ b/src/menu/components/chart/antv-bar/index.jsx @@ -8,7 +8,7 @@ import MKEmitter from '@/utils/events.js' import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import Utils from '@/utils/utils.js' import { chartColors } from '@/utils/option.js' import zhCN from '@/locales/zh-CN/model.js' @@ -35,6 +35,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, card: null, + appType: sessionStorage.getItem('appType'), eventListener: null } @@ -50,6 +51,7 @@ width: card.width || 24, height: 400, barSize: 35, + color: 'rgba(0, 0, 0, 0.65)', name: card.name } @@ -73,7 +75,7 @@ parentId: card.parentId || '', format: 'array', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� - switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + switchable: card.type === 'bar' ? true : false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� dataName: card.dataName || '', width: _plot.width, name: _plot.name, @@ -121,9 +123,11 @@ } componentDidMount () { - this.viewrender() MKEmitter.addListener('submitStyle', this.getStyle) MKEmitter.addListener('tabsChange', this.handleTabsChange) + setTimeout(() => { + this.viewrender() + }, 1000) } shouldComponentUpdate (nextProps, nextState) { @@ -150,7 +154,8 @@ _element.innerHTML = '' } - setTimeout(this.viewrender, 100) + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(this.viewrender, 100) } } @@ -193,10 +198,14 @@ */ linerender = () => { const { card } = this.state - let plot = {...card.plot, height: card.plot.height - 80} // 鍘婚櫎title鎵�鍗犵┖闂� - let color = plot.color || 'rgba(0, 0, 0, 0.85)' + let plot = {...card.plot} // 鍘婚櫎title鎵�鍗犵┖闂� + let color = plot.color || 'rgba(0, 0, 0, 0.65)' let X_axis = plot.Xaxis || 'x' let Y_axis = plot.Yaxis || ['y'] + + if (card.plot.title || card.search.length > 0) { + plot.height = card.plot.height - 70 + } let data = this.getdata(X_axis, Y_axis) @@ -235,8 +244,29 @@ chart.data(dv.rows) - chart.axis(X_axis, { label: { style: { fill: color } }, line: { style: { fill: color } } }) - chart.axis('value', { grid: { style: { fill: color } }, label: { style: { fill: color } } }) + // chart.axis(X_axis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) + // chart.axis('value', { grid: { line: { style: { stroke: color } }}, label: { style: { fill: color } } }) + + let xc = {label: { style: { fill: color } }} + let yc = {label: { style: { fill: color } }} + if (plot.grid === 'hidden') { + yc.grid = null + } + if (plot.y_line === 'show') { + yc.line = {style: { stroke: '#D1D2CE' }} + } + if (plot.lineColor) { + xc.tickLine = {style: { stroke: plot.lineColor }} + xc.line = { style: { stroke: plot.lineColor } } + if (yc.grid !== null) { + yc.grid = { line: { style: { stroke: plot.lineColor } }} + } + if (yc.line) { + yc.line = { style: { stroke: plot.lineColor } } + } + } + chart.axis(X_axis, xc) + chart.axis('value', yc) if (plot.coordinate !== 'polar') { chart.scale(X_axis, { @@ -245,7 +275,7 @@ } chart.scale('value', { nice: true, - range: [0, 0.93] + range: [0, 0.9] }) if (!plot.legend || plot.legend === 'hidden') { @@ -280,11 +310,23 @@ let colorIndex = 0 if (plot.colors && plot.colors.length > 0) { - plot.colors.forEach(item => { - if (!colors.has(transfield[item.type])) { - colors.set(transfield[item.type], item.color) + if (plot.ramp === 'true') { + let _s = 'l(0) ' + if (plot.rampDirection === 'vertical') { + _s = 'l(90) ' } - }) + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], `${_s}0:${item.color} 1:${item.color1}` ) + } + }) + } else { + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], item.color) + } + }) + } } let _chart = chart @@ -304,25 +346,33 @@ if (plot.colors && plot.colors.length > 0) { let limit = chartColors.length _chart.color('key', (key) => { - if (colors.get(key)) { + if (colors.has(key)) { + if (plot.area === 'true' && plot.rampDirection === 'vertical') { + return colors.get(key).replace(/l\(9?0\) 0:|\s1:.*/ig, '') + } return colors.get(key) } else { - colors.set(key, chartColors[colorIndex % limit]) colorIndex++ + return chartColors[(colorIndex - 1) % limit] } }) } else { _chart.color('key') } - if (plot.label === 'true') { - _chart.label('value', (value) => { + if (plot.label !== 'false') { + _chart.label('value*key', (value, key) => { if (plot.show === 'percent') { value = value + '%' + } + let _color = color + + if (plot.labelColor === 'custom' && colors.has(key)) { + _color = colors.get(key) } return { content: value, style: { - fill: color + fill: _color } } }) @@ -336,6 +386,32 @@ .size(3) .shape('circle') } + + if (plot.area === 'true') { + let area = chart.area().position(`${X_axis}*value`).tooltip(false) + if (plot.shape === 'smooth') { + area.shape('smooth') + } + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + area.color('key', (key) => { + if (colors.has(key)) { + return colors.get(key) + } else { + colorIndex++ + return chartColors[(colorIndex - 1) % limit] + } + }) + } else { + area.color('key') + } + } + + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) + } chart.render() } else { this.customrender(data) @@ -347,11 +423,16 @@ */ customrender = (data) => { let card = fromJS(this.state.card).toJS() - let plot = {...card.plot, height: card.plot.height - 80} // 鍘婚櫎title鎵�鍗犵┖闂� - let color = plot.color || 'rgba(0, 0, 0, 0.85)' + let plot = {...card.plot} // 鍘婚櫎title鎵�鍗犵┖闂� + let color = plot.color || 'rgba(0, 0, 0, 0.65)' let fields = [] let legends = [] let transfield = {} + let Bar_axis = [] + + if (card.plot.title || card.search.length > 0) { + plot.height = card.plot.height - 70 + } card.columns.forEach(col => { if (col.field) { @@ -364,41 +445,90 @@ let limit = chartColors.length if (plot.colors && plot.colors.length > 0) { - plot.colors.forEach(item => { - if (!colors.has(item.type)) { - colors.set(item.type, item.color) - } - }) + if (plot.ramp === 'true') { + let bars = {} + plot.customs.forEach(item => { + if (!item.shape || !item.shape[0] || item.shape[0] === 'bar') { + bars[item.type] = true + } + }) + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + if (bars[item.type]) { + colors.set(transfield[item.type], `l(90) 0:${item.color} 1:${item.color1}` ) + } else { + colors.set(transfield[item.type], `l(0) 0:${item.color} 1:${item.color1}` ) + } + } + }) + } else { + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], item.color) + } + }) + } } let axisIndex = 0 let hasBar = false + + plot.$paddingLeft = 30 + plot.$paddingRight = 30 plot.customs.forEach(item => { item.name = transfield[item.type] || item.type item.chartType = item.shape ? (item.shape[0] || 'bar') : 'bar' item.shape = item.shape ? (item.shape[1] || '') : '' - if (colors.get(item.type)) { - item.color = colors.get(item.type) + if (colors.has(item.name)) { + item.color = colors.get(item.name) } else { item.color = chartColors[colorIndex % limit] colorIndex++ } - if (item.chartType === 'bar' && !hasBar) { + if (item.chartType === 'bar') { + Bar_axis.push(item.type) hasBar = true - } else if (item.chartType === 'bar') { - item.chartType = 'line' - item.shape = 'smooth' } if (item.axis === 'true' && axisIndex < 2) { if (axisIndex === 0) { - item.axis = { grid: {style: { fill: color }}, title: { style: { fill: color } }, label: {style: { fill: color }} } + // item.axis = { grid: {line: { style: { stroke: color } }}, title: { style: { fill: color } }, label: {style: { fill: color }} } + item.axis = { label: {style: { fill: color }} } + if (item.title !== 'false') { + item.axis.title = { style: { fill: color } } + plot.$paddingLeft = 50 + } + if (plot.grid === 'hidden') { + item.axis.grid = null + } + if (plot.y_line === 'show') { + item.axis.line = {style: { stroke: '#D1D2CE' }} + } + if (plot.lineColor) { + if (item.axis.grid !== null) { + item.axis.grid = { line: { style: { stroke: plot.lineColor } }} + } + if (item.axis.line) { + item.axis.line = { style: { stroke: plot.lineColor } } + } + } + fields.unshift(item) } else { - item.axis = { grid: null, title: {style: { fill: color }}, label: {style: { fill: color }} } + item.axis = { grid: null, label: {style: { fill: color }} } + if (item.title !== 'false') { + item.axis.title = { style: { fill: color } } + plot.$paddingRight = 60 + } + if (plot.y_line === 'show') { + item.axis.line = {style: { stroke: '#D1D2CE' }} + } + if (plot.lineColor && item.axis.line) { + item.axis.line = { style: { stroke: plot.lineColor } } + } fields.splice(1, 0, item) } axisIndex++ @@ -426,15 +556,29 @@ } }) + let padding = [10, 30, 30, 30] + if (plot.mutilBar === 'overlap') { + Bar_axis = [] + } + + if (!Bar_axis.length) { + padding = [10, plot.$paddingRight, 30, plot.$paddingLeft] + } + const chart = new Chart({ container: card.uuid + 'canvas', autoFit: true, - height: plot.height || 400 + height: plot.height || 400, }) - chart.data(dv.rows) + // chart.axis(plot.Xaxis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) - chart.axis(plot.Xaxis, { label: { style: { fill: color } }, line: { style: { fill: color } } }) + let xc = {label: { style: { fill: color } }} + if (plot.lineColor) { + xc.tickLine = {style: { stroke: plot.lineColor }} + xc.line = { style: { stroke: plot.lineColor } } + } + chart.axis(plot.Xaxis, xc) if (!hasBar) { chart.scale(plot.Xaxis, { @@ -465,16 +609,211 @@ nice: true }) - fields.forEach(item => { - chart.axis(item.name, item.axis) - - chart.scale(item.name, { - nice: true, - range: [0, 0.93] + let lablecfg = { + position: 'top', + offset: 2, + style: { + fill: '#fff' + } + } + + if (plot.label === 'top') { + lablecfg.offset = -5 + lablecfg.style.textBaseline = 'top' + } else if (plot.label === 'middle') { + lablecfg.position = 'middle' + lablecfg.offset = 0 + } else if (plot.label === 'bottom') { + lablecfg.position = 'bottom' + lablecfg.offset = 0 + } else if (plot.label === 'true') { + lablecfg.style.fill = color + } + + if (Bar_axis.length) { + const view1 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + const dst = new DataSet() + const dvt = dst.createView().source(data) + + dvt.transform({ + type: 'fold', + fields: [...Bar_axis], + key: 'key', + value: 'value' + }) + + dvt.transform({ + type: 'map', + callback(row) { + row.key = transfield[row.key] || row.key + return row + }, }) - if (item.chartType === 'bar') { - let _chart = chart + view1.data(dvt.rows) + view1.scale('value', { + nice: true, + range: [0, 0.9] + }) + + let yc = {label: { style: { fill: color } }} + if (plot.grid === 'hidden') { + yc.grid = null + } + if (plot.y_line === 'show') { + yc.line = {style: { stroke: '#D1D2CE' }} + } + if (plot.lineColor) { + if (yc.grid !== null) { + yc.grid = { line: { style: { stroke: plot.lineColor } }} + } + if (yc.line) { + yc.line = { style: { stroke: plot.lineColor } } + } + } + view1.axis('value', yc) + + view1.legend(false) + + if (plot.mutilBar !== 'stack') { + let _chart = view1 + .interval() + .position(`${plot.Xaxis}*value`) + .adjust([ + { + type: 'dodge', + marginRatio: 0 + } + ]) + .shape(plot.shape || 'rect') + .tooltip(`${plot.Xaxis}*value*key`, (name, value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: key, + value: value + } + }) + + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (colors.has(key)) { + return colors.get(key) + } else { + colorIndex++ + return chartColors[(colorIndex - 1) % limit] + } + }) + } else { + _chart.color('key') + } + if (plot.label !== 'false') { + _chart.label('value*key', (value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + + if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { + lablecfg.style.fill = colors.get(key) + } + return { + content: value, + ...lablecfg + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } else if (plot.mutilBar === 'stack') { + let _chart = view1 + .interval() + .position(`${plot.Xaxis}*value`) + .adjust('stack') + .shape(plot.shape || 'rect') + .tooltip(`${plot.Xaxis}*value*key`, (name, value, type) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: type, + value: value + } + }) + + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (colors.has(key)) { + return colors.get(key) + } else { + colorIndex++ + return chartColors[(colorIndex - 1) % limit] + } + }) + } else { + _chart.color('key') + } + if (plot.label !== 'false') { + _chart.label('value*key', (value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + + if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { + lablecfg.style.fill = colors.get(key) + } + + return { + content: value, + ...lablecfg + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } + } + + const view2 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + + view2.data(dv.rows) + + view2.legend(false) + + fields.forEach(item => { + if (item.chartType === 'bar' && !Bar_axis.length) { + view2.axis(item.name, item.axis) + + view2.scale(item.name, { + nice: true, + range: [0, 0.9] + }) + + let _chart = view2 .interval() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) @@ -492,21 +831,35 @@ if (plot.barSize) { _chart.size(plot.barSize || 35) } - if (item.label === 'true') { + if (item.label !== 'false') { _chart.label(item.name, (value) => { if (plot.show === 'percent') { value = value + '%' } + + if (plot.label === 'true' && plot.labelColor === 'custom') { + lablecfg.style.fill = item.color + } return { content: value, - style: { - fill: color - } + ...lablecfg } }) } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } } else if (item.chartType === 'line') { - let _chart = chart + if (!Bar_axis.length) { + view2.axis(item.name, item.axis) + } else { + view2.axis(item.name, { grid: null, title: null, label: null }) + } + view2.scale(item.name, { + nice: true, + range: [0, 0.9] + }) + let _chart = view2 .line() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) @@ -521,15 +874,20 @@ } }) - if (item.label === 'true') { + if (item.label !== 'false') { _chart.label(item.name, (value) => { if (plot.show === 'percent') { value = value + '%' } + let _color = color + + if (plot.labelColor === 'custom') { + _color = item.color + } return { content: value, style: { - fill: color + fill: _color } } }) @@ -546,6 +904,14 @@ } }) + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + if (t === 'element-active' || t === 'element-highlight') { + chart.interaction(t) + } + }) + } + chart.render() } @@ -554,10 +920,14 @@ */ barrender = () => { const { card } = this.state - let plot = {...card.plot, height: card.plot.height - 80} - let color = plot.color || 'rgba(0, 0, 0, 0.85)' + let plot = {...card.plot} + let color = plot.color || 'rgba(0, 0, 0, 0.65)' let X_axis = plot.Xaxis || 'x' let Y_axis = plot.Yaxis || ['y'] + + if (card.plot.title || card.search.length > 0) { + plot.height = card.plot.height - 70 + } let data = this.getdata(X_axis, Y_axis) @@ -594,15 +964,36 @@ autoFit: true, height: plot.height || 400 }) - + chart.data(dv.rows) - chart.axis(X_axis, { label: { style: { fill: color } }, line: { style: { fill: color } } }) - chart.axis('value', { grid: { style: { fill: color } }, label: { style: { fill: color } } }) + // chart.axis(X_axis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) + // chart.axis('value', { grid: { line: { style: { stroke: color } }}, label: { style: { fill: color } } }) + + let xc = {label: { style: { fill: color } }} + let yc = {label: { style: { fill: color } }} + if (plot.grid === 'hidden') { + yc.grid = null + } + if (plot.y_line === 'show') { + yc.line = {style: { stroke: '#D1D2CE' }} + } + if (plot.lineColor) { + xc.tickLine = {style: { stroke: plot.lineColor }} + xc.line = { style: { stroke: plot.lineColor } } + if (yc.grid !== null) { + yc.grid = { line: { style: { stroke: plot.lineColor } }} + } + if (yc.line) { + yc.line = { style: { stroke: plot.lineColor } } + } + } + chart.axis(X_axis, xc) + chart.axis('value', yc) chart.scale('value', { nice: true, - range: [0, 0.93] + range: [0, 0.9] }) if (!plot.legend || plot.legend === 'hidden') { @@ -622,10 +1013,6 @@ }) } - if (plot.transpose === 'true') { - chart.coordinate().transpose() - } - if (plot.coordinate === 'polar') { chart.coordinate('polar', { innerRadius: 0.1, @@ -635,13 +1022,60 @@ let colors = new Map() let colorIndex = 0 + let lablecfg = { + position: 'top', + offset: 2, + style: { + fill: '#fff' + } + } + + if (plot.label === 'top') { + lablecfg.offset = -5 + lablecfg.style.textBaseline = 'top' + } else if (plot.label === 'middle') { + lablecfg.position = 'middle' + lablecfg.offset = 0 + } else if (plot.label === 'bottom') { + lablecfg.position = 'bottom' + lablecfg.offset = 0 + } else if (plot.label === 'true') { + lablecfg.style.fill = color + } + + if (plot.transpose === 'true') { + chart.coordinate().transpose() + if (plot.label === 'top') { + delete lablecfg.style.textBaseline + lablecfg.position = 'right' + lablecfg.offset = -3 + lablecfg.style.textAlign = 'end' + } else if (plot.label === 'middle') { + lablecfg.position = 'middle' + lablecfg.offset = 0 + } else if (plot.label === 'bottom') { + lablecfg.position = 'left' + lablecfg.offset = 2 + } else if (plot.label === 'true') { + lablecfg.position = 'right' + lablecfg.offset = 2 + } + } if (plot.colors && plot.colors.length > 0) { - plot.colors.forEach(item => { - if (!colors.has(transfield[item.type])) { - colors.set(transfield[item.type], item.color) - } - }) + if (plot.ramp === 'true') { + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], `l(90) 0:${item.color} 1:${item.color1}` ) + } + }) + } else { + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], item.color) + } + }) + } } if (plot.adjust !== 'stack') { @@ -668,32 +1102,47 @@ if (plot.colors && plot.colors.length > 0) { let limit = chartColors.length _chart.color('key', (key) => { - if (colors.get(key)) { + if (colors.has(key)) { return colors.get(key) } else { - colors.set(key, chartColors[colorIndex % limit]) colorIndex++ + return chartColors[(colorIndex - 1) % limit] } }) } else { _chart.color('key') } - if (plot.label === 'true') { - _chart.label('value', (value) => { + if (plot.label !== 'false') { + _chart.label('value*key', (value, key) => { if (plot.show === 'percent') { value = value + '%' } + + if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { + lablecfg.style.fill = colors.get(key) + } + return { content: value, - style: { - fill: color - } + ...lablecfg } }) } if (plot.barSize || plot.correction) { _chart.size(plot.barSize || 35) + } + if (plot.selectColor) { + _chart.state({ + selected: { + style: { + fill: plot.selectColor, + } + } + }) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) } } else if (plot.adjust === 'stack') { let _chart = chart @@ -714,26 +1163,28 @@ if (plot.colors && plot.colors.length > 0) { let limit = chartColors.length _chart.color('key', (key) => { - if (colors.get(key)) { + if (colors.has(key)) { return colors.get(key) } else { - colors.set(key, chartColors[colorIndex % limit]) colorIndex++ + return chartColors[(colorIndex - 1) % limit] } }) } else { _chart.color('key') } - if (plot.label === 'true') { - _chart.label('value', (value) => { + if (plot.label !== 'false') { + _chart.label('value*key', (value, key) => { if (plot.show === 'percent') { value = value + '%' } + + if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { + lablecfg.style.fill = colors.get(key) + } return { content: value, - style: { - fill: color - } + ...lablecfg } }) } @@ -741,6 +1192,24 @@ if (plot.barSize || plot.correction) { _chart.size(plot.barSize || 35) } + if (plot.selectColor) { + _chart.state({ + selected: { + style: { + fill: plot.selectColor, + } + } + }) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } + + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) } chart.render() @@ -751,13 +1220,15 @@ updateComponent = (component) => { const card = fromJS(this.state.card).toJS() - let refresh = false if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) { let _element = document.getElementById(card.uuid + 'canvas') if (_element) { _element.innerHTML = '' } - refresh = true + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(() => { + this.viewrender() + }, 150) } component.width = component.plot.width @@ -765,12 +1236,6 @@ this.setState({ card: component - }, () => { - if (refresh) { - setTimeout(() => { - this.viewrender() - }, 100) - } }) this.props.updateConfig(component) } @@ -875,15 +1340,15 @@ } render() { - const { card } = this.state + const { card, appType } = this.state + let _style = resetStyle(card.style) return ( - <div className="menu-line-chart-edit-box" style={{...card.style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> - <NormalHeader config={card} updateComponent={this.updateComponent}/> + <div className="menu-line-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> - <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> - <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null} + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> : null} <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> <CopyComponent type="line" card={card}/> <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} /> @@ -897,12 +1362,13 @@ } trigger="hover"> <Icon type="tool" /> </Popover> - <ActionComponent + {card.plot.title || card.search.length > 0 ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} + <div className="canvas" id={card.uuid + 'canvas'}></div> + {appType !== 'mob' ? <ActionComponent type="chart" config={card} updateaction={this.updateComponent} - /> - <div className="canvas" id={card.uuid + 'canvas'}></div> + /> : null} </div> ) } diff --git a/src/menu/components/chart/antv-bar/index.scss b/src/menu/components/chart/antv-bar/index.scss index 9754b3c..0c212d3 100644 --- a/src/menu/components/chart/antv-bar/index.scss +++ b/src/menu/components/chart/antv-bar/index.scss @@ -8,9 +8,12 @@ .canvas { margin: 0px; - // padding: 20px 15px 15px; - padding: 15px; + padding: 15px 10px 10px; letter-spacing: 0px; + height: 100%; + } + .normal-header + .canvas { + height: calc(100% - 45px); } .chart-header { @@ -47,6 +50,7 @@ .model-menu-action-list { position: absolute; right: 0px; + top: 30px; z-index: 4; font-size: 16px; @@ -58,6 +62,9 @@ float: right; } } + .normal-header + .canvas + .model-menu-action-list { + top: 45px; + } } .menu-line-chart-edit-box:hover { z-index: 1; diff --git a/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx new file mode 100644 index 0000000..335df94 --- /dev/null +++ b/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx @@ -0,0 +1,233 @@ +// import zhCN from '@/locales/zh-CN/model.js' +// import enUS from '@/locales/en-US/model.js' + +// const Formdict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS + +/** + * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟 + * @param {object} card // 鍥捐〃瀵硅薄 + */ +export function getBaseForm (card) { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + return [ + { + type: 'text', + key: 'title', + label: '鏍囬', + initVal: card.title, + required: false + }, + { + type: 'text', + key: 'name', + label: '缁勪欢鍚嶇О', + initVal: card.name, + tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�', + required: true + }, + { + type: 'number', + key: 'width', + label: '瀹藉害', + initVal: card.width, + tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��', + min: 1, + max: 24, + decimal: 0, + required: true + }, + { + type: 'number', + key: 'height', + label: '楂樺害', + initVal: card.height, + min: 100, + max: 1000, + decimal: 0, + required: true + }, + { + type: 'select', + key: 'blacklist', + label: '榛戝悕鍗�', + initVal: card.blacklist || [], + multi: true, + required: false, + options: roleList + } + ] +} +/** + * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟 + * @param {object} card // 鍥捐〃瀵硅薄 + * @param {Array} columns // 鏄剧ず鍒� + */ +export function getOptionForm (card, columns) { + let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) + + return [ + { + type: 'text', + key: 'label', + label: '鎸囨爣鍚嶇О', + initVal: card.label || '', + required: false + }, + { + type: 'select', + key: 'valueField', + label: '鏄剧ず鍊�', + initVal: card.valueField || '', + required: true, + options: yfields + }, + { + type: 'number', + key: 'maxValue', + label: '鏈�澶у��', + initVal: card.maxValue || 100, + tooltip: '浠〃鐩樻渶澶у埢搴﹀��', + min: 0, + max: 999999, + decimal: 1, + required: true + }, + { + type: 'number', + key: 'tickInterval', + label: '闂撮殧', + initVal: card.tickInterval || 10, + tooltip: '浠〃鐩樺埢搴﹂棿闅斿�笺��', + min: 0, + max: 999999, + decimal: 1, + required: true + }, + { + type: 'radio', + key: 'percent', + label: '鐧惧垎鐜�', + initVal: card.percent || 'true', + required: false, + options: [{ + value: 'true', + text: '浣跨敤' + }, { + value: 'false', + text: '涓嶄娇鐢�' + }] + }, + { + type: 'color', + key: 'tickColor', + label: '鍒诲害绾�', + initVal: card.tickColor || '#CBCBCB', + required: false + }, + { + type: 'color', + key: 'labelColor', + label: '鎸囨爣棰滆壊', + initVal: card.labelColor || '#545454', + required: false + } + ] +} + +/** + * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟 + * @param {object} card // 鍥捐〃瀵硅薄 + * @param {Array} columns // 鏄剧ず鍒� + */ +export function getRadioOptionForm (card, columns) { + let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) + let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) + + return [ + { + type: 'select', + key: 'labelField', + label: '鎸囨爣', + initVal: card.labelField || '', + required: true, + options: xfields + }, + { + type: 'select', + key: 'valueField', + label: '鍊�', + initVal: card.valueField || '', + required: true, + options: yfields + }, + { + type: 'number', + key: 'maxValue', + label: '鏈�澶у��', + initVal: card.maxValue || 100, + min: 0, + max: 999999, + decimal: 1, + required: true + }, + { + type: 'number', + key: 'radius', + label: '澶栫幆', + initVal: card.radius || 75, + tooltip: '鍥惧舰鎵�鍗犲尯鍩熺殑鐧惧垎鐜囥��', + min: 30, + max: 100, + decimal: 0, + required: true + }, + { + type: 'number', + key: 'fontSize', + label: '瀛椾綋澶у皬', + initVal: card.fontSize || 28, + min: 12, + max: 200, + decimal: 0, + required: true + }, + { + type: 'radio', + key: 'percent', + label: '鐧惧垎鐜�', + initVal: card.percent || 'true', + required: false, + options: [{ + value: 'true', + text: '浣跨敤' + }, { + value: 'false', + text: '涓嶄娇鐢�' + }] + }, + { + type: 'color', + key: 'backColor', + label: '鑳屾櫙鑹�', + initVal: card.backColor || '#ebedf0', + required: false + }, + { + type: 'color', + key: 'labelColor', + label: '瀛椾綋棰滆壊', + initVal: card.labelColor || '#8c8c8c', + required: false + } + ] +} diff --git a/src/menu/components/chart/antv-dashboard/chartcompile/index.jsx b/src/menu/components/chart/antv-dashboard/chartcompile/index.jsx new file mode 100644 index 0000000..76effa8 --- /dev/null +++ b/src/menu/components/chart/antv-dashboard/chartcompile/index.jsx @@ -0,0 +1,333 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Modal, Form, Row, Col, Select, Icon, Radio, Tooltip, Input, InputNumber, Tabs, Button } from 'antd' + +import Utils from '@/utils/utils.js' +import { getBaseForm, getOptionForm, getRadioOptionForm } from './formconfig' +import asyncComponent from '@/utils/asyncComponent' +import ColorSketch from '@/mob/colorsketch' +import './index.scss' + +const { TabPane } = Tabs + +const EditTable = asyncComponent(() => import('@/templates/zshare/editTable')) +const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform')) + +class LineChartDrawerForm extends Component { + static propTpyes = { + dict: PropTypes.object, + plot: PropTypes.object, + config: PropTypes.object, + plotchange: PropTypes.func + } + + state = { + visible: false, + plot: null, + formlist: null, + baseFormlist: null, + view: 'normal', + colorColumns: [ + { + title: '鎸囨爣', + dataIndex: 'tick', + inputType: this.props.config.subtype === 'ratioboard' ? 'text' : 'number', + editable: true, + width: '40%' + }, + { + title: '棰滆壊', + dataIndex: 'color', + inputType: 'color', + editable: true, + width: '40%', + render: (text, record) => { + return (<div style={{width: '80px', height: '23px', background: text}}></div>) + } + }, + ] + } + + showDrawer = () => { + const { config } = this.props + + this.setState({ + visible: true, + view: 'normal', + plot: fromJS(config.plot).toJS(), + baseFormlist: getBaseForm(config.plot), + formlist: config.subtype === 'ratioboard' ? getRadioOptionForm(config.plot, config.columns) : getOptionForm(config.plot, config.columns) + }) + } + + getFields() { + const { formlist } = this.state + const { getFieldDecorator } = this.props.form + const fields = [] + + if (!formlist) { + return fields + } + + formlist.forEach((item, index) => { + if (item.hidden || item.forbid) return + + if (item.type === 'text') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Select mode={item.multi ? 'multiple' : ''}> + {item.options.map((option, index) => + <Select.Option key={index} value={option.field}> + {option.label} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Radio.Group disabled={item.readonly}> + {item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + })} + </Radio.Group> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'color') { + fields.push( + <Col span={12} key={index} className="color-col"> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })( + <ColorSketch /> + )} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + onSubmit = () => { + const { config } = this.props + const { plot, view } = this.state + + if (view === 'normal') { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let _plot = {...plot, ...values} + + this.setState({ + plot: _plot, + visible: false + }) + + this.props.plotchange({...config, plot: _plot}) + } + }) + } else if (view === 'base') { + this.baseRef.handleConfirm().then(res => { + let _plot = {...plot, ...res} + + this.setState({ + plot: _plot, + visible: false + }) + + this.props.plotchange({...config, plot: _plot}) + }) + } else { + this.setState({ + visible: false + }) + + this.props.plotchange({...config, plot: plot}) + } + } + + changeTab = (tab) => { + const { plot, view } = this.state + + if (view === 'normal') { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let _plot = {...plot, ...values} + + this.setState({ + plot: _plot, + view: tab + }) + } + }) + } else if (view === 'base') { + this.baseRef.handleConfirm().then(res => { + let _plot = {...plot, ...res} + + this.setState({ + plot: _plot, + view: tab + }) + }) + } else { + this.setState({ + view: tab + }) + } + } + + addColor = () => { + let plot = fromJS(this.state.plot).toJS() + plot.colors = plot.colors || [] + + plot.colors.push({ + uuid: Utils.getuuid(), + tick: plot.maxValue || 1, + color: '#1890ff' + }) + + this.setState({plot}) + } + + changeColor = (colors) => { + const { plot } = this.state + + this.setState({plot: {...plot, colors}}) + } + + render() { + const { visible, plot, colorColumns, view, baseFormlist } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + + return ( + <div className="line-chart-drawer-form"> + <Icon type="edit" title="缂栬緫" onClick={this.showDrawer} /> + <Modal + wrapClassName="popview-modal menu-chart-edit-modal" + title="鍥捐〃缂栬緫" + visible={visible} + width={850} + maskClosable={false} + onOk={this.onSubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}> + <TabPane tab="缁勪欢璁剧疆" key="base"> + <NormalForm dict={this.props.dict} formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/> + </TabPane> + <TabPane tab="鍥捐〃璁剧疆" key="normal"> + <Form {...formItemLayout}> + <Row gutter={16}>{this.getFields()}</Row> + </Form> + </TabPane> + {plot ? <TabPane tab="棰滆壊璁剧疆" key="color"> + <div> + <Button className="color-add mk-green" onClick={this.addColor}>{this.props.dict['model.add']}</Button> + <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={colorColumns} onChange={this.changeColor}/> + </div> + </TabPane> : null} + </Tabs> + + </Modal> + </div> + ); + } +} + +export default Form.create()(LineChartDrawerForm) \ No newline at end of file diff --git a/src/menu/components/chart/antv-dashboard/chartcompile/index.scss b/src/menu/components/chart/antv-dashboard/chartcompile/index.scss new file mode 100644 index 0000000..607a36d --- /dev/null +++ b/src/menu/components/chart/antv-dashboard/chartcompile/index.scss @@ -0,0 +1,44 @@ +.line-chart-drawer-form { + display: inline-block; + > .anticon-edit { + color: #1890ff; + } +} +.menu-chart-edit-modal { + .ant-modal { + top: 50px; + .ant-modal-body { + min-height: 50vh; + max-height: calc(100vh - 190px); + padding-top: 10px; + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .ant-input-number { + width: 100%; + } + .ant-tabs-nav-wrap { + text-align: center; + } + .color-sketch-block { + position: relative; + top: 5px; + width: 240px; + } + .color-add { + float: right; + margin-bottom: 10px; + position: relative; + z-index: 1; + } + .color-col { + .ant-form-item-control { + height: 40px; + } + } + } + } +} + diff --git a/src/menu/components/chart/antv-dashboard/index.jsx b/src/menu/components/chart/antv-dashboard/index.jsx new file mode 100644 index 0000000..54f8e71 --- /dev/null +++ b/src/menu/components/chart/antv-dashboard/index.jsx @@ -0,0 +1,538 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover } from 'antd' +import { Chart, registerShape } from '@antv/g2' + +import MKEmitter from '@/utils/events.js' +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' +import { resetStyle } from '@/utils/utils-custom.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import './index.scss' + +const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) +const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) +const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) +const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) + +registerShape('point', 'pointer', { + draw(cfg, container) { + const group = container.addGroup({}); + // 鑾峰彇鏋佸潗鏍囩郴涓嬬敾甯冧腑蹇冪偣 + const center = this.parsePoint({ x: 0, y: 0 }); + // 缁樺埗鎸囬拡 + group.addShape('line', { + attrs: { + x1: center.x, + y1: center.y, + x2: cfg.x, + y2: cfg.y, + stroke: cfg.color, + lineWidth: 5, + lineCap: 'round', + }, + }); + group.addShape('circle', { + attrs: { + x: center.x, + y: center.y, + r: 9.75, + stroke: cfg.color, + lineWidth: 4.5, + fill: '#fff', + }, + }); + return group; + }, +}) + +registerShape('point', 'hidden', { + draw(cfg, container) { + return container.addGroup({}) + } +}) + +class antvDashboardChart extends Component { + static propTpyes = { + card: PropTypes.object, + updateConfig: PropTypes.func, + deletecomponent: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + ismob: sessionStorage.getItem('appType') === 'mob', + eventListener: null + } + + UNSAFE_componentWillMount () { + const { card, ismob } = this.props + + if (card.isNew) { + let _plot = null + if (card.subtype === 'ratioboard') { + _plot = { + width: card.width || 12, + height: 400, + labelField: '', + valueField: '', + name: card.name, + maxValue: 100, + radius: 75, + fontSize: 28, + percent: 'true', + backColor: '#ebedf0', + labelColor: '#8c8c8c' + } + } else { + _plot = { + width: card.width || 12, + height: 400, + label: '', + valueField: '', + name: card.name, + maxValue: 100, + tickInterval: 10, + labelColor: '#545454', + tickColor: '#CBCBCB', + percent: 'true' + } + } + + if (ismob) { + _plot.width = 24 + } + + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + tabId: card.tabId || '', + parentId: card.parentId || '', + format: card.subtype === 'ratioboard' ? 'array' : 'object', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 + pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� + switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + dataName: card.dataName || '', + width: _plot.width, + name: _plot.name, + subtype: card.subtype, + setting: { interType: 'system' }, + style: { + borderWidth: '1px', borderColor: 'rgb(217, 217, 217)', + marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' + }, + headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, + columns: [], + scripts: [], + search: [], + action: [], + plot: _plot, + btnlog: [], + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.plot = config.plot + _card.plot.name = card.name + _card.style = config.style + _card.headerStyle = config.headerStyle + } + + this.props.updateConfig(_card) + this.setState({ + card: _card + }) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('tabsChange', this.handleTabsChange) + MKEmitter.addListener('submitStyle', this.getStyle) + + setTimeout(() => { + this.viewrender() + }, 1000) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('tabsChange', this.handleTabsChange) + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + handleTabsChange = (parentId) => { + const { card } = this.state + + if (parentId === card.parentId) { + let _element = document.getElementById(card.uuid + 'canvas') + if (_element) { + _element.innerHTML = '' + } + + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(this.viewrender, 100) + } + } + + viewrender = () => { + const { card } = this.state + if (card.subtype === 'ratioboard') { + this.ratioboardrender() + } else { + this.dashboardrender() + } + } + + getratiodata = () => { + const { card } = this.state + + let val = (Math.random() * card.plot.maxValue).toFixed(1) + let data = [ + { type: '鏂扮敤鎴�', value: val, $percent: val / card.plot.maxValue, $color: '#1890ff' }, + ] + if (card.plot.colors && card.plot.colors.length > 0) { + data = [] + card.plot.colors.forEach(item => { + let _val = (Math.random() * card.plot.maxValue).toFixed(1) + data.push({ + type: item.tick, + value: _val, + $percent: _val / card.plot.maxValue, + $color: item.color + }) + }) + } + + return data + } + + ratioboardrender = () => { + const { card } = this.state + const plot = card.plot + + const data = this.getratiodata() + + const chart = new Chart({ + container: card.uuid + 'dashboard', + autoFit: true, + height: plot.title ? plot.height - 45 : plot.height, + }) + + chart.data(data) + chart.coordinate('polar', { + startAngle: -Math.PI / 2, + endAngle: 3 * Math.PI / 2, + radius: (plot.radius || 75) / 100 + }) + chart.scale('$percent', { + min: 0, + max: 1, + tickInterval: 1, + }) + chart.axis(false) + chart.facet('rect', { + fields: ['type'], + showTitle: false, + eachView: function eachView(view, facet) { + const data = facet.data[0] + + view.point().position('').shape('hidden') + + view.annotation().arc({ + top: false, + start: [0, 1], + end: [0.9999, 1], + style: { + stroke: plot.backColor, + lineWidth: 10 + } + }) + + let _tick = data.$percent + if (_tick >= 1) { + _tick = 0.9999 + } + + view.annotation().arc({ + start: [0, 1], + end: [_tick, 1], + style: { + stroke: data.$color, + lineWidth: 10, + } + }) + // 浠〃鐩樹俊鎭� + let text = '' + if (plot.percent === 'true') { + text = +(data.$percent * 100).toFixed(2) + '%' + } else { + text = data.value + } + + view.annotation().text({ + position: ['50%', '45%'], + content: data.type, + style: { + fontSize: plot.fontSize * 0.8, + fill: plot.labelColor, + fontWeight: 300, + textAlign: 'center' + }, + offsetX: 0 + }) + view.annotation().text({ + position: ['50%', '55%'], + content: text, + style: { + fontSize: plot.fontSize, + fill: plot.labelColor, + fontWeight: 500, + textAlign: 'center' + }, + offsetX: 0, + offsetY: 10 + }) + } + }) + chart.render() + } + + getdata = () => { + const { card } = this.state + + const data = [] + const val = (Math.random() * card.plot.maxValue).toFixed(1) + data.push({ value: +val }) + return data + } + + dashboardrender = () => { + const { card } = this.state + const plot = card.plot + const data = this.getdata() + + const chart = new Chart({ + container: card.uuid + 'dashboard', + autoFit: true, + height: plot.title ? plot.height - 45 : plot.height, + padding: [0, 0, 0, 0], + }) + chart.data(data) + chart.scale('value', { + min: 0, + max: plot.maxValue, + tickInterval: plot.tickInterval, + }) + chart.coordinate('polar', { + startAngle: (-9 / 8) * Math.PI, + endAngle: (1 / 8) * Math.PI, + radius: 0.75, + }) + + chart.axis('1', false) + chart.axis('value', { + line: null, + label: { + offset: -36, + style: { + fontSize: 18, + fill: plot.tickColor, + textAlign: 'center', + textBaseline: 'middle', + }, + }, + tickLine: { + length: -24, + style: { + stroke: plot.tickColor + } + }, + grid: null, + }) + chart.legend(false) + chart.tooltip(false) + chart + .point() + .position('value*1') + .shape('pointer') + .color('value', (val) => { + let _color = '#1890FF' + if (plot.colors && plot.colors.length > 0) { + _color = plot.colors[plot.colors.length - 1].color || '#1890FF' + plot.colors.some(item => { + if (item.tick > val) { + _color = item.color + return true + } + return false + }) + } + return _color + }) + .animate({ + appear: { + animation: 'fade-in' + } + }) + + // 缁樺埗浠〃鐩樿儗鏅� + chart.annotation().arc({ + top: false, + start: [0, 1], + end: [plot.maxValue, 1], + style: { + stroke: '#ebedf0', + lineWidth: 18, + lineDash: null, + }, + }) + + if (!plot.colors || plot.colors.length === 0) { + chart.annotation().arc({ + start: [0, 1], + end: [plot.maxValue, 1], + style: { + stroke: '#1890FF', + lineWidth: 18, + lineDash: null, + }, + }); + } else { + let start = 0 + plot.colors.forEach(item => { + chart.annotation().arc({ + start: [start, 1], + end: [item.tick, 1], + style: { + stroke: item.color, + lineWidth: 18, + lineDash: null, + }, + }) + start = item.tick + }) + } + + if (plot.label) { + chart.annotation().text({ + position: ['50%', '85%'], + content: plot.label, + style: { + fontSize: 20, + fill: plot.labelColor, + textAlign: 'center', + }, + }) + } + + let val = data[0].value + if (plot.percent !== 'false' && plot.maxValue) { + val = +(val / plot.maxValue * 100).toFixed(2) + ' %' + } + + chart.annotation().text({ + position: ['50%', '90%'], + content: val, + style: { + fontSize: 36, + fill: plot.labelColor, + textAlign: 'center', + }, + offsetY: 15, + }) + + chart.render() + } + + updateComponent = (component) => { + const card = fromJS(this.state.card).toJS() + + if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) { + let _element = document.getElementById(card.uuid + 'dashboard') + if (_element) { + _element.innerHTML = '' + } + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(() => { + this.viewrender() + }, 150) + } + + component.width = component.plot.width + component.name = component.plot.name + + this.setState({ + card: component + }) + this.props.updateConfig(component) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds[0] !== card.uuid || comIds.length > 1) return + + let _card = {...card, style} + + this.updateComponent(_card) + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + render() { + const { card } = this.state + let _style = resetStyle(card.style) + + return ( + <div className="menu-dashboard-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> + <CopyComponent type="dashboard" card={card}/> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <ClockComponent config={card} updateConfig={this.updateComponent}/> + <UserComponent config={card}/> + <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + <SettingComponent config={card} updateConfig={this.updateComponent}/> + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + {card.plot.title ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} + <div className="canvas" id={card.uuid + 'dashboard'}></div> + </div> + ) + } +} + +export default antvDashboardChart \ No newline at end of file diff --git a/src/menu/components/chart/antv-dashboard/index.scss b/src/menu/components/chart/antv-dashboard/index.scss new file mode 100644 index 0000000..efb4267 --- /dev/null +++ b/src/menu/components/chart/antv-dashboard/index.scss @@ -0,0 +1,50 @@ +.menu-dashboard-edit-box { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + + .canvas { + margin: 0px; + padding: 15px; + letter-spacing: 0px; + height: 100%; + } + .normal-header + .canvas { + height: calc(100% - 45px); + } + + >.anticon-tool { + position: absolute; + right: 1px; + top: 1px; + z-index: 2; + font-size: 16px; + padding: 5px; + cursor: pointer; + color: rgba(0, 0, 0, 0.85); + background: rgba(255, 255, 255, 0.55); + } + + .model-menu-action-list { + position: absolute; + right: 0px; + z-index: 4; + padding-top: 10px; + font-size: 16px; + + .ant-row .anticon-plus { + float: right; + } + + .page-card { + float: right; + } + } +} +.menu-dashboard-edit-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx index 6c4e322..20a3b61 100644 --- a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx +++ b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx @@ -8,7 +8,8 @@ * @param {object} card // 鍥捐〃瀵硅薄 */ export function getBaseForm (card) { - let isApp = sessionStorage.getItem('appType') === 'pc' + let appType = sessionStorage.getItem('appType') + let isApp = appType === 'pc' || appType === 'mob' let menulist = null if (isApp) { @@ -131,6 +132,7 @@ * @param {Array} columns // 鏄剧ず鍒� */ export function getOptionForm (card, columns) { + let appType = sessionStorage.getItem('appType') let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) @@ -144,13 +146,14 @@ options: [ { value: 'pie', text: '楗煎浘' }, { value: 'ring', text: '鐜浘' }, + { value: 'nest', text: '宓屽' }, { value: 'nightingale', text: '鍗椾竵鏍煎皵鍥�' } ] }, { type: 'select', key: 'Xaxis', - label: 'X-杞�', + label: '鍚嶇О', initVal: card.Xaxis || '', required: true, options: xfields @@ -158,10 +161,20 @@ { type: 'select', key: 'Yaxis', - label: 'Y-杞�', + label: '鍊�', initVal: card.Yaxis || '', required: true, options: yfields + }, + { + type: 'select', + key: 'type', + label: '绫诲瀷', + initVal: card.type || '', + tooltip: '鍐呯幆鐨勫垎绫诲瓧娈点��', + required: true, + options: xfields, + hidden: card.shape !== 'nest', }, { type: 'select', @@ -183,7 +196,8 @@ { field: 'left-top', label: '宸︿笂' }, { field: 'left-bottom', label: '宸︿笅' }, { field: 'hidden', label: '闅愯棌' } - ] + ], + hidden: card.shape === 'nest', }, { type: 'number', @@ -239,7 +253,7 @@ { type: 'radio', key: 'label', - label: '鏍囨敞鍊�', + label: '鏍囩', initVal: card.label || 'false', required: false, options: [{ @@ -250,8 +264,11 @@ text: '鍐呬晶' }, { value: 'outer', - text: '澶栦晶' - }] + text: '铚樿洓' + }, { + value: 'normal', + text: '甯歌' + }], }, { type: 'radio', key: 'repeat', @@ -269,19 +286,51 @@ text: '绱姞' }] }, { + type: 'number', + key: 'splitLine', + label: '鍒嗛殧绾�', + initVal: card.splitLine || '', + tooltip: '鍒嗛殧绾跨殑瀹藉害銆�', + min: 0, + max: 20, + decimal: 0, + required: false + }, { + type: 'color', + key: 'splitColor', + label: '鍒嗛殧鑹�', + initVal: card.splitColor || '#ffffff', + tooltip: '鍒嗛殧绾跨殑棰滆壊锛屽瓨鍦ㄥ垎闅旂嚎鏃舵湁鏁堛��', + required: false + }, { type: 'color', key: 'color', label: '鑹茬郴', initVal: card.color || 'rgba(0, 0, 0, 0.85)', tooltip: '鍧愭爣杞村強绀轰緥绛夋彁绀烘枃瀛椾娇鐢ㄧ殑棰滆壊銆�', + required: false + }, { + type: 'select', + key: 'interaction', + label: '浜や簰鏁堟灉', + initVal: card.interaction || [], + multi: true, required: false, - options: [{ - value: 'black', - text: '榛戣壊' - }, { - value: 'white', - text: '鐧借壊' - }] + forbid: appType === 'mob', + options: [ + { value: 'element-active', label: '鍏冪礌鑱氱劍' }, + { value: 'element-selected', label: '鍏冪礌閫変腑锛堝閫夛級' }, + { value: 'element-single-selected', label: '鍏冪礌閫変腑锛堝崟閫夛級' }, + // { value: 'active-region', label: '鑳屾櫙妗�' }, + // { value: 'view-zoom', label: '瑙嗗浘缂╂斁' }, + { value: 'element-highlight', label: '鍏冪礌楂樹寒' }, + // { value: 'element-highlight-by-color', label: '鍚岃壊鍏冪礌楂樹寒' }, + // { value: 'element-highlight-by-x', label: '鍚孹杞村厓绱犻珮浜�' }, + { value: 'legend-filter', label: '鍥句緥杩囨护' }, + { value: 'legend-active', label: '鍥句緥鑱氱劍' }, + { value: 'legend-highlight', label: '鍥句緥楂樹寒' }, + // { value: 'brush', label: '閫夋杩囨护' }, + ] } ] } diff --git a/src/menu/components/chart/antv-pie/chartcompile/index.jsx b/src/menu/components/chart/antv-pie/chartcompile/index.jsx index 2152dde..4f2638b 100644 --- a/src/menu/components/chart/antv-pie/chartcompile/index.jsx +++ b/src/menu/components/chart/antv-pie/chartcompile/index.jsx @@ -70,6 +70,10 @@ formlist: formlist.map(item => { if (item.key === 'innerRadius') { item.hidden = val === 'pie' + } else if (item.key === 'type') { + item.hidden = val !== 'nest' + } else if (item.key === 'legend') { + item.hidden = val === 'nest' } return item }) @@ -157,7 +161,7 @@ })( <Select mode={item.multi ? 'multiple' : ''}> {item.options.map((option, index) => - <Select.Option key={index} value={option.field}> + <Select.Option key={index} value={option.field || option.value}> {option.label} </Select.Option> )} @@ -184,7 +188,7 @@ } ] })( - <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> + <Radio.Group style={{whiteSpace: 'nowrap'}} disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> {item.options.map(option => { return ( <Radio key={option.value} value={option.value}>{option.text}</Radio> diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx index 374720a..593fcd5 100644 --- a/src/menu/components/chart/antv-pie/index.jsx +++ b/src/menu/components/chart/antv-pie/index.jsx @@ -1,14 +1,14 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Icon, Popover, notification } from 'antd' +import { Icon, Popover } from 'antd' import { Chart } from '@antv/g2' -import DataSet from '@antv/data-set' +import DataSet, { DataView } from '@antv/data-set' import MKEmitter from '@/utils/events.js' import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' @@ -18,7 +18,6 @@ const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) -const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) @@ -33,11 +32,12 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, card: null, + ismob: sessionStorage.getItem('appType') === 'mob', eventListener: null } UNSAFE_componentWillMount () { - const { card } = this.props + const { card, ismob } = this.props if (card.isNew) { let _plot = { @@ -48,8 +48,15 @@ name: card.name } + if (ismob) { + _plot.width = 24 + } + if (card.subtype === 'ring') { _plot.innerRadius = 50 + } else if (card.subtype === 'nest') { + _plot.innerRadius = 30 + _plot.radius = 80 } let _card = { @@ -105,9 +112,12 @@ } componentDidMount () { - this.pierender() MKEmitter.addListener('tabsChange', this.handleTabsChange) MKEmitter.addListener('submitStyle', this.getStyle) + + setTimeout(() => { + this.viewrender() + }, 1000) } shouldComponentUpdate (nextProps, nextState) { @@ -134,7 +144,18 @@ _element.innerHTML = '' } - setTimeout(this.pierender, 100) + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(this.viewrender, 100) + } + } + + viewrender = () => { + const { card } = this.state + + if (card.plot.shape === 'nest') { + this.nestrender() + } else { + this.pierender() } } @@ -145,13 +166,6 @@ { label: '2003', value: 33.7 }, { label: '2004', value: 30.7 }, { label: '2005', value: 25.8 }, - { label: '2006', value: 31.7 }, - { label: '2007', value: 33 }, - { label: '2008', value: 46 }, - { label: '2009', value: 38.3 }, - { label: '2010', value: 28 }, - { label: '2011', value: 42.5 }, - { label: '2012', value: 30.3 } ] let data = xdata.map(item => { @@ -164,13 +178,252 @@ return data } - pierender = () => { - const { card } = this.state - let plot = {...card.plot, height: card.plot.height - 80} - let color = plot.color || 'rgba(0, 0, 0, 0.85)' + getnestdata = (X_axis, Y_axis, type) => { + const xdata = [ + { name: '鐙瓙', type: '鐏薄', value: 11 }, + { name: '鐧界緤', type: '鐏薄', value: 10 }, + { name: '姘寸摱', type: '椋庡悜', value: 14 }, + { name: '灏勬墜', type: '鐏薄', value: 10 }, + { name: '鍙屽瓙', type: '椋庡悜', value: 7 }, + { name: '澶╁钩', type: '椋庡悜', value: 7 }, + { name: '鎽╃警', type: '鍦熻薄', value: 14 }, + { name: '閲戠墰', type: '鍦熻薄', value: 3 }, + { name: '澶勫コ', type: '鍦熻薄', value: 3 }, + { name: '澶╄潕', type: '姘磋薄', value: 11 }, + { name: '宸ㄨ煿', type: '姘磋薄', value: 5 }, + { name: '鍙岄奔', type: '姘磋薄', value: 5 }, + ] + let map = new Map() + let sort = 1 + let data = xdata.map(item => { + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + return { + [X_axis]: item.name, + [Y_axis]: item.value, + [type]: item.type, + $sort: _sort + } + }) + + return data + } + + nestrender = () => { + const { card } = this.state + const plot = card.plot + + let color = plot.color || 'rgba(0, 0, 0, 0.85)' let X_axis = plot.Xaxis || 'x' let Y_axis = plot.Yaxis || 'y' + let type = plot.type || 'type' + let height = plot.height || 400 + if (card.plot.title || card.search.length > 0) { + height = height - 45 + } + + const _data = this.getnestdata(X_axis, Y_axis, type) + const dvx = new DataView().source(_data) + + dvx.transform({ + type: 'sort-by', + fields: ['$sort'] + }) + + let data = dvx.rows + + // 閫氳繃 DataSet 璁$畻鐧惧垎姣� + const dv = new DataView() + dv.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: type, + as: '$percent' + }) + + const dv1 = new DataView() + dv1.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: X_axis, + as: '$percent', + }) + + const chart = new Chart({ + container: card.uuid + 'canvas', + autoFit: true, + height: height, + padding: 0, + }) + + chart.data(dv.rows) + + if (plot.show !== 'value') { + chart.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + + Y_axis = '$percent' + } + let radius = plot.radius / 100 + let innerRadius = plot.innerRadius / 100 + + chart.coordinate('theta', { + innerRadius: innerRadius, + radius: innerRadius + (radius - innerRadius) / 2, + }) + + if (plot.tooltip !== 'true') { + chart.tooltip(false) + } else { + chart.tooltip({ + showTitle: false, + showMarkers: false + }) + } + + chart.legend(false) + let chart1 = chart + .interval() + .adjust('stack') + .position(Y_axis) + .color(type) + .tooltip(`${type}*${Y_axis}`, (type, percent) => { + if (plot.show !== 'value') { + percent = (percent * 100).toFixed(2) + '%' + } + return { + name: type, + value: percent, + } + }) + + if (plot.splitLine) { + chart1.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, + }) + } + if (plot.label !== 'false') { + chart1.label(type, { + offset: -10, + }) + } + + const outterView = chart.createView() + + outterView.data(dv1.rows) + + if (plot.show !== 'value') { + outterView.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + } + outterView.coordinate('theta', { + innerRadius: (innerRadius + (radius - innerRadius) / 2) / radius, + radius: radius + }) + let chart2 = outterView + .interval() + .adjust('stack') + .position(Y_axis) + .color(X_axis) + .tooltip(`${X_axis}*${Y_axis}`, (name, value) => { + if (plot.show !== 'value') { + value = (value * 100).toFixed(2) + '%' + } + return { + name: name, + value: value + } + }) + + if (plot.splitLine) { + chart2.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, + }) + } + + if (plot.label !== 'false') { + if (plot.label === 'inner') { + chart2.label(Y_axis, { + offset: -30, + content: (data) => { + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + return _val + }, + style: { + textAlign: 'center', + fontSize: 16, + shadowBlur: 2, + shadowColor: 'rgba(0, 0, 0, .45)', + fill: '#fff', + } + }) + } else { + chart2.label(Y_axis, { + layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' }, + labelHeight: 20, + content: (data) => { + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + + return `${data[X_axis]}: ${_val}` + }, + labelLine: { + style: { + lineWidth: 0.5, + }, + }, + style: { + fill: color + } + }) + } + } + + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) + } + + chart.render() + } + + pierender = () => { + const { card } = this.state + const plot = card.plot + + let color = plot.color || 'rgba(0, 0, 0, 0.85)' + let X_axis = plot.Xaxis || 'x' + let Y_axis = plot.Yaxis || 'y' + let height = plot.height || 400 + if (card.plot.title || card.search.length > 0) { + height = height - 45 + } let data = this.getdata(X_axis, Y_axis) @@ -180,7 +433,7 @@ const chart = new Chart({ container: card.uuid + 'canvas', autoFit: true, - height: plot.height || 400 + height: height }) if (plot.shape !== 'nightingale' && plot.show !== 'value') { @@ -245,6 +498,7 @@ }) } + // 楗煎浘鎴栫幆鍥� if (plot.shape !== 'nightingale') { let _chart = chart .interval() @@ -260,24 +514,26 @@ value: value } }) + + if (plot.splitLine) { + _chart.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, + }) + } + if (plot.label !== 'false') { if (plot.label === 'inner') { _chart.label(Y_axis, { offset: -30, content: (data) => { - let _label = '' let _val = '' if (plot.show !== 'value') { _val = `${(data[Y_axis] * 100).toFixed(2)}%` } else { _val = `${data[Y_axis]}` } - if (plot.label === 'inner') { - _label = _val - } else { - _label = `${data[X_axis]}: ${_val}` - } - return _label + return _val }, style: { textAlign: 'center', @@ -289,22 +545,17 @@ }) } else { _chart.label(Y_axis, { - layout: { type: 'pie-spider' }, + layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' }, labelHeight: 20, content: (data) => { - let _label = '' let _val = '' if (plot.show !== 'value') { _val = `${(data[Y_axis] * 100).toFixed(2)}%` } else { _val = `${data[Y_axis]}` } - if (plot.label === 'inner') { - _label = _val - } else { - _label = `${data[X_axis]}: ${_val}` - } - return _label + + return `${data[X_axis]}: ${_val}` }, labelLine: { style: { @@ -317,10 +568,8 @@ }) } } - chart.interaction('element-active') } else { chart.axis(false) - chart.interaction('element-highlight') let _chart = chart .interval() .position(`${X_axis}*${Y_axis}`) @@ -337,11 +586,19 @@ } _chart.label(X_axis, _label) - .style({ - lineWidth: 1, - stroke: '#fff', + } + if (plot.splitLine) { + _chart.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, }) } + } + + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) } chart.render() @@ -349,13 +606,16 @@ updateComponent = (component) => { const card = fromJS(this.state.card).toJS() - let refresh = false + if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) { let _element = document.getElementById(card.uuid + 'canvas') if (_element) { _element.innerHTML = '' } - refresh = true + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(() => { + this.viewrender() + }, 150) } component.width = component.plot.width @@ -363,12 +623,6 @@ this.setState({ card: component - }, () => { - if (refresh) { - setTimeout(() => { - this.pierender() - }, 100) - } }) this.props.updateConfig(component) } @@ -410,32 +664,6 @@ this.updateComponent(_card) } - handleLog = (type, logs, item) => { - let card = fromJS(this.state.card).toJS() - - if (type === 'revert') { - card.action = card.action ? [...card.action, item] : [item] - card.btnlog = logs - - this.setState({ card }) - this.props.updateConfig(card) - notification.success({ - top: 92, - message: '鎭㈠鎴愬姛锛�', - duration: 2 - }) - } else { - card.btnlog = logs - this.setState({ card }) - this.props.updateConfig(card) - notification.success({ - top: 92, - message: '娓呴櫎鎴愬姛锛�', - duration: 2 - }) - } - } - clickComponent = (e) => { if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { e.stopPropagation() @@ -444,19 +672,18 @@ } render() { - const { card } = this.state + const { card, ismob } = this.state + let _style = resetStyle(card.style) return ( - <div className="menu-pie-chart-edit-box" style={{...card.style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> - <NormalHeader config={card} updateComponent={this.updateComponent}/> + <div className="menu-pie-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> - <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> + {!ismob ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null} <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> <CopyComponent type="pie" card={card}/> <PasteComponent config={card} options={['search', 'form']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> - <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <ClockComponent config={card} updateConfig={this.updateComponent}/> <UserComponent config={card}/> <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> @@ -465,6 +692,7 @@ } trigger="hover"> <Icon type="tool" /> </Popover> + {card.plot.title || card.search.length > 0 ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} <div className="canvas" id={card.uuid + 'canvas'}></div> </div> ) diff --git a/src/menu/components/chart/antv-pie/index.scss b/src/menu/components/chart/antv-pie/index.scss index 560f140..43bf1c5 100644 --- a/src/menu/components/chart/antv-pie/index.scss +++ b/src/menu/components/chart/antv-pie/index.scss @@ -10,6 +10,10 @@ margin: 0px; padding: 15px; letter-spacing: 0px; + height: 100%; + } + .normal-header + .canvas { + height: calc(100% - 45px); } >.anticon-tool { diff --git a/src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx new file mode 100644 index 0000000..20b0331 --- /dev/null +++ b/src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx @@ -0,0 +1,174 @@ +/** + * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟 + * @param {object} card // 鍥捐〃瀵硅薄 + */ +export function getBaseForm (card) { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + return [ + { + type: 'text', + key: 'title', + label: '鏍囬', + initVal: card.title, + required: false + }, + { + type: 'text', + key: 'name', + label: '缁勪欢鍚嶇О', + initVal: card.name, + tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�', + required: true + }, + { + type: 'number', + key: 'width', + label: '瀹藉害', + initVal: card.width, + tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��', + min: 1, + max: 24, + decimal: 0, + required: true + }, + { + type: 'number', + key: 'height', + label: '楂樺害', + initVal: card.height, + min: 100, + max: 1000, + decimal: 0, + required: true + }, + { + type: 'select', + key: 'blacklist', + label: '榛戝悕鍗�', + initVal: card.blacklist || [], + multi: true, + required: false, + options: roleList + } + ] +} + +/** + * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟 + * @param {object} card // 鍥捐〃瀵硅薄 + * @param {Array} columns // 鏄剧ず鍒� + */ +export function getOptionForm (card, columns) { + let appType = sessionStorage.getItem('appType') + let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) + let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) + + return [ + { + type: 'select', + key: 'gender', + label: '绫诲瀷', + initVal: card.gender || '', + required: true, + options: xfields + }, + { + type: 'select', + key: 'Xaxis', + label: 'X-杞�', + initVal: card.Xaxis || '', + required: true, + options: columns + }, + { + type: 'select', + key: 'Yaxis', + label: 'Y-杞�', + initVal: card.Yaxis || '', + required: true, + options: yfields + }, + { + type: 'radio', + key: 'shape', + label: '褰㈢姸', + initVal: card.shape || 'circle', + required: false, + options: [{ + value: 'circle', + text: 'circle' + }, { + value: 'square', + text: 'square' + }] + }, + { + type: 'radio', + key: 'tooltip', + label: '鎮诞鎻愮ず', + initVal: card.tooltip || 'true', + required: false, + options: [{ + value: 'true', + text: '鏄剧ず' + }, { + value: 'false', + text: '闅愯棌' + }] + }, + { + type: 'text', + key: 'Xunit', + label: 'X杞村崟浣�', + initVal: card.Xunit || '', + required: false + }, + { + type: 'text', + key: 'Yunit', + label: 'Y杞村崟浣�', + initVal: card.Yunit || '', + required: false + }, + { + type: 'color', + key: 'color', + label: '鑹茬郴', + initVal: card.color || 'rgba(0, 0, 0, 0.65)', + tooltip: '鍧愭爣杞存彁绀烘枃瀛楀強绀轰緥鐨勯鑹层��', + required: false + }, { + type: 'select', + key: 'interaction', + label: '浜や簰鏁堟灉', + initVal: card.interaction || [], + multi: true, + required: false, + forbid: appType === 'mob', + options: [ + { value: 'element-active', label: '鍏冪礌鑱氱劍' }, + { value: 'element-selected', label: '鍏冪礌閫変腑锛堝閫夛級' }, + { value: 'element-single-selected', label: '鍏冪礌閫変腑锛堝崟閫夛級' }, + // { value: 'active-region', label: '鑳屾櫙妗�' }, + { value: 'view-zoom', label: '瑙嗗浘缂╂斁' }, + { value: 'element-highlight', label: '鍏冪礌楂樹寒' }, + { value: 'element-highlight-by-color', label: '鍚岃壊鍏冪礌楂樹寒' }, + { value: 'element-highlight-by-x', label: '鍚孹杞村厓绱犻珮浜�' }, + { value: 'legend-filter', label: '鍥句緥杩囨护' }, + { value: 'legend-active', label: '鍥句緥鑱氱劍' }, + { value: 'legend-highlight', label: '鍥句緥楂樹寒' }, + { value: 'brush', label: '閫夋杩囨护' }, + ] + } + ] +} diff --git a/src/menu/components/chart/antv-scatter/chartcompile/index.jsx b/src/menu/components/chart/antv-scatter/chartcompile/index.jsx new file mode 100644 index 0000000..0982251 --- /dev/null +++ b/src/menu/components/chart/antv-scatter/chartcompile/index.jsx @@ -0,0 +1,271 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Modal, Form, Row, Col, Select, Icon, Radio, Tooltip, Input, InputNumber, Tabs } from 'antd' + +import { getBaseForm, getOptionForm } from './formconfig' +import asyncComponent from '@/utils/asyncComponent' +import ColorSketch from '@/mob/colorsketch' +import './index.scss' + +const { TabPane } = Tabs +const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform')) + +class LineChartDrawerForm extends Component { + static propTpyes = { + dict: PropTypes.object, + plot: PropTypes.object, + config: PropTypes.object, + plotchange: PropTypes.func + } + + state = { + view: 'normal', + visible: false, + plot: null, + formlist: null, + baseFormlist: null + } + + showDrawer = () => { + const { config } = this.props + + this.setState({ + visible: true, + view: 'normal', + plot: fromJS(config.plot).toJS(), + baseFormlist: getBaseForm(config.plot), + formlist: getOptionForm(config.plot, config.columns) + }) + } + + getFields() { + const { formlist } = this.state + const { getFieldDecorator } = this.props.form + const fields = [] + + if (!formlist) { + return fields + } + + formlist.forEach((item, index) => { + if (item.hidden || item.forbid) return + + if (item.type === 'text') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Select mode={item.multi ? 'multiple' : ''}> + {item.options.map((option, index) => + <Select.Option key={index} value={option.field || option.value}> + {option.label || option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Radio.Group disabled={item.readonly}> + {item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + })} + </Radio.Group> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'color') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })( + <ColorSketch /> + )} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + onSubmit = () => { + const { config } = this.props + const { plot, view } = this.state + + if (view === 'normal') { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let _plot = {...plot, ...values} + + this.setState({ + plot: _plot, + visible: false + }) + + this.props.plotchange({...config, plot: _plot}) + } + }) + } else if (view === 'base') { + this.baseRef.handleConfirm().then(res => { + let _plot = {...plot, ...res} + + this.setState({ + plot: _plot, + visible: false + }) + + this.props.plotchange({...config, plot: _plot}) + }) + } + } + + changeTab = (tab) => { + const { plot, view } = this.state + + if (view === 'normal') { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + this.setState({ + plot: {...plot, ...values}, + view: tab + }) + } + }) + } else if (view === 'base') { + this.baseRef.handleConfirm().then(res => { + this.setState({ + plot: {...plot, ...res}, + view: tab + }) + }) + } + } + + render() { + const { view, visible, baseFormlist } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + + return ( + <div className="line-chart-drawer-form"> + <Icon type="edit" title="缂栬緫" onClick={this.showDrawer} /> + <Modal + wrapClassName="popview-modal menu-chart-edit-modal" + title="鍥捐〃缂栬緫" + visible={visible} + width={850} + maskClosable={false} + onOk={this.onSubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}> + <TabPane tab="缁勪欢璁剧疆" key="base"> + <NormalForm dict={this.props.dict} formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/> + </TabPane> + <TabPane tab="鍥捐〃璁剧疆" key="normal"> + <Form {...formItemLayout}> + <Row gutter={16}>{this.getFields()}</Row> + </Form> + </TabPane> + </Tabs> + </Modal> + </div> + ); + } +} + +export default Form.create()(LineChartDrawerForm) \ No newline at end of file diff --git a/src/menu/components/chart/antv-scatter/chartcompile/index.scss b/src/menu/components/chart/antv-scatter/chartcompile/index.scss new file mode 100644 index 0000000..5928db8 --- /dev/null +++ b/src/menu/components/chart/antv-scatter/chartcompile/index.scss @@ -0,0 +1,41 @@ +.line-chart-drawer-form { + display: inline-block; + > .anticon-edit { + color: #1890ff; + } +} +.menu-chart-edit-modal { + .ant-modal { + top: 50px; + .ant-modal-body { + max-height: calc(100vh - 190px); + min-height: 50vh; + padding-top: 10px; + .menu-chart-edit-box { + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .ant-input-number { + width: 100%; + } + .ant-tabs-nav-wrap { + text-align: center; + } + .color-sketch-block { + position: relative; + top: 5px; + width: 240px; + } + .color-add { + float: right; + margin-bottom: 10px; + position: relative; + z-index: 1; + } + } + } + } +} + diff --git a/src/menu/components/chart/antv-scatter/index.jsx b/src/menu/components/chart/antv-scatter/index.jsx new file mode 100644 index 0000000..a002498 --- /dev/null +++ b/src/menu/components/chart/antv-scatter/index.jsx @@ -0,0 +1,404 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover, notification } from 'antd' +import { Chart } from '@antv/g2' + +import MKEmitter from '@/utils/events.js' +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' +import { resetStyle } from '@/utils/utils-custom.js' +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import './index.scss' + +const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) +const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) +const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) +const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) +const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent')) +const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) +const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) + +class antvScatterChart extends Component { + static propTpyes = { + card: PropTypes.object, + updateConfig: PropTypes.func, + deletecomponent: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + appType: sessionStorage.getItem('appType'), + eventListener: null + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _plot = { + width: card.width || 24, + height: 400, + gender: '', + Xaxis: '', + Xunit: '', + Yaxis: '', + Yunit: '', + shape: 'circle', + color: 'rgba(0, 0, 0, 0.65)', + name: card.name + } + + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + tabId: card.tabId || '', + parentId: card.parentId || '', + format: 'array', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 + pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� + switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + dataName: card.dataName || '', + width: _plot.width, + name: _plot.name, + subtype: card.subtype, + setting: { interType: 'system' }, + style: { + borderWidth: '1px', borderColor: 'rgb(217, 217, 217)', + marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' + }, + headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, + columns: [], + scripts: [], + search: [], + action: [], + plot: _plot, + btnlog: [], + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.plot = config.plot + _card.plot.name = card.name + _card.style = config.style + _card.headerStyle = config.headerStyle + + _card.action = config.action.map(col => { + col.uuid = Utils.getuuid() + return col + }) + _card.search = config.search.map(col => { + col.uuid = Utils.getuuid() + return col + }) + } + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + MKEmitter.addListener('tabsChange', this.handleTabsChange) + setTimeout(() => { + this.ponitrender() + }, 1000) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + MKEmitter.removeListener('tabsChange', this.handleTabsChange) + } + + handleTabsChange = (parentId) => { + const { card } = this.state + + if (parentId === card.parentId) { + let _element = document.getElementById(card.uuid + 'canvas') + if (_element) { + _element.innerHTML = '' + } + + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(this.ponitrender, 100) + } + } + + getdata = () => { + let data = [] + + for (let i = 0; i < 500; i++) { + let item = {} + let n = Math.random() + let m = Math.random() + if (n > 0.7) { + n = n * n + } else if (n < 0.3) { + n = Math.sqrt(n) + } + if (m > 0.7) { + m = m * m + } else if (m < 0.3) { + m = Math.sqrt(m) + } + + if (i % 2 === 0) { + item.gender = 'male' + item.height = 160 + Math.floor(n * 35 * 10) / 10 + item.weight = 50 + Math.floor(m * 55 * 10) / 10 + } else { + item.gender = 'female' + item.height = 140 + Math.floor(n * 40 * 10) / 10 + item.weight = 41 + Math.floor(m * 45 * 10) / 10 + } + + data.push(item) + } + + return data + } + + /** + * @description 鏁g偣鍥� + */ + ponitrender = () => { + const { card } = this.state + const plot = card.plot + const data = this.getdata() + let height = plot.height - 25 + + if (card.plot.title || card.search.length > 0) { + height = plot.height - 70 + } + + const chart = new Chart({ + container: card.uuid + 'canvas', + autoFit: true, + height: height + }) + + chart.data(data); + chart.scale({ + height: { nice: true }, + weight: { nice: true }, + }) + + // chart.axis('height', { label: { style: { fill: plot.color } }, tickLine: {style: { stroke: plot.color }}, line: { style: { stroke: plot.color } } }) + // chart.axis('weight', { grid: { line: { style: { stroke: plot.color } }}, label: { style: { fill: plot.color } } }) + chart.axis('height', { label: { style: { fill: plot.color } } }) + chart.axis('weight', { label: { style: { fill: plot.color } } }) + chart.legend({ + position: plot.legend || 'bottom', + itemName: { style: { fill: plot.color } } + }) + + if (plot.tooltip !== 'true') { + chart.tooltip(false) + } else { + chart.tooltip({ + showTitle: false, + showCrosshairs: true, + crosshairs: { + type: 'xy', + } + }) + } + + chart + .point() + .position('height*weight') + .color('gender') + .shape(plot.shape) + .tooltip('gender*height*weight', (gender, height, weight) => { + return { + name: gender, + value: height + (plot.Xunit ? `(${plot.Xunit}), ` : ', ') + weight + (plot.Yunit ? `(${plot.Yunit})` : '') + }; + }) + .style({ + fillOpacity: 0.85 + }) + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) + } + chart.render() + } + + updateComponent = (component) => { + const card = fromJS(this.state.card).toJS() + + if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) { + let _element = document.getElementById(card.uuid + 'canvas') + if (_element) { + _element.innerHTML = '' + } + this.$timer && clearTimeout(this.$timer) + this.$timer = setTimeout(() => { + this.ponitrender() + }, 150) + } + + component.width = component.plot.width + component.name = component.plot.name + + this.setState({ + card: component + }) + this.props.updateConfig(component) + } + + addSearch = () => { + const { card } = this.state + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.label = 'label' + newcard.initval = '' + newcard.type = 'select' + newcard.resourceType = '0' + newcard.options = [] + newcard.setAll = 'false' + newcard.orderType = 'asc' + newcard.display = 'dropdown' + newcard.match = '=' + + // 娉ㄥ唽浜嬩欢-娣诲姞鎼滅储 + MKEmitter.emit('addSearch', card.uuid, newcard) + } + + addButton = () => { + const { card } = this.state + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.label = '瀵煎嚭Excel' + newcard.sqlType = '' + newcard.Ot = 'requiredSgl' + newcard.OpenType = 'excelOut' + newcard.icon = 'download' + newcard.class = 'dgreen' + newcard.intertype = card.setting.interType + newcard.innerFunc = card.setting.innerFunc || '' + newcard.sysInterface = card.setting.sysInterface || '' + newcard.outerFunc = card.setting.outerFunc || '' + newcard.interface = card.setting.interface || '' + newcard.execSuccess = 'grid' + newcard.execError = 'never' + newcard.popClose = 'never' + newcard.errorTime = 10 + newcard.verify = null + newcard.show = 'icon' + + // 娉ㄥ唽浜嬩欢-娣诲姞鎸夐挳 + MKEmitter.emit('addButton', card.uuid, newcard) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds[0] !== card.uuid || comIds.length > 1) return + + let _card = {...card, style} + + this.updateComponent(_card) + } + + handleLog = (type, logs, item) => { + let card = fromJS(this.state.card).toJS() + + if (type === 'revert') { + card.action = card.action ? [...card.action, item] : [item] + card.btnlog = logs + + this.setState({ card }) + this.props.updateConfig(card) + notification.success({ + top: 92, + message: '鎭㈠鎴愬姛锛�', + duration: 2 + }) + } else { + card.btnlog = logs + this.setState({ card }) + this.props.updateConfig(card) + notification.success({ + top: 92, + message: '娓呴櫎鎴愬姛锛�', + duration: 2 + }) + } + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + render() { + const { card, appType } = this.state + let _style = resetStyle(card.style) + + return ( + <div className="menu-scatter-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle"/> : null} + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> : null} + <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> + <CopyComponent type="line" card={card}/> + <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent}/> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors"/> + <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/> + <ClockComponent config={card} updateConfig={this.updateComponent}/> + <UserComponent config={card}/> + <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)}/> + <SettingComponent config={card} updateConfig={this.updateComponent}/> + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + {card.plot.title || card.search.length > 0 ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} + <div className="canvas" id={card.uuid + 'canvas'}></div> + {appType !== 'mob' ? <ActionComponent type="chart" config={card} updateaction={this.updateComponent}/> : null} + </div> + ) + } +} + +export default antvScatterChart \ No newline at end of file diff --git a/src/menu/components/chart/antv-scatter/index.scss b/src/menu/components/chart/antv-scatter/index.scss new file mode 100644 index 0000000..4403718 --- /dev/null +++ b/src/menu/components/chart/antv-scatter/index.scss @@ -0,0 +1,72 @@ +.menu-scatter-chart-edit-box { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + + .canvas { + margin: 0px; + padding: 15px 10px 10px; + letter-spacing: 0px; + height: 100%; + } + .normal-header + .canvas { + height: calc(100% - 45px); + } + + .chart-header { + position: relative; + height: 45px; + border-bottom: 1px solid #e8e8e8; + overflow: hidden; + padding-right: 35px; + + .chart-title { + text-decoration: inherit; + font-weight: inherit; + font-style: inherit; + float: left; + line-height: 45px; + margin-left: 10px; + position: relative; + z-index: 1; + } + } + + >.anticon-tool { + position: absolute; + right: 1px; + top: 1px; + z-index: 2; + font-size: 16px; + padding: 5px; + cursor: pointer; + color: rgba(0, 0, 0, 0.85); + background: rgba(255, 255, 255, 0.55); + } + + .model-menu-action-list { + position: absolute; + right: 0px; + top: 30px; + z-index: 4; + font-size: 16px; + + .ant-row .anticon-plus { + float: right; + } + + .page-card { + float: right; + } + } + .normal-header + .canvas + .model-menu-action-list { + top: 45px; + } +} +.menu-scatter-chart-edit-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/menu/components/code/sandbox/index.jsx b/src/menu/components/code/sandbox/index.jsx index 7e1fb66..e125817 100644 --- a/src/menu/components/code/sandbox/index.jsx +++ b/src/menu/components/code/sandbox/index.jsx @@ -5,7 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' @@ -152,8 +152,10 @@ render() { const { card } = this.state + let _style = resetStyle(card.style) + return ( - <div className="menu-editor-sand-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-editor-sand-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <WrapComponent config={card} updateConfig={this.updateComponent} /> diff --git a/src/menu/components/form/formaction/actionform/index.jsx b/src/menu/components/form/formaction/actionform/index.jsx index 454a16e..35fb01b 100644 --- a/src/menu/components/form/formaction/actionform/index.jsx +++ b/src/menu/components/form/formaction/actionform/index.jsx @@ -49,11 +49,11 @@ const { card } = this.props if (card.type === 'prev') { - return ['type', 'label'] + return ['type', 'label', 'enable'] } else if (card.type === 'next') { return ['type', 'label', 'enable'] } - let _options = ['type', 'label', 'intertype', 'syncComponent', 'linkmenu', 'open'] // 閫夐」鍒楄〃 + let _options = ['type', 'label', 'intertype', 'syncComponent', 'linkmenu', 'open', 'enable'] // 閫夐」鍒楄〃 if (_intertype === 'custom') { _options.push('procMode', 'interface', 'callbackType', 'cbTable', 'proInterface', 'method', 'cross') diff --git a/src/menu/components/form/formaction/formconfig.jsx b/src/menu/components/form/formaction/formconfig.jsx index 1a84804..6eb2048 100644 --- a/src/menu/components/form/formaction/formconfig.jsx +++ b/src/menu/components/form/formaction/formconfig.jsx @@ -10,7 +10,7 @@ */ export function getActionForm (card, functip, tableName, usefulFields, modules) { - const isApp = sessionStorage.getItem('appType') === 'pc' + const appType = sessionStorage.getItem('appType') let _type = '鎻愪氦' if (card.type === 'prev') { _type = '涓婁竴姝�' @@ -19,7 +19,7 @@ } let menulist = [] - if (isApp) { + if (appType === 'pc' || appType === 'mob') { menulist = sessionStorage.getItem('appMenus') if (menulist) { try { @@ -242,7 +242,7 @@ readonly: false }, { - type: isApp ? 'select' : 'cascader', + type: (appType === 'pc' || appType === 'mob') ? 'select' : 'cascader', key: 'linkmenu', label: '鎵撳紑鑿滃崟', tooltip: '鎵ц鎴愬姛鍚庨渶瑕佹墦寮�鐨勮彍鍗曘��', @@ -256,7 +256,7 @@ label: '鎵撳紑鏂瑰紡', initVal: card.open || 'blank', required: false, - forbid: !isApp, + forbid: appType !== 'pc', options: [{ value: 'blank', text: '鏂扮獥鍙�' @@ -278,7 +278,7 @@ type: 'radio', key: 'enable', label: '鏄惁鏄剧ず', - initVal: card.enable || 'false', + initVal: card.enable || 'true', required: false, options: [{ value: 'true', diff --git a/src/menu/components/form/formaction/index.jsx b/src/menu/components/form/formaction/index.jsx index fcbdb30..8127e42 100644 --- a/src/menu/components/form/formaction/index.jsx +++ b/src/menu/components/form/formaction/index.jsx @@ -7,6 +7,7 @@ import enUS from '@/locales/en-US/model.js' import asyncComponent from '@/utils/asyncComponent' import { getActionForm } from './formconfig' +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import MenuUtils from '@/utils/utils-custom.js' @@ -23,6 +24,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, // 缂栬緫涓厓绱� formlist: null, // 琛ㄥ崟淇℃伅 visible: false, // 妯℃�佹鎺у埗 @@ -172,6 +174,21 @@ }) } + changeMenu = () => { + const { appType } = this.state + const { group } = this.props + + if (appType !== 'pc' && appType !== 'mob') return + if (!group.subButton.linkmenu) return + + MKEmitter.emit('changeEditMenu', { + MenuID: group.subButton.linkmenu, + copyMenuId: '', + MenuNo: '', + MenuName: '', + }) + } + render() { const { group, config } = this.props const { visible, profVisible, card, dict } = this.state @@ -184,7 +201,7 @@ <Icon className="style" title="璋冩暣鏍峰紡" onClick={() => this.handleStyle(group.prevButton)} type="font-colors" /> </div> } trigger="hover"> - <Button type="link" className="prev" style={group.prevButton.style}>{group.prevButton.label}</Button> + <Button type="link" className={'prev ' + group.prevButton.enable} style={resetStyle(group.prevButton.style)}>{group.prevButton.label}</Button> </Popover> : null} <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> @@ -193,7 +210,7 @@ <Icon className="profile" title="setting" type="profile" onClick={() => this.profileAction()} /> </div> } trigger="hover"> - <Button type="link" className="submit mk-primary" style={group.subButton.style}>{group.subButton.label}</Button> + <Button type="link" className="submit mk-primary" onDoubleClick={this.changeMenu} style={resetStyle(group.subButton.style)}>{group.subButton.label}</Button> </Popover> {group.sort !== config.subcards.length ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> @@ -201,7 +218,7 @@ <Icon className="style" title="璋冩暣鏍峰紡" onClick={() => this.handleStyle(group.nextButton)} type="font-colors" /> </div> } trigger="hover"> - <Button type="link" className={'skip ' + group.nextButton.enable} style={group.nextButton.style}>{group.nextButton.label}</Button> + <Button type="link" className={'skip ' + group.nextButton.enable} style={resetStyle(group.nextButton.style)}>{group.nextButton.label}</Button> </Popover> : null} {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */} <Modal diff --git a/src/menu/components/form/formaction/index.scss b/src/menu/components/form/formaction/index.scss index 1fa18b5..b7a1cd3 100644 --- a/src/menu/components/form/formaction/index.scss +++ b/src/menu/components/form/formaction/index.scss @@ -6,6 +6,11 @@ .prev { margin-right: 15px; } + .prev.false { + span { + text-decoration: line-through; + } + } .submit { border: none; } diff --git a/src/menu/components/form/normal-form/groupform/index.jsx b/src/menu/components/form/normal-form/groupform/index.jsx index c1611f9..488cd6c 100644 --- a/src/menu/components/form/normal-form/groupform/index.jsx +++ b/src/menu/components/form/normal-form/groupform/index.jsx @@ -18,13 +18,22 @@ UNSAFE_componentWillMount () { const { group } = this.props + const { appType } = this.state let fields = [] - group.fields.forEach(f => { - if (f.field && ['select', 'link', 'text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') { - fields.push(f) - } - }) + if (appType === 'mob') { + group.fields.forEach(f => { + if (f.field && ['text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') { + fields.push(f) + } + }) + } else { + group.fields.forEach(f => { + if (f.field && ['select', 'link', 'text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') { + fields.push(f) + } + }) + } this.setState({ fields: fields @@ -55,7 +64,7 @@ render() { const { group, dict } = this.props const { getFieldDecorator } = this.props.form - const { fields } = this.state + const { fields, appType } = this.state const formItemLayout = { labelCol: { @@ -123,7 +132,7 @@ )} </Form.Item> </Col> - <Col span={12}> + {appType !== 'mob' ? <Col span={12}> <Form.Item label="琛ㄥ崟鎺掑垪"> {getFieldDecorator('align', { initialValue: group.setting.align || 'left_right' @@ -134,7 +143,7 @@ </Radio.Group> )} </Form.Item> - </Col> + </Col> : null} </Row> </Form> ) diff --git a/src/menu/components/form/normal-form/index.jsx b/src/menu/components/form/normal-form/index.jsx index 1610711..eae27ac 100644 --- a/src/menu/components/form/normal-form/index.jsx +++ b/src/menu/components/form/normal-form/index.jsx @@ -8,16 +8,18 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' import { getModalForm } from '@/templates/zshare/formconfig' -import ModalForm from '@/templates/zshare/modalform' +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' import './index.scss' +const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const WrapComponent = asyncIconComponent(() => import('@/menu/components/form/wrapsetting')) const CardComponent = asyncComponent(() => import('@/templates/modalconfig/dragelement')) +const MobCardComponent = asyncComponent(() => import('@/mob/components/formdragelement')) const FormTitle = asyncComponent(() => import('../dragtitle')) const GroupForm = asyncComponent(() => import('./groupform')) const FormAction = asyncComponent(() => import('../formaction')) @@ -37,6 +39,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, back: false, group: null, @@ -66,7 +69,7 @@ name: card.name, subtype: card.subtype, setting: { }, - wrap: { name: card.name, width: card.width || 24, datatype: 'static', color: '#1890ff' }, + wrap: { name: card.name, width: card.width || 24, datatype: 'static', groupLabel: 'show', color: '#1890ff' }, style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, columns: [], scripts: [], @@ -76,8 +79,8 @@ sort: 1, style: {}, fields: [], - prevButton: {label: '涓婁竴姝�', type: 'prev'}, - subButton: {label: '鎻愪氦', type: 'submit', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, + prevButton: {label: '涓婁竴姝�', type: 'prev', enable: 'true'}, + subButton: {label: '鎻愪氦', type: 'submit', enable: 'true', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, nextButton: {label: '璺宠繃', type: 'next', enable: 'false'} }] } @@ -179,33 +182,6 @@ this.props.updateConfig(card) } - /** - * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 - */ - deleteCard = (cell) => { - let card = fromJS(this.state.card).toJS() - let _this = this - - confirm({ - content: '纭畾鍒犻櫎琛ㄥ崟鍚楋紵', - onOk() { - card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) - - let uuids = [] - cell.elements && cell.elements.forEach(c => { - if (c.eleType === 'button') { - uuids.push(c.uuid) - } - }) - MKEmitter.emit('delButtons', uuids) - - _this.setState({card}) - _this.props.updateConfig(card) - }, - onCancel() {} - }) - } - changeStyle = () => { const { card } = this.state @@ -235,8 +211,8 @@ sort: card.subcards.length + 1, style: {}, fields: [], - prevButton: {label: '涓婁竴姝�', type: 'prev'}, - subButton: {label: '鎻愪氦', type: 'submit', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, + prevButton: {label: '涓婁竴姝�', type: 'prev', enable: 'true'}, + subButton: {label: '鎻愪氦', type: 'submit', enable: 'true', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, nextButton: {label: '璺宠繃', type: 'next', enable: 'false'} } @@ -362,7 +338,7 @@ }) } - handleList = (list) => { + handleList = (list, newcard) => { let group = fromJS(this.state.group).toJS() let card = fromJS(this.state.card).toJS() @@ -375,7 +351,11 @@ return item }) - this.setState({card, group}) + this.setState({card, group}, () => { + if (newcard) { + this.handleForm(newcard) + } + }) this.props.updateConfig(card) } @@ -404,9 +384,13 @@ } addForm = () => { + const { appType } = this.state let group = fromJS(this.state.group).toJS() let lastItem = group.fields[group.fields.length - 1] - let span = lastItem ? lastItem.span : 12 + let span = appType === 'mob' ? 24 : 12 + if (lastItem && lastItem.span) { + span = lastItem.span + } let newcard = { uuid: Utils.getuuid(), @@ -439,13 +423,14 @@ group.fields = group.fields.filter(item => !item.focus) this.setState({group, visible: false, editform: null}) + this.updateGroup(group) } /** * @description 琛ㄥ崟缂栬緫 */ handleForm = (_item) => { - const { card, group } = this.state + const { card, group, appType } = this.state let _form = fromJS(_item).toJS() let _inputfields = [] let _tabfields = [] @@ -457,7 +442,11 @@ let standardform = null _inputfields = group.fields.filter(item => item.type === 'text' || item.type === 'number' || item.type === 'textarea' || item.type === 'color') - _tabfields = group.fields.filter(item => _form.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) + if (appType === 'mob') { + _tabfields = group.fields.filter(item => _form.field !== item.field && item.hidden !== 'true' && ['text', 'number'].includes(item.type)) + } else { + _tabfields = group.fields.filter(item => _form.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) + } _tabfields.unshift({field: '', text: '鍘熻〃鍗�'}) let uniq = new Map() @@ -467,7 +456,8 @@ if (_form.uuid === item.uuid) { index = i } - if (item.type !== 'select' && item.type !== 'link' && item.type !== 'radio') return + + if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return if (item.field && !uniq.has(item.field)) { uniq.set(item.field, true) @@ -505,7 +495,7 @@ _form.linkSubField = _form.linkSubField.filter(item => fields.includes(item)) } - if (!_form.span && standardform && standardform.span) { + if (appType !== 'mob' && !_form.span && standardform && standardform.span) { _form.span = standardform.span _form.labelwidth = standardform.labelwidth } @@ -560,7 +550,7 @@ return } - if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { + if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { this.setState({ sqlVerifing: true }) @@ -607,6 +597,47 @@ }) } + pasteForm = (res) => { + let _config = fromJS(this.state.group).toJS() + let fieldrepet = false // 瀛楁閲嶅 + let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅 + + _config.fields.forEach(item => { + if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { + fieldrepet = true + } else if (res.label && item.label === res.label) { + labelrepet = true + } + }) + + if (fieldrepet) { + notification.warning({ + top: 92, + message: '瀛楁宸插瓨鍦紒', + duration: 10 + }) + return + } else if (labelrepet) { + notification.warning({ + top: 92, + message: '鍚嶇О宸插瓨鍦紒', + duration: 10 + }) + return + } + _config.fields.push(res) + + this.updateGroup(_config) + + this.handleForm(res) + + notification.success({ + top: 92, + message: '绮樿创鎴愬姛锛�', + duration: 2 + }) + } + clickComponent = (e) => { if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { e.stopPropagation() @@ -615,16 +646,16 @@ } render() { - const { card, dict, group } = this.state + const { card, dict, group, appType } = this.state return ( - <div className="menu-normal-form-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-normal-form-edit-box" style={resetStyle(card.style)} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞鍒嗙粍" onClick={this.addCard} type="plus" /> <WrapComponent config={card} updateConfig={this.updateComponent} /> <CopyComponent type="propcard" card={card}/> - <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} /> + <PasteComponent config={card} options={['form']} updateConfig={this.pasteForm} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <UserComponent config={card}/> <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> @@ -646,12 +677,12 @@ <Icon className="plus" title="娣诲姞琛ㄥ崟" onClick={this.addForm} type="plus" /> <FieldsComponent config={group} type="form" updatefield={this.updateGroup} /> <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} /> - <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1鍒�</Button> - <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2鍒�</Button> - <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3鍒�</Button> - <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4鍒�</Button> + {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1鍒�</Button> : null} + {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2鍒�</Button> : null} + {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3鍒�</Button> : null} + {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4鍒�</Button> : null} <div style={{clear: 'both'}}></div> - <CardComponent + {appType !== 'mob' ? <CardComponent list={group.fields} setting={group.setting} showField={this.state.showField} @@ -659,7 +690,14 @@ handleList={this.handleList} handleForm={this.handleForm} closeForm={this.closeForm} - /> + /> : <MobCardComponent + list={group.fields} + setting={group.setting} + showField={this.state.showField} + handleList={this.handleList} + handleForm={this.handleForm} + closeForm={this.closeForm} + />} <FormAction config={card} group={group} updateconfig={this.updateGroup}/> </div> : null} <Modal diff --git a/src/menu/components/form/wrapsetting/settingform/index.jsx b/src/menu/components/form/wrapsetting/settingform/index.jsx index 78d7589..ea4257c 100644 --- a/src/menu/components/form/wrapsetting/settingform/index.jsx +++ b/src/menu/components/form/wrapsetting/settingform/index.jsx @@ -149,6 +149,23 @@ </Col> <Col span={12}> <Form.Item label={ + <Tooltip placement="topLeft" title="鍔犺浇鏃舵槸鍚︽樉绀哄垎缁勫悕绉般��"> + <Icon type="question-circle" /> + 鍒嗙粍鍚嶇О + </Tooltip> + }> + {getFieldDecorator('groupLabel', { + initialValue: wrap.groupLabel || 'show' + })( + <Radio.Group> + <Radio value="show">鏄剧ず</Radio> + <Radio value="hidden">闅愯棌</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ <Tooltip placement="topLeft" title="瀹屾垚鍚庣殑棰滆壊"> <Icon type="question-circle" /> 棰滆壊鎺у埗 diff --git a/src/menu/components/form/wrapsetting/settingform/index.scss b/src/menu/components/form/wrapsetting/settingform/index.scss index a85d1ac..65d3417 100644 --- a/src/menu/components/form/wrapsetting/settingform/index.scss +++ b/src/menu/components/form/wrapsetting/settingform/index.scss @@ -9,6 +9,7 @@ width: 100%; } .color-sketch-block { - margin-top: 6px; + position: relative; + top: 6px; } } \ No newline at end of file diff --git a/src/menu/components/group/groupcomponents/card.jsx b/src/menu/components/group/groupcomponents/card.jsx index 99d3e95..ec99ddf 100644 --- a/src/menu/components/group/groupcomponents/card.jsx +++ b/src/menu/components/group/groupcomponents/card.jsx @@ -9,8 +9,15 @@ const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) +const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) +const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) +const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) +const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) +const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) +const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) +const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { const originalIndex = findCard(id).index @@ -50,6 +57,14 @@ return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard} />) } else if (card.type === 'pie') { return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'dashboard') { + return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'tree') { + return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'scatter') { + return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'form') { + return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'card' && card.subtype === 'datacard') { return (<DataCard card={card} updateConfig={updateConfig} deletecomponent={delCard} />) } else if (card.type === 'card' && card.subtype === 'propcard') { @@ -58,8 +73,14 @@ return (<TableCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'table' && card.subtype === 'normaltable') { return (<NormalTable card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'carousel' && card.subtype === 'datacard') { + return (<CarouselDataCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'carousel' && card.subtype === 'propcard') { + return (<CarouselPropCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'editor') { return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'code') { + return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } } diff --git a/src/menu/components/group/groupcomponents/index.jsx b/src/menu/components/group/groupcomponents/index.jsx index 7a8719e..ac14bfa 100644 --- a/src/menu/components/group/groupcomponents/index.jsx +++ b/src/menu/components/group/groupcomponents/index.jsx @@ -6,6 +6,7 @@ import Utils from '@/utils/utils.js' import MKEmitter from '@/utils/events.js' +import MenuUtils from '@/utils/utils-custom.js' import Card from './card' import './index.scss' @@ -38,49 +39,16 @@ const deleteCard = (id) => { const { card } = findCard(id) - let uuids = [] - if (card.action && card.action.length) { - card.action.forEach(act => { - if (!act.origin) { - uuids.push(act.uuid) - } - }) - } - if (card.type === 'card') { - card.subcards.forEach(_card => { - _card.elements && _card.elements.forEach(cell => { - if (cell.eleType === 'button') { - uuids.push(cell.uuid) - } - }) - _card.backElements && _card.backElements.forEach(cell => { - if (cell.eleType === 'button') { - uuids.push(cell.uuid) - } - }) - }) - } else if (card.type === 'table' && card.subtype === 'tablecard') { - card.subcards.forEach(_card => { - _card.elements && _card.elements.forEach(cell => { - if (cell.eleType === 'button') { - uuids.push(cell.uuid) - } - }) - }) - } else if (card.type === 'table' && card.subtype === 'normaltable') { - card.cols && card.cols.forEach(col => { - if (col.type !== 'action') return - col.elements && col.elements.forEach(cell => { - uuids.push(cell.uuid) - }) - }) - } + let uuids = MenuUtils.getDelButtonIds(card) confirm({ title: `纭畾鍒犻櫎銆�${card.name}銆嬪悧锛焋, onOk() { - MKEmitter.emit('delButtons', uuids) handleList({...config, components: cards.filter(item => item.uuid !== card.uuid)}) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -99,11 +67,20 @@ let name = '' let names = { - bar: '鏌辩姸鍥�', + bbar: '鏌辩姸鍥�', line: '鎶樼嚎鍥�', + tabs: '鏍囩缁�', pie: '楗煎浘', + search: '鎼滅储', table: '琛ㄦ牸', + group: '鍒嗙粍', editor: '瀵屾枃鏈�', + code: '鑷畾涔�', + carousel: '杞挱', + form: '琛ㄥ崟', + dashboard: '浠〃鐩�', + scatter: '鏁g偣鍥�', + tree: '鏍戝舰鍒楄〃', card: '鍗$墖' } let i = 1 diff --git a/src/menu/components/group/groupcomponents/index.scss b/src/menu/components/group/groupcomponents/index.scss index ad63183..b739fe0 100644 --- a/src/menu/components/group/groupcomponents/index.scss +++ b/src/menu/components/group/groupcomponents/index.scss @@ -1,9 +1,6 @@ .group-shell-inner { - margin: -8px; + margin: 0px; - >.ant-col { - padding: 8px; - } .anticon { cursor: unset; } diff --git a/src/menu/components/group/groupsetting/settingform/index.jsx b/src/menu/components/group/groupsetting/settingform/index.jsx index e8240e5..bfbacf7 100644 --- a/src/menu/components/group/groupsetting/settingform/index.jsx +++ b/src/menu/components/group/groupsetting/settingform/index.jsx @@ -13,6 +13,7 @@ state = { roleList: [], + appType: sessionStorage.getItem('appType'), print: this.props.setting.print || 'false' } @@ -55,7 +56,7 @@ render() { const { setting, dict } = this.props const { getFieldDecorator } = this.props.form - const { roleList, print } = this.state + const { roleList, print, appType } = this.state const formItemLayout = { labelCol: { @@ -108,7 +109,7 @@ })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} </Form.Item> </Col> - <Col span={12}> + {appType !== 'mob' ? <Col span={12}> <Form.Item label="鎵撳嵃鎸夐挳"> {getFieldDecorator('print', { initialValue: print @@ -119,8 +120,8 @@ </Radio.Group> )} </Form.Item> - </Col> - {print === 'true' ? <Col span={12}> + </Col> : null} + {print === 'true' && appType !== 'mob' ? <Col span={12}> <Form.Item label="鎵撳嵃灏哄"> {getFieldDecorator('pageSize', { initialValue: setting.pageSize || 'A4', @@ -139,7 +140,7 @@ )} </Form.Item> </Col> : null} - {print === 'true' ? <Col span={12}> + {print === 'true' && appType !== 'mob' ? <Col span={12}> <Form.Item label="鎵撳嵃甯冨眬"> {getFieldDecorator('pageLayout', { initialValue: setting.pageLayout || 'vertical', diff --git a/src/menu/components/group/normal-group/index.jsx b/src/menu/components/group/normal-group/index.jsx index c6021fa..a0ac08f 100644 --- a/src/menu/components/group/normal-group/index.jsx +++ b/src/menu/components/group/normal-group/index.jsx @@ -6,7 +6,7 @@ import MKEmitter from '@/utils/events.js' import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' import './index.scss' @@ -161,9 +161,15 @@ render() { const { group } = this.state + let _style = resetStyle(group.style) + + let paddingTop = true + if (group.style.paddingTop && parseInt(group.style.paddingTop) >= 28) { + paddingTop = false + } return ( - <div className="menu-group-edit-box" style={group.style} onClick={this.clickComponent} id={group.uuid}> + <div className={'menu-group-edit-box' + (paddingTop ? ' padding' : '')} style={_style} onClick={this.clickComponent} id={group.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <SettingComponent config={group} updateConfig={this.updateComponent} /> diff --git a/src/menu/components/group/normal-group/index.scss b/src/menu/components/group/normal-group/index.scss index 7af5313..54c6b75 100644 --- a/src/menu/components/group/normal-group/index.scss +++ b/src/menu/components/group/normal-group/index.scss @@ -26,7 +26,7 @@ color: #bcbcbc; } } -.menu-group-edit-box::before { +.menu-group-edit-box.padding:before { content: ' '; display: block; float: right; diff --git a/src/menu/components/search/main-search/dragsearch/card.jsx b/src/menu/components/search/main-search/dragsearch/card.jsx index 47a7283..9a93ae5 100644 --- a/src/menu/components/search/main-search/dragsearch/card.jsx +++ b/src/menu/components/search/main-search/dragsearch/card.jsx @@ -3,12 +3,16 @@ import { Icon, Select, DatePicker, Input, Popover, Form } from 'antd' import moment from 'moment' +import asyncComponent from '@/utils/asyncComponent' import DateGroup from '../dategroup' import './index.scss' const { MonthPicker, WeekPicker, RangePicker } = DatePicker +const { Search } = Input +const CheckCard = asyncComponent(() => import('@/templates/modalconfig/checkCard')) +const appType = sessionStorage.getItem('appType') -const Card = ({ id, card, moveCard, copyCard, findCard, editCard, delCard }) => { +const Card = ({ id, card, showField, moveCard, copyCard, findCard, editCard, delCard }) => { const originalIndex = findCard(id).index const [{ isDragging }, drag] = useDrag({ item: { type: 'search', id, originalIndex }, @@ -55,6 +59,38 @@ } } + let formItem = null + if (card.type === 'text') { + if (card.inputType === 'search') { + formItem = (<Search style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} enterButton />) + } else { + formItem = (<Input style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} />) + } + } else if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link') { + formItem = (<Select value={_defaultValue}></Select>) + } else if (card.type === 'date' && appType === 'mob') { + formItem = (<div className="mob-list-item">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD') : '璇烽�夋嫨'}<Icon type="right" /></div>) + } else if (card.type === 'datemonth' && appType === 'mob') { + formItem = (<div className="mob-list-item">{card.initval ? moment().subtract(card.initval, 'month').format('YYYY-MM') : '璇烽�夋嫨'}<Icon type="right" /></div>) + } else if (card.type === 'date') { + formItem = (<Input style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} />) + } else if (card.type === 'dateweek') { + formItem = (<WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} />) + } else if (card.type === 'datemonth') { + formItem = (<MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} />) + } else if (card.type === 'daterange') { + formItem = (<RangePicker + className="data-range" + placeholder={['BeginTime', 'EndTime']} + renderExtraFooter={() => 'extra footer'} + value={_defaultValue} + />) + } else if (card.type === 'group') { + formItem = (<DateGroup card={card} />) + } else if (card.type === 'checkcard') { + formItem = <CheckCard config={card} /> + } + return ( <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> @@ -63,38 +99,16 @@ <Icon className="close" title="delete" type="close" onClick={() => delCard(id)} /> </div> } trigger="hover"> - <div className={'page-card ' + card.labelShow} style={{ opacity: opacity}}> + <div className={'page-card ' + card.labelShow + ' ' + card.type} style={{ opacity: opacity}}> <div ref={node => drag(drop(node))}> <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 8 }}} wrapperCol = {{xs: { span: 24 }, sm: { span: 16 }}} label={card.labelShow !== 'false' ? card.label : ''} required={card.required === 'true'} + help={showField ? card.field + (card.datefield ? ', ' + card.datefield : '') : ''} > - {card.type === 'text' ? - <Input style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} /> : null - } - {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ? - <Select value={_defaultValue}></Select> : null - } - {card.type === 'date' ? - <DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null - } - {card.type === 'dateweek' ? - <WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null - } - {card.type === 'datemonth' ? - <MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null - } - {card.type === 'daterange' ? - <RangePicker - className="data-range" - placeholder={['BeginTime', 'EndTime']} - renderExtraFooter={() => 'extra footer'} - value={_defaultValue} - /> : null - } - {card.type === 'group' ? <DateGroup card={card} /> : null } + {formItem} </Form.Item> </div> </div> diff --git a/src/menu/components/search/main-search/dragsearch/index.jsx b/src/menu/components/search/main-search/dragsearch/index.jsx index 4193afa..ae6179e 100644 --- a/src/menu/components/search/main-search/dragsearch/index.jsx +++ b/src/menu/components/search/main-search/dragsearch/index.jsx @@ -7,7 +7,7 @@ import Card from './card' import './index.scss' -const Container = ({list, placeholder, handleList, handleMenu, deleteMenu }) => { +const Container = ({list, showField, placeholder, handleList, handleMenu, deleteMenu }) => { const [cards, setCards] = useState(list) const moveCard = (id, atIndex) => { const { card, index } = findCard(id) @@ -77,13 +77,27 @@ drop() {} }) + const appType = sessionStorage.getItem('appType') + return ( <div ref={drop} className="ant-row"> + {cards.length > 0 ? <Col key="preaction" className="action pre-action" span={6}> + <div className="ant-row ant-form-item" style={{lineHeight: '40px', height: '55px', marginBottom: 0}}> + <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8"> + </div> + <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16"> + <Button type="primary">鎼滅储</Button> + {appType !== 'mob' ? <Button style={{ marginLeft: 8 }}>閲嶇疆</Button> : null} + <div style={{position: 'absolute', top: 0, bottom: 0, left: 0, right: 0}}></div> + </div> + </div> + </Col> : null} {cards.map(card => ( <Col key={card.uuid} span={card.ratio || 6}> <Card id={`${card.uuid}`} card={card} + showField={showField} moveCard={moveCard} copyCard={copyCard} editCard={editCard} @@ -92,13 +106,13 @@ /> </Col> ))} - {cards.length > 0 ? <Col key="action" className="action" span={6}> + {cards.length > 0 ? <Col key="nextaction" className="action next-action" span={6}> <div className="ant-row ant-form-item" style={{lineHeight: '40px', height: '55px', marginBottom: 0}}> <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8"> </div> <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16"> <Button type="primary">鎼滅储</Button> - <Button style={{ marginLeft: 8 }}>閲嶇疆</Button> + {appType !== 'mob' ? <Button style={{ marginLeft: 8 }}>閲嶇疆</Button> : null} <div style={{position: 'absolute', top: 0, bottom: 0, left: 0, right: 0}}></div> </div> </div> diff --git a/src/menu/components/search/main-search/index.jsx b/src/menu/components/search/main-search/index.jsx index 0ab9015..2de3892 100644 --- a/src/menu/components/search/main-search/index.jsx +++ b/src/menu/components/search/main-search/index.jsx @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Modal, notification, Popover, Icon } from 'antd' +import { Modal, notification, Popover, Icon, Switch } from 'antd' import moment from 'moment' import Api from '@/api' @@ -9,9 +9,8 @@ import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' import { getSearchForm } from '@/templates/zshare/formconfig' - +import { resetStyle } from '@/utils/utils-custom.js' import asyncIconComponent from '@/utils/asyncIconComponent' -import SearchForm from '@/templates/sharecomponent/searchcomponent/searchform' import DragElement from './dragsearch' import MKEmitter from '@/utils/events.js' import './index.scss' @@ -19,6 +18,7 @@ const { confirm } = Modal const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) +const SearchForm = asyncIconComponent(() => import('@/templates/sharecomponent/searchcomponent/searchform')) const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) @@ -31,9 +31,11 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), searchlist: null, // 鎼滅储鏉′欢闆� sqlVerifing: false, // sql楠岃瘉涓� visible: false, // 妯℃�佹鎺у埗 + showField: false, editcard: null // 缂栬緫涓厓绱� } @@ -53,7 +55,7 @@ width: 24, name: card.name, subtype: card.subtype, - wrap: { name: card.name, width: 24, show: 'true', float: 'left' }, + wrap: { name: card.name, width: 24, show: this.state.appType === 'mob' ? 'false' : 'true', float: 'left' }, style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' }, @@ -120,6 +122,20 @@ component.name = component.wrap.name this.props.updateConfig(component) + } + + checkComponent = (component) => { + this.updateComponent(component) + + let _item = null + component.search.forEach(item => { + if (!_item && item.focus) { + _item = item + } + }) + if (_item) { + this.handleSearch(_item) + } } /** @@ -248,7 +264,7 @@ return } - if (['select', 'multiselect', 'link'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { + if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { this.setState({ sqlVerifing: true }) @@ -339,6 +355,14 @@ }) } + onFieldChange = () => { + const { showField } = this.state + + this.setState({ + showField: !showField + }) + } + clickComponent = (e) => { if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { e.stopPropagation() @@ -347,12 +371,15 @@ } render() { - const { dict, card, visible, sqlVerifing } = this.state + const { dict, card, visible, sqlVerifing, showField } = this.state + let _style = resetStyle(card.style) return ( - <div className={`main-search-edit-list ${card.wrap.float} ${card.wrap.show || ''}`} onClick={this.clickComponent} id={card.uuid} style={card.style}> + <div className={`main-search-edit-list ${card.wrap.float} ${card.wrap.show || ''}`} onClick={this.clickComponent} id={card.uuid} style={_style}> + <Switch checkedChildren={dict['model.switch.open']} size="small" unCheckedChildren={dict['model.switch.close']} defaultChecked={showField} onChange={this.onFieldChange} /> <DragElement list={card.search} + showField={showField} handleList={this.handleList} handleMenu={this.handleSearch} deleteMenu={this.deleteElement} @@ -363,7 +390,7 @@ <Icon className="plus" title="娣诲姞" onClick={this.addSearch} type="plus" /> <WrapComponent config={card} updateConfig={this.updateComponent}/> <CopyComponent type="mainsearch" card={card}/> - <PasteComponent config={card} options={['search', 'form']} updateConfig={this.updateComponent} /> + <PasteComponent config={card} options={['search', 'form']} updateConfig={this.checkComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> </div> diff --git a/src/menu/components/search/main-search/index.scss b/src/menu/components/search/main-search/index.scss index 6d9928c..09caf96 100644 --- a/src/menu/components/search/main-search/index.scss +++ b/src/menu/components/search/main-search/index.scss @@ -2,7 +2,17 @@ min-height: 50px; position: relative; background: #ffffff; + padding-bottom: 15px; + .ant-form-item-control { + line-height: 1.5; + } + >.ant-switch { + position: absolute; + z-index: 3; + right: 10px; + bottom: 5px; + } >.anticon-tool { position: absolute; z-index: 3; @@ -15,9 +25,16 @@ } > .ant-row { min-height: 65px; + > .ant-col { + padding: 0 12px!important; + } } - .ant-row .ant-col-6 { - padding: 0 12px!important; + >.ant-row:not(.ant-form-item) { + > .ant-col { + display: inline-block; + float: none; + vertical-align: top; + } } .ant-row.ant-form-item .ant-col { padding: 0; @@ -73,14 +90,31 @@ min-width: 100px!important; width: 100%; } + .check-card-edit-box { + margin-top: 5px!important; + } + .mob-list-item { + text-align: right; + line-height: 40px; + white-space: nowrap; + padding-right: 5px; + i { + margin-left: 5px; + } + } +} +.main-search-edit-list:not(.right) { + .pre-action { + display: none!important; + } } .main-search-edit-list.right { + .next-action { + display: none!important; + } >.ant-row { >.ant-col { float: right; - } - >.ant-col.action { - display: none; } } } diff --git a/src/menu/components/search/main-search/wrapsetting/settingform/index.jsx b/src/menu/components/search/main-search/wrapsetting/settingform/index.jsx index 9d728db..1789480 100644 --- a/src/menu/components/search/main-search/wrapsetting/settingform/index.jsx +++ b/src/menu/components/search/main-search/wrapsetting/settingform/index.jsx @@ -12,8 +12,8 @@ } state = { - float: this.props.wrap.float, - roleList: [] + roleList: [], + appType: sessionStorage.getItem('appType') } UNSAFE_componentWillMount () { @@ -55,7 +55,7 @@ render() { const { wrap } = this.props const { getFieldDecorator } = this.props.form - const { float, roleList } = this.state + const { roleList, appType } = this.state const formItemLayout = { labelCol: { @@ -108,6 +108,18 @@ })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} </Form.Item> </Col> + {appType !== 'mob' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��"> + <Icon type="question-circle" /> + 楂樼骇鎼滅储 + </Tooltip> + }> + {getFieldDecorator('advanceWidth', { + initialValue: wrap.advanceWidth || 1000 + })(<InputNumber min={10} max={3000} precision={0}/>)} + </Form.Item> + </Col> : null} <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="鍙冲榻愭椂锛岄殣钘忔悳绱㈡寜閽��"> @@ -118,14 +130,14 @@ {getFieldDecorator('float', { initialValue: wrap.float || 'left' })( - <Radio.Group onChange={(e) => this.setState({float: e.target.value})}> + <Radio.Group> <Radio value="left">宸﹀榻�</Radio> <Radio value="right">鍙冲榻�</Radio> </Radio.Group> )} </Form.Item> </Col> - {float !== 'right' ? <Col span={12}> + <Col span={12}> <Form.Item label="鎼滅储鎸夐挳"> {getFieldDecorator('show', { initialValue: wrap.show || 'true' @@ -136,7 +148,7 @@ </Radio.Group> )} </Form.Item> - </Col> : null} + </Col> <Col span={12}> <Form.Item label="榛戝悕鍗�"> {getFieldDecorator('blacklist', { diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx index f7494bf..26122e5 100644 --- a/src/menu/components/share/actioncomponent/actionform/index.jsx +++ b/src/menu/components/share/actioncomponent/actionform/index.jsx @@ -2,15 +2,17 @@ import PropTypes from 'prop-types' import { fromJS } from 'immutable' import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber, Cascader } from 'antd' -import { btnIcons, btnCustomClasses, formRule } from '@/utils/option.js' +import { btnCustomClasses, formRule } from '@/utils/option.js' +import asyncComponent from '@/utils/asyncComponent' import './index.scss' const { TextArea } = Input +const MkIcon = asyncComponent(() => import('@/components/mkIcon')) const actionTypeOptions = { - pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], - prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], - exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], + pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width', 'openmenu', 'open'], + prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width', 'openmenu', 'open'], + exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width', 'openmenu', 'open'], excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'sheet', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], excelOut: ['label', 'OpenType', 'intertype', 'show', 'icon', 'class', 'execSuccess', 'execError', 'syncComponent', 'resetPageIndex', 'pagination', 'search', 'width'], popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'popClose', 'resetPageIndex', 'width'], @@ -35,6 +37,8 @@ interType: null, // 鎺ュ彛绫诲瀷锛氬唴閮ㄣ�佸閮� funcType: null, // 鍔熻兘绫诲瀷 procMode: null, // 鍙傛暟鏂瑰紡 + pageTemplate: null, + Ot: null, requireOptions: [{ value: 'notRequired', text: this.props.dict['header.form.notRequired'] @@ -90,15 +94,19 @@ let _opentype = card.OpenType // 鎵撳紑鏂瑰紡 let _intertype = card.intertype || 'system' // 鎺ュ彛绫诲瀷 let _funcType = card.funcType || '' // 鍔熻兘鎸夐挳榛樿绫诲瀷 - let _procMode = card.procMode || 'system' // 鍙傛暟璇锋眰鏂瑰紡 + let _procMode = card.procMode || 'system' + let _Ot = card.Ot || 'requiredSgl' + let _pageTemplate = card.pageTemplate || '' - let _options = this.getOptions(_opentype, _intertype, _funcType, card.pageTemplate, _procMode) + let _options = this.getOptions(_opentype, _intertype, _funcType, _pageTemplate, _procMode, _Ot) this.setState({ + Ot: _Ot, openType: _opentype, interType: _intertype, procMode: _procMode, funcType: _funcType, + pageTemplate: _pageTemplate, formlist: this.props.formlist.map(item => { if (item.key === 'class') { item.options = btnCustomClasses @@ -107,12 +115,10 @@ } else if (item.key === 'intertype') { let iscustom = ['pop', 'prompt', 'exec'].includes(_opentype) item.options = this.state.interTypeOptions.filter(op => (iscustom || op.value !== 'custom')) - } else if (item.key === 'icon') { - item.options = btnIcons } else if (item.key === 'Ot') { if (type === 'card') { item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) - } else if (card.pageTemplate === 'pay') { // 琛岀骇鎸夐挳銆佹敮浠樻寜閽紝鍙兘閫夊崟琛� + } else if (_pageTemplate === 'pay') { // 琛岀骇鎸夐挳銆佹敮浠樻寜閽紝鍙兘閫夊崟琛� item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value)) } else if (['innerpage', 'tab', 'popview', 'excelIn'].includes(_opentype)) { item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) @@ -137,8 +143,8 @@ }) } - getOptions = (_opentype, _intertype, _funcType, _pageTemplate, _procMode) => { - let _options = fromJS(actionTypeOptions[_opentype]).toJS() // 閫夐」鍒楄〃 + getOptions = (_opentype, _intertype, _funcType, _pageTemplate, _procMode, _Ot) => { + let _options = actionTypeOptions[_opentype] ? fromJS(actionTypeOptions[_opentype]).toJS() : [] // 閫夐」鍒楄〃 if (_opentype === 'innerpage') { // 鏂伴〉闈紝鍙�夋ā鏉�(鑷畾涔夋椂锛屽彲濉叆澶栭儴閾炬帴) if (_pageTemplate === 'custom') { @@ -186,6 +192,13 @@ } } + if (_Ot !== 'notRequired' && _opentype !== 'excelOut') { + _options.push('controlField', 'controlVal') + } + if (_Ot === 'requiredSgl' && ['pop', 'prompt', 'exec'].includes(_opentype)) { + _options.push('swipe') + } + return _options } @@ -210,13 +223,12 @@ */ optionChange = (key, value) => { const { card, type } = this.props - const { openType, procMode } = this.state + const { openType, procMode, Ot, pageTemplate } = this.state if (key === 'OpenType') { - let _options = this.getOptions(value, 'system', this.state.funcType, card.pageTemplate, 'system') + let _options = this.getOptions(value, 'system', this.state.funcType, '', 'system', Ot) let _fieldval = {} - let _formlist = this.state.formlist.map(item => { item.hidden = !_options.includes(item.key) @@ -248,6 +260,8 @@ item.options = this.state.insertUpdateOptions } _fieldval.sqlType = '' + } else if (item.key === 'pageTemplate') { + item.initVal = '' } return item @@ -257,6 +271,7 @@ openType: value, intertype: 'system', procMode: 'system', + pageTemplate: '', formlist: _formlist }, () => { if (value === 'excelIn') { @@ -270,7 +285,7 @@ this.props.form.setFieldsValue(_fieldval) }) } else if (key === 'funcType') { - let _options = this.getOptions(openType, this.state.interType, value, card.pageTemplate, procMode) + let _options = this.getOptions(openType, this.state.interType, value, pageTemplate, procMode, Ot) let _fieldval = {} this.setState({ @@ -334,9 +349,10 @@ }) } else if (key === 'pageTemplate') { let _fieldval = {} - let _options = this.getOptions(openType, this.state.interType, this.state.funcType, value, procMode) + let _options = this.getOptions(openType, this.state.interType, this.state.funcType, value, procMode, Ot) this.setState({ + pageTemplate: value, formlist: this.state.formlist.map(item => { item.hidden = !_options.includes(item.key) @@ -357,7 +373,7 @@ this.props.form.setFieldsValue(_fieldval) }) } else if (key === 'intertype') { - let _options = this.getOptions(openType, value, this.state.funcType, '', procMode) + let _options = this.getOptions(openType, value, this.state.funcType, pageTemplate, procMode, Ot) this.setState({ interType: value, @@ -379,7 +395,7 @@ }) }) } else if (key === 'procMode') { - let _options = this.getOptions(openType, this.state.interType, this.state.funcType, '', value) + let _options = this.getOptions(openType, this.state.interType, this.state.funcType, pageTemplate, value, Ot) this.setState({ procMode: value, @@ -389,6 +405,16 @@ if (item.key === 'innerFunc') { item.required = true } + return item + }) + }) + } else if (key === 'Ot') { + let _options = this.getOptions(openType, this.state.interType, this.state.funcType, pageTemplate, procMode, value) + + this.setState({ + Ot: value, + formlist: this.state.formlist.map(item => { + item.hidden = !_options.includes(item.key) return item }) }) @@ -503,7 +529,7 @@ </Form.Item> </Col> ) - } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + } else if (item.type === 'select') { fields.push( <Col span={12} key={index}> <Form.Item label={item.tooltip ? @@ -523,13 +549,14 @@ })( <Select showSearch - filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0} + allowClear={item.allowClear === true} + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} onChange={(value) => {this.optionChange(item.key, value)}} getPopupContainer={() => document.getElementById('winter')} > {item.options.map((option, index) => - <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}> - {item.key === 'icon' && option.value && <Icon type={option.value} />} {option.text} + <Select.Option key={index} value={(option.value || option.field)}> + {(option.text || option.label)} </Select.Option> )} </Select> @@ -602,6 +629,24 @@ </Form.Item> </Col> ) + } else if (item.type === 'icon') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <MkIcon allowClear/> + )} + </Form.Item> + </Col> + ) } else if (item.type === 'mcascader') { fields.push( <Col span={12} key={index}> @@ -627,6 +672,7 @@ if (!err) { values.uuid = card.uuid values.verify = card.verify || null + values.modal = card.modal || null if (values.show === 'icon' && !values.icon) { notification.warning({ diff --git a/src/menu/components/share/actioncomponent/dragaction/card.jsx b/src/menu/components/share/actioncomponent/dragaction/card.jsx index 8bdf734..d0af55e 100644 --- a/src/menu/components/share/actioncomponent/dragaction/card.jsx +++ b/src/menu/components/share/actioncomponent/dragaction/card.jsx @@ -1,6 +1,7 @@ import React from 'react' import { useDrag, useDrop } from 'react-dnd' import { Icon, Button, Popover } from 'antd' +import { resetStyle } from '@/utils/utils-custom.js' import './index.scss' const Card = ({ id, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, profileCard, doubleClickCard }) => { @@ -36,12 +37,13 @@ } let btnElement = null + let _style = resetStyle(card.style) if (card.show === 'icon') { btnElement = ( <Button type="link" icon={card.icon} - style={card.btnstyle} + style={_style} onDoubleClick={() => doubleClickCard(id)} >{card.icon ? '' : card.label}</Button> ) @@ -49,7 +51,7 @@ btnElement = ( <Button type="link" - style={card.btnstyle} + style={_style} onDoubleClick={() => doubleClickCard(id)} >{card.label}{card.icon ? <Icon type={card.icon}/> : null}</Button> ) @@ -57,7 +59,7 @@ btnElement = ( <Button icon={card.icon} - style={card.btnstyle} + style={_style} onDoubleClick={() => doubleClickCard(id)} > {card.label} diff --git a/src/menu/components/share/actioncomponent/formconfig.jsx b/src/menu/components/share/actioncomponent/formconfig.jsx index 6d9fab1..b038d5c 100644 --- a/src/menu/components/share/actioncomponent/formconfig.jsx +++ b/src/menu/components/share/actioncomponent/formconfig.jsx @@ -11,7 +11,10 @@ * @param {*} usefulFields 瀛樺偍杩囩▼鍙敤鐨勫紑濮嬪瓧娈� * @param {*} type 鎸夐挳绫诲瀷锛岀敤浜庡尯鍒嗗彲閫夌殑鎵撳紑鏂瑰紡 */ -export function getActionForm (card, functip, setting, usefulFields, type, menulist = [], modules = []) { +export function getActionForm (card, functip, config, usefulFields, type, menulist = [], modules = []) { + let appType = sessionStorage.getItem('appType') + let setting = config.setting || {} + let columns = config.columns || [] let appMenus = [] let opentypes = [ { @@ -49,7 +52,7 @@ { value: 'pay', text: Formdict['model.pay'] }, { value: 'custom', text: Formdict['header.form.custom'] } ] - const isApp = sessionStorage.getItem('appType') === 'pc' + const isApp = ['pc', 'mob'].includes(appType) let funTypes = [ { value: 'changeuser', text: Formdict['header.form.func.changeuser'] }, @@ -57,9 +60,8 @@ ] if (isApp) { - opentypes = opentypes.filter(item => item.value !== 'tab') pageTemps = [ - { value: 'page', text: '鑿滃崟' }, + // { value: 'page', text: '鑿滃崟' }, { value: 'linkpage', text: '鍏宠仈鑿滃崟' }, { value: 'billprint', text: '鍗曟嵁鎵撳嵃' }, { value: 'pay', text: Formdict['model.pay'] }, @@ -79,9 +81,15 @@ } else { appMenus = [] } + + if (appType === 'mob') { + opentypes = opentypes.filter(item => ['pop', 'prompt', 'exec', 'innerpage'].includes(item.value)) + } else { + opentypes = opentypes.filter(item => item.value !== 'tab') + } } - if (type === 'chart') { + if (type === 'chart' && appType !== 'mob') { opentypes = opentypes.filter(item => item.value === 'excelIn' || item.value === 'excelOut') } @@ -107,7 +115,7 @@ type: 'radio', key: 'funcType', label: Formdict['header.form.funcType'], - initVal: card.funcType || (isApp ? 'changeuser' : ''), + initVal: card.funcType || '', required: true, options: funTypes }, @@ -193,34 +201,12 @@ options: pageTemps }, { - type: 'radio', - key: 'open', - label: '閾炬帴鏂瑰紡', - initVal: card.open || 'blank', - required: true, - forbid: !isApp, - options: [{ - value: 'blank', - text: '鏂扮獥鍙�' - }, { - value: 'self', - text: '褰撳墠绐楀彛' - }] - }, - { type: 'select', key: 'linkmenu', label: '鍏宠仈鑿滃崟', initVal: card.linkmenu || '', required: true, - options: appMenus - }, - { - type: 'select', - key: 'copyMenuId', - label: '澶嶅埗鑿滃崟', - initVal: card.copyMenuId || '', - required: false, + forbid: !isApp, options: appMenus }, { @@ -430,21 +416,39 @@ type: 'radio', key: 'show', label: "鏄剧ず涓�", - initVal: card.show || 'icon', + initVal: card.show || 'button', required: true, options: [{ value: 'icon', text: '鍥炬爣' }, { value: 'button', - text: '鎸夐挳' + text: '鍥炬爣+鏂囧瓧' }, { value: 'link', - text: '閾炬帴' + text: '鏂囧瓧+鍥炬爣' }] }, { - type: 'select', + type: 'radio', + key: 'swipe', + label: "婊戝姩鏄剧ず", + initVal: card.swipe || 'false', + required: false, + forbid: (type !== 'datacard' || appType !== 'mob'), + options: [{ + value: 'false', + text: '鍚�' + }, { + value: 'left', + text: '宸︽粦' + }, { + value: 'right', + text: '鍙虫粦' + }] + }, + { + type: 'icon', key: 'icon', label: Formdict['model.icon'], initVal: card.icon, @@ -456,6 +460,7 @@ key: 'class', label: Formdict['model.form.color'], initVal: card.class, + tooltip: '姝ら鑹蹭负鎸夐挳鍒濆鍖栭鑹诧紝鍙湪鏍峰紡璋冩暣涓慨鏀广��', required: false, options: [] }, @@ -515,6 +520,50 @@ initVal: card.syncComponent || [], required: false, options: modules + }, + { + type: 'select', + key: 'controlField', + label: '鎺у埗瀛楁', + tooltip: '绂佺敤鎺у埗瀛楁锛屽彲鏍规嵁鏁版嵁鎺у埗鎸夐挳鏄惁绂佺敤銆�', + initVal: card.controlField || '', + required: false, + allowClear: true, + options: columns + }, + { + type: 'text', + key: 'controlVal', + label: '鎺у埗鍊�', + tooltip: '褰撻�夋嫨鎺у埗瀛楁锛屼笖瀛楁鍊间笌鎺у埗鍊肩浉绛夋椂锛屾寜閽細绂佺敤锛屽涓�肩敤閫楀彿鍒嗛殧銆�', + initVal: card.controlVal || '', + required: false + }, + { + type: 'select', + key: 'openmenu', + label: '鎵撳紑鑿滃崟', + tooltip: '鎵ц鎴愬姛鍚庨渶瑕佹墦寮�鐨勮彍鍗曘��', + initVal: card.openmenu || '', + forbid: appType !== 'pc' && appType !== 'mob', + required: false, + allowClear: true, + options: appMenus + }, + { + type: 'radio', + key: 'open', + label: '鎵撳紑鏂瑰紡', + initVal: card.open || 'blank', + required: true, + forbid: appType !== 'pc', + options: [{ + value: 'blank', + text: '鏂扮獥鍙�' + }, { + value: 'self', + text: '褰撳墠绐楀彛' + }] } ] diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx index c6964ec..32764df 100644 --- a/src/menu/components/share/actioncomponent/index.jsx +++ b/src/menu/components/share/actioncomponent/index.jsx @@ -32,6 +32,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, // 缂栬緫涓厓绱� formlist: null, // 琛ㄥ崟淇℃伅 actionlist: null, // 鎸夐挳缁� @@ -43,8 +44,20 @@ * @description 鎼滅储鏉′欢鍒濆鍖� */ UNSAFE_componentWillMount () { + const { config } = this.props + + let actionlist = fromJS(config.action).toJS() || [] + this.setState({ - actionlist: fromJS(this.props.config.action).toJS() + actionlist: actionlist.map(item => { + if (item.btnstyle) { // 鍏煎 + item.style = item.style || {} + item.style = {...item.style, ...item.btnstyle} + delete item.btnstyle + } + + return item + }) }) } @@ -85,7 +98,7 @@ if (comIds[0] !== config.uuid || comIds[1] !== 'actionlist') return let _card = fromJS(card).toJS() - _card.btnstyle = style + _card.style = style let _actionlist = actionlist.map(cell => { if (cell.uuid === _card.uuid) return _card @@ -102,8 +115,8 @@ changeBtnStyle = (element) => { const { config } = this.props - let _style = element.btnstyle ? fromJS(element.btnstyle).toJS() : {} - let options = ['font', 'border', 'background', 'margin'] + let _style = element.style ? fromJS(element.style).toJS() : {} + let options = ['font', 'border', 'background', 'margin', 'padding'] this.setState({ card: element @@ -175,7 +188,7 @@ this.setState({ visible: true, card: card, - formlist: getActionForm(card, functip, config.setting, usefulFields, this.props.type, menulist, modules) + formlist: getActionForm(card, functip, config, usefulFields, this.props.type, menulist, modules) }) } @@ -221,15 +234,15 @@ } if (item.uuid === btn.uuid) { - btn.btnstyle = item.btnstyle || {} + btn.style = item.style || {} - if (btn.class !== item.class || btn.show !== item.show || !btn.btnstyle.color) { + if (btn.class !== item.class || btn.show !== item.show || !btn.style.color) { if (btn.show === 'link' || btn.show === 'icon') { - btn.btnstyle.color = color[btn.class] - btn.btnstyle.backgroundColor = 'transparent' + btn.style.color = color[btn.class] + btn.style.backgroundColor = 'transparent' } else { - btn.btnstyle.color = '#ffffff' - btn.btnstyle.backgroundColor = color[btn.class] + btn.style.color = '#ffffff' + btn.style.backgroundColor = color[btn.class] } } return btn @@ -261,7 +274,7 @@ */ deleteElement = (card) => { const { config } = this.props - const { dict } = this.state + const { dict, appType } = this.state let _this = this confirm({ @@ -270,10 +283,6 @@ let _actionlist = fromJS(_this.state.actionlist).toJS() _actionlist = _actionlist.filter(item => item.uuid !== card.uuid) - - if (!card.origin) { - MKEmitter.emit('delButtons', [card.uuid]) - } let btnlog = config.btnlog || [] if (card.OpenType === 'popview' || card.verify || card.modal) { @@ -285,6 +294,11 @@ }, () => { _this.props.updateaction({...config, action: _actionlist, btnlog}) }) + + if (card.origin || appType === 'mob') return + if (appType === 'pc' && card.OpenType !== 'popview') return + + MKEmitter.emit('delButtons', [card.uuid]) }, onCancel() {} }) @@ -354,7 +368,7 @@ let _param = { funcName: btn.innerFunc, name: _config.setting.tableName || '', - fields: btn.fields, + fields: btn.modal ? btn.modal.fields : [], menuNo: menu.MenuNo } newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config)) @@ -392,8 +406,8 @@ * @description 鎸夐挳鍙屽嚮瑙﹀彂瀛愰厤缃� */ btnDoubleClick = (element) => { - if (sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') !== 'false') return - + if (sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') === 'true') return + if (element.OpenType === 'pop' || element.OpenType === 'popview' || element.execMode === 'pop') { this.props.setSubConfig(element) } else if (element.OpenType === 'innerpage' && element.pageTemplate === 'page') { diff --git a/src/menu/components/share/actioncomponent/index.scss b/src/menu/components/share/actioncomponent/index.scss index 79f0b8a..baca0f7 100644 --- a/src/menu/components/share/actioncomponent/index.scss +++ b/src/menu/components/share/actioncomponent/index.scss @@ -23,12 +23,19 @@ } button { cursor: move; + height: auto; + min-height: 32px; .anticon-table { font-size: 10px; position: absolute; right: 1px; bottom: 0px; } + span { + font-style: inherit; + text-decoration: inherit; + font-weight: inherit; + } } } } diff --git a/src/menu/components/share/logcomponent/index.jsx b/src/menu/components/share/logcomponent/index.jsx index 570e93d..403d3bc 100644 --- a/src/menu/components/share/logcomponent/index.jsx +++ b/src/menu/components/share/logcomponent/index.jsx @@ -18,6 +18,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), visible: false, data: [], columns: [ @@ -69,11 +70,15 @@ } revert = (item) => { + const { appType } = this.state const data = this.state.data.filter(d => d.uuid !== item.uuid) this.setState({data}) - MKEmitter.emit('thawButtons', item.uuid) this.props.handlelog('revert', data, item) + + if (appType === 'mob' || (appType === 'pc' && item.OpenType !== 'popview')) return + + MKEmitter.emit('thawButtons', item.uuid) } handleDelete = (item) => { diff --git a/src/menu/components/share/markcomponent/index.jsx b/src/menu/components/share/markcomponent/index.jsx index af08d0c..4518ab6 100644 --- a/src/menu/components/share/markcomponent/index.jsx +++ b/src/menu/components/share/markcomponent/index.jsx @@ -13,6 +13,7 @@ import '@/assets/css/table.scss' const EditTable = asyncComponent(() => import('@/templates/zshare/editTable')) +const { confirm } = Modal class MarkColumn extends Component { static propTpyes = { @@ -128,8 +129,11 @@ resetMark = () => { const { marks, columns, type } = this.props let markColumns = fromJS(this.state.markColumns).toJS() + let _columns = fromJS(columns).toJS() - let options = columns.map(col => { + _columns.unshift({field: '$Index', label: '搴忓彿'}) + + let options = _columns.map(col => { return { value: col.field, label: col.label, @@ -142,7 +146,7 @@ { value: 'dynamic', label: '鍔ㄦ�佸��', - children: columns.map(cell => { + children: _columns.map(cell => { return { value: cell.field, label: cell.label @@ -250,7 +254,7 @@ } ] - if (type === 'line') { + if (type === 'line' || type === 'sequence') { signs.pop() } else if (type === 'slider') { markColumns = markColumns.filter(col => { @@ -278,9 +282,13 @@ } markSubmit = () => { - this.setState({ - visible: false - }) + let save = false + let input = document.getElementById('contrastValue') + let val = input && input.value ? input.value : '' + + if (!val) { + save = true + } let marks = this.state.marks.map(item => { if (item.signType && item.signType[0] === 'background') { @@ -295,10 +303,28 @@ item.fontColor = '' } } + if (val && item.contrastValue === val) { + save = true + } return item }) - this.props.onSubmit(marks) + if (save) { + this.setState({ + visible: false + }) + this.props.onSubmit(marks) + } else { + const _this = this + confirm({ + title: '瀛樺湪鏈繚瀛樻爣璁帮紝纭畾蹇界暐鍚楋紵', + onOk() { + _this.setState({ visible: false }) + _this.props.onSubmit(marks) + }, + onCancel() {} + }) + } } render() { diff --git a/src/menu/components/share/mobPagination/index.jsx b/src/menu/components/share/mobPagination/index.jsx new file mode 100644 index 0000000..d46c722 --- /dev/null +++ b/src/menu/components/share/mobPagination/index.jsx @@ -0,0 +1,20 @@ +import React, {Component} from 'react' +import { Icon, Pagination } from 'antd-mobile' + +import './index.scss' + +class MobPagination extends Component { + render () { + return ( + <Pagination className="mob-pagination" total={5} + current={1} + locale={{ + prevText: (<span><Icon type="left" />涓婁竴椤�</span>), + nextText: (<span>涓嬩竴椤�<Icon type="right" /></span>), + }} + /> + ) + } +} + +export default MobPagination \ No newline at end of file diff --git a/src/menu/components/share/mobPagination/index.scss b/src/menu/components/share/mobPagination/index.scss new file mode 100644 index 0000000..2537123 --- /dev/null +++ b/src/menu/components/share/mobPagination/index.scss @@ -0,0 +1,14 @@ +.mob-pagination { + .am-button::before { + display: none; + } + .am-button { + border: none; + font-size: 16px; + background: transparent; + .am-icon { + position: relative; + top: 5px; + } + } +} \ No newline at end of file diff --git a/src/menu/components/share/normalheader/index.jsx b/src/menu/components/share/normalheader/index.jsx index d5bc448..fca49ac 100644 --- a/src/menu/components/share/normalheader/index.jsx +++ b/src/menu/components/share/normalheader/index.jsx @@ -5,6 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import MKEmitter from '@/utils/events.js' +import { resetStyle } from '@/utils/utils-custom.js' import './index.scss' const SearchComponent = asyncComponent(() => import('@/menu/components/share/searchcomponent')) @@ -15,6 +16,10 @@ hideSearch: PropTypes.any, // 闅愯棌鎼滅储鏉′欢 config: PropTypes.object, // 閰嶇疆淇℃伅 updateComponent: PropTypes.func // 閰嶇疆鏇存柊 + } + + state = { + appType: sessionStorage.getItem('appType') } componentDidMount () { @@ -48,22 +53,30 @@ changeStyle = () => { const { config } = this.props + // MKEmitter.emit('changeStyle', [config.uuid, 'header'], ['font', 'height', 'border'], config.headerStyle) MKEmitter.emit('changeStyle', [config.uuid, 'header'], ['font', 'border'], config.headerStyle) } render() { const { config, defaultshow, hideSearch } = this.props + const { appType } = this.state let title = config.plot ? config.plot.title : config.wrap.title let show = true + + if (!title && appType === 'mob' && config.type === 'card' && config.subtype === 'datacard' && config.action && config.action.length) { + title = ' ' + } + if (defaultshow === 'hidden') { if (!title && (!config.search || config.search.length === 0)) { show = false } } + let _style = resetStyle(config.headerStyle) return ( - <div className={'normal-header' + (!show ? ' hidden' : '')} style={config.headerStyle}> + <div className={'normal-header' + (!show ? ' hidden' : '') + (config.wrap && config.wrap.searchable === 'true' ? ' tree-search' : '')} style={_style}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> @@ -71,6 +84,7 @@ } trigger="hover"> <span className="title">{title}</span> </Popover> + {config.wrap && config.wrap.searchable === 'true' ? <span className="ant-input-search ant-input-affix-wrapper"><span className="ant-input-suffix"><Icon type="search" /></span></span> : null} {hideSearch !== 'true' && config.search ? <SearchComponent config={config} updatesearch={this.props.updateComponent}/> : null} </div> ) diff --git a/src/menu/components/share/normalheader/index.scss b/src/menu/components/share/normalheader/index.scss index ceac790..ed805b2 100644 --- a/src/menu/components/share/normalheader/index.scss +++ b/src/menu/components/share/normalheader/index.scss @@ -3,19 +3,37 @@ height: 45px; border-bottom: 1px solid #e8e8e8; overflow: hidden; + line-height: 45px; .title { text-decoration: inherit; font-weight: inherit; font-style: inherit; float: left; - line-height: 45px; + line-height: inherit; margin-left: 10px; position: relative; z-index: 1; min-height: 45px; min-width: 30px; } + .model-custom-header-search-list { + flex: 1; + } + .ant-input-search.ant-input-affix-wrapper { + width: calc(100% - 140px); + max-width: 130px; + margin-top: 8px; + margin-right: 25px; + float: right; + height: 28px; + border-radius: 20px; + border: 1px solid #d9d9d9; + opacity: 0.6; + } +} +.normal-header:not(.tree-search) { + display: flex; } .normal-header.hidden { display: none; diff --git a/src/menu/components/share/pastecomponent/index.jsx b/src/menu/components/share/pastecomponent/index.jsx index 2d12bb3..553d24d 100644 --- a/src/menu/components/share/pastecomponent/index.jsx +++ b/src/menu/components/share/pastecomponent/index.jsx @@ -24,7 +24,7 @@ this.setState({visible: true}) } - resetconfig = (item, copyBtns) => { + resetconfig = (item, copyBtns, config) => { let _uuid = Utils.getuuid() if (item.OpenType === 'popview') { @@ -38,9 +38,33 @@ item.uuid = _uuid } - if (item.copyType === 'cardcell') { + if (item.copyType === 'cardcell' && config.subtype === 'datacard') { + item.setting = item.setting || {} + item.$cardType = 'extendCard' + item.setting.width = item.setting.width || 6 + + if (item.elements) { + item.elements = item.elements.map(cell => { + if (cell.datatype === 'dynamic') { + cell.datatype = 'static' + } + cell.uuid = Utils.getuuid() + return cell + }) + } + if (item.backElements) { + item.backElements = item.backElements.map(cell => { + if (cell.datatype === 'dynamic') { + cell.datatype = 'static' + } + cell.uuid = Utils.getuuid() + return cell + }) + } + } else if (item.copyType === 'cardcell') { item.setting = item.setting || {} item.setting.width = item.setting.width || 6 + delete item.$cardType if (item.elements) { item.elements = item.elements.map(cell => { @@ -105,12 +129,9 @@ pasteSubmit = () => { const { options } = this.props this.pasteFormRef.handleConfirm().then(res => { + if (!options.includes(res.copyType)) { - notification.warning({ - top: 92, - message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', - duration: 5 - }) + notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', duration: 5 }) return } @@ -118,7 +139,7 @@ let config = fromJS(this.props.config).toJS() let copyBtns = new Map() - res = this.resetconfig(res, copyBtns) + res = this.resetconfig(res, copyBtns, config) delete res.copyType copyBtns = [...copyBtns.values()] @@ -127,10 +148,18 @@ MKEmitter.emit('copyButtons', copyBtns) } - if (type === 'action') { + if (config.type === 'form' && config.subtype === 'stepform') { + this.props.updateConfig(res) + this.setState({visible: false}) + return + } else if (type === 'action') { config.action = config.action || [] config.action = config.action.filter(item => !item.origin) + if (['line', 'bar', 'scatter'].includes(config.type) && !['excelOut', 'excelIn'].includes(res.OpenType)) { + notification.warning({ top: 92, message: '鍥捐〃涓笉鏀寔姝ょ被鎸夐挳锛�', duration: 5 }) + return + } MKEmitter.emit('addButton', config.uuid, res) } else if (type === 'search' || type === 'form') { config.search = config.search || [] @@ -139,7 +168,7 @@ let keys = config.search.map(item => item.field.toLowerCase()) if (type === 'form') { - if (['number', 'switch', 'textarea', 'checkcard', 'fileupload', 'hint', 'color', 'funcvar'].includes(res.type)) { + if (['number', 'switch', 'textarea', 'fileupload', 'hint', 'color', 'funcvar'].includes(res.type)) { res.type = 'text' } else if (res.type === 'radio') { res.type = 'select' @@ -162,6 +191,8 @@ config.search.push(res) } else if (type === 'cardcell') { config.subcards.push(res) + } else if (type === 'menucell') { + config.subMenus.push(res) } else if (type === 'cols') { config.cols = config.cols.filter(col => !col.origin) diff --git a/src/menu/components/share/searchcomponent/dategroup/index.jsx b/src/menu/components/share/searchcomponent/dategroup/index.jsx deleted file mode 100644 index 37b8769..0000000 --- a/src/menu/components/share/searchcomponent/dategroup/index.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' -import { Tag } from 'antd' -import './index.scss' - -const { CheckableTag } = Tag - -class DateGroup extends Component { - static propTpyes = { - card: PropTypes.object // 瀛楀吀椤� - } - - render() { - const { card } = this.props - let tabs = {day: '鏃�', week: '鍛�', month: '鏈�', quarter: '瀛�', year: '骞�', customized: '鑷畾涔�'} - - return ( - <div className="model-date-group"> - {card.items.map(tab => ( - <CheckableTag - key={tab} - checked={card.initval && card.initval.includes(tab)} - > - {tabs[tab]} - </CheckableTag> - ))} - </div> - ) - } -} - -export default DateGroup \ No newline at end of file diff --git a/src/menu/components/share/searchcomponent/dategroup/index.scss b/src/menu/components/share/searchcomponent/dategroup/index.scss deleted file mode 100644 index 6782732..0000000 --- a/src/menu/components/share/searchcomponent/dategroup/index.scss +++ /dev/null @@ -1,38 +0,0 @@ -.model-date-group { - white-space: nowrap; - line-height: 40px; - position: relative; - z-index: 1; - - .ant-tag-checkable { - border-color: #d1d5d9; - border-radius: 2px; - margin-right: 2px; - padding: 2px 6px; - } - .ant-tag-checkable-checked { - border-color: #1890ff; - } -} - -@media screen and (min-width: 1440px) { - .model-date-group { - .ant-tag-checkable { - padding: 2px 7px; - } - } -} -@media screen and (min-width: 1600px) { - .model-date-group { - .ant-tag-checkable { - padding: 2px 9px; - } - } -} -@media screen and (min-width: 1920px) { - .model-date-group { - .ant-tag-checkable { - padding: 2px 11px; - } - } -} \ No newline at end of file diff --git a/src/menu/components/share/searchcomponent/dragsearch/card.jsx b/src/menu/components/share/searchcomponent/dragsearch/card.jsx index ad010e7..d0d41c2 100644 --- a/src/menu/components/share/searchcomponent/dragsearch/card.jsx +++ b/src/menu/components/share/searchcomponent/dragsearch/card.jsx @@ -3,7 +3,7 @@ import { Icon, Select, DatePicker, Input, Popover, Form } from 'antd' import moment from 'moment' -import DateGroup from '../dategroup' +import DateGroup from '@/menu/components/search/main-search/dategroup' import './index.scss' const { MonthPicker, WeekPicker, RangePicker } = DatePicker diff --git a/src/menu/components/share/searchcomponent/dragsearch/index.scss b/src/menu/components/share/searchcomponent/dragsearch/index.scss index 369ae98..e69de29 100644 --- a/src/menu/components/share/searchcomponent/dragsearch/index.scss +++ b/src/menu/components/share/searchcomponent/dragsearch/index.scss @@ -1,6 +0,0 @@ -.common-drawarea-placeholder { - width: 100%; - line-height: 65px; - text-align: center; - color: #bcbcbc; -} \ No newline at end of file diff --git a/src/menu/components/share/searchcomponent/index.jsx b/src/menu/components/share/searchcomponent/index.jsx index c123995..5aa9876 100644 --- a/src/menu/components/share/searchcomponent/index.jsx +++ b/src/menu/components/share/searchcomponent/index.jsx @@ -210,7 +210,7 @@ return } - if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { + if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { this.setState({ sqlVerifing: true }) diff --git a/src/menu/components/share/sourcecomponent/index.jsx b/src/menu/components/share/sourcecomponent/index.jsx index a5ed3e6..a5b88bc 100644 --- a/src/menu/components/share/sourcecomponent/index.jsx +++ b/src/menu/components/share/sourcecomponent/index.jsx @@ -14,12 +14,23 @@ } state = { - url: this.props.value, + url: '', visible: '' } UNSAFE_componentWillMount () { + const { value } = this.props + let val = '' + if (value) { + val = value + } else if (this.props['data-__meta']) { + val = this.props['data-__meta'].initialValue || '' + } + + this.setState({ + url: val, + }) } shouldComponentUpdate (nextProps, nextState) { @@ -67,6 +78,8 @@ width={visible !== 'system' ? 600 : 1000} closable={false} maskClosable={false} + okText="纭畾" + cancelText="鍙栨秷" onOk={this.popSubmit} onCancel={() => {this.setState({visible: ''})}} destroyOnClose diff --git a/src/menu/components/share/sourcecomponent/inputform/index.jsx b/src/menu/components/share/sourcecomponent/inputform/index.jsx index 0312024..f178a9e 100644 --- a/src/menu/components/share/sourcecomponent/inputform/index.jsx +++ b/src/menu/components/share/sourcecomponent/inputform/index.jsx @@ -27,7 +27,6 @@ originlist: [], list: [], pagelist: [], - fileList: [], searchKey: '', pageSize: 12, pageIndex: 1, @@ -79,7 +78,7 @@ let list = originlist let pagelist = list.filter((item, index) => index < this.state.pageSize) - this.setState({originlist, list, url: '', searchKey: '', pageIndex: 1, fileList: [], pagelist}) + this.setState({originlist, list, url: '', searchKey: '', pageIndex: 1, pagelist}) } changeSearch = () => { @@ -100,12 +99,8 @@ this.setState({pageIndex: page, pagelist}) } - changeFile = (vals) => { - this.setState({fileList: vals}) - - if (vals && vals[0] && vals[0].status === 'done' && vals[0].response) { - this.setState({url: vals[0].response}) - } + changeFile = (val) => { + this.setState({url: val}) } selectItem = (item) => { @@ -162,7 +157,7 @@ render () { const { type, keyword } = this.props - const { list, url, pagelist, fileList, searchKey, pageIndex, pageSize, selectId, editvisible, card } = this.state + const { list, url, pagelist, searchKey, pageIndex, pageSize, selectId, editvisible, card } = this.state return ( <div className="mk-source-pop-wrap"> @@ -170,7 +165,12 @@ <TextArea id="source-input" value={url} rows={4} onChange={this.changeValue}/> </Form.Item> : null} {keyword === 'upload' ? <Form.Item label="涓婁紶" labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={{xs: { span: 24 }, sm: { span: 20 }}}> - <FileUpload value={fileList} onChange={this.changeFile} accept={type === 'video' ? '.mp4,.webm,.ogg' : '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp'} maxFile={1} fileType={type === 'video' ? 'text' : 'picture'} /> + <FileUpload config={{ + initval: '', + suffix: type === 'video' ? '.mp4,.webm,.ogg' : '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp', + maxfile: 1, + fileType: type === 'video' ? 'text' : 'picture' + }} onChange={this.changeFile} /> </Form.Item> : null} {keyword === 'system' ? <Search value={searchKey} placeholder="" onChange={(e) => this.setState({searchKey: e.target.value})} onSearch={this.changeSearch} enterButton/> : null} diff --git a/src/menu/components/share/styleInput/index.jsx b/src/menu/components/share/styleInput/index.jsx new file mode 100644 index 0000000..361265b --- /dev/null +++ b/src/menu/components/share/styleInput/index.jsx @@ -0,0 +1,140 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Select, Input } from 'antd' + +import './index.scss' + +const { Option } = Select + +class StyleInput extends Component { + static propTpyes = { + defaultValue: PropTypes.any, + options: PropTypes.any, + value: PropTypes.any, + onChange: PropTypes.func, + } + + state = { + value: '', + unit: '', + options: null + } + + UNSAFE_componentWillMount () { + const { value, options } = this.props + + let val = value || '' + let unit = options[0] + + if (val) { + if (val.indexOf('px') > -1) { + unit = 'px' + } else if (val.indexOf('%') > -1) { + unit = '%' + } else if (val.indexOf('vw') > -1) { + unit = 'vw' + } else if (val.indexOf('vh') > -1) { + unit = 'vh' + } + } + + let _val = parseFloat(val) + + if (isNaN(_val)) { + _val = '' + } + + this.setState({value: _val, options: options, unit}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + UNSAFE_componentWillReceiveProps(nextProps) { + if (nextProps.value === '' && this.state.value !== '') { + this.setState({value: ''}) + } else if (nextProps.value && nextProps.value !== `${this.state.value}${this.state.unit}`) { + let val = nextProps.value + let unit = this.state.unit + + if (val) { + if (val.indexOf('px') > -1) { + unit = 'px' + } else if (val.indexOf('%') > -1) { + unit = '%' + } else if (val.indexOf('vw') > -1) { + unit = 'vw' + } else if (val.indexOf('vh') > -1) { + unit = 'vh' + } + } + + let _val = parseFloat(val) + + if (isNaN(_val)) { + _val = '' + } + this.setState({value: _val, unit}) + } + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + changeValue = (e) => { + const { unit } = this.state + let val = e.target.value + + if (/\d+\.$/.test(val)) { + this.setState({ + value: val + }) + return + } + let _val = parseFloat(val) + + if (isNaN(_val)) { + _val = '' + } + + this.setState({ + value: _val, + }, () => { + this.props.onChange(_val !== '' ? `${_val}${unit}` : '') + }) + } + + changeUnit = (val) => { + const { value } = this.state + + this.setState({unit: val}, () => { + this.props.onChange(value !== '' ? `${value}${val}` : '') + }) + } + + render () { + const { value, options, unit } = this.state + + return ( + <div className="style-input-wrap"> + <Input value={value} addonAfter={ + options.length > 1 ? + <Select value={unit} onChange={this.changeUnit}> + {options.map(item => <Option key={item} value={item}>{item}</Option>)} + </Select> : + <div className="single-unit">{unit}</div> + } onChange={this.changeValue}/> + </div> + ) + } +} + +export default StyleInput \ No newline at end of file diff --git a/src/menu/components/share/styleInput/index.scss b/src/menu/components/share/styleInput/index.scss new file mode 100644 index 0000000..b058a37 --- /dev/null +++ b/src/menu/components/share/styleInput/index.scss @@ -0,0 +1,11 @@ +.style-input-wrap { + line-height: 32px; + .ant-select { + width: 60px!important; + } + .single-unit { + width: 38px; + text-align: left; + color: rgba(255, 255, 255, 0.65); + } +} diff --git a/src/menu/components/share/usercomponent/index.jsx b/src/menu/components/share/usercomponent/index.jsx index 30caa31..e10fa99 100644 --- a/src/menu/components/share/usercomponent/index.jsx +++ b/src/menu/components/share/usercomponent/index.jsx @@ -163,6 +163,7 @@ func: 's_custom_components_adduptdel', c_id: config.uuid, images: Utils.getcloudurl(result.Images), + typename: sessionStorage.getItem('appType') || '', c_name: res.name, long_param: window.btoa(window.encodeURIComponent(JSON.stringify(template))), del_type: '' diff --git a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx index 46484ca..c362bd8 100644 --- a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx +++ b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx @@ -6,9 +6,9 @@ /** * @description 鑾峰彇鏄剧ず鍒楄〃鍗曢厤缃俊鎭� * @param {object} card // 鎼滅储鏉′欢瀵硅薄 - * @param {Array} menulist // 鑿滃崟鍒楄〃-鐢ㄤ簬瀛楁閫忚 */ -export function getColumnForm (card, menulist = [], fields = []) { +export function getColumnForm (card, fields = []) { + let appType = sessionStorage.getItem('appType') let roleList = sessionStorage.getItem('sysRoles') if (roleList) { try { @@ -18,6 +18,24 @@ } } else { roleList = [] + } + + let menulist = [] + + if (appType === 'pc') { + menulist = sessionStorage.getItem('appMenus') + } else if (!appType) { + menulist = sessionStorage.getItem('fstMenuList') + } + + if (menulist) { + try { + menulist = JSON.parse(menulist) + } catch { + menulist = [] + } + } else { + menulist = [] } let options = [{ @@ -41,6 +59,9 @@ }, { value: 'colspan', text: '鍚堝苟鍒�' + }, { + value: 'index', + text: '搴忓彿' }] if (!card.isSub) { @@ -243,21 +264,32 @@ key: 'postfix', label: Formdict['header.form.postfix'], initVal: card.postfix || '', - tooltipClass: 'middle', required: false, readonly: false }, { - type: 'radio', + type: 'select', key: 'lenWidRadio', label: '闀垮姣�', initVal: card.lenWidRadio || '1:1', required: true, options: [ { value: '1:1', text: '1:1' }, - { value: '3:2', text: '3:2' }, { value: '4:3', text: '4:3' }, - { value: '16:9', text: '16:9' } + { value: '3:2', text: '3:2' }, + { value: '16:9', text: '16:9' }, + { value: '2:1', text: '2:1' }, + { value: '3:1', text: '3:1' }, + { value: '4:1', text: '4:1' }, + { value: '5:1', text: '5:1' }, + { value: '6:1', text: '6:1' }, + { value: '7:1', text: '7:1' }, + { value: '8:1', text: '8:1' }, + { value: '9:1', text: '9:1' }, + { value: '10:1', text: '10:1' }, + { value: '3:4', text: '3:4' }, + { value: '2:3', text: '2:3' }, + { value: '9:16', text: '9:16' }, ] }, { @@ -309,22 +341,25 @@ }, { value: 'linkurl', text: '閾炬帴' - }] + }], + forbidden: appType === 'mob' }, { - type: 'cascader', + type: appType === 'pc' ? 'select' : 'cascader', key: 'linkmenu', label: Formdict['model.menu'], - initVal: card.linkmenu || [], + initVal: card.linkmenu || (appType === 'pc' ? '' : []), required: true, - options: menulist + options: menulist, + forbidden: appType === 'mob' }, { type: 'textarea', key: 'linkurl', label: '閾炬帴鍦板潃', initVal: card.linkurl || '', - required: true + required: true, + forbidden: appType === 'mob' }, { type: 'multiselect', @@ -332,7 +367,20 @@ label: '鍏宠仈瀛楁', initVal: card.linkfields || [], required: false, - options: fields + options: fields, + forbidden: appType === 'mob' + }, + { + type: 'radio', + key: 'open', + label: '鎵撳紑鏂瑰紡', + initVal: card.open || 'blank', + required: false, + forbid: appType !== 'pc', + options: [ + { value: 'blank', text: '鏂扮獥鍙�' }, + { value: 'self', text: '褰撳墠绐楀彛' } + ] }, { type: 'multiselect', diff --git a/src/menu/components/table/normal-table/columns/editColumn/index.jsx b/src/menu/components/table/normal-table/columns/editColumn/index.jsx index 43c63ac..d5450d3 100644 --- a/src/menu/components/table/normal-table/columns/editColumn/index.jsx +++ b/src/menu/components/table/normal-table/columns/editColumn/index.jsx @@ -16,7 +16,8 @@ picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'picSort'], colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'], custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'], - action: ['label', 'type', 'Align', 'Width'] + action: ['label', 'type', 'Align', 'Width'], + index: ['label', 'type', 'Align', 'Width'] } class MainSearch extends Component { @@ -41,24 +42,13 @@ } editColumn = (column) => { - let menulist = sessionStorage.getItem('fstMenuList') - if (menulist) { - try { - menulist = JSON.parse(menulist) - } catch { - menulist = [] - } - } else { - menulist = [] - } - - let formlist = getColumnForm(column, menulist, this.props.fields) + let formlist = getColumnForm(column, this.props.fields) let _options = fromJS(columnTypeOptions[column.type]).toJS() if (column.type === 'text' || column.type === 'number') { if (column.perspective === 'linkmenu') { - _options.push('linkmenu', 'linkfields') + _options.push('linkmenu', 'linkfields', 'open') } else if (column.perspective === 'linkurl') { - _options.push('linkurl', 'linkfields') + _options.push('linkurl', 'linkfields', 'open') } } @@ -103,13 +93,34 @@ } }) } else if (key === 'field') { - this.props.form.setFieldsValue({label: option.props.children}) - if (this.state.type === 'number') { + let values = {label: option.props.children} + if (/Decimal|int/ig.test(option.props.datatype)) { let decimal = 0 if (/Decimal/ig.test(option.props.datatype)) { decimal = +option.props.datatype.replace(/Decimal\(18,/ig, '').replace(')', '') } - this.props.form.setFieldsValue({decimal}) + values.type = 'number' + values.decimal = decimal + } else if (/nvarchar/ig.test(option.props.datatype)) { + values.type = 'text' + } + + if (values.type !== this.state.type) { + values.perspective = '' + let _options = fromJS(columnTypeOptions[values.type]).toJS() + + this.setState({ + type: values.type, + formlist: this.state.formlist.map(item => { + item.hidden = !_options.includes(item.key) + + return item + }) + }, () => { + this.props.form.setFieldsValue(values) + }) + } else { + this.props.form.setFieldsValue(values) } } else if (key === 'format' && value === 'percent') { this.props.form.setFieldsValue({postfix: '%'}) @@ -121,9 +132,9 @@ let _options = fromJS(columnTypeOptions[this.state.type]).toJS() if (value === 'linkmenu') { - _options.push('linkmenu', 'linkfields') + _options.push('linkmenu', 'linkfields', 'open') } else if (value === 'linkurl') { - _options.push('linkurl', 'linkfields') + _options.push('linkurl', 'linkfields', 'open') } this.setState({ @@ -157,7 +168,7 @@ fields.push( <Col span={12} key={index}> <Form.Item label={item.tooltip ? - <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Tooltip placement="topLeft" title={item.tooltip}> <Icon type="question-circle" /> {item.label} </Tooltip> : item.label @@ -179,7 +190,7 @@ fields.push( <Col span={12} key={index}> <Form.Item label={item.tooltip ? - <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Tooltip placement="topLeft" title={item.tooltip}> <Icon type="question-circle" /> {item.label} </Tooltip> : item.label @@ -197,7 +208,7 @@ </Form.Item> </Col> ) - } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + } else if (item.type === 'select') { fields.push( <Col span={12} key={index}> <Form.Item label={item.label}> @@ -217,8 +228,8 @@ getPopupContainer={() => document.getElementById('columnwinter')} > {item.options.map((option, index) => - <Select.Option key={`${option.value || option.field}${index}`} datatype={option.datatype || ''} value={option.value || option.field}> - {option.text || option.label} + <Select.Option key={index} datatype={option.datatype || ''} value={(option.value || option.field || option.MenuID)}> + {(option.text || option.label || option.MenuName)} </Select.Option> )} </Select> @@ -230,7 +241,7 @@ fields.push( <Col span={12} key={index}> <Form.Item label={item.tooltip ? - <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Tooltip placement="topLeft" title={item.tooltip}> <Icon type="question-circle" /> {item.label} </Tooltip> : item.label diff --git a/src/menu/components/table/normal-table/columns/index.jsx b/src/menu/components/table/normal-table/columns/index.jsx index 2e38088..c88a996 100644 --- a/src/menu/components/table/normal-table/columns/index.jsx +++ b/src/menu/components/table/normal-table/columns/index.jsx @@ -37,17 +37,19 @@ shouldComponentUpdate (nextProps, nextState) { + if (this.props.rowSpan !== nextProps.rowSpan || this.props.colSpan !== nextProps.colSpan) { + return true + } + if (!nextProps.column) return false return !is(fromJS(this.props.column), fromJS(nextProps.column)) || !is(fromJS(this.props.fields), fromJS(nextProps.fields)) || - this.props.index !== nextProps.index || - this.props.rowSpan !== nextProps.rowSpan || - this.props.colSpan !== nextProps.colSpan + this.props.index !== nextProps.index } render() { - const { connectDragSource, connectDropTarget, moveCol, addElement, updateCol, editColumn, deleteCol, index, column, align, fields, children, ...restProps } = this.props + const { connectDragSource, connectDropTarget, moveCol, addElement, updateCol, editColumn, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props if (index !== undefined) { return connectDragSource( @@ -58,6 +60,7 @@ <Icon className="plus" title="娣诲姞" type="plus" onClick={() => this.props.addElement(column)} /> : null } <Icon className="edit" title="缂栬緫" type="edit" onClick={() => this.props.editColumn(column)} /> + {column && column.type === 'custom' ? <Icon className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)} type="font-colors" /> : null} <Icon className="close" title="鍒犻櫎" type="delete" onClick={this.deleteCol} /> {column && ['text', 'number'].includes(column.type) ? <MarkColumn columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null } </div> @@ -141,7 +144,7 @@ if (column && column.type === 'custom') { return ( - <td style={{padding: 0, minWidth: column.Width || 100}} className={className}> + <td style={{padding: 0, minWidth: column.Width || 100, ...(column.style || {})}} className={className}> <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/> </td> ) @@ -154,7 +157,7 @@ } else if (column) { return ( <td style={{...style, minWidth: column.Width || 100}} className={className}> - {column.field} + {column.field || (column.type === 'index' ? '$Index' : '')} {column.marks && column.marks.length ? <Icon className="profile" type="ant-design"/> : null} </td> ) @@ -176,11 +179,13 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), tableId: '', data: [{uuid: Utils.getuuid()}], refresh: false, // 寮哄埗鍒锋柊 columns: [], fields: [], + editStyleCard: null, lineMarks: [] } @@ -341,6 +346,24 @@ this.updateCol(col) } + changeStyle = (col) => { + this.setState({ + editStyleCard: fromJS(col).toJS() + }) + + MKEmitter.emit('changeStyle', [col.uuid], ['font', 'padding'], col.style || {}) + } + + getStyle = (comIds, style) => { + const { editStyleCard } = this.state + + if (!editStyleCard || comIds[0] !== editStyleCard.uuid || comIds.length !== 1) return + + let _card = {...editStyleCard, style} + + this.updateCol(_card) + } + cancelCol = () => { const { card } = this.state @@ -361,22 +384,29 @@ } deleteCol = (col) => { + const { appType } = this.state let _columns = fromJS(this.state.columns).toJS() - _columns = this.loopDelCol(_columns, col) - if (col.type === 'action') { - let uuids = [] - col.elements && col.elements.forEach(c => { - uuids.push(c.uuid) - }) - MKEmitter.emit('delButtons', uuids) - } + _columns = this.loopDelCol(_columns, col) this.setState({ columns: _columns }, () => { this.props.updatecolumn({...this.props.config, cols: _columns}) }) + + if (col.type !== 'action' || appType === 'mob') return + + let uuids = [] + col.elements && col.elements.forEach(c => { + if (appType === 'pc' && c.OpenType !== 'popview') return + + uuids.push(c.uuid) + }) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) } updateLineMarks = (vals) => { @@ -433,6 +463,7 @@ updateCol: this.updateCol, addElement: this.addElement, editColumn: this.editColumn, + changeStyle: this.changeStyle, deleteCol: this.deleteCol, }), children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, true) : null, @@ -480,6 +511,20 @@ }) } + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + render() { const { config } = this.props const { fields, card, lineMarks, dict, tableId } = this.state @@ -494,8 +539,16 @@ const columns = this.handlecolumns(this.state.columns, fields, config) + let style = {} + if (config.wrap.color) { + style.color = config.wrap.color + } + if (config.wrap.fontSize) { + style.fontSize = config.wrap.fontSize + } + return ( - <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType}`} id={tableId}> + <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''}`} id={tableId}> <div className="col-control"> <Icon title="澶嶅埗" type="copy" onClick={this.copycolumn} /> <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} /> @@ -506,6 +559,7 @@ rowKey="uuid" size={config.wrap.size || 'middle'} rowClassName="editable-row" + style={style} bordered={config.wrap.bordered !== 'false'} components={components} dataSource={this.state.data} diff --git a/src/menu/components/table/normal-table/columns/index.scss b/src/menu/components/table/normal-table/columns/index.scss index 41f4111..5c733b7 100644 --- a/src/menu/components/table/normal-table/columns/index.scss +++ b/src/menu/components/table/normal-table/columns/index.scss @@ -1,5 +1,9 @@ .normal-table-columns { position: relative; + .ant-table { + color: inherit; + font-size: inherit; + } .ant-table-body { overflow-x: auto; tr { @@ -89,3 +93,29 @@ border-radius: 0; } } + +.normal-table-columns.ghost { + .ant-table-thead > tr { + > th { + color: inherit; + background: transparent; + .ant-table-column-sorter .ant-table-column-sorter-inner { + color: inherit; + } + } + > th:hover { + background: transparent; + } + } + .ant-table-body { + overflow-x: auto; + tr { + td { + background: transparent; + } + } + tr:hover td { + background: transparent!important; + } + } +} diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx index cd1a336..4bd4dd7 100644 --- a/src/menu/components/table/normal-table/index.jsx +++ b/src/menu/components/table/normal-table/index.jsx @@ -5,7 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' - +import { resetStyle } from '@/utils/utils-custom.js' import MKEmitter from '@/utils/events.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' @@ -35,6 +35,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, back: false } @@ -60,9 +61,9 @@ { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'date', match: 'greater' } ], action: [ - { origin: true, uuid: Utils.getuuid(), label: '娣诲姞', intertype: 'system', OpenType: 'pop', icon: 'plus', class: 'green', btnstyle: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} }, - { origin: true, uuid: Utils.getuuid(), label: '淇敼', intertype: 'system', OpenType: 'pop', icon: 'form', class: 'purple', btnstyle: {color: 'rgb(255, 255, 255)', background: 'rgb(142, 68, 173)', marginRight: '15px'} }, - { origin: true, uuid: Utils.getuuid(), label: '鍒犻櫎', intertype: 'system', OpenType: 'prompt', icon: 'delete', class: 'danger', btnstyle: {color: 'rgb(255, 255, 255)', background: 'rgb(255, 77, 79)', marginRight: '15px'} } + { origin: true, uuid: Utils.getuuid(), label: '娣诲姞', intertype: 'system', OpenType: 'pop', icon: 'plus', class: 'green', style: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} }, + { origin: true, uuid: Utils.getuuid(), label: '淇敼', intertype: 'system', OpenType: 'pop', icon: 'form', class: 'purple', style: {color: 'rgb(255, 255, 255)', background: 'rgb(142, 68, 173)', marginRight: '15px'} }, + { origin: true, uuid: Utils.getuuid(), label: '鍒犻櫎', intertype: 'system', OpenType: 'prompt', icon: 'delete', class: 'danger', style: {color: 'rgb(255, 255, 255)', background: 'rgb(255, 77, 79)', marginRight: '15px'} } ], name: card.name, subtype: card.subtype, @@ -88,8 +89,11 @@ _card.style = config.style _card.headerStyle = config.headerStyle + let oriUids = {} _card.action = config.action.map(item => { - item.uuid = Utils.getuuid() + let _uuid = Utils.getuuid() + oriUids[item.uuid] = _uuid + item.uuid = _uuid return item }) _card.search = config.search.map(item => { @@ -113,6 +117,10 @@ } return col }) + + if (_card.wrap.doubleClick) { + _card.wrap.doubleClick = oriUids[_card.wrap.doubleClick] || '' + } } this.setState({ @@ -274,7 +282,7 @@ newcard.errorTime = 10 newcard.verify = null newcard.show = 'button' - newcard.btnstyle = {marginRight: '15px'} + newcard.style = {marginRight: '15px'} // 娉ㄥ唽浜嬩欢-娣诲姞鎸夐挳 MKEmitter.emit('addButton', card.uuid, newcard) @@ -291,13 +299,13 @@ } setSubConfig = (item) => { - const { card } = this.state + const { card, appType } = this.state let btn = fromJS(item).toJS() if (btn.OpenType === 'pop' || btn.execMode === 'pop') { if (!btn.modal) { btn.modal = { - setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, + setting: { title: btn.label, width: appType === 'mob' ? 100 : 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, tables: [], groups: [], fields: [] @@ -378,15 +386,16 @@ } render() { - const { card } = this.state + const { card, appType } = this.state + let _style = resetStyle(card.style) return ( - <div className="menu-normal-table-edit-box" style={{...card.style, height: card.wrap.height}} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-normal-table-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <NormalHeader defaultshow="hidden" hideSearch="true" config={card} updateComponent={this.updateComponent}/> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞鍒�" onClick={this.addColumns} type="plus" /> - <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null} <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> <WrapComponent config={card} updateConfig={this.updateComponent} /> <CopyComponent type="normaltable" card={card}/> diff --git a/src/menu/components/table/normal-table/wrapsetting/index.jsx b/src/menu/components/table/normal-table/wrapsetting/index.jsx index be1ea1b..d5772f8 100644 --- a/src/menu/components/table/normal-table/wrapsetting/index.jsx +++ b/src/menu/components/table/normal-table/wrapsetting/index.jsx @@ -60,7 +60,7 @@ wrapClassName="popview-modal" title="琛ㄦ牸璁剧疆" visible={visible} - width={700} + width={750} maskClosable={false} okText={dict['model.submit']} onOk={this.verifySubmit} diff --git a/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx b/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx index 77ea6f9..f42f1a5 100644 --- a/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx +++ b/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx @@ -14,7 +14,8 @@ } state = { - roleList: [] + roleList: [], + appType: sessionStorage.getItem('appType') } UNSAFE_componentWillMount () { @@ -56,7 +57,7 @@ render() { const { wrap, config } = this.props const { getFieldDecorator } = this.props.form - const { roleList } = this.state + const { roleList, appType } = this.state const formItemLayout = { labelCol: { @@ -135,6 +136,18 @@ )} </Form.Item> </Col> + {appType !== 'mob' ? <Col span={12}> + <Form.Item label="鍙敹璧�"> + {getFieldDecorator('collapse', { + initialValue: wrap.collapse || 'false' + })( + <Radio.Group> + <Radio key="true" value="true"> 鏄� </Radio> + <Radio key="false" value="false"> 鍚� </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} <Col span={12}> <Form.Item label="琛ㄦ牸澶у皬"> {getFieldDecorator('size', { @@ -163,6 +176,39 @@ </Form.Item> </Col> <Col span={12}> + <Form.Item label="妯″紡"> + {getFieldDecorator('mode', { + initialValue: wrap.mode || 'default' + })( + <Radio.Group> + <Radio key="default" value="default"> 甯歌 </Radio> + <Radio key="ghost" value="ghost"> 閫忔槑 </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12} style={{height: '64px'}}> + <Form.Item label={ + <Tooltip placement="topLeft" title="榛樿鍊� rgba(0, 0, 0, 0.65)銆�"> + <Icon type="question-circle" /> + 瀛椾綋棰滆壊 + </Tooltip> + }> + {getFieldDecorator('color', { + initialValue: wrap.color || 'rgba(0, 0, 0, 0.65)' + })( + <ColorSketch /> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="瀛椾綋澶у皬"> + {getFieldDecorator('fontSize', { + initialValue: wrap.fontSize || 14 + })(<InputNumber min={14} max={30} precision={0} />)} + </Form.Item> + </Col> + <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��"> <Icon type="question-circle" /> @@ -180,7 +226,19 @@ })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} </Form.Item> </Col> - <Col span={12}> + {appType !== 'mob' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��"> + <Icon type="question-circle" /> + 楂樼骇鎼滅储 + </Tooltip> + }> + {getFieldDecorator('advanceWidth', { + initialValue: wrap.advanceWidth || 1000 + })(<InputNumber min={10} max={3000} precision={0} onPressEnter={this.handleSubmit}/>)} + </Form.Item> + </Col> : null} + {appType !== 'mob' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="鍙屽嚮琛ㄦ牸涓锛岃Е鍙戠殑鎸夐挳銆�"> <Icon type="question-circle" /> @@ -197,7 +255,7 @@ </Select> )} </Form.Item> - </Col> + </Col> : null} <Col span={12}> <Form.Item label="榛戝悕鍗�"> {getFieldDecorator('blacklist', { diff --git a/src/menu/components/tabs/antv-tabs/dragabletabs.jsx b/src/menu/components/tabs/antv-tabs/dragabletabs.jsx index 74ef3ef..b2d7ef7 100644 --- a/src/menu/components/tabs/antv-tabs/dragabletabs.jsx +++ b/src/menu/components/tabs/antv-tabs/dragabletabs.jsx @@ -1,5 +1,6 @@ import React, { Component } from 'react' import { Tabs } from 'antd' +import { is, fromJS } from 'immutable' import { DndProvider, DragSource, DropTarget } from 'react-dnd' // Drag & Drop node @@ -52,8 +53,6 @@ const newOrder = this.state.order.slice() const { children } = this.props - if (dragKey === 'tool' || hoverKey === 'tool') return - React.Children.forEach(children, c => { if (newOrder.indexOf(c.key) === -1) { newOrder.push(c.key) @@ -65,12 +64,11 @@ newOrder.splice(dragIndex, 1) newOrder.splice(hoverIndex, 0, dragKey) - let _order = newOrder.filter(item => item !== 'tool') this.setState({ - order: [..._order, 'tool'] + order: newOrder }) - this.props.tabsMove(_order) + this.props.tabsMove(newOrder) } renderTabBar = (props, DefaultTabBar) => ( @@ -83,10 +81,16 @@ </DefaultTabBar> ) + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) || + !is(fromJS(nextProps.children), fromJS(this.props.children)) || + nextProps.tabPosition !== this.props.tabPosition || + nextProps.type !== this.props.type + } + render() { const { order } = this.state const { children } = this.props - const tabs = [] React.Children.forEach(children, c => { tabs.push(c) diff --git a/src/menu/components/tabs/antv-tabs/index.jsx b/src/menu/components/tabs/antv-tabs/index.jsx index 3879bea..0cb7d7d 100644 --- a/src/menu/components/tabs/antv-tabs/index.jsx +++ b/src/menu/components/tabs/antv-tabs/index.jsx @@ -7,7 +7,8 @@ import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' import DraggableTabs from './dragabletabs' - +import { resetStyle } from '@/utils/utils-custom.js' +import MenuUtils from '@/utils/utils-custom.js' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/model.js' import enUS from '@/locales/en-US/model.js' @@ -31,6 +32,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), tabs: null, editab: null, labelvisible: false @@ -74,6 +76,7 @@ componentDidMount () { MKEmitter.addListener('submitStyle', this.getStyle) + MKEmitter.addListener('submitSearch', this.getSearch) MKEmitter.addListener('tabsChange', this.handleTabsChange) MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) } @@ -86,6 +89,7 @@ return } MKEmitter.removeListener('submitStyle', this.getStyle) + MKEmitter.removeListener('submitSearch', this.getSearch) MKEmitter.removeListener('tabsChange', this.handleTabsChange) MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) } @@ -215,6 +219,7 @@ this.tabLabelRef.handleConfirm().then(res => { editab.label = res.label editab.icon = res.icon + editab.hasSearch = res.hasSearch || '' editab.blacklist = res.blacklist if (editab.uuid) { @@ -245,12 +250,18 @@ tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid) + let uuids = MenuUtils.getDelButtonIds({...tab, type: 'group'}) + confirm({ title: '纭畾鍒犻櫎鏍囩锛�', content: '', onOk() { _this.setState({tabs}) _this.props.updateConfig(tabs) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -288,6 +299,45 @@ this.props.updateConfig(tabs) } + getSearch = (config) => { + const { tabs } = this.state + + if (tabs.uuid !== config.uuid) return + + let _tabs = fromJS(tabs).toJS() + + _tabs.subtabs = _tabs.subtabs.map(t => { + if (t.uuid === config.tabId) { + t.search = config.search + } + return t + }) + + this.setState({ + tabs: _tabs + }) + this.props.updateConfig(_tabs) + } + + setSearch = (tab) => { + const { tabs } = this.state + let card = { + uuid: tabs.uuid, + tabId: tab.uuid, + search: tab.search + } + + if (!card.search) { + card.search = { + floor: 1, + setting: { type: 'title', field: '', title: '', focus: 'true', btn: 'hidden' }, + groups: [], + fields: [] + } + } + MKEmitter.emit('changeSearch', card) + } + clickComponent = (e) => { if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { e.stopPropagation() @@ -296,9 +346,11 @@ } render() { - const { tabs, dict, labelvisible, editab } = this.state + const { tabs, dict, labelvisible, editab, appType } = this.state + let _style = resetStyle(tabs.style) + return ( - <div className="menu-tabs-edit-box" style={tabs.style} onClick={this.clickComponent} id={tabs.uuid}> + <div className={'menu-tabs-edit-box ' + tabs.setting.display} style={_style} onClick={this.clickComponent} id={tabs.uuid}> <DraggableTabs tabPosition={tabs.setting.position} type={tabs.setting.tabStyle} tabsMove={this.moveSwitch}> {tabs.subtabs.map(tab => ( <TabPane tab={ @@ -312,24 +364,23 @@ <span>{tab.icon ? <Icon type={tab.icon} /> : null}{tab.label}</span> </Popover> } key={tab.uuid}> + {appType === 'mob' && tabs.setting.position === 'top' && tabs.setting.display === 'inline-block' && tab.hasSearch === 'icon' ? + <Icon className="search-icon" onDoubleClick={() => this.setSearch(tab)} type="search" /> : null} <TabComponents config={tab} handleList={this.updateTabComponent} deleteCard={this.deleteCard} /> </TabPane> ))} - <TabPane disabled tab={ - <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ - <div className="mk-popover-control"> - <Icon className="plus" title="娣诲姞鏍囩" type="plus" onClick={this.tabAdd} /> - <SettingComponent config={tabs} updateConfig={this.updateComponent} /> - <CopyComponent type="tabs" card={tabs}/> - <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> - <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} /> - </div> - } trigger="hover"> - <Icon type="tool" /> - </Popover> - } key="tool"> - </TabPane> </DraggableTabs> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="plus" title="娣诲姞鏍囩" type="plus" onClick={this.tabAdd} /> + <SettingComponent config={tabs} updateConfig={this.updateComponent} /> + <CopyComponent type="tabs" card={tabs}/> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} /> + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> <Modal wrapClassName="popview-modal" title={'鏍囩缂栬緫'} @@ -344,6 +395,7 @@ <TabLabelComponent dict={dict} tab={editab} + setting={tabs.setting} inputSubmit={this.tabLabelSubmit} wrappedComponentRef={(inst) => this.tabLabelRef = inst} /> diff --git a/src/menu/components/tabs/antv-tabs/index.scss b/src/menu/components/tabs/antv-tabs/index.scss index ceee292..7ad16c9 100644 --- a/src/menu/components/tabs/antv-tabs/index.scss +++ b/src/menu/components/tabs/antv-tabs/index.scss @@ -6,6 +6,23 @@ background-repeat: no-repeat; background-size: cover; + >.anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + + .ant-tabs.ant-tabs-left, .ant-tabs.ant-tabs-bottom { + .tab-shell-inner { + padding-top: 25px; + } + } + .ant-tabs-tabpane-active { min-height: 200px; } @@ -20,41 +37,25 @@ } .ant-tabs .ant-tabs-left-bar .ant-tabs-tab { - padding: 0px; text-align: right; > span { display: inline-block; padding: 8px 24px; } - .anticon-tool { - padding: 8px 24px; - } } .ant-tabs .ant-tabs-right-bar .ant-tabs-tab { - padding: 0px; text-align: left; > span { display: inline-block; padding: 8px 24px; } - .anticon-tool { - padding: 8px 24px; - } } .ant-tabs-tab { - padding: 0px; + padding: 0px!important; text-align: center; > span { display: inline-block; padding: 12px 16px; - } - .anticon-tool { - color: rgba(0, 0, 0, 0.65); - font-size: 16px; - padding: 12px 16px; - margin-right: 0px; - min-width: 100%; - cursor: pointer; } } .ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-ink-bar { @@ -66,9 +67,6 @@ > span { padding: 0px 16px; } - .anticon-tool { - padding: 0px 16px; - } } .ant-tabs-tab-active { padding-left: 0px!important; @@ -78,24 +76,47 @@ .ant-tabs-card-bar { .ant-tabs-tab { - padding: 0px; > span { display: inline-block; padding: 0px 16px; } } - .ant-tabs-tab:last-child { - padding: 0px; - border: 0px; - background: transparent; - .anticon-tool { - padding: 12px 16px; - } - } } + } + .search-icon { + position: absolute; + top: 10px; + right: 40px; + font-size: 18px; + cursor: pointer; + padding: 3px; } } .menu-tabs-edit-box:hover { z-index: 1; box-shadow: 0px 0px 4px #1890ff; } + +.mob-shell { + .menu-tabs-edit-box.flex { + >.ant-tabs.ant-tabs-top, >.ant-tabs.ant-tabs-bottom { + >.ant-tabs-bar { + >.ant-tabs-nav-container { + >.ant-tabs-nav-wrap { + >.ant-tabs-nav-scroll { + >.ant-tabs-nav { + display: block; + >div { + display: flex; + >.ant-tabs-tab { + flex: 1; + } + } + } + } + } + } + } + } + } +} diff --git a/src/menu/components/tabs/tabcomponents/card.jsx b/src/menu/components/tabs/tabcomponents/card.jsx index ca9c1fe..32d1080 100644 --- a/src/menu/components/tabs/tabcomponents/card.jsx +++ b/src/menu/components/tabs/tabcomponents/card.jsx @@ -7,15 +7,20 @@ const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar')) const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search')) const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie')) +const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) +const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs')) const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) +const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) +const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) +const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { const originalIndex = findCard(id).index @@ -57,6 +62,14 @@ return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'pie') { return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'dashboard') { + return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'tree') { + return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'scatter') { + return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'form') { + return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'tabs') { return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard} />) } else if (card.type === 'card' && card.subtype === 'datacard') { @@ -75,6 +88,8 @@ return (<NormalGroup group={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'editor') { return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'code') { + return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } } diff --git a/src/menu/components/tabs/tabcomponents/index.jsx b/src/menu/components/tabs/tabcomponents/index.jsx index 7a913bc..412a698 100644 --- a/src/menu/components/tabs/tabcomponents/index.jsx +++ b/src/menu/components/tabs/tabcomponents/index.jsx @@ -54,8 +54,11 @@ title: `纭畾鍒犻櫎銆�${card.name}銆嬪悧锛焋, content: hasComponent ? '褰撳墠缁勪欢涓惈鏈夊瓙缁勪欢锛�' : '', onOk() { - MKEmitter.emit('delButtons', uuids) handleList({...config, components: cards.filter(item => item.uuid !== card.uuid)}) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -89,7 +92,7 @@ let name = '' let names = { - bar: '鏌辩姸鍥�', + bbar: '鏌辩姸鍥�', line: '鎶樼嚎鍥�', tabs: '鏍囩缁�', pie: '楗煎浘', @@ -97,7 +100,12 @@ table: '琛ㄦ牸', group: '鍒嗙粍', editor: '瀵屾枃鏈�', + code: '鑷畾涔�', carousel: '杞挱', + form: '琛ㄥ崟', + dashboard: '浠〃鐩�', + scatter: '鏁g偣鍥�', + tree: '鏍戝舰鍒楄〃', card: '鍗$墖' } let i = 1 diff --git a/src/menu/components/tabs/tabcomponents/index.scss b/src/menu/components/tabs/tabcomponents/index.scss index b65895c..f21f784 100644 --- a/src/menu/components/tabs/tabcomponents/index.scss +++ b/src/menu/components/tabs/tabcomponents/index.scss @@ -1,9 +1,6 @@ .tab-shell-inner { - margin: -8px; + margin: 0px; - >.ant-col { - padding: 8px; - } .anticon { cursor: unset; } diff --git a/src/menu/components/tabs/tablabelform/index.jsx b/src/menu/components/tabs/tablabelform/index.jsx index 784a9f9..335976a 100644 --- a/src/menu/components/tabs/tablabelform/index.jsx +++ b/src/menu/components/tabs/tablabelform/index.jsx @@ -1,18 +1,18 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Input, Icon, Select } from 'antd' +import { Form, Row, Col, Input, Icon, Select, Radio } from 'antd' -// import { formRule } from '@/utils/option.js' import './index.scss' class SettingForm extends Component { static propTpyes = { - dict: PropTypes.object, // 瀛楀吀椤� - tab: PropTypes.object, // 鏁版嵁婧愰厤缃� - inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + dict: PropTypes.object, + setting: PropTypes.object, + tab: PropTypes.object, + inputSubmit: PropTypes.func } - state = {roleList: []} + state = {roleList: [], appType: sessionStorage.getItem('appType')} UNSAFE_componentWillMount () { let roleList = sessionStorage.getItem('sysRoles') @@ -51,9 +51,9 @@ } render() { - const { tab } = this.props + const { tab, setting } = this.props const { getFieldDecorator } = this.props.form - const { roleList } = this.state + const { roleList, appType } = this.state const formItemLayout = { labelCol: { @@ -97,6 +97,18 @@ )} </Form.Item> </Col> + {appType === 'mob' && setting.position === 'top' && setting.display === 'inline-block' ? <Col span={24}> + <Form.Item label="鎼滅储"> + {getFieldDecorator('hasSearch', { + initialValue: tab.hasSearch || 'false' + })( + <Radio.Group> + <Radio value="false">鏃�</Radio> + <Radio value="icon">鏈�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} <Col span={24}> <Form.Item label="榛戝悕鍗�"> {getFieldDecorator('blacklist', { diff --git a/src/menu/components/tabs/tabsetting/settingform/index.jsx b/src/menu/components/tabs/tabsetting/settingform/index.jsx index 6362d5a..a8190c2 100644 --- a/src/menu/components/tabs/tabsetting/settingform/index.jsx +++ b/src/menu/components/tabs/tabsetting/settingform/index.jsx @@ -12,6 +12,8 @@ } state = { + appType: sessionStorage.getItem('appType'), + position: this.props.setting.position, roleList: [] } @@ -54,7 +56,7 @@ render() { const { setting } = this.props const { getFieldDecorator } = this.props.form - const { roleList } = this.state + const { roleList, appType, position } = this.state const formItemLayout = { labelCol: { @@ -112,7 +114,7 @@ {getFieldDecorator('position', { initialValue: setting.position || 'top' })( - <Select> + <Select onChange={(val) => this.setState({position: val})}> <Select.Option key="top" value="top"> top </Select.Option> <Select.Option key="bottom" value="bottom"> bottom </Select.Option> <Select.Option key="left" value="left"> left </Select.Option> @@ -121,7 +123,7 @@ )} </Form.Item> </Col> - <Col span={12}> + {appType !== 'mob' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="鏍囩浣嶇疆涓簍op鏃舵湁鏁堬紝榛樿鍊间负line銆�"> <Icon type="question-circle" /> @@ -137,7 +139,19 @@ </Radio.Group> )} </Form.Item> - </Col> + </Col> : null} + {appType === 'mob' && (position === 'top' || position === 'bottom') ? <Col span={12}> + <Form.Item label="鏍囩鏄剧ず"> + {getFieldDecorator('display', { + initialValue: setting.display || 'flex' + })( + <Radio.Group> + <Radio value="flex">寮规�у竷灞�</Radio> + <Radio value="inline-block">瀹氬</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} <Col span={12}> <Form.Item label="榛戝悕鍗�"> {getFieldDecorator('blacklist', { diff --git a/src/menu/components/tree/antd-tree/index.jsx b/src/menu/components/tree/antd-tree/index.jsx new file mode 100644 index 0000000..18f83e7 --- /dev/null +++ b/src/menu/components/tree/antd-tree/index.jsx @@ -0,0 +1,188 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover, Tree } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' +import { resetStyle } from '@/utils/utils-custom.js' +import MKEmitter from '@/utils/events.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' + +import './index.scss' + +const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) +const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) +const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) +const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) + +const { TreeNode } = Tree + +class AntdTree extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + back: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + tabId: card.tabId || '', + parentId: card.parentId || '', + dataName: card.dataName || '', + format: 'array', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 + pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� + switchable: true, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + width: card.width || 12, + name: card.name, + subtype: card.subtype, + setting: { interType: 'system' }, + wrap: { name: card.name, title: '', width: card.width || 12, showIcon: 'false', showLine: 'false', searchable: 'false' }, + style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' }, + headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, + columns: [], + scripts: [], + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.wrap.name = card.name + _card.style = config.style + _card.headerStyle = config.headerStyle + } + + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (component) => { + this.setState({ + card: component + }) + + component.width = component.wrap.width + component.name = component.wrap.name + + this.props.updateConfig(component) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds[0] !== card.uuid || comIds.length !== 1) return + + let _card = {...card, style} + + this.setState({ + card: _card + }) + + this.props.updateConfig(_card) + } + + /** + * @description 鏇存柊鎼滅储鏉′欢閰嶇疆淇℃伅 + */ + updateconfig = (config) => { + this.setState({ + card: config + }) + this.props.updateConfig(config) + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + render() { + const { card } = this.state + let _style = resetStyle(card.style) + + return ( + <div className="menu-editor-sand-box" style={_style} onClick={this.clickComponent} id={card.uuid}> + <NormalHeader config={card} updateComponent={this.updateComponent}/> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="normaltable" card={card}/> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <ClockComponent config={card} updateConfig={this.updateComponent}/> + <UserComponent config={card}/> + <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + <SettingComponent config={card} updateConfig={this.updateComponent} /> + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + <div className="tree-box"> + <Tree defaultExpandAll={true} blockNode showIcon={card.wrap.showIcon === 'true'} showLine={card.wrap.showLine === 'true'} > + <TreeNode icon={<Icon type="folder-open" />} title="parent 0" key="0-0"> + <TreeNode icon={<Icon type="file" />} title="leaf 0-0" key="0-0-0" isLeaf /> + <TreeNode icon={<Icon type="file" />} title="leaf 0-1" key="0-0-1" isLeaf /> + </TreeNode> + <TreeNode icon={<Icon type="folder-open" />} title="parent 1" key="0-1"> + <TreeNode icon={<Icon type="file" />} title="leaf 1-0" key="0-1-0" isLeaf /> + <TreeNode icon={<Icon type="file" />} title="leaf 1-1" key="0-1-1" isLeaf /> + </TreeNode> + </Tree> + </div> + </div> + ) + } +} + +export default AntdTree \ No newline at end of file diff --git a/src/menu/components/tree/antd-tree/index.scss b/src/menu/components/tree/antd-tree/index.scss new file mode 100644 index 0000000..c096ca8 --- /dev/null +++ b/src/menu/components/tree/antd-tree/index.scss @@ -0,0 +1,36 @@ +.menu-editor-sand-box { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 30px; + + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + .empty-content { + text-align: center; + font-size: 30px; + margin: 0; + line-height: 90px; + color: #bcbcbc; + } +} +.menu-editor-sand-box::after { + display: block; + content: ' '; + clear: both; +} +.menu-editor-sand-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/menu/components/tree/antd-tree/wrapsetting/index.jsx b/src/menu/components/tree/antd-tree/wrapsetting/index.jsx new file mode 100644 index 0000000..595cb9e --- /dev/null +++ b/src/menu/components/tree/antd-tree/wrapsetting/index.jsx @@ -0,0 +1,83 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import './index.scss' + +class DataSource extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + wrap: null + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({wrap: fromJS(config.wrap).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + editDataSource = () => { + this.setState({ + visible: true + }) + } + + verifySubmit = () => { + const { config } = this.props + + this.verifyRef.handleConfirm().then(res => { + + this.setState({ + wrap: res, + visible: false + }) + this.props.updateConfig({...config, wrap: res}) + }) + } + + render () { + const { config } = this.props + const { visible, dict, wrap } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="edit" onClick={() => this.editDataSource()} /> + <Modal + wrapClassName="popview-modal" + title="鍩烘湰璁剧疆" + visible={visible} + width={700} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + wrap={wrap} + config={config} + inputSubmit={this.verifySubmit} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default DataSource \ No newline at end of file diff --git a/src/menu/components/tree/antd-tree/wrapsetting/index.scss b/src/menu/components/tree/antd-tree/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/menu/components/tree/antd-tree/wrapsetting/index.scss @@ -0,0 +1,7 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/menu/components/tree/antd-tree/wrapsetting/settingform/index.jsx b/src/menu/components/tree/antd-tree/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..d1a1479 --- /dev/null +++ b/src/menu/components/tree/antd-tree/wrapsetting/settingform/index.jsx @@ -0,0 +1,262 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + config: PropTypes.object, // 鍗$墖琛屼俊鎭� + wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + roleList: [], + } + + UNSAFE_componentWillMount () { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + this.setState({roleList}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { wrap, config } = this.props + const { getFieldDecorator } = this.props.form + const { roleList } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="鏍囬"> + {getFieldDecorator('title', { + initialValue: wrap.title || '' + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�"> + <Icon type="question-circle" /> + 缁勪欢鍚嶇О + </Tooltip> + }> + {getFieldDecorator('name', { + initialValue: wrap.name, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏁版嵁鍊煎瓧娈点��"> + <Icon type="question-circle" /> + Value + </Tooltip> + }> + {getFieldDecorator('valueField', { + initialValue: wrap.valueField || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + 'Value瀛楁!' + } + ] + })( + <Select> + {config.columns.map(option => + <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏄剧ず鏂囧瓧瀛楁銆�"> + <Icon type="question-circle" /> + Label + </Tooltip> + }> + {getFieldDecorator('labelField', { + initialValue: wrap.labelField || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + 'Label瀛楁!' + } + ] + })( + <Select> + {config.columns.map(option => + <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐖剁骇瀛楁銆�"> + <Icon type="question-circle" /> + Parent + </Tooltip> + }> + {getFieldDecorator('parentField', { + initialValue: wrap.parentField || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + 'Parent瀛楁!' + } + ] + })( + <Select> + {config.columns.map(option => + <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title={'鐖剁骇瀛楁鍊间笌椤剁骇鏍囪瘑鐩稿悓鏃讹紝瑙嗕负椤剁骇鑺傜偣銆�'}> + <Icon type="question-circle" /> + 椤剁骇鏍囪瘑 + </Tooltip> + }> + {getFieldDecorator('mark', { + initialValue: wrap.mark || '' + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��"> + <Icon type="question-circle" /> + 瀹藉害 + </Tooltip> + }> + {getFieldDecorator('width', { + initialValue: wrap.width || 24, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '瀹藉害!' + } + ] + })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鍥炬爣"> + {getFieldDecorator('showIcon', { + initialValue: wrap.showIcon || 'false' + })( + <Radio.Group> + <Radio value="true">鏄剧ず</Radio> + <Radio value="false">闅愯棌</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鍒嗗壊绾�"> + {getFieldDecorator('showLine', { + initialValue: wrap.showLine || 'false' + })( + <Radio.Group> + <Radio value="true">鏄剧ず</Radio> + <Radio value="false">闅愯棌</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="杩囨护鏉′欢"> + {getFieldDecorator('searchable', { + initialValue: wrap.searchable || 'false' + })( + <Radio.Group> + <Radio value="true">鏄剧ず</Radio> + <Radio value="false">闅愯棌</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="榛戝悕鍗�"> + {getFieldDecorator('blacklist', { + initialValue: wrap.blacklist || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {roleList.map(option => + <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/menu/components/tree/antd-tree/wrapsetting/settingform/index.scss b/src/menu/components/tree/antd-tree/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..c530b18 --- /dev/null +++ b/src/menu/components/tree/antd-tree/wrapsetting/settingform/index.scss @@ -0,0 +1,15 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } + .color-sketch-block { + position: relative; + top: 7px; + } +} \ No newline at end of file diff --git a/src/menu/datasource/index.jsx b/src/menu/datasource/index.jsx index 9732b5a..8115d65 100644 --- a/src/menu/datasource/index.jsx +++ b/src/menu/datasource/index.jsx @@ -16,6 +16,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), sourcelist: [], mainSearch: [], visible: false, @@ -35,42 +36,129 @@ editDataSource = () => { const { config } = this.props + const { appType } = this.state let search = [] - let parents = [] - let _conf = config - let getParents = (box) => { - box.components.forEach(item => { - if (item.type !== 'tabs') return + let menu = fromJS(window.GLOB.customMenu).toJS() - item.subtabs.forEach(tab => { - if (_conf.parentId === tab.parentId && _conf.tabId === tab.uuid) { - parents.unshift(tab) - _conf = item - - if (_conf.parentId && _conf.tabId) { - getParents(tab) - } - } else { - getParents(tab) - } - }) - }) - } - - if (config.parentId && config.tabId) { - getParents(window.GLOB.customMenu) - } - - parents.unshift(window.GLOB.customMenu) - - parents.forEach(parent => { - parent.components.forEach(item => { - if (item.type === 'search') { - search = item.search + if (appType === 'mob') { + let ms = null + menu.components.forEach(item => { + if (item.type === 'topbar' && (item.wrap.type === 'search' || (item.wrap.type === 'navbar' && item.wrap.search === 'true'))) { + ms = item.search } }) - }) + + if (config.floor > 1) { + let _search = null + let filterComponent = (box) => { + box.components.forEach(item => { + if (_search) return + + if (item.uuid === config.uuid) { + _search = box.slist.pop() + } else if (item.type === 'group') { + item.components.forEach(m => { + if (m.uuid !== config.uuid) return + _search = box.slist.pop() + }) + } else if (item.type === 'tabs') { + let able = item.setting.display === 'inline-block' && item.setting.position === 'top' + item.subtabs.forEach(tab => { + if (able && tab.hasSearch === 'icon' && tab.search) { + tab.slist = [...box.slist, tab.search] + } else { + tab.slist = [...box.slist] + } + + filterComponent(tab) + }) + } + }) + } + menu.slist = [] + filterComponent(menu) + + if (_search) { + ms = _search + } + } + + if (ms) { + if (ms.setting.type === 'search') { + search.push({ + type: 'text', + label: '鎼滅储鏍�', + field: ms.setting.field, + match: ms.setting.match, + required: ms.setting.required, + value: ms.setting.initval || '' + }) + } + ms.fields.forEach(item => { + if (item.type === 'range') { + item.initval = `${item.minValue},${item.maxValue}` + } + search.push(item) + }) + + ms.groups.forEach(group => { + if (group.setting.type === 'search') { + search.push({ + type: 'text', + label: group.wrap.name, + field: group.setting.field, + match: group.setting.match, + required: group.setting.required, + value: group.setting.initval || '' + }) + } + + group.fields.forEach(item => { + if (item.type === 'range') { + item.initval = `${item.minValue},${item.maxValue}` + } + search.push(item) + }) + }) + } + } else { + if (config.floor > 1) { + let _search = null + let filterComponent = (box) => { + box.components.forEach(item => { + if (_search) return + + if (item.type === 'search') { + box.slist = [...box.slist, item.search] + } else if (item.uuid === config.uuid) { + _search = box.slist.pop() + } else if (item.type === 'group') { + item.components.forEach(m => { + if (m.uuid !== config.uuid) return + _search = box.slist.pop() + }) + } else if (item.type === 'tabs') { + item.subtabs.forEach(tab => { + tab.slist = [...box.slist] + filterComponent(tab) + }) + } + }) + } + menu.slist = [] + filterComponent(menu) + + if (_search) { + search = _search + } + } else { + menu.components.forEach(item => { + if (item.type !== 'search') return + search = item.search + }) + } + } this.setState({ visible: true, @@ -100,7 +188,19 @@ return item }) } - + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig') + if (res.setting.dataresource) { + res.setting.dataresource = res.setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + } + res.scripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + }) + } + this.setState({loading: false, visible: false}) this.props.updateConfig({...config, ...res}) }, () => { diff --git a/src/menu/datasource/verifycard/customscript/index.jsx b/src/menu/datasource/verifycard/customscript/index.jsx index 24e92d2..27fb640 100644 --- a/src/menu/datasource/verifycard/customscript/index.jsx +++ b/src/menu/datasource/verifycard/customscript/index.jsx @@ -32,9 +32,7 @@ if (!item.field) return if (item.type === 'group') { - if (item.transfer === 'true') { - _usefulFields.push(item.field) - } + _usefulFields.push(item.field) _usefulFields.push(item.datefield) _usefulFields.push(item.datefield + '1') } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { @@ -60,9 +58,7 @@ if (!item.field) return if (item.type === 'group') { - if (item.transfer === 'true') { - _usefulFields.push(item.field) - } + _usefulFields.push(item.field) _usefulFields.push(item.datefield) _usefulFields.push(item.datefield + '1') } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { @@ -220,7 +216,7 @@ </Col> <Col span={24} className="sqlfield"> <Form.Item label={'鍙敤瀛楁'}> - id, bid, loginuid, sessionuid, userid, username, fullname, login_city, appkey, time_id, orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''} + id, bid, loginuid, sessionuid, userid, username, fullname, login_city, appkey, time_id, orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{window.GLOB.urlFields && window.GLOB.urlFields.length > 0 ? ', ' + window.GLOB.urlFields.join(', ') : ''} </Form.Item> </Col> <Col span={10} style={{width: '43%'}}> diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx index 18aba05..2e247f9 100644 --- a/src/menu/datasource/verifycard/index.jsx +++ b/src/menu/datasource/verifycard/index.jsx @@ -1,7 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { fromJS } from 'immutable' -import { Form, Tabs, Popconfirm, Icon, notification, Modal, Typography, Spin } from 'antd' +import { Form, Tabs, Popconfirm, Icon, notification, Modal, Typography, Spin, message } from 'antd' import moment from 'moment' import Api from '@/api' @@ -34,6 +34,7 @@ initsql: '', // sql楠岃瘉鏃跺彉閲忓0鏄庡強璧嬪�� usefulfields: '', defaultsql: '', // 榛樿Sql + defaultSearch: '', systemScripts: [], colColumns: [ { @@ -49,6 +50,7 @@ inputType: 'input', editable: true, unique: true, + copy: true, width: '28%' }, { @@ -193,12 +195,32 @@ getcomponentmarks(menu, config) let _setting = fromJS(config.setting).toJS() + let scripts = fromJS(config.scripts).toJS() + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig') + if (_setting.dataresource) { + _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`) + } + scripts && scripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + }) + } + + let _search = this.formatSearch(search) + _search = Utils.joinMainSearchkey(_search) + + _search = _search.replace(/@\$@/ig, '') + _search = _search ? 'where ' + _search : '' this.setState({ + scripts, columns: fromJS(config.columns).toJS(), setting: _setting, - scripts: fromJS(config.scripts).toJS(), searches: search, + defaultSearch: _search, varMarks: Marks }) @@ -372,8 +394,15 @@ return } + let _search = this.formatSearch(search) + _search = Utils.joinMainSearchkey(_search) + + _search = _search.replace(/@\$@/ig, '') + _search = _search ? 'where ' + _search : '' + this.setState({ searches: search, + defaultSearch: _search, setting: res }, () => { this.sqlverify(() => { // 楠岃瘉鎴愬姛 @@ -427,15 +456,9 @@ } getdefaultSql = () => { - const { columns, searches, setting } = this.state + const { columns, setting, defaultSearch } = this.state let defaultsql = '' let arr_field = columns.map(col => col.field).join(',') - - let _search = this.formatSearch(searches) - _search = Utils.joinMainSearchkey(_search) - - _search = _search.replace(/@\$@/ig, '') - _search = _search ? 'where ' + _search : '' if (setting.dataresource) { let _dataresource = setting.dataresource @@ -444,7 +467,7 @@ _dataresource = '(' + _dataresource + ') tb' } - defaultsql = `select top @pageSize@ ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${_dataresource} ${_search}) tmptable where rows > (@pageSize@ * (@pageIndex@ - 1)) order by tmptable.rows` + defaultsql = `select top @pageSize@ ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${_dataresource} ${defaultSearch}) tmptable where rows > (@pageSize@ * (@pageIndex@ - 1)) order by tmptable.rows` } this.setState({defaultsql}) @@ -455,7 +478,7 @@ * @param {Array} searches 鎼滅储鏉′欢鏁扮粍 */ formatSearch (searches) { - if (!searches || searches.length === 0) return [] + if (!searches) return [] let newsearches = [] searches.forEach(search => { @@ -470,37 +493,32 @@ required: search.required === 'true' } if (item.type === 'group') { - let copy = fromJS(item).toJS() - copy.key = search.datefield + item.key = search.datefield + item.type = 'daterange' + item.match = 'between' + item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') - item.value = search.initval && search.initval[0] ? search.initval[0] : '@$@' - item.match = '=' - - copy.type = 'daterange' - copy.match = 'between' - copy.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')] - - if (search.transfer === 'true') { - newsearches.push(item) - } - newsearches.push(copy) + newsearches.push(item) return } else if (item.type === 'date') { item.value = moment().format('YYYY-MM-DD') } else if (item.type === 'datemonth') { item.value = moment().format('YYYY-MM') } else if (item.type === 'dateweek') { - item.value = [moment().startOf('week').format('YYYY-MM-DD'), moment().endOf('week').format('YYYY-MM-DD')] + item.value = moment().format('YYYY-MM-DD') } else if (item.type === 'daterange') { - item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')] - } else if (item.type === 'multiselect') { - item.value = ['@$@'] + item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') + } else if (item.type === 'range') { + + } else if (item.type === 'multiselect' || (item.type === 'checkcard' && search.multiple === 'true')) { + item.type = 'multi' + item.value = '@$@' } else { item.value = '@$@' } newsearches.push(item) }) - + return newsearches } @@ -527,8 +545,15 @@ return } + let _search = this.formatSearch(search) + _search = Utils.joinMainSearchkey(_search) + + _search = _search.replace(/@\$@/ig, '') + _search = _search ? 'where ' + _search : '' + this.setState({ searches: search, + defaultSearch: _search, setting: res }, () => { this.sqlverify(() => { resolve({setting: res, columns, scripts }) }, reject, false) @@ -562,7 +587,7 @@ } sqlverify = (resolve, reject, change = false, testScripts) => { - const { columns, setting, scripts, searches } = this.state + const { columns, setting, scripts, searches, defaultSearch } = this.state let _scripts = scripts.filter(item => item.status !== 'false') @@ -580,7 +605,7 @@ } if ((setting.interType === 'system' && setting.execute !== 'false') || _scripts.length > 0) { - let result = SettingUtils.getDebugSql(setting, _scripts, columns, searches) + let result = SettingUtils.getDebugSql(setting, _scripts, columns, searches, defaultSearch) if (result.error) { notification.warning({ @@ -622,6 +647,27 @@ }) } + copyColumns = () => { + const { columns } = this.state + let m = [] + let n = [] + + columns.forEach(col => { + m.push(`${col.field}(${col.label})`) + n.push(col.field) + }) + + let oInput = document.createElement('input') + oInput.value = `/*${m.join(',')}*/ + ${n.join(',')}` + document.body.appendChild(oInput) + oInput.select() + document.execCommand('Copy') + document.body.removeChild(oInput) + + message.success('澶嶅埗鎴愬姛銆�') + } + /** * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 */ @@ -657,6 +703,7 @@ type="fields" updatefield={this.updatefields} /> + <Icon type="copy" onClick={this.copyColumns} style={{position: 'absolute', cursor: 'pointer', zIndex: 1, top: '-35px', right: '0px', color: '#1890ff'}} /> <EditTable actions={['edit', 'move', 'copy', 'del']} type="datasourcefield" data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/> </TabPane> <TabPane tab={ diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx index c114793..d7916a3 100644 --- a/src/menu/datasource/verifycard/settingform/index.jsx +++ b/src/menu/datasource/verifycard/settingform/index.jsx @@ -8,6 +8,8 @@ import CodeMirror from '@/templates/zshare/codemirror' import './index.scss' +const { TextArea } = Input + class SettingForm extends Component { static propTpyes = { dict: PropTypes.object, // 瀛楀吀椤� @@ -182,6 +184,10 @@ required: true, message: this.props.dict['form.required.input'] + '琛ㄥ悕!' }, + { + max: 50, + message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!' + } ] })(<Input placeholder={''} autoComplete="off" />)} </Form.Item> @@ -245,7 +251,7 @@ })(<Input placeholder={''} autoComplete="off" />)} </Form.Item> </Col> : null} - {interType === 'outer' ? <Col span={8}> + {interType === 'outer' ? <Col className="outer-interface" span={24}> <Form.Item label="鎺ュ彛鍦板潃"> {getFieldDecorator('interface', { initialValue: setting.interface || '', @@ -255,7 +261,18 @@ message: this.props.dict['form.required.input'] + '鎺ュ彛鍦板潃!' } ] - })(<Input placeholder={''} autoComplete="off" />)} + })(<TextArea rows={2}/>)} + </Form.Item> + </Col> : null} + {interType === 'outer' ? <Col className="outer-interface" span={24}> + <Form.Item label={<Tooltip placement="topLeft" title="姝e紡绯荤粺鎺ュ彛鍦板潃锛屼负绌烘椂浣跨敤鎺ュ彛鍦板潃"> + <Icon type="question-circle" /> + 姝e紡鍦板潃 + </Tooltip> + }> + {getFieldDecorator('proInterface', { + initialValue: setting.proInterface || '' + })(<TextArea rows={2}/>)} </Form.Item> </Col> : null} {interType === 'outer' ? <Col span={8}> @@ -270,7 +287,7 @@ </Col> : null} {interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}> <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={ - <Tooltip placement="topLeft" title={'浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\''}> + <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''锛涙煡璇㈡浛鎹㈢ $select@ -> /* 鎴� ''銆� @select$ -> */ 鎴� ''锛涚粺璁℃浛鎹㈢ $sum@ -> /* 鎴� ''銆� @sum$ -> */ 鎴� ''銆俙}> <Icon type="question-circle" /> 鏁版嵁婧� </Tooltip> @@ -336,7 +353,7 @@ </Radio.Group>)} </Form.Item> </Col> : null} - <Col span={8}> + {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'璇ョ粍浠跺鏋滃彈鍏朵粬缁勪欢鎺у埗锛岃閫夐」鐩稿簲鐨勭粍浠讹紝娌℃湁鏃堕�夆�滄棤鈥濄��'}> <Icon type="question-circle" /> @@ -355,7 +372,7 @@ <Cascader options={modules} onChange={this.changeSupModule} expandTrigger="hover" placeholder="" /> )} </Form.Item> - </Col> + </Col> : null} {config.pageable ? <Col span={8}> <Form.Item label="鍒嗛〉"> {getFieldDecorator('laypage', { @@ -387,7 +404,7 @@ </Form.Item> </Col> : null} {/* 1銆佷笉鍒嗛〉涓斾笉瀛樺湪涓婄骇妯″潡 */} - {(!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}> + {config.type !== 'navbar' && (!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹紝娉細浠呭湪浣跨敤绯荤粺鍑芥暟锛屼笖鍒濆鍖栧姞杞芥暟鎹椂鏈夋晥锛屽垎椤佃姹傛椂鏃犳晥銆�'}> <Icon type="question-circle" /> @@ -404,7 +421,7 @@ )} </Form.Item> </Col> : null} - <Col span={8}> + {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'浼樺厛浣跨敤鍚岀骇鐨勬悳绱㈡潯浠剁粍浠讹紝鍚岀骇鎼滅储涓嶅瓨鍦ㄦ椂锛屼緷娆″悜涓婇�夊彇锛屼笌褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵竴鍚岀敤浣滄暟鎹繃婊わ紙褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵紭鍏堬級銆�'}> <Icon type="question-circle" /> @@ -420,8 +437,8 @@ </Radio.Group> )} </Form.Item> - </Col> - {useMSearch === 'true' ? <Col span={8}> + </Col> : null} + {config.type !== 'navbar' && config.type !== 'balcony' && useMSearch === 'true' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'澶栧眰鎼滅储鏉′欢鏀瑰彉鏃讹紝鏄惁鍒锋柊褰撳墠缁勪欢鏁版嵁銆�'}> <Icon type="question-circle" /> @@ -438,7 +455,7 @@ )} </Form.Item> </Col> : null} - <Col span={8}> + {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> <Form.Item label="鍒濆鍖栨暟鎹�"> {getFieldDecorator('onload', { initialValue: setting.onload || 'true' @@ -449,7 +466,7 @@ </Radio.Group> )} </Form.Item> - </Col> + </Col> : null} </Row> </Form> </div> diff --git a/src/menu/datasource/verifycard/settingform/index.scss b/src/menu/datasource/verifycard/settingform/index.scss index 5bd14b5..d0943f6 100644 --- a/src/menu/datasource/verifycard/settingform/index.scss +++ b/src/menu/datasource/verifycard/settingform/index.scss @@ -24,4 +24,12 @@ .ant-radio-group { white-space: nowrap; } + .outer-interface { + .ant-form-item-label { + width: 10.5%; + } + .ant-form-item-control-wrapper { + width: 89.5%; + } + } } \ No newline at end of file diff --git a/src/menu/datasource/verifycard/utils.jsx b/src/menu/datasource/verifycard/utils.jsx index 9bb5840..fa55bc3 100644 --- a/src/menu/datasource/verifycard/utils.jsx +++ b/src/menu/datasource/verifycard/utils.jsx @@ -7,7 +7,7 @@ * @return {Object} setting 椤甸潰璁剧疆 * @return {Array} columns 鏄剧ず瀛楁 */ - static getDebugSql (setting, scripts, columns, searches = []) { + static getDebugSql (setting, scripts, columns, searches = [], defSearch) { let sql = '' let error = '' let _dataresource = '' @@ -26,8 +26,20 @@ _dataresource = setting.dataresource || '' } + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } + _dataresource = _dataresource.replace(/@\$|\$@/ig, '') _customScript = _customScript.replace(/@\$|\$@/ig, '') + _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '') + _customScript = _customScript.replace(/@select\$|\$select@/ig, '') + _dataresource = _dataresource.replace(/@sum\$|\$sum@/ig, '') + _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '') if (_customScript) { _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50) select @ErrorCode='',@retmsg ='' @@ -48,8 +60,7 @@ _customScript = _customScript.replace(reg, '0') }) } - - + // 姝e垯鏇挎崲 let _regoptions = [] let _fields = [] @@ -66,7 +77,7 @@ reg: new RegExp('@' + item.datefield + '1@', 'ig') }) } - if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { + if (['dateweek', 'datemonth', 'daterange', 'range'].includes(item.type)) { _regoptions.push({ var: new RegExp('@' + item.field, 'ig'), reg: new RegExp('@' + item.field + '@', 'ig') @@ -103,7 +114,7 @@ } }) - let _search = '' + let _search = defSearch if (setting.queryType === 'statistics' && _dataresource) { _regoptions.forEach(item => { @@ -125,7 +136,7 @@ }, { reg: new RegExp('@FullName@', 'ig'), }) - if (setting.laypage !== 'false') { + if (setting.laypage === 'true') { _regoptions.push({ reg: new RegExp('@pageSize@', 'ig'), }, { @@ -140,6 +151,9 @@ if (setting.varMark) { originscript = originscript.replace(/@ErrorCode/ig, '') originscript = originscript.replace(/@retmsg/ig, '') + originscript = originscript.replace(/@UserName@/ig, '').replace(/@UserName/ig, '') + originscript = originscript.replace(/@FullName@/ig, '').replace(/@FullName/ig, '') + originscript = originscript.replace(/@login_city@/ig, '').replace(/@login_city/ig, '') originscript = originscript.replace(/@id@/ig, '').replace(/@id/ig, '') originscript = originscript.replace(/@bid@/ig, '').replace(/@bid/ig, '') originscript = originscript.replace(/@loginuid@/ig, '').replace(/@loginuid/ig, '') @@ -162,7 +176,11 @@ _dataresource = '(' + _dataresource + ') tb' } - _dataresource = `select${setting.laypage !== 'false' ? ' top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage !== 'false' ? 'where rows > 0' : ''} order by tmptable.rows` + if (setting.order) { + _dataresource = `select${setting.laypage === 'true' ? ' top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage === 'true' ? 'where rows > 0' : ''} order by tmptable.rows` + } else { + _dataresource = `select${setting.laypage === 'true' ? ' top 10' : ''} ${arr_field} from ${_dataresource} ${_search}` + } } if (_customScript) { diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx index b89e539..b12b583 100644 --- a/src/menu/menushell/card.jsx +++ b/src/menu/menushell/card.jsx @@ -7,9 +7,13 @@ const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar')) const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search')) const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie')) +const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) +const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs')) const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) +const Balcony = asyncComponent(() => import('@/menu/components/card/balcony')) +const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) @@ -59,6 +63,12 @@ return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'pie') { return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'dashboard') { + return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'tree') { + return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'scatter') { + return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'form') { return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'tabs') { @@ -81,6 +91,8 @@ return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'code') { return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'balcony') { + return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } } return ( diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx index 6ac5ace..7e03f6c 100644 --- a/src/menu/menushell/index.jsx +++ b/src/menu/menushell/index.jsx @@ -19,6 +19,10 @@ handleList({...menu, components: _cards}) setCards(_cards) } + + if (menu.components.length > cards.length) { + setCards(menu.components) + } const findCard = id => { const card = cards.filter(c => `${c.uuid}` === id)[0] @@ -53,9 +57,12 @@ content: hasComponent ? '褰撳墠缁勪欢涓惈鏈夊瓙缁勪欢锛�' : '', onOk() { const _cards = cards.filter(item => item.uuid !== card.uuid) - MKEmitter.emit('delButtons', uuids) handleList({...menu, components: _cards}) setCards(_cards) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -93,6 +100,10 @@ code: '鑷畾涔�', carousel: '杞挱', form: '琛ㄥ崟', + dashboard: '浠〃鐩�', + scatter: '鏁g偣鍥�', + tree: '鏍戝舰鍒楄〃', + balcony: '娴姩鍗�', card: '鍗$墖' } let i = 1 diff --git a/src/menu/modalconfig/controller.jsx b/src/menu/modalconfig/controller.jsx index 6cae222..881883d 100644 --- a/src/menu/modalconfig/controller.jsx +++ b/src/menu/modalconfig/controller.jsx @@ -48,12 +48,6 @@ handleSave = (modal) => { const { config, btn } = this.state MKEmitter.emit('submitModal', config, btn, modal) - - this.setState({ - visible: false, - config: null, - btn: null - }) } render () { diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx index 6f3cd48..cf6bab2 100644 --- a/src/menu/modalconfig/index.jsx +++ b/src/menu/modalconfig/index.jsx @@ -12,7 +12,6 @@ import enUS from '@/locales/en-US/model.js' import { getModalForm } from '@/templates/zshare/formconfig' -import ModalForm from '@/templates/zshare/modalform' import SourceElement from '@/templates/modalconfig/dragelement/source' import SettingForm from '@/templates/modalconfig/settingform' import asyncComponent from '@/utils/asyncComponent' @@ -22,6 +21,7 @@ const { Panel } = Collapse const { confirm } = Modal const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS +const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent')) const DragElement = asyncComponent(() => import('@/templates/modalconfig/dragelement')) const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) @@ -37,20 +37,11 @@ dict: CommonDict, // 瀛楀吀 config: null, // 椤甸潰閰嶇疆锛屽寘鎷ā鏉跨被鍨嬨�佹ā鎬佹璁剧疆銆佹坊鍔犺〃鍚嶃�佽〃鍗曞垪琛� visible: false, // 琛ㄥ崟缂栬緫妯℃�佹锛屾樉绀烘帶鍒� - tableVisible: false, // 鏁版嵁琛ㄥ瓧娈靛垪琛ㄦā鎬佹锛屾樉绀烘帶鍒� - tableColumns: [], // 琛ㄦ牸瀛楁鍚嶅垪琛� - fields: null, // 琛ㄥ崟锛屽彲閫夊瓧娈碉紙鍘婚噸鍚庯級 formlist: null, // 琛ㄥ崟缂栬緫妯℃�佹锛屽彲缂栬緫瀛楁 card: null, // 缂栬緫鍏冪礌 - closeloading: false, // 鑿滃崟淇濆瓨涓� settingVisible: false, // 鍏ㄥ眬閰嶇疆妯℃�佹 - closeVisible: false, // 鍏抽棴妯℃�佹 - tables: [], // 鍙敤琛ㄥ悕 - selectedTables: [], // 宸查�夎〃鍚� originConfig: null, // 鍘熷鑿滃崟 - sources: null, // 琛ㄥ崟绫诲瀷 sqlVerifing: false, // sql楠岃瘉 - openEdition: '', // 缂栬緫鐗堟湰鏍囪锛岄槻姝㈠浜烘搷浣� showField: false, // 鏄剧ず琛ㄥ崟瀛楁鍊� standardform: null } @@ -132,7 +123,7 @@ if (card.uuid === item.uuid) { index = i } - if (item.type !== 'select' && item.type !== 'link' && item.type !== 'radio') return + if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return if (item.field && !uniq.has(item.field)) { uniq.set(item.field, true) @@ -227,7 +218,7 @@ _config.fields = _config.fields.filter(item => !item.origin) - if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { + if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { this.setState({ sqlVerifing: true }) @@ -297,15 +288,26 @@ submitConfig = () => { const { config } = this.state + this.setState({originConfig: fromJS(config).toJS()}) this.props.handleSave(config) + notification.success({ + top: 92, + message: '淇濆瓨鎴愬姛銆�', + duration: 2 + }) } cancelConfig = () => { const { config, originConfig } = this.state if (!is(fromJS(config), fromJS(originConfig))) { - this.setState({ - closeVisible: true + let _this = this + confirm({ + content: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾杩斿洖鍚楋紵', + onOk() { + _this.props.handleBack() + }, + onCancel() {} }) } else { this.props.handleBack() @@ -423,8 +425,8 @@ <Card title={dict['header.menu.form.configurable']} bordered={false} extra={ <div> <EditComponent dict={dict} options={['form']} config={this.state.config} refresh={(res) => this.updateConfig(res.config)}/> - <Button type="primary" onClick={this.submitConfig}>{dict['model.confirm']}</Button> - <Button onClick={this.cancelConfig}>{dict['model.cancel']}</Button> + <Button type="primary" onClick={this.submitConfig}>淇濆瓨</Button> + <Button onClick={this.cancelConfig}>杩斿洖</Button> </div> } style={{ width: '100%' }}> <Icon type="setting" onClick={this.changeSetting} /> @@ -486,7 +488,7 @@ <Modal title={this.state.dict['model.edit']} visible={this.state.settingVisible} - width={700} + width={850} maskClosable={false} onOk={this.settingSave} onCancel={() => { this.setState({ settingVisible: false }) }} @@ -499,21 +501,6 @@ inputSubmit={this.settingSave} wrappedComponentRef={(inst) => this.settingRef = inst} /> - </Modal> - <Modal - bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}} - closable={false} - maskClosable={false} - visible={this.state.closeVisible} - onCancel={() => { this.setState({closeVisible: false}) }} - footer={[ - <Button key="save" className="mk-btn mk-green" loading={this.state.closeloading} onClick={this.submitConfig}>{this.state.dict['model.save']}</Button>, - <Button key="confirm" className="mk-btn mk-yellow" onClick={this.props.handleBack}>{this.state.dict['model.notsave']}</Button>, - <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['model.cancel']}</Button> - ]} - destroyOnClose - > - {this.state.dict['header.menu.config.placeholder']} </Modal> </div> ) diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss index 163f1e6..19fe376 100644 --- a/src/menu/modalconfig/index.scss +++ b/src/menu/modalconfig/index.scss @@ -127,6 +127,20 @@ .ant-card-body { position: relative; padding: 0; + + .modal-fields-row.up_down { + .ant-form-item { + display: block!important; + .ant-form-item-label { + width: 100%!important; + text-align: left; + } + .ant-form-item-control-wrapper { + width: 100%!important; + } + } + } + .ant-modal-content { max-width: 95%; margin: 0 auto; @@ -292,6 +306,7 @@ } } + .modal-fields { .ant-modal { top: 50px; diff --git a/src/menu/modulesource/index.jsx b/src/menu/modulesource/index.jsx index 03f268a..2233f75 100644 --- a/src/menu/modulesource/index.jsx +++ b/src/menu/modulesource/index.jsx @@ -55,6 +55,7 @@ c_id: item.uuid, images: '', c_name: item.title, + typename: sessionStorage.getItem('appType') || '', long_param: '', del_type: 'Y' }).then(result => { diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx index e88ceca..e9e1833 100644 --- a/src/menu/modulesource/option.jsx +++ b/src/menu/modulesource/option.jsx @@ -12,11 +12,16 @@ import Editor from '@/assets/mobimg/editor.png' import SandBox from '@/assets/mobimg/sandbox.png' import Pie1 from '@/assets/mobimg/ring.png' +import Pie3 from '@/assets/mobimg/nest.png' import Pie2 from '@/assets/mobimg/nightingale.png' import Mainsearch from '@/assets/mobimg/mainsearch.png' import Carousel from '@/assets/mobimg/carousel.png' import Carousel1 from '@/assets/mobimg/carousel1.png' import form from '@/assets/mobimg/form.png' +import dashboard from '@/assets/mobimg/dashboard.png' +import ratioboard from '@/assets/mobimg/ratioboard.png' +import scatter from '@/assets/mobimg/scatter.png' +import tree from '@/assets/mobimg/tree.png' // 缁勪欢閰嶇疆淇℃伅 export const menuOptions = [ @@ -24,19 +29,25 @@ { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�', width: 24 }, { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '灞炴�у崱', width: 24 }, + { type: 'menu', url: card2, component: 'balcony', subtype: 'balcony', title: '鍙诞鍔ㄥ崱', width: 24 }, { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '琛ㄥ崟', width: 24 }, { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '杞挱-鍔ㄦ�佹暟鎹�', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: Carousel1, component: 'carousel', subtype: 'propcard', title: '杞挱-闈欐�佹暟鎹�', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: NormalTable, component: 'table', subtype: 'normaltable', title: '甯哥敤琛�', width: 24 }, { type: 'menu', url: TableCard, component: 'table', subtype: 'tablecard', title: '琛ㄦ牸', width: 12 }, + { type: 'menu', url: tree, component: 'tree', subtype: 'normaltree', title: '鏍戝舰鍒楄〃', width: 12 }, { type: 'menu', url: line, component: 'line', subtype: 'line', title: '鎶樼嚎鍥�', width: 24 }, { type: 'menu', url: line1, component: 'line', subtype: 'line1', title: '闃舵鎶樼嚎鍥�', width: 24 }, { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '鏌辩姸鍥�', width: 24 }, { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�', width: 24 }, { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '楗煎浘', width: 12 }, { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '鐜浘', width: 12 }, + { type: 'menu', url: Pie3, component: 'pie', subtype: 'nest', title: '宓屽楗煎浘', width: 12 }, + { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 }, + { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '浠〃鐩�', width: 12 }, + { type: 'menu', url: ratioboard, component: 'dashboard', subtype: 'ratioboard', title: '鍗犳瘮鍥�', width: 12 }, + { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '鏁g偣鍥�', width: 24 }, { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '瀵屾枃鏈�', width: 24 }, { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 }, - { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 }, { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24, forbid: ['billPrint'] }, ] diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx index 9df7a55..7b3153c 100644 --- a/src/menu/pastecontroller/index.jsx +++ b/src/menu/pastecontroller/index.jsx @@ -60,8 +60,13 @@ cell = this.resetconfig(cell, item, true, copyBtns) return cell }) + } else if (item.type === 'menubar') { + item.subMenus = item.subMenus.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) { - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { card.uuid = Utils.getuuid() if (card.elements) { if (sessionStorage.getItem('editMenuType') === 'popview') { @@ -149,12 +154,16 @@ item.btnlog = [] } + let oriUids = {} if (item.action) { if (sessionStorage.getItem('editMenuType') === 'popview') { item.action = item.action.filter(c => c.OpenType !== 'popview' && c.OpenType !== 'funcbutton') } item.action = item.action.map(cell => { let _uuid = Utils.getuuid() + + oriUids[cell.uuid] = _uuid + if (cell.OpenType === 'popview') { let _cell = fromJS(cell).toJS() _cell.$originUuid = _cell.uuid @@ -177,6 +186,13 @@ return cell }) } + if (item.setting && item.setting.supModule) { + item.setting.supModule = '' + } + + if (item.wrap && item.wrap.doubleClick) { + item.wrap.doubleClick = oriUids[item.wrap.doubleClick] || '' + } return item } @@ -185,16 +201,20 @@ const { Tab } = this.props let isgroup = Tab && Tab.type === 'group' ? true : false + let options = ['tabs', 'datacard', 'propcard', 'mainsearch', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter'] + if (sessionStorage.getItem('appType') === 'mob') { + options.push('menubar') + } this.pasteFormRef.handleConfirm().then(res => { - if (!isgroup && !['tabs', 'datacard', 'propcard', 'mainsearch', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie'].includes(res.copyType)) { + if (!isgroup && !options.includes(res.copyType)) { notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', duration: 5 }) return - } else if (isgroup && !['datacard', 'propcard', 'normaltable', 'tablecard', 'line', 'bar', 'pie'].includes(res.copyType)) { + } else if (isgroup && !['datacard', 'propcard', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter'].includes(res.copyType)) { notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', diff --git a/src/menu/picturecontroller/editform/index.jsx b/src/menu/picturecontroller/editform/index.jsx index e12d46d..934ebd7 100644 --- a/src/menu/picturecontroller/editform/index.jsx +++ b/src/menu/picturecontroller/editform/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Input, Radio, notification } from 'antd' +import { Form, Row, Col, Input, Radio } from 'antd' import FileUpload from '@/tabviews/zshare/fileupload' import './index.scss' @@ -14,7 +14,6 @@ } state = { - urls: [], linkurl: '', plusType: 'upload' } @@ -24,29 +23,8 @@ return new Promise((resolve, reject) => { this.props.form.validateFieldsAndScroll((err, values) => { if (!err) { - if (values.urls && values.urls[0].status === 'error') { - notification.warning({ - top: 92, - message: '璇烽噸鏂颁笂浼犳枃浠讹紒', - duration: 5 - }) - return - } else if (values.urls && values.urls[0] && values.urls[0].status !== 'done') { - notification.warning({ - top: 92, - message: '鏂囦欢涓婁紶涓紝璇风◢鍚庯紒', - duration: 5 - }) - return - } else if (values.urls && values.urls[0] && values.urls[0].response) { - values.linkurl = values.urls[0].response - } else { - notification.warning({ - top: 92, - message: '鏈幏鍙栧埌鏂囦欢璺緞锛�', - duration: 5 - }) - return + if (values.urls) { + values.linkurl = values.urls } resolve(values) } else { @@ -57,28 +35,19 @@ } changeType = (val) => { - const { linkurl, urls } = this.state - let _urls = this.props.form.getFieldValue('urls') || '' - let _url = this.props.form.getFieldValue('linkurl') || '' + let _url = '' if (val === 'input') { - if (_urls && _urls[0] && _urls[0].status === 'done' && (_urls[0].url || _urls[0].response)) { - _url = _urls[0].url || _urls[0].response - } else { - _url = linkurl || '' - } - } else { - _urls = urls.filter(item => item.status === 'done') - _url = linkurl + _url = this.props.form.getFieldValue('urls') || '' } - this.setState({plusType: val, urls: _urls, linkurl: _url}) + this.setState({plusType: val, linkurl: _url}) } render() { const { getFieldDecorator } = this.props.form const { card } = this.props - const { urls, linkurl, plusType } = this.state + const { linkurl, plusType } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -103,7 +72,7 @@ {!card.id && card.typecharone === 'image' && plusType === 'upload' ? <Col span={24}> <Form.Item label="鍥剧墖涓婁紶"> {getFieldDecorator('urls', { - initialValue: urls, + initialValue: '', rules: [ { required: true, @@ -111,14 +80,19 @@ } ] })( - <FileUpload accept=".jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp" maxFile={1} fileType={'picture'} /> + <FileUpload config={{ + initval: '', + suffix: '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp', + maxfile: 1, + fileType: 'picture' + }} /> )} </Form.Item> </Col> : null} {!card.id && card.typecharone === 'video' && plusType === 'upload' ? <Col span={24}> <Form.Item label="瑙嗛涓婁紶"> {getFieldDecorator('urls', { - initialValue: urls, + initialValue: '', rules: [ { required: true, @@ -126,7 +100,12 @@ } ] })( - <FileUpload accept=".mp4,.webm,.ogg" maxFile={1} fileType={'text'} /> + <FileUpload config={{ + initval: '', + suffix: '.mp4,.webm,.ogg', + maxfile: 1, + fileType: 'text' + }}/> )} </Form.Item> </Col> : null} diff --git a/src/menu/popview/index.jsx b/src/menu/popview/index.jsx index 59da6e1..55a0f13 100644 --- a/src/menu/popview/index.jsx +++ b/src/menu/popview/index.jsx @@ -19,8 +19,10 @@ const { confirm } = Modal const MenuForm = asyncComponent(() => import('./menuform')) +const Header = asyncComponent(() => import('@/menu/header')) const SourceWrap = asyncComponent(() => import('@/menu/modulesource')) const MenuShell = asyncComponent(() => import('@/menu/menushell')) +const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) const BgController = asyncComponent(() => import('@/menu/bgcontroller')) const PasteController = asyncComponent(() => import('@/menu/pastecontroller')) const PaddingController = asyncComponent(() => import('@/menu/padcontroller')) @@ -84,6 +86,7 @@ updateCustomComponent = () => { Api.getSystemConfig({ func: 's_get_custom_components', + typename: sessionStorage.getItem('appType'), typecharone: '' }).then(res => { let coms = [] @@ -245,7 +248,7 @@ buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { card.elements && card.elements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) @@ -527,6 +530,18 @@ window.GLOB.customMenu = config } + resetConfig = (config) => { + this.setState({ + config: {...config, components: []}, + }, () => { + this.setState({ + config: config + }) + }) + + window.GLOB.customMenu = config + } + /** * @description 鏇存柊甯哥敤琛ㄤ俊鎭紝蹇嵎娣诲姞鍚庢洿鏂伴厤缃俊鎭� */ @@ -550,49 +565,53 @@ const { activeKey, MenuType, dict, config, menuloading, customComponents } = this.state return ( - <DndProvider backend={HTML5Backend}> - <div className="menu-body"> - <div className="menu-setting"> - <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> - {/* 鍩烘湰淇℃伅 */} - <Panel header={dict['mob.basemsg']} key="basedata"> - {/* 鑿滃崟淇℃伅 */} - {config ? <MenuForm dict={dict} config={config} btn={btn} updateConfig={this.updateConfig}/> : null} - {/* 琛ㄥ悕娣诲姞 */} - {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null} - </Panel> - {/* 缁勪欢娣诲姞 */} - <Panel header={dict['mob.component']} key="component"> - <SourceWrap MenuType={MenuType} /> - </Panel> - {customComponents && customComponents.length ? <Panel header="鑷畾涔夌粍浠�" key="cuscomponent"> - <SourceWrap components={customComponents} MenuType={MenuType} /> - </Panel> : null} - <Panel header={'椤甸潰鑳屾櫙'} key="background"> - {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null} - </Panel> - <Panel header={'椤甸潰鍐呰竟璺�'} key="padding"> - {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null} - </Panel> - </Collapse> + <div className="pc-poper-view"> + <Header /> + <DndProvider backend={HTML5Backend}> + <div className="menu-body"> + <div className="menu-setting"> + <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> + {/* 鍩烘湰淇℃伅 */} + <Panel header={dict['mob.basemsg']} key="basedata"> + {/* 鑿滃崟淇℃伅 */} + {config ? <MenuForm dict={dict} config={config} btn={btn} updateConfig={this.updateConfig}/> : null} + {/* 琛ㄥ悕娣诲姞 */} + {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null} + </Panel> + {/* 缁勪欢娣诲姞 */} + <Panel header={dict['mob.component']} key="component"> + <SourceWrap MenuType={MenuType} /> + </Panel> + {customComponents && customComponents.length ? <Panel header="鑷畾涔夌粍浠�" key="cuscomponent"> + <SourceWrap components={customComponents} MenuType={MenuType} /> + </Panel> : null} + <Panel header={'椤甸潰鑳屾櫙'} key="background"> + {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null} + </Panel> + <Panel header={'椤甸潰鍐呰竟璺�'} key="padding"> + {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null} + </Panel> + </Collapse> + </div> + <div className={'menu-view ' + (menuloading ? 'saving' : '')}> + <Card title={ + <div> {config && config.MenuName} </div> + } bordered={false} extra={ + <div> + <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/> + <StyleCombControlButton menu={config} /> + <PasteController type="menu" Tab={null} insert={this.insert} /> + {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null} + <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> + <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> + </div> + } style={{ width: '100%' }}> + {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} + </Card> + </div> </div> - <div className={'menu-view ' + (menuloading ? 'saving' : '')}> - <Card title={ - <div> {config && config.MenuName} </div> - } bordered={false} extra={ - <div> - <StyleCombControlButton menu={config} /> - <PasteController type="menu" Tab={null} insert={this.insert} /> - {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null} - <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> - <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> - </div> - } style={{ width: '100%' }}> - {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} - </Card> - </div> - </div> - </DndProvider> + </DndProvider> + </div> ) } } diff --git a/src/menu/popview/index.scss b/src/menu/popview/index.scss index e69de29..d1a7fda 100644 --- a/src/menu/popview/index.scss +++ b/src/menu/popview/index.scss @@ -0,0 +1,162 @@ +.pc-poper-view { + background: #000; + min-height: 100vh; + >.menu-body { + width: 100vw; + height: 100vh; + overflow-x: hidden; + position: relative; + background: #ffffff; + padding: 50px 0px 0px 0px; + + .menu-setting { + position: fixed; + left: 0; + top: 48px; + z-index: 10; + height: calc(100vh - 48px); + width: 300px; + background: #ffffff; + box-shadow: 0px 2px 5px #bcbcbc; + overflow-y: auto; + overflow-x: hidden; + + > .ant-collapse { + background-color: #ffffff; + .ant-collapse-item.ant-collapse-item-active { + border-bottom: 1px solid #d9d9d9; + } + .ant-collapse-header { + padding: 11px 16px 10px 40px; + border-bottom: 1px solid #d9d9d9; + background: #1890ff; + color: #ffffff; + } + .ant-collapse-content-box { + .ant-form-item { + margin-bottom: 10px; + } + .model-table-tablemanage-view { + >.ant-list { + margin-top: 20px; + .ant-list-item { + display: -webkit-box; + padding-right: 20px; + position: relative; + padding-left: 5px; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + min-height: 55px; + width: 100%; + .anticon { + position: absolute; + top: 0px; + right: 0px; + padding: 3px 3px 10px 10px; + cursor: pointer; + } + } + } + >.tables { + width: 66.66666667%!important; + } + >.ant-form-item-label { + width: 33.33333333%; + } + } + } + } + + >.ant-tabs { + >.ant-tabs-bar { + border-bottom: 1px solid #181F29; + margin-bottom: 0px; + min-height: 48px; + .ant-tabs-tab { + padding: 14px 16px; + color: rgba(255, 255, 255, 0.85); + } + .ant-tabs-tab-active.ant-tabs-tab { + color: #1890ff; + } + } + } + } + .menu-setting::-webkit-scrollbar { + width: 4px; + } + .menu-setting::-webkit-scrollbar-thumb { + border-radius: 5px; + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08); + background: rgba(0, 0, 0, 0.08); + } + .menu-setting::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); + border-radius: 3px; + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0); + } + + .menu-view { + position: relative; + width: calc(100vw - 300px); + margin-left: 300px; + height: calc(100vh - 50px); + overflow-y: auto; + + > .ant-card { + >.ant-card-head { + margin-bottom: 0px; + position: relative; + .ant-card-head-title { + color: #1890ff; + padding: 5px 0; + } + .ant-card-extra { + padding: 5px 0; + button { + margin-left: 20px; + } + .ant-switch.big { + min-width: 60px; + height: 28px; + line-height: 28px; + margin-top: -2px; + .ant-switch-inner { + font-size: 14px; + } + } + .ant-switch.big:after { + width: 24px; + height: 24px; + } + } + } + >.ant-card-body { + padding: 0px; + } + } + } + .menu-view.saving { + .anticon-tool { + display: none; + } + } + .menu-view::-webkit-scrollbar { + width: 7px; + } + .menu-view::-webkit-scrollbar-thumb { + border-radius: 5px; + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08); + background: rgba(0, 0, 0, 0.08); + } + .menu-view::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); + border-radius: 3px; + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0); + } + } +} \ No newline at end of file diff --git a/src/menu/replaceField/index.jsx b/src/menu/replaceField/index.jsx new file mode 100644 index 0000000..d965cba --- /dev/null +++ b/src/menu/replaceField/index.jsx @@ -0,0 +1,381 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Modal, Button, notification } from 'antd' +import moment from 'moment' + +import Api from '@/api' +import options from '@/store/options.js' +import Utils from '@/utils/utils.js' +import SettingForm from './settingform' +import { queryTableSql } from '@/utils/option.js' +import './index.scss' + +class ReplaceField extends Component { + static propTpyes = { + type: PropTypes.string, + config: PropTypes.object, + updateConfig: PropTypes.func + } + + state = { + visible: false, + loadingTable: false, + confirming: false, + tables: [], + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + trigger = () => { + const { tables } = this.state + + if (tables.length === 0) { + let param = { + func: 'sPC_Get_SelectedList', + LText: queryTableSql, + obj_name: 'data', + arr_field: 'TbName,Remark' + } + + param.LText = Utils.formatOptions(param.LText) + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉 + + if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧� + param.rduri = options.cloudServiceApi + param.userid = sessionStorage.getItem('CloudUserID') || '' + param.LoginUID = sessionStorage.getItem('CloudLoginUID') || '' + } + + this.setState({ + loadingTable: true + }) + + Api.getSystemCacheConfig(param).then(res => { + if (res.status) { + this.setState({ + visible: true, + confirming: false, + tables: res.data, + loadingTable: false + }) + } else { + this.setState({ + confirming: false, + loadingTable: false + }) + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } + }) + } else { + this.setState({ + confirming: false, + visible: true + }) + } + } + + submit = () => { + let config = fromJS(this.props.config).toJS() + + this.settingRef.handleConfirm().then(res => { + this.setState({confirming: true}) + + let param = {func: 'sPC_Get_FieldName', TBName: res.table} + if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧� + param.rduri = options.cloudServiceApi + param.userid = sessionStorage.getItem('CloudUserID') || '' + param.LoginUID = sessionStorage.getItem('CloudLoginUID') || '' + } + + Api.getSystemCacheConfig(param).then(result => { + if (!result.status) { + this.setState({ + confirming: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + return + } + + let map = {} + + result.FDName.forEach(item => { + if (/NVARCHAR|INT|Decimal/ig.test(item.FieldType)) { + item.datatype = item.FieldType + } + map[item.FieldDec] = item + }) + + if (this.props.type === 'custom') { + let _replace = (components) => { + return components.map(item => { + if (item.type === 'tabs') { + item.subtabs.forEach(tab => { + tab.components = _replace(tab.components) + }) + return item + } else if (item.type === 'group') { + item.components = _replace(item.components) + return item + } + + if (item.columns) { + item.columns = item.columns.map(col => { + if (map[col.field]) { + col.field = map[col.field].FieldName + if (map[col.field].datatype) { + col.datatype = map[col.field].datatype + } + } + return col + }) + } + if (item.search) { + item.search = item.search.map(col => { + if (map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + } + + if (item.action) { + item.action.forEach(m => { + if (m.modal && m.modal.fields) { + m.modal.fields = m.modal.fields.map(col => { + if (map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + } + }) + } + + if (item.subcards) { + item.subcards.forEach(card => { + if (card.elements) { // 鍗$墖 + card.elements = card.elements.map(m => { + if (m.datatype === 'dynamic' && map[m.field]) { + m.field = map[m.field].FieldName + } + if (m.modal && m.modal.fields) { + m.modal.fields = m.modal.fields.map(col => { + if (map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + } + return m + }) + } + + if (card.backElements) { // 鍗$墖 + card.backElements = card.backElements.map(m => { + if (m.datatype === 'dynamic' && map[m.field]) { + m.field = map[m.field].FieldName + } + if (m.modal && m.modal.fields) { + m.modal.fields = m.modal.fields.map(col => { + if (map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + } + return m + }) + } + + if (card.fields) { // 琛ㄥ崟 + card.fields = card.fields.map(m => { + if (map[m.field]) { + m.field = map[m.field].FieldName + } + return m + }) + } + }) + } + + if (item.elements) { + item.elements = item.elements.map(m => { + if (m.datatype === 'dynamic' && map[m.field]) { + m.field = map[m.field].FieldName + } + if (m.modal && m.modal.fields) { + m.modal.fields = m.modal.fields.map(col => { + if (map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + } + return m + }) + } + + if (item.plot) { + if (item.plot.Xaxis && map[item.plot.Xaxis]) { + item.plot.Xaxis = map[item.plot.Xaxis].FieldName + } + // 缁熻鍥� + if (item.plot.InfoValue && map[item.plot.InfoValue]) { + item.plot.InfoValue = map[item.plot.InfoValue].FieldName + } + if (item.plot.InfoType && map[item.plot.InfoType]) { + item.plot.InfoType = map[item.plot.InfoType].FieldName + } + // 鍗犳瘮鍥� + if (item.plot.valueField && map[item.plot.valueField]) { + item.plot.valueField = map[item.plot.valueField].FieldName + } + if (item.plot.labelField && map[item.plot.labelField]) { + item.plot.labelField = map[item.plot.labelField].FieldName + } + // 楗煎浘 + if (item.plot.type && map[item.plot.type]) { + item.plot.type = map[item.plot.type].FieldName + } + // 鏁g偣鍥� + if (item.plot.gender && map[item.plot.gender]) { + item.plot.gender = map[item.plot.gender].FieldName + } + if (item.Yaxis) { + if (Array.isArray(item.Yaxis)) { + item.Yaxis = item.Yaxis.map(m => { + if (map[m]) { + return map[m].FieldName + } + return m + }) + } else { + if (map[item.Yaxis]) { + item.Yaxis = map[item.Yaxis].FieldName + } + } + } + } + + if (item.cols) { + let _update = (cols) => { + return cols.map(col => { + if (col.type === 'action' && col.elements) { + col.elements = col.elements.map(m => { + if (m.modal && m.modal.fields) { + m.modal.fields = m.modal.fields.map(col => { + if (map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + } + + return m + }) + } else if (col.type === 'custom' && col.elements) { + col.elements = col.elements.map(m => { + if (m.datatype === 'dynamic' && map[m.field]) { + m.field = map[m.field].FieldName + } + + return m + }) + } else if (col.type === 'colspan') { + col.subcols = _update(col.subcols) + } else if (col.field) { + if (map[col.field]) { + col.field = map[col.field].FieldName + } + } + + return col + }) + } + + item.cols = _update(item.cols) + } + + return item + }) + } + + config.components = _replace(config.components) + } else if (this.props.type === 'table') { + config.columns = config.columns.map(col => { + if (col.field && map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + config.search = config.search.map(col => { + if (col.field && map[col.field]) { + col.field = map[col.field].FieldName + } + if (col.datefield && map[col.datefield]) { + col.datefield = map[col.datefield].FieldName + } + return col + }) + } else if (this.props.type === 'form') { + config.fields = config.fields.map(col => { + if (col.field && map[col.field]) { + col.field = map[col.field].FieldName + } + return col + }) + } + + this.setState({ + confirming: false, + visible: false + }) + + notification.success({ + top: 92, + message: '鏇存柊宸插畬鎴愩��', + duration: 3 + }) + this.props.updateConfig(config) + }) + }) + } + + render() { + const { visible, loadingTable, tables, confirming } = this.state + + return ( + <div style={{display: 'inline-block'}}> + <Button className="mk-border-yellow" icon="swap" loading={loadingTable} onClick={this.trigger}>瀛楁鏇挎崲</Button> + <Modal + title="瀛楁鏇挎崲" + wrapClassName="replace-field-modal" + visible={visible} + width={600} + maskClosable={false} + onOk={this.submit} + onCancel={() => { this.setState({ visible: false })}} + confirmLoading={confirming} + destroyOnClose + > + <SettingForm tables={tables} wrappedComponentRef={(inst) => this.settingRef = inst}/> + </Modal> + </div> + ) + } +} + +export default ReplaceField \ No newline at end of file diff --git a/src/menu/replaceField/index.scss b/src/menu/replaceField/index.scss new file mode 100644 index 0000000..de57aff --- /dev/null +++ b/src/menu/replaceField/index.scss @@ -0,0 +1,9 @@ +.replace-field-modal { + .ant-modal { + top: 70px; + } + .ant-modal-body { + min-height: 150px; + padding-top: 40px; + } +} \ No newline at end of file diff --git a/src/menu/replaceField/settingform/index.jsx b/src/menu/replaceField/settingform/index.jsx new file mode 100644 index 0000000..bbbea31 --- /dev/null +++ b/src/menu/replaceField/settingform/index.jsx @@ -0,0 +1,78 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Tooltip, Icon, Select } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + tables: PropTypes.object + } + + state = {} + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + render() { + const { tables } = this.props + const { getFieldDecorator } = this.props.form + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={20}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐢ㄤ簬瀛楁鏇挎崲鐨勮〃鍚嶃��"> + <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}} /> + 琛ㄥ悕 + </Tooltip> + }> + {getFieldDecorator('table', { + initialValue: '', + rules: [ + { + required: true, + message: '璇烽�夋嫨琛ㄥ悕' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {tables.map((option, i) => + <Select.Option key={i} title={option.Remark + ' (' + option.TbName + ')'} value={option.TbName}>{option.Remark + ' (' + option.TbName + ')'}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/menu/replaceField/settingform/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/menu/replaceField/settingform/index.scss diff --git a/src/menu/stylecombcontrolbutton/index.jsx b/src/menu/stylecombcontrolbutton/index.jsx index 19f3454..b644e5b 100644 --- a/src/menu/stylecombcontrolbutton/index.jsx +++ b/src/menu/stylecombcontrolbutton/index.jsx @@ -12,7 +12,7 @@ } state = { - label: '璋冩暣', + label: '鎵归噺璋冩暣', parent: null, type: '', components: [] @@ -127,7 +127,7 @@ triggerStyleChange = () => { const { label, components } = this.state - if (label === '璋冩暣') { + if (label === '鎵归噺璋冩暣') { document.body.className = 'style-control' sessionStorage.setItem('style-control', 'true') this.setState({label: '閫�鍑�'}) @@ -141,14 +141,14 @@ MKEmitter.emit('closeCombineStyle') - this.setState({label: '璋冩暣', parent: null, components: []}) + this.setState({label: '鎵归噺璋冩暣', parent: null, components: []}) } } render() { const { label } = this.state return ( - <Button className="style-control-button" icon="font-colors" title="璋冩暣鏍峰紡" onClick={this.triggerStyleChange}>{label}</Button> + <Button className="style-control-button" icon="font-colors" title="鎵归噺璋冩暣鏍峰紡" onClick={this.triggerStyleChange}>{label}</Button> ) } } diff --git a/src/menu/stylecombcontrolbutton/index.scss b/src/menu/stylecombcontrolbutton/index.scss index 09668c2..3732704 100644 --- a/src/menu/stylecombcontrolbutton/index.scss +++ b/src/menu/stylecombcontrolbutton/index.scss @@ -15,11 +15,19 @@ bottom: 0; right: 0; z-index: 12; - background:rgba(0, 0, 0, 0.3); + background:rgba(0, 0, 0, 0.2); } .menu-body .menu-view >.ant-card >.ant-card-body { position: relative; z-index: 13; + background:#ffffff; + } + .menu-view { + .anticon-tool { + display: none; + } + } + .mk-mob-view .mob-shell { .anticon-tool { display: none; } diff --git a/src/menu/stylecontroller/index.jsx b/src/menu/stylecontroller/index.jsx index 595e8ff..69d11e7 100644 --- a/src/menu/stylecontroller/index.jsx +++ b/src/menu/stylecontroller/index.jsx @@ -194,6 +194,27 @@ } /** + * @description 淇敼鑳屾櫙澶у皬 + */ + changeBackgroundSize = (val) => { + this.updateStyle({backgroundSize: val}) + } + + /** + * @description 淇敼鑳屾櫙浣嶇疆 + */ + changeBackgroundPositon= (val) => { + this.updateStyle({backgroundPositon: val}) + } + + /** + * @description 淇敼鑳屾櫙閲嶅璁剧疆 + */ + changeBackgroundRepeat = (val) => { + this.updateStyle({backgroundRepeat: val}) + } + + /** * @description 淇敼闃村奖棰滆壊 锛岄鑹叉帶浠� */ changeShadowColor = (val) => { @@ -329,7 +350,7 @@ label={<Icon title="瀹藉害" type="column-width" />} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.width || ''} options={['px', 'vh', 'vw']} onChange={this.changeWidth}/> + <StyleInput defaultValue={card.width || ''} options={['px', 'vh', 'vw', '%']} onChange={this.changeWidth}/> </Form.Item> </Col> </Panel> : null} @@ -448,6 +469,48 @@ <SourceComponent value={backgroundImage} type="" placement="right" onChange={this.imgChange}/> </Form.Item> </Col> : null} + {!options.includes('backgroundColor') ? <Col span={24}> + <Form.Item + colon={false} + label="姣斾緥" + labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } + > + <Select defaultValue={card.backgroundSize || 'cover'} onChange={this.changeBackgroundSize}> + <Option value="100%">100%</Option> + <Option value="100% 100%">100% 100%</Option> + <Option value="auto 100%">auto 100%</Option> + <Option value="contain">contain</Option> + <Option value="cover">cover</Option> + </Select> + </Form.Item> + </Col> : null} + {!options.includes('backgroundColor') ? <Col span={24}> + <Form.Item + colon={false} + label="閲嶅" + labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } + > + <Select defaultValue={card.backgroundRepeat || 'no-repeat'} onChange={this.changeBackgroundRepeat}> + <Option value="repeat">repeat</Option> + <Option value="no-repeat">no-repeat</Option> + <Option value="repeat-x">repeat-x</Option> + <Option value="repeat-y">repeat-y</Option> + </Select> + </Form.Item> + </Col> : null} + {!options.includes('backgroundColor') ? <Col span={24}> + <Form.Item + colon={false} + label="浣嶇疆" + labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } + > + <Select defaultValue={card.backgroundPositon || 'center'} onChange={this.changeBackgroundPositon}> + <Option value="center">center</Option> + <Option value="top">top</Option> + <Option value="bottom">bottom</Option> + </Select> + </Form.Item> + </Col> : null} </Panel> : null} {options.includes('border') ? <Panel header="杈规" key="border"> <Col span={24}> @@ -557,7 +620,7 @@ label={<Icon title="涓婅竟璺�" type="arrow-up"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.marginTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/> + <StyleInput defaultValue={card.marginTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/> </Form.Item> </Col> <Col span={24}> @@ -566,7 +629,7 @@ label={<Icon title="涓嬭竟璺�" type="arrow-down"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.marginBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/> + <StyleInput defaultValue={card.marginBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/> </Form.Item> </Col> <Col span={24}> @@ -575,7 +638,7 @@ label={<Icon title="宸﹁竟璺�" type="arrow-left"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.marginLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/> + <StyleInput defaultValue={card.marginLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/> </Form.Item> </Col> <Col span={24}> @@ -584,7 +647,7 @@ label={<Icon title="鍙宠竟璺�" type="arrow-right"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.marginRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/> + <StyleInput defaultValue={card.marginRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/> </Form.Item> </Col> </Panel> : null} @@ -595,7 +658,7 @@ label={<Icon title="涓婅竟璺�" type="arrow-up"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/> + <StyleInput defaultValue={card.paddingTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/> </Form.Item> </Col> <Col span={24}> @@ -604,7 +667,7 @@ label={<Icon title="涓嬭竟璺�" type="arrow-down"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/> + <StyleInput defaultValue={card.paddingBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/> </Form.Item> </Col> <Col span={24}> @@ -613,7 +676,7 @@ label={<Icon title="宸﹁竟璺�" type="arrow-left"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/> + <StyleInput defaultValue={card.paddingLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/> </Form.Item> </Col> <Col span={24}> @@ -622,7 +685,7 @@ label={<Icon title="鍙宠竟璺�" type="arrow-right"/>} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <StyleInput defaultValue={card.paddingRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/> + <StyleInput defaultValue={card.paddingRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/> </Form.Item> </Col> </Panel> : null} @@ -633,7 +696,7 @@ label={<Icon title="娴姩" type="swap" />} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } > - <Radio.Group defaultValue={card.float || 'left'} onChange={(e) => this.changeNormalStyle(e.target.value, 'float')}> + <Radio.Group style={{whiteSpace: 'nowrap'}} defaultValue={card.float || 'left'} onChange={(e) => this.changeNormalStyle(e.target.value, 'float')}> <Radio value="left">宸︽诞鍔�</Radio> <Radio value="right">鍙虫诞鍔�</Radio> <Radio value="none">涓嶆诞鍔�</Radio> diff --git a/src/menu/sysinterface/settingform/baseform/index.jsx b/src/menu/sysinterface/settingform/baseform/index.jsx index fbb22d6..431a905 100644 --- a/src/menu/sysinterface/settingform/baseform/index.jsx +++ b/src/menu/sysinterface/settingform/baseform/index.jsx @@ -242,8 +242,8 @@ message: dict['form.required.input'] + '鍥炶皟琛ㄥ悕!' }, { - max: formRule.input.max, - message: formRule.input.message + max: 50, + message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!' } ] })(<Input placeholder={''} autoComplete="off" />)} diff --git a/src/mob/colorsketch/index.jsx b/src/mob/colorsketch/index.jsx index 753a443..7eb42c9 100644 --- a/src/mob/colorsketch/index.jsx +++ b/src/mob/colorsketch/index.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types' // import { is, fromJS } from 'immutable' import { SketchPicker } from 'react-color' -import { Popover } from 'antd' +import { Popover, Icon } from 'antd' import './index.scss' @@ -20,10 +20,11 @@ } state = { color: '', + allowClear: false } UNSAFE_componentWillMount () { - const { defaultValue, value } = this.props + const { defaultValue, value, allowClear } = this.props let initVal = '' if (this.props['data-__meta']) { @@ -34,7 +35,7 @@ initVal = value } - this.setState({color: initVal}) + this.setState({color: initVal, allowClear: allowClear === true}) } handleChange = (color) => { @@ -45,6 +46,12 @@ }) } + clear = () => { + this.setState({ color: '' }, () => { + this.props.onChange && this.props.onChange('') + }) + } + UNSAFE_componentWillReceiveProps(nextProps) { if (nextProps.value !== undefined && nextProps.value !== this.state.color) { this.setState({ color: nextProps.value }) @@ -52,7 +59,7 @@ } render() { - const { color } = this.state + const { color, allowClear } = this.state return ( <div className="color-sketch-block"> <Popover content={ @@ -62,7 +69,7 @@ <div className="color-sketch-block-inner" style={ {background: color} }></div> </div> </Popover> - <div className="color-sketch-value">{color}</div> + <div className="color-sketch-value">{color}{allowClear && color ? <Icon onClick={this.clear} type="close"/> : null}</div> </div> ) } diff --git a/src/mob/colorsketch/index.scss b/src/mob/colorsketch/index.scss index b6aec44..ce226de 100644 --- a/src/mob/colorsketch/index.scss +++ b/src/mob/colorsketch/index.scss @@ -18,6 +18,7 @@ height: 100%; } .color-sketch-value { + position: relative; display: inline-block; font-size: 13px; width: 160px; @@ -27,6 +28,23 @@ vertical-align: top; white-space: nowrap; overflow: visible; + + .anticon-close { + position: relative; + right: -10px; + font-size: 10px; + padding: 3px; + background: #eeeeee; + border-radius: 50%; + cursor: pointer; + opacity: 0; + transition: opacity 0.3s; + } + } +} +.color-sketch-block:hover { + .anticon-close { + opacity: 1; } } diff --git a/src/mob/components/formdragelement/card.jsx b/src/mob/components/formdragelement/card.jsx new file mode 100644 index 0000000..7447e32 --- /dev/null +++ b/src/mob/components/formdragelement/card.jsx @@ -0,0 +1,200 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon, Button, Popover, Switch, Checkbox, Form } from 'antd' +import moment from 'moment' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const CheckCard = asyncComponent(() => import('@/templates/modalconfig/checkCard')) + +const Card = ({ id, card, moveCard, findCard, editCard, closeCard, copyCard, showField }) => { + const originalIndex = findCard(id).index + const [{ isDragging }, drag] = useDrag({ + item: { type: 'form', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + const [, drop] = useDrop({ + accept: 'form', + canDrop: () => true, + drop: (item) => { + const { id: draggedId, originalIndex } = item + + if (originalIndex === undefined) { + item.dropTargetId = id + } else if (draggedId && draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + } + }) + const opacity = isDragging ? 0 : 1 + + const edit = () => { + editCard(id) + } + + const close = () => { + closeCard(id) + } + + const copy = () => { + copyCard(id) + } + + let selectval = '' + if (card.type === 'select' || card.type === 'link') { + if (card.initval) { + let _option = card.options.filter(option => option.Value === card.initval)[0] + if (_option) { + selectval = _option.Text || '' + } else { + selectval = '' + } + } else if (card.setAll === 'true') { + selectval = card.emptyText || '绌�' + } + } + + let formItem = null + if (card.type === 'text' || card.type === 'number') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval}</div>{card.scan && card.scan !== 'false' ? <div className="am-list-extra"><Icon type="scan" /></div> : null}</div></div>) + } else if (card.type === 'number') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval}</div></div></div>) + } else if (card.type === 'select' || card.type === 'link') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{selectval || '璇烽�夋嫨'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) + } else if (card.type === 'date') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD') : '璇烽�夋嫨'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) + } else if (card.type === 'datemonth') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'month').format('YYYY-MM') : '璇烽�夋嫨'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) + } else if (card.type === 'datetime') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD HH:mm') : '璇烽�夋嫨'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) + } else if (card.type === 'textarea') { + let height = (card.maxRows || 2) * 25 + formItem = (<div className="am-list-item check-card"> + <div className="am-list-line"> + <div className="am-input-label">{card.label}</div> + <div className="am-input-control"> + <div style={{textAlign: 'left', position: 'relative', height, lineHeight: 1.5}}> + {card.initval ? card.initval : <span style={{color: '#bcbcbc'}}>璇疯緭鍏�</span> } + {card.count === 'true' ? <span style={{position: 'absolute', right: 0, bottom: 0}}>0/{card.fieldlength}</span> : null} + </div> + </div> + </div> + </div>) + } else if (card.type === 'fileupload') { + formItem = ( + <div className="am-list-item checkbox"> + <div className="am-list-line"> + <div className="am-input-label">{card.label}</div> + <div className="am-input-control" style={{textAlign: 'left'}}> + {card.fileType !== 'picture-card' ? <Icon type="upload" style={{position: 'absolute', right: '10px', top: '10px'}} /> : null} + {card.fileType === 'picture-card' ? <Button style={{width: '100px', marginBottom: '10px', height: '100px', fontSize: '50px', color: '#d9d9d9'}}><Icon type="plus" /></Button> : null} + </div> + </div> + </div> + ) + } else if (card.type === 'funcvar') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.linkfield}</div></div></div>) + } else if (card.type === 'switch') { + formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-list-switch"><Switch checked={card.initval}/></div></div></div>) + } else if (card.type === 'radio') { + let options = null + if (card.options && card.options.length > 0) { + options = card.options + } else { + options = [ + {key: 'A', Value: 'A', Text: 'A'}, + {key: 'B', Value: 'B', Text: 'B'}, + {key: 'C', Value: 'C', Text: 'C'} + ] + } + + formItem = ( + <div className={'am-list-item checkbox mk-radio ' + (card.arrange || '')}> + <div className="am-list-line"> + <div className="am-input-label">{card.label}</div> + <div className="am-input-control"> + {card.arrange !== 'line' ? <Checkbox.Group value={[card.initval]}> + {options.map(cell => <Checkbox key={cell.key} value={cell.Value}>{cell.Text}</Checkbox>)} + </Checkbox.Group> : <div className="mk-radio-group"> + {options.map(cell => (<div key={cell.key} className="mk-radio-wrapper"> + <span className="radio-value">{cell.Text}</span> + <span className={'radio-check ' + (card.initval === cell.Value ? 'checked' : '')}></span> + </div>))} + </div>} + </div> + </div> + </div>) + } else if (card.type === 'checkbox') { + let _val = card.initval ? card.initval.split(',') : [] + let options = null + if (card.options && card.options.length > 0) { + options = card.options + } else { + options = [ + {key: 'A', Value: 'A', Text: 'A'}, + {key: 'B', Value: 'B', Text: 'B'}, + {key: 'C', Value: 'C', Text: 'C'} + ] + } + + formItem = ( + <div className={'am-list-item checkbox ' + (card.arrange || '')}> + <div className="am-list-line"> + <div className="am-input-label">{card.label}</div> + <div className="am-input-control"> + {<Checkbox.Group value={_val}> + {options.map(cell => <Checkbox key={cell.key} value={cell.Value}>{cell.Text}</Checkbox>)} + </Checkbox.Group>} + </div> + </div> + </div> + ) + + } else if (card.type === 'hint') { + formItem = <div className="am-list-item hint"> + <div className="am-list-line"> + <div className="am-input-label">{card.label}</div> + <div className="am-input-control"> + {card.message} + </div> + </div> + </div> + } else if (card.type === 'split') { + formItem = <div className="split-line">{card.label}</div> + } else if (card.type === 'checkcard') { + formItem = (<div className="am-list-item check-card"> + <div className="am-list-line"> + {card.hidelabel !== 'true' ? <div className="am-input-label">{card.label}</div> : null} + <div className="am-input-control"> + <CheckCard config={card} /> + </div> + </div> + </div>) + } + + return ( + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="edit" type="edit" onClick={edit} /> + <Icon className="copy" type="copy" onClick={copy} /> + <Icon className="close" type="close" onClick={close} /> + </div> + } trigger="hover"> + <div className="page-card" style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + {card.type === 'split' ? formItem : <Form.Item + className={'ant-form-item' + (card.required === 'true' ? ' required' : '') + (card.splitline === 'false' ? ' no-boder' : '')} + > + {formItem} + {showField ? <div className="field-name">{card.field}{card.hidden === 'true' ? '(闅愯棌)' : ''}</div> : ''} + </Form.Item>} + </div> + </div> + </Popover> + ) +} +export default Card diff --git a/src/mob/components/formdragelement/index.jsx b/src/mob/components/formdragelement/index.jsx new file mode 100644 index 0000000..38485bc --- /dev/null +++ b/src/mob/components/formdragelement/index.jsx @@ -0,0 +1,132 @@ +import React, { useState } from 'react' +import { useDrop } from 'react-dnd' +import { is, fromJS } from 'immutable' +import update from 'immutability-helper' +import Utils from '@/utils/utils.js' +import Card from './card' +import './index.scss' + +const Container = ({list, setting, handleList, handleForm, closeForm, showField }) => { + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + + if (!card) return + + const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) + + handleList(_cards) + } + + if (!is(fromJS(cards), fromJS(list))) { + setCards(list) + } + + const findCard = id => { + const card = cards.filter(c => `${c.uuid}` === id)[0] + return { + card, + index: cards.indexOf(card), + } + } + + const editCard = id => { + const { card } = findCard(id) + delete card.focus + handleForm(card) + } + + const closeCard = id => { + const { card } = findCard(id) + closeForm(card) + } + + const copyCard = id => { + const { card, index: overIndex } = findCard(id) + + let _card = fromJS(card).toJS() + _card.uuid = Utils.getuuid() + _card.focus = true + + // 澶嶅埗鍒板壀鍒囨澘 + let oInput = document.createElement('input') + let val = JSON.parse(JSON.stringify(_card)) + val.copyType = 'form' + + oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val))) + document.body.appendChild(oInput) + oInput.select() + document.execCommand('Copy') + oInput.className = 'oInput' + oInput.style.display = 'none' + document.body.removeChild(oInput) + + const _cards = update(cards, { $splice: [[overIndex + 1, 0, _card]] }) + + setCards(_cards) + + handleList(_cards, _card) + } + + const [, drop] = useDrop({ + accept: 'form', + drop(item) { + if (item.hasOwnProperty('originalIndex')) { + return + } + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.label = 'label' + newcard.type = item.subType + newcard.resourceType = '0' + newcard.options = [] + newcard.readonly = 'false' + newcard.required = 'true' + newcard.focus = true + + let targetId = '' + + if (item.dropTargetId) { + targetId = item.dropTargetId + delete item.dropTargetId + } else if (cards.length > 0) { + targetId = cards[cards.length - 1].uuid + } + + const { index: overIndex } = findCard(`${targetId}`) // cards涓虹┖鏃� overIndex 涓� -1 + const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) + + setCards(_cards) + + handleList(_cards, newcard) + } + }) + + let style = {} + if (setting.paddingLeft) { + style.paddingLeft = setting.paddingLeft + } + if (setting.paddingRight) { + style.paddingRight = setting.paddingRight + } + + return ( + <div ref={drop} className="ant-row modal-fields-row mob-form" style={style}> + {cards.map(card => { + return <Card + id={card.uuid} + key={card.uuid} + card={card} + showField={showField} + moveCard={moveCard} + editCard={editCard} + closeCard={closeCard} + copyCard={copyCard} + findCard={findCard} + /> + })} + </div> + ) +} +export default Container diff --git a/src/mob/components/formdragelement/index.scss b/src/mob/components/formdragelement/index.scss new file mode 100644 index 0000000..28a32dc --- /dev/null +++ b/src/mob/components/formdragelement/index.scss @@ -0,0 +1,245 @@ + +.modal-fields-row { + padding-bottom: 35px; + .mob-col.ant-col { + display: inline-block; + float: none; + vertical-align: top; + padding-left: 1.2%; + padding-right: 1.2%; + } + .am-list-item { + font-size: 16px; + padding-left: 10px; + position: relative; + display: flex; + height: 44px; + min-height: 44px; + background-color: #fff; + vertical-align: middle; + overflow: hidden; + transition: background-color 200ms; + align-items: center; + + .am-list-line { + border-bottom: 1px solid #ddd; + align-items: center; + position: relative; + display: flex; + flex: 1 1; + align-self: stretch; + padding-right: 15px; + overflow: hidden; + .am-input-label { + width: 28%; + color: #000; + font-size: 16px; + margin-left: 0; + margin-right: 5px; + text-align: left; + white-space: nowrap; + overflow: hidden; + padding: 2px 0; + text-overflow: ellipsis; + } + .am-list-switch { + flex: 1; + text-align: right; + } + .am-input-control { + font-size: 16px; + flex: 1 1; + text-align: right; + } + .am-input-control.left { + text-align: left; + } + .am-list-extra { + display: block; + width: 15px; + height: 15px; + margin-left: 8px; + i { + vertical-align: top; + } + } + } + } + .am-list-item.check-card { + height: auto; + .am-list-line { + align-items: start; + display: block; + .check-card-edit-box { + margin-top: 0!important; + } + } + } + .am-list-item.hint { + height: auto; + .am-list-line { + align-items: start; + display: block; + .am-input-label { + line-height: 2; + } + .am-input-control { + font-size: 14px; + line-height: 1.5; + text-align: left; + padding-bottom: 5px; + } + } + } + .am-list-item.checkbox { + height: auto; + .am-list-line { + align-items: start; + display: block; + } + .mk-radio-group { + padding-left: 10px; + text-align: left; + + .mk-radio-wrapper:not(:last-child) { + border-bottom: 1px solid #ddd; + } + span { + display: inline-block; + } + .radio-value { + width: calc(100% - 50px); + white-space: nowrap; + overflow: hidden; + padding: 2px 0; + text-overflow: ellipsis; + vertical-align: top; + } + .radio-check { + position: relative; + width: 50px; + height: 30px; + top: 8px; + } + .radio-check.checked::after { + content: ' '; + position: absolute; + display: table; + border: 1px solid #1890ff; + border-top: 0; + border-left: 0; + top: 50%; + left: 22%; + width: 12px; + height: 20px; + transform: rotate(45deg) scale(1) translate(-50%, -50%); + } + } + .ant-checkbox-group { + display: block; + padding-left: 10px; + .ant-checkbox-wrapper { + display: flex; + text-align: left; + font-size: 16px; + .ant-checkbox { + display: block; + width: 30px; + .ant-checkbox-inner { + width: 22px; + height: 22px; + top: 12px; + } + .ant-checkbox-inner::after { + width: 9px; + height: 14px; + } + } + .ant-checkbox + span { + display: block; + flex: 1 1; + border-bottom: 1px solid #ddd; + } + } + .ant-checkbox-wrapper:last-child { + .ant-checkbox + span { + border-bottom: none; + } + } + } + } + .am-list-item.checkbox.mk-radio { + .ant-checkbox-inner { + border-radius: 50%; + } + } + .am-list-item.checkbox:not(.line) { + .ant-checkbox-group { + .ant-checkbox-wrapper { + float: left; + margin-right: 15px; + .ant-checkbox + span { + border-bottom: none; + } + } + } + .mk-radio-group { + .mk-radio-wrapper { + float: left; + margin-right: 15px; + } + } + } + .split-line { + color: #1890ff; + font-size: 16px; + padding-left: 10px; + padding-top: 10px; + border-bottom: 1px solid #e9e9e9; + } + .check-card-edit-box .card-cell span { + line-height: 1.5; + } + .ant-form-item { + cursor: move; + display: flex; + margin-bottom: 0px; + .ant-form-item-control-wrapper::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0; + z-index: 1; + } + .field-name { + margin-left: 10px; + } + .ant-form-item-children { + vertical-align: top; + } + } + .ant-form-item.required { + .am-input-label::before { + display: inline-block; + margin-right: 4px; + color: #f5222d; + font-size: 14px; + font-family: SimSun, sans-serif; + line-height: 1; + content: '*'; + } + } + .ant-form-item.no-boder { + .am-list-line { + border-bottom: none; + } + } +} +.mob-form.modal-fields-row { + .page-card { + margin-bottom: 10px; + } +} \ No newline at end of file diff --git a/src/mob/components/login/mob-login-1/index.jsx b/src/mob/components/login/mob-login-1/index.jsx deleted file mode 100644 index e0b2891..0000000 --- a/src/mob/components/login/mob-login-1/index.jsx +++ /dev/null @@ -1,228 +0,0 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' -import { is, fromJS } from 'immutable' -import { InputItem, Icon, Checkbox, List, Button } from 'antd-mobile' -// import { createForm } from 'rc-form' - -import zhCN from '@/locales/zh-CN/mob.js' -import enUS from '@/locales/en-US/mob.js' -import Utils from '@/utils/utils.js' -import ContentUpdate from '@/mob/contupdate' -import mklogo from '@/assets/mobimg/mklogo.png' -import './index.scss' - -const CheckboxItem = Checkbox.CheckboxItem - -class MobLogin extends Component { - static propTpyes = { - card: PropTypes.object, - editId: PropTypes.any, - triggerEdit: PropTypes.func, - updateConfig: PropTypes.func, - onDoubleClick: PropTypes.func - } - - state = { - dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, - rember: true, - param: { - type: 'login', - subtype: 'mob-login-1', - box: { uuid: Utils.getuuid(), eleType: 'box', style: {color: '#ffffff', backgroundImage: 'linear-gradient(#378DBE, #46C29E, #48A9D6)'}}, - logo: { uuid: Utils.getuuid(), eleType: 'img', content: mklogo, style: {marginTop: '17vh', marginBottom: '15px'} }, - title: { uuid: Utils.getuuid(), eleType: 'text', content: '鏄庣鍟嗕笟鏅鸿兘寮�鏀惧钩鍙�', style: {fontSize: '20px', fontWeight: 'bold', color: '#ffffff', textAlign: 'center', marginTop: '15px', marginBottom: '30px'}}, - login: { uuid: Utils.getuuid(), eleType: 'button', content: '鐧诲綍', style: {fontSize: '18px', color: '#ffffff', textAlign: 'center', lineHeight: 2.4, borderRadius: '25px', marginBottom: '15vh'}}, - copyright: { uuid: Utils.getuuid(), eleType: 'textarea', content: 'Copyright漏2017 鎵�鏈夌浉鍏崇増鏉冨綊 鍖椾含鏄庣鏅崕淇℃伅鎶�鏈湁闄愬叕鍙�', style: {fontSize: '12px', color: '#ffffff', textAlign: 'center'} } - } - } - - UNSAFE_componentWillMount () { - const { card } = this.props - const { param } = this.state - - if (!card.box) { - this.props.updateConfig({...param, ...card}) - } - } - - shouldComponentUpdate (nextProps, nextState) { - return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) - } - - onChange = (e) => { - const { rember } = this.state - e.stopPropagation() - - this.setState({ - rember: !rember - }) - } - - onChangeLang = (value) => { - this.setState({ - lang: value - }) - } - - editLogo = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.logo.style).toJS(), - componentId: card.uuid, - uuid: card.logo.uuid, - items: ['margin'] - } - this.props.triggerEdit(element) - } - - editTitle = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.title.style).toJS(), - componentId: card.uuid, - uuid: card.title.uuid, - items: ['font', 'margin'], - } - this.props.triggerEdit(element) - } - - editMsg = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.copyright.style).toJS(), - componentId: card.uuid, - uuid: card.copyright.uuid, - items: ['font'], - } - this.props.triggerEdit(element) - } - - editLogin = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.login.style).toJS(), - componentId: card.uuid, - uuid: card.login.uuid, - items: ['font', 'background', 'border', 'margin'] - } - this.props.triggerEdit(element) - } - - editBox = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.box.style).toJS(), - componentId: card.uuid, - uuid: card.box.uuid, - items: ['font', 'padding', 'background'], - } - this.props.triggerEdit(element) - } - - updateContent = (card) => { - Object.keys(card).forEach(key => { - if (card[key] === null) { - delete card[key] - } - }) - this.props.updateConfig(card) - } - - render () { - const { card, editId } = this.props - // const { getFieldProps } = this.props.form - const { rember } = this.state - - if (!card.box) return null - - let logoStyle = card.logo && card.logo.style ? fromJS(card.logo.style).toJS() : null - if (logoStyle && logoStyle.marginTop && /vh$/ig.test(logoStyle.marginTop)) { - let percent = parseInt(logoStyle.marginTop) - logoStyle.marginTop = `calc(${(percent / 100) * 615}px)` - } - if (logoStyle && logoStyle.marginBottom && /vh$/ig.test(logoStyle.marginBottom)) { - let percent = parseInt(logoStyle.marginBottom) - logoStyle.marginBottom = `calc(${(percent / 100) * 625}px)` - } - - let titleStyle = card.title && card.title.style ? fromJS(card.title.style).toJS() : null - if (titleStyle && titleStyle.marginTop && /vh$/ig.test(titleStyle.marginTop)) { - let percent = parseInt(titleStyle.marginTop) - titleStyle.marginTop = `calc(${(percent / 100) * 615}px)` - } - if (titleStyle && titleStyle.marginBottom && /vh$/ig.test(titleStyle.marginBottom)) { - let percent = parseInt(titleStyle.marginBottom) - titleStyle.marginBottom = `calc(${(percent / 100) * 615}px)` - } - - let loginStyle = fromJS(card.login.style).toJS() - if (loginStyle.marginTop && /vh$/ig.test(loginStyle.marginTop)) { - let percent = parseInt(loginStyle.marginTop) - loginStyle.marginTop = `calc(${(percent / 100) * 615}px)` - } - if (loginStyle.marginBottom && /vh$/ig.test(loginStyle.marginBottom)) { - let percent = parseInt(loginStyle.marginBottom) - loginStyle.marginBottom = `calc(${(percent / 100) * 615}px)` - } - - return ( - <div className="mob-login-1" onClick={this.editBox} style={card.box.style}> - {card.logo ? <div className={'logo ' + (editId === card.logo.uuid ? 'editing' : '')} style={logoStyle} onClick={this.editLogo}> - <ContentUpdate element={card.logo} updateContent={(ele) => this.updateContent({...card, logo: ele})}/> - <img src={card.logo.content} alt=""/> - </div> : null} - {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}> - <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/> - {card.title.content} - </div> : null} - <InputItem - placeholder={"UserName"} - prefixListCls="mk-login-item am-list" - disabled={true} - > - <Icon type="check-circle-o" /> - </InputItem> - <InputItem - placeholder="Password" - prefixListCls="mk-login-item am-list" - type={'password'} - disabled={true} - > - <Icon type="check-circle" /> - </InputItem> - <div className="other-setting"> - <CheckboxItem checked={rember} onChange={this.onChange}> - <span onClick={this.onChange}>璁颁綇瀵嗙爜</span> - </CheckboxItem> - {/* <Picker data={langs} value={lang} cols={1} onChange={this.onChangeLang} className="forss"> - <List.Item>{lang}</List.Item> - </Picker> */} - <List.Item className="lang">涓枃绠�浣�</List.Item> - <div className="clear-both"></div> - </div> - <Button - type="primary" - className={'login ' + (editId === card.login.uuid ? 'editing' : '')} - onDoubleClick={() => this.props.doubleClickCard(card.login)} - style={loginStyle} - onClick={this.editLogin} - > - <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/> - {card.login.content} - </Button> - {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}> - <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/> - {card.copyright.content} - </div> : null} - </div> - ) - } -} - -// export default createForm()(MobLogin) -export default MobLogin \ No newline at end of file diff --git a/src/mob/components/login/mob-login-1/index.scss b/src/mob/components/login/mob-login-1/index.scss deleted file mode 100644 index 4ce0042..0000000 --- a/src/mob/components/login/mob-login-1/index.scss +++ /dev/null @@ -1,192 +0,0 @@ -.mob-login-1 { - position: relative; - width: 100%; - min-height: 100%; - overflow-x: hidden; - background-repeat: no-repeat; - background-size: cover; - background-position: center center; - border-top: 1px solid transparent; - - .logo { - position: relative; - font-size: 14px; - max-width: 280px; - min-height: 10px; - margin: 0 auto; - text-align: center; - line-height: 1.5; - border: 1px dotted transparent; - img { - max-width: 100%; - } - } - .logo.editing { - border: 1px solid #1890ff; - box-shadow: 0px 0px 2px #1890ff; - } - .logo:not(.editing):hover { - border-color: #535353; - } - - .plat-name { - position: relative; - max-width: 280px; - min-height: 10px; - margin: 0 auto; - margin-top: 15px; - margin-bottom: 30px; - text-align: center; - line-height: 1.5; - font-size: 20px; - color: #ffffff; - font-weight: bold; - letter-spacing: 0px; - border: 1px dotted transparent; - } - .plat-name.editing { - border: 1px solid #1890ff; - box-shadow: 0px 0px 2px #1890ff; - } - .plat-name:not(.editing):hover { - border-color: #535353; - } - - .mk-login-item.am-list-item { - position: relative; - z-index: 1; - width: 245px; - font-size: 14px; - max-width: 270px; - line-height: 1.5; - margin: 0 auto; - margin-bottom: 10px; - border-radius: 30px; - background-color: rgba(255, 255, 255, 0.3); - .am-input-label { - width: 30px; - color: inherit; - padding-top: 10px; - } - input { - color: inherit; - } - input::-webkit-input-placeholder { - color: inherit; - } - input:-moz-placeholder { - color: inherit; - } - input::-moz-placeholder { - color: inherit; - } - input:-ms-input-placeholder { - color: inherit; - } - - .am-input-control input:disabled { - background-color: transparent; - } - } - .am-list-item:not(:last-child) .am-list-line { - border: none; - } - .other-setting { - position: relative; - z-index: 1; - font-size: 14px; - width: 245px; - max-width: 270px; - line-height: 1.5; - margin: 0 auto; - margin-bottom: 10px; - .am-list-item { - float: left; - background: transparent; - width: 50%; - padding: 0; - .am-list-thumb:first-child { - margin-right: 5px; - cursor: pointer; - - .am-checkbox-inner { - width: 18px; - height: 18px; - } - .am-checkbox-inner:after { - width: 5px; - height: 9px; - } - } - .am-list-line .am-list-content { - font-size: 14px; - color: inherit; - cursor: pointer; - } - .am-list-extra { - display: none; - } - } - - .am-list-item.lang { - float: right; - .am-list-line { - padding-right: 10px; - .am-list-content { - text-align: right; - cursor: default; - } - } - } - } - .am-button { - position: relative; - z-index: 1; - width: 245px; - max-width: 270px; - margin: 0 auto; - border: 1px dotted transparent; - overflow: visible; - letter-spacing: 0px; - background-repeat: no-repeat; - background-size: cover; - background-position: center center; - - span { - font-style: inherit; - font-weight: inherit; - } - } - .am-button:hover { - color: #fff; - border-color: #535353; - } - .company-msg { - max-width: 280px; - min-height: 10px; - margin: 0 auto; - font-size: 12px; - color: #fafafa; - text-align: center; - line-height: 1.5; - letter-spacing: 0px; - border: 1px dotted transparent; - } - .company-msg.editing { - border: 1px solid #1890ff; - box-shadow: 0px 0px 2px #1890ff; - } - .company-msg:not(.editing):hover { - border-color: #535353; - } -} -.am-picker-popup-wrap { - left: calc(50vw - 305px); - right: calc(50vw - 45px); - bottom: 54px; - overflow: hidden; -} -.clear-both { - float: none!important; - clear: both; -} \ No newline at end of file diff --git a/src/mob/components/login/mob-login-2/index.jsx b/src/mob/components/login/mob-login-2/index.jsx deleted file mode 100644 index e9aa20c..0000000 --- a/src/mob/components/login/mob-login-2/index.jsx +++ /dev/null @@ -1,423 +0,0 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' -import { is, fromJS } from 'immutable' -import { InputItem, Button } from 'antd-mobile' -import { Icon } from 'antd' - -import zhCN from '@/locales/zh-CN/mob.js' -import enUS from '@/locales/en-US/mob.js' -import Utils from '@/utils/utils.js' -import ContentUpdate from '@/mob/contupdate' -import ContentDelete from '@/mob/contdelete' -import './index.scss' - -class MobLogin2 extends Component { - static propTpyes = { - card: PropTypes.object, - editId: PropTypes.any, - triggerEdit: PropTypes.func, - updateConfig: PropTypes.func, - onDoubleClick: PropTypes.func - } - - state = { - dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, - view: 'account', - param: { - type: 'login', - subtype: 'mob-login-2', - box: { uuid: Utils.getuuid(), eleType: 'box', style: {}}, - title: { - uuid: Utils.getuuid(), eleType: 'text', content: '鐧诲綍', - style: { - fontSize: '18px', fontWeight: 'bold', color: '#000000', textAlign: 'center', marginTop: '10vh', marginBottom: '10vh' - } - }, - user: { uuid: Utils.getuuid(), eleType: 'input', content: '閭/鎵嬫満', style: {}}, - password: { uuid: Utils.getuuid(), eleType: 'input', content: '瀵嗙爜', style: {}}, - login: { - uuid: Utils.getuuid(), eleType: 'button', content: '鐧诲綍', - style: { - fontSize: '16px', color: '#ffffff', textAlign: 'center', lineHeight: 2.4, backgroundColor: '#44a8f2' - } - }, - phone: { - uuid: Utils.getuuid(), eleType: 'button', content: '鎵嬫満鐭俊鐧诲綍', - style: { - fontSize: '16px', color: '#44a8f2', textAlign: 'center', lineHeight: 2.4, border: '1px solid #44a8f2' - } - }, - register: { - uuid: Utils.getuuid(), eleType: 'text', content: '娉ㄥ唽', - style: { - fontSize: '14px', color: '#44a8f2', textAlign: 'left' - } - }, - lose: { - uuid: Utils.getuuid(), eleType: 'text', content: '蹇樿瀵嗙爜锛�', - style: { - fontSize: '14px', color: '#44a8f2', textAlign: 'right', textDecoration: 'underline' - } - }, - auth: { - uuid: Utils.getuuid(), eleType: 'text', content: '鍏朵粬鐧诲綍鏂瑰紡', - style: { - fontSize: '14px', color: '#bcbcbc', textAlign: 'center', marginTop: '30px', marginBottom: '20px' - } - }, - authlist: { - uuid: Utils.getuuid(), - subItems: [ - {uuid: 'qq', type: 'qq', icon: 'qq', label: 'QQ'}, - {uuid: 'wechat', type: 'wechat', icon: 'wechat', label: '寰俊'}, - ], - }, - copyright: { - uuid: Utils.getuuid(), eleType: 'textarea', content: 'Copyright漏2017 鎵�鏈夌浉鍏崇増鏉冨綊 鍖椾含鏄庣鏅崕淇℃伅鎶�鏈湁闄愬叕鍙�', - style: { - fontSize: '12px', textAlign: 'center', color: 'rgba(0, 0, 0, 0.65)' - } - }, - links: { - uuid: Utils.getuuid(), eleType: 'link', substyle: false, - subItems: [ - {eleType: 'link', content: '闅愮鏀跨瓥', url: '', uuid: Utils.getuuid()}, - {eleType: 'link', content: '浣跨敤鏉℃', url: '', uuid: Utils.getuuid()}, - ], - style: { - fontSize: '12px', textAlign: 'center', color: '#44a8f2', textDecoration: 'underline' - } - }, - account: { - uuid: Utils.getuuid(), eleType: 'button', content: '璐﹀彿瀵嗙爜鐧诲綍', - style: { - fontSize: '16px', color: '#44a8f2', textAlign: 'center', lineHeight: 2.4, border: '1px solid #44a8f2' - } - }, - } - } - - UNSAFE_componentWillMount () { - const { card } = this.props - const { param } = this.state - - if (!card.box) { - this.props.updateConfig({...param, ...card}) - } - } - - shouldComponentUpdate (nextProps, nextState) { - return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) - } - - editTitle = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.title.style).toJS(), - componentId: card.uuid, - uuid: card.title.uuid, - items: ['font', 'margin'], - } - this.props.triggerEdit(element) - } - - editPlaceholder = (e, type) => { - const { card } = this.props - e.stopPropagation() - let element = { - componentId: card.uuid, - uuid: card[type].uuid, - items: [''], - } - this.props.triggerEdit(element) - } - - editMsg = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.copyright.style).toJS(), - componentId: card.uuid, - uuid: card.copyright.uuid, - items: ['font', 'margin'], - } - this.props.triggerEdit(element) - } - - editLinks = (e, item) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.links.style).toJS(), - componentId: card.uuid, - classId: card.links.uuid, - uuid: item.uuid, - items: ['font'], - } - this.props.triggerEdit(element) - } - - editLogin = (e, type) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card[type].style).toJS(), - componentId: card.uuid, - uuid: card[type].uuid, - items: ['font', 'background', 'border', 'margin'] - } - this.props.triggerEdit(element) - } - - editLose = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.lose.style).toJS(), - componentId: card.uuid, - uuid: card.lose.uuid, - items: ['font'], - } - this.props.triggerEdit(element) - } - - editRegister = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.register.style).toJS(), - componentId: card.uuid, - uuid: card.register.uuid, - items: ['font'], - } - this.props.triggerEdit(element) - } - - editAuth = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.auth.style).toJS(), - componentId: card.uuid, - uuid: card.auth.uuid, - items: ['font', 'margin'], - } - this.props.triggerEdit(element) - } - - editBox = (e) => { - const { card } = this.props - e.stopPropagation() - let element = { - ...fromJS(card.box.style).toJS(), - componentId: card.uuid, - uuid: card.box.uuid, - items: ['font', 'padding', 'background'], - } - this.props.triggerEdit(element) - } - - linkItemAdd = (e) => { - let card = fromJS(this.props.card).toJS() - e.stopPropagation() - - card.links.subItems.push({ - eleType: 'link', - content: 'link', - url: '', - uuid: Utils.getuuid() - }) - - this.props.updateConfig(card) - } - - updateContent = (card) => { - this.props.updateConfig(card) - } - - updateLinkItem = (val, item) => { - let card = fromJS(this.props.card).toJS() - - if (!val) { - card.links.subItems = card.links.subItems.filter(cell => cell.uuid !== item.uuid) - } else { - card.links.subItems = card.links.subItems.map(cell => { - if (cell.uuid === item.uuid) { - return val - } else { - return cell - } - }) - } - - this.props.updateConfig(card) - } - - render () { - const { card, editId } = this.props - const { view } = this.state - - if (!card.box) return null - - let titleStyle = card.title && card.title.style ? fromJS(card.title.style).toJS() : null - if (titleStyle && titleStyle.marginTop && /vh$/ig.test(titleStyle.marginTop)) { - let percent = parseInt(titleStyle.marginTop) - titleStyle.marginTop = `calc(${(percent / 100) * 615}px)` - } - if (titleStyle && titleStyle.marginBottom && /vh$/ig.test(titleStyle.marginBottom)) { - let percent = parseInt(titleStyle.marginBottom) - titleStyle.marginBottom = `calc(${(percent / 100) * 615}px)` - } - - if (view === 'account') { - return ( - <div className="mob-login-2" onClick={this.editBox} style={card.box.style}> - {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}> - <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/> - {card.title.content} - </div> : null} - - <div className={`mk-login-input ${editId === card.user.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'user')}> - <ContentUpdate element={card.user} deletable={false} updateContent={(ele) => this.updateContent({...card, user: ele})}/> - <InputItem disabled={true} placeholder={card.user.content}></InputItem> - </div> - <div className={`mk-login-input ${editId === card.password.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'password')}> - <ContentUpdate element={card.password} deletable={false} updateContent={(ele) => this.updateContent({...card, password: ele})}/> - <InputItem disabled={true} placeholder={card.password.content}></InputItem> - </div> - <Button - className={'login ' + (editId === card.login.uuid ? 'editing' : '')} - onDoubleClick={() => this.props.doubleClickCard(card.login)} - style={card.login.style} - onClick={(e) => this.editLogin(e, 'login')} - > - <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/> - {card.login.content} - </Button> - <Button - className={'login ' + (editId === card.phone.uuid ? 'editing' : '')} - onDoubleClick={() => this.setState({view: 'phone'})} - style={card.phone.style} - onClick={(e) => this.editLogin(e, 'phone')} - > - <ContentUpdate element={card.phone} updateContent={(ele) => this.updateContent({...card, phone: ele})}/> - {card.phone.content} - </Button> - <div className="row-box"> - {card.register ? <div className={'col-item ' + (editId === card.register.uuid ? 'editing' : '')} style={card.register.style} onClick={this.editRegister}> - <ContentUpdate element={card.register} updateContent={(ele) => this.updateContent({...card, register: ele})}/> - {card.register.content} - </div> : null} - {card.lose ? <div className={'col-item right ' + (editId === card.lose.uuid ? 'editing' : '')} style={card.lose.style} onClick={this.editLose}> - <ContentUpdate element={card.lose} updateContent={(ele) => this.updateContent({...card, lose: ele})}/> - {card.lose.content} - </div> : null} - <div style={{clear: 'both'}}></div> - </div> - {card.auth ? <div className={'plat-name ' + (editId === card.auth.uuid ? 'editing' : '')} style={card.auth.style} onClick={this.editAuth}> - <ContentUpdate element={card.auth} updateContent={(ele) => this.updateContent({...card, auth: ele})}/> - {card.auth.content} - </div> : null} - {card.authlist ? <div className="other-auth"> - {card.authlist.subItems.map(cell => ( - <span className="deletable-item" key={cell.type}> - <ContentDelete element={cell} list={card.authlist} updateContent={(ele) => this.updateContent({...card, authlist: ele})}/> - <Icon type={cell.icon} /> - <p>{cell.label}</p> - </span> - ))} - </div> : null} - {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}> - <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/> - {card.copyright.content} - </div> : null} - {card.links ? <div className="links" style={card.links.style}> - {card.links.subItems.map(item => ( - <span className={(editId === item.uuid ? 'editing' : '')} key={item.uuid} onClick={(e) => this.editLinks(e, item)}> - <ContentUpdate element={item} updateContent={(val) => this.updateLinkItem(val, item)}/> - {item.content} - </span> - ))} - <Icon type="plus" onClick={this.linkItemAdd} /> - </div> : null} - </div> - ) - } else if (view === 'phone') { - return ( - <div className="mob-login-2" onClick={this.editBox} style={card.box.style}> - {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}> - <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/> - {card.title.content} - </div> : null} - - <div className={`mk-login-input ${editId === card.user.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'user')}> - <ContentUpdate element={card.user} deletable={false} updateContent={(ele) => this.updateContent({...card, user: ele})}/> - <InputItem disabled={true} placeholder={card.user.content}></InputItem> - </div> - <div className={`mk-login-input ${editId === card.password.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'password')}> - <ContentUpdate element={card.password} deletable={false} updateContent={(ele) => this.updateContent({...card, password: ele})}/> - <InputItem disabled={true} placeholder={card.password.content}></InputItem> - </div> - <Button - className={'login ' + (editId === card.login.uuid ? 'editing' : '')} - onDoubleClick={() => this.props.doubleClickCard(card.login)} - style={card.login.style} - onClick={(e) => this.editLogin(e, 'login')} - > - <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/> - {card.login.content} - </Button> - <Button - className={'login ' + (editId === card.account.uuid ? 'editing' : '')} - onDoubleClick={() => this.setState({view: 'account'})} - style={card.account.style} - onClick={(e) => this.editLogin(e, 'account')} - > - <ContentUpdate element={card.account} updateContent={(ele) => this.updateContent({...card, account: ele})}/> - {card.account.content} - </Button> - <div className="row-box"> - {card.register ? <div className={'col-item ' + (editId === card.register.uuid ? 'editing' : '')} style={card.register.style} onClick={this.editRegister}> - <ContentUpdate element={card.register} updateContent={(ele) => this.updateContent({...card, register: ele})}/> - {card.register.content} - </div> : null} - {card.lose ? <div className={'col-item right ' + (editId === card.lose.uuid ? 'editing' : '')} style={card.lose.style} onClick={this.editLose}> - <ContentUpdate element={card.lose} updateContent={(ele) => this.updateContent({...card, lose: ele})}/> - {card.lose.content} - </div> : null} - <div style={{clear: 'both'}}></div> - </div> - {card.auth ? <div className={'plat-name ' + (editId === card.auth.uuid ? 'editing' : '')} style={card.auth.style} onClick={this.editAuth}> - <ContentUpdate element={card.auth} updateContent={(ele) => this.updateContent({...card, auth: ele})}/> - {card.auth.content} - </div> : null} - {card.authlist ? <div className="other-auth"> - {card.authlist.subItems.map(cell => ( - <span className="deletable-item" key={cell.type}> - <ContentDelete element={cell} list={card.authlist} updateContent={(ele) => this.updateContent({...card, authlist: ele})}/> - <Icon type={cell.icon} /> - <p>{cell.label}</p> - </span> - ))} - </div> : null} - {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}> - <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/> - {card.copyright.content} - </div> : null} - {card.links ? <div className="links" style={card.links.style}> - {card.links.subItems.map(item => ( - <span className={(editId === item.uuid ? 'editing' : '')} key={item.uuid} onClick={(e) => this.editLinks(e, item)}> - <ContentUpdate element={item} updateContent={(val) => this.updateLinkItem(val, item)}/> - {item.content} - </span> - ))} - <Icon type="plus" onClick={this.linkItemAdd} /> - </div> : null} - </div> - ) - } - } -} - -export default MobLogin2 \ No newline at end of file diff --git a/src/mob/components/login/mob-login-2/index.scss b/src/mob/components/login/mob-login-2/index.scss deleted file mode 100644 index 59cd1e1..0000000 --- a/src/mob/components/login/mob-login-2/index.scss +++ /dev/null @@ -1,201 +0,0 @@ -.mob-login-2 { - position: relative; - width: 100%; - min-height: 100%; - overflow-x: hidden; - background-repeat: no-repeat; - background-size: cover; - background-position: center center; - - .plat-name { - position: relative; - max-width: 280px; - min-height: 10px; - margin: 0 auto; - text-align: center; - line-height: 1.5; - font-size: 18px; - color: #ffffff; - border: 1px dotted transparent; - } - .plat-name.editing { - border: 1px solid #1890ff; - box-shadow: 0px 0px 2px #1890ff; - } - .plat-name:not(.editing):hover { - border-color: #535353; - } - .row-box { - position: relative; - width: 280px; - margin: 0 auto; - line-height: 1.5; - - .col-item { - position: relative; - display: inline-block; - width: 50%; - border: 1px dotted transparent; - } - .col-item.right { - float: right; - } - - .col-item.editing { - border: 1px solid #1890ff; - box-shadow: 0px 0px 2px #1890ff; - } - .col-item:not(.editing):hover { - border-color: #535353; - } - } - .other-auth { - text-align: center; - font-size: 26px; - color: rgb(68, 168, 242); - - span { - position: relative; - display: inline-block; - vertical-align: top; - p { - font-size: 12px; - margin-bottom: 10px; - } - } - span:not(:last-child) { - margin-right: 15px; - } - } - - .am-list-item { - position: relative; - z-index: 1; - width: 100%; - font-size: 14px; - height: 38px; - min-height: 38px; - line-height: 1.5; - margin-bottom: 10px; - border: 1px solid #dddddd; - - .am-input-control input:disabled { - color: rgba(0, 0, 0, 0.65); - } - - .am-input-label { - width: 30px; - color: inherit; - padding-top: 10px; - } - input { - font-size: 14px; - color: inherit; - } - input::-webkit-input-placeholder { - color: inherit; - opacity: 0.5; - } - input:-moz-placeholder { - color: inherit; - opacity: 0.5; - } - input::-moz-placeholder { - color: inherit; - opacity: 0.5; - } - input:-ms-input-placeholder { - color: inherit; - opacity: 0.5; - } - } - .am-list-item:not(:last-child) .am-list-line { - border: none; - } - - .mk-login-input { - width: 280px; - position: relative; - margin: 0 auto; - } - - .am-button { - position: relative; - z-index: 1; - width: 280px; - margin: 0 auto 10px; - border: 1px dotted transparent; - overflow: visible; - letter-spacing: 0px; - background-repeat: no-repeat; - background-size: cover; - background-position: center center; - border-radius: 0; - - span { - font-style: inherit; - font-weight: inherit; - } - } - .am-button:hover { - color: unset; - border-color: #535353; - } - .company-msg { - width: 88%; - min-height: 10px; - margin-left: 6%; - font-size: 12px; - text-align: center; - line-height: 1.5; - letter-spacing: 0px; - border: 1px dotted transparent; - } - .company-msg.editing { - border: 1px solid #1890ff; - box-shadow: 0px 0px 2px #1890ff; - } - .company-msg:not(.editing):hover { - border-color: #535353; - } - - .links { - min-height: 10px; - font-size: 12px; - text-align: center; - line-height: 1.5; - - span { - display: inline-block; - position: relative; - text-decoration: inherit; - font-style: inherit; - min-width: 40px; - border: 1px dotted transparent; - } - span:not(:last-child) { - margin-right: 10px; - } - span:hover { - border-color: #535353; - } - span.editing { - border: 1px solid #1890ff; - box-shadow: 0px 0px 2px #1890ff; - } - >.anticon-plus { - cursor: pointer; - color: #26C281; - } - } -} -.am-picker-popup-wrap { - left: calc(50vw - 305px); - right: calc(50vw - 45px); - bottom: 54px; - overflow: hidden; -} -.clear-both { - float: none!important; - clear: both; -} \ No newline at end of file diff --git a/src/mob/components/menubar/normal-menubar/index.jsx b/src/mob/components/menubar/normal-menubar/index.jsx new file mode 100644 index 0000000..e02f32e --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/index.jsx @@ -0,0 +1,265 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover, Modal } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' +import { resetStyle } from '@/utils/utils-custom.js' +import MKEmitter from '@/utils/events.js' +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import './index.scss' + +const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) +const MenuComponent = asyncComponent(() => import('./menucomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) +const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) +const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) + +const { confirm } = Modal + +class NoramlMenuBar extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + back: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + tabId: '', + parentId: '', + dataName: card.dataName || '', + width: card.width || 24, + name: card.name, + subtype: card.subtype, + wrap: { name: card.name, width: card.width || 24, title: '' }, + style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, + headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, + subMenus: [{ + uuid: Utils.getuuid(), + setting: { type: 'menu', width: 6, sign: 'icon', icon: 'user', name: '瀹㈡埛', url: '', color: '#ffffff', iconFont: 20, padding: 12, background: '#1890ff', imgWidth: '' }, + style: { + paddingTop: '15px', paddingBottom: '15px' + } + }] + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.wrap.name = card.name + _card.style = config.style + _card.headerStyle = config.headerStyle + + _card.subMenus = config.subMenus.map(item => { + item.uuid = Utils.getuuid() + + return item + }) + } + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (component) => { + this.setState({ + card: component + }) + + component.width = component.wrap.width + component.name = component.wrap.name + + this.props.updateConfig(component) + } + + /** + * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 + */ + updateCard = (cell) => { + let card = fromJS(this.state.card).toJS() + + card.subMenus = card.subMenus.map(item => { + if (item.uuid === cell.uuid) return cell + return item + }) + + this.setState({card}) + + this.props.updateConfig(card) + } + + /** + * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 + */ + deleteCard = (cell) => { + let card = fromJS(this.state.card).toJS() + let _this = this + + confirm({ + content: '纭畾鍒犻櫎鍗$墖鍚楋紵', + onOk() { + card.subMenus = card.subMenus.filter(item => item.uuid !== cell.uuid) + + _this.setState({card}) + _this.props.updateConfig(card) + }, + onCancel() {} + }) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds.length !== 1 || comIds[0] !== card.uuid) return + + let _card = {...card, style} + + this.setState({ + card: _card + }) + + this.props.updateConfig(_card) + } + + addMenu = () => { + let card = fromJS(this.state.card).toJS() + + let newcard = { + uuid: Utils.getuuid(), + setting: { type: 'menu', width: 6, sign: 'icon', icon: 'user', name: '瀹㈡埛', url: '', color: '#ffffff', iconFont: 20, padding: 12, background: '#1890ff', imgWidth: '' }, + style: { + paddingTop: '15px', paddingBottom: '15px' + }, + isnew: true + } + + if (card.subMenus.length > 0) { + newcard = fromJS(card.subMenus.slice(-1)[0]).toJS() + newcard.uuid = Utils.getuuid() + newcard.isnew = true + } + + card.subMenus.push(newcard) + + this.setState({card}) + this.props.updateConfig(card) + } + + move = (item, direction) => { + let card = fromJS(this.state.card).toJS() + + let dragIndex = card.subMenus.findIndex(c => c.uuid === item.uuid) + let hoverIndex = null + + if (direction === 'left') { + hoverIndex = dragIndex - 1 + } else { + hoverIndex = dragIndex + 1 + } + + if (hoverIndex === -1 || hoverIndex === card.subMenus.length) return + + card.subMenus.splice(hoverIndex, 0, ...card.subMenus.splice(dragIndex, 1)) + + this.setState({card}) + this.props.updateConfig(card) + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + render() { + const { card } = this.state + + let offset = 0 + if (card.wrap.cardFloat && card.wrap.cardFloat !== 'left') { + let _width = 0 + card.subMenus.forEach(card => { + _width += card.setting.width + }) + offset = _width < 24 ? 24 - _width : 0 + if (card.wrap.cardFloat === 'center') { + offset = Math.floor(offset / 2) + } + } + + let _style = resetStyle(card.style) + + return ( + <div className="menu-menubar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> + <NormalHeader config={card} updateComponent={this.updateComponent}/> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="plus" title="娣诲姞鑿滃崟" onClick={this.addMenu} type="plus" /> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="normalmenu" card={card}/> + <PasteComponent config={card} options={['menucell']} updateConfig={this.updateComponent} /> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <UserComponent config={card}/> + <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + {card.subMenus.map((menu, index) => (<MenuComponent key={menu.uuid} offset={!index ? offset : 0} cards={card} card={menu} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} + </div> + ) + } +} + +export default NoramlMenuBar \ No newline at end of file diff --git a/src/mob/components/menubar/normal-menubar/index.scss b/src/mob/components/menubar/normal-menubar/index.scss new file mode 100644 index 0000000..c4c97f1 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/index.scss @@ -0,0 +1,62 @@ +.menu-menubar-edit-box { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 20px; + + .card-control { + position: absolute; + top: 0px; + left: 0px; + .anticon-tool { + right: auto; + left: 1px; + padding: 1px; + } + } + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + + .menu-item { + overflow: hidden; + position: relative; + min-height: 20px; + .menu-name { + text-align: center; + font-style: inherit; + font-weight: inherit; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .menu-sign { + text-align: center; + .anticon { + border-radius: 50%; + } + img { + border-radius: 50%; + } + } + } +} +.menu-menubar-edit-box::after { + display: block; + content: ' '; + clear: both; +} +.menu-menubar-edit-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/index.jsx b/src/mob/components/menubar/normal-menubar/menucomponent/index.jsx new file mode 100644 index 0000000..b85cfd5 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/menucomponent/index.jsx @@ -0,0 +1,218 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Modal, Popover, Icon, Col } from 'antd' + +import asyncIconComponent from '@/utils/asyncIconComponent' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import Utils from '@/utils/utils.js' +import SettingForm from './settingform' +import { resetStyle } from '@/utils/utils-custom.js' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const { confirm } = Modal +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) + +class MenuBoxComponent extends Component { + static propTpyes = { + offset: PropTypes.any, // 鍋忕Щ閲� + cards: PropTypes.object, // 鍗$墖琛岄厤缃俊鎭� + card: PropTypes.object, // 鍗$墖閰嶇疆淇℃伅 + move: PropTypes.func, // 鍗$墖绉诲姩 + deleteElement: PropTypes.func, // 鍗$墖鍒犻櫎 + updateElement: PropTypes.func // 鑿滃崟閰嶇疆鏇存柊 + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + formlist: null, + visible: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + this.setState({ + card: fromJS(card).toJS() + }) + } + + componentDidMount () { + const { card } = this.props + MKEmitter.addListener('submitStyle', this.getStyle) + + if (card.isnew) { + this.setState({ + visible: true + }) + } + } + + shouldComponentUpdate (nextProps, nextState) { + const { cards } = this.props + + return !is(fromJS(cards.wrap), fromJS(nextProps.cards.wrap)) || !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + getStyle = (comIds, style) => { + const { cards } = this.props + const { card } = this.state + + if (comIds.length !== 2 || comIds[0] !== cards.uuid || comIds[1] !== card.uuid) return + + let _card = fromJS(card).toJS() + _card.style = style + + this.setState({ + card: _card + }) + + this.props.updateElement(_card) + } + + changeStyle = () => { + const { cards } = this.props + const { card } = this.state + + let _style = card.style ? fromJS(card.style).toJS() : {} + let options = ['font', 'border', 'padding'] + + MKEmitter.emit('changeStyle', [cards.uuid, card.uuid], options, _style) + } + + settingSubmit = () => { + const { card } = this.state + + this.settingRef.handleConfirm().then(res => { + let _card = {...card, setting: res} + + if (!card.isnew && card.setting.type === 'menu' && _card.setting.type !== 'menu') { + const _this = this + confirm({ + content: '鑿滃崟灞炴�х敱鈥滆彍鍗曗�濆垏鎹㈣嚦鍏朵粬绫诲瀷鏃讹紝鑿滃崟灏嗚閲嶇疆锛屽嵆瑙i櫎涔嬪墠鑿滃崟鐨勭粦瀹氬叧绯伙紝纭畾淇敼鍚楋紵', + onOk() { + _card.uuid = Utils.getuuid() + _this.setState({ visible: false, card: _card }) + _this.props.updateElement(_card) + }, + onCancel() {} + }) + } else { + delete _card.isnew + this.setState({ visible: false, card: _card }) + this.props.updateElement(_card) + } + }) + } + + cancel = () => { + const { card } = this.state + + if (card.isnew) { + let _card = fromJS(card).toJS() + delete _card.isnew + + this.setState({ visible: false, card: _card }) + this.props.updateElement(_card) + } else { + this.setState({ visible: false }) + } + } + + changeMenu = () => { + const { card } = this.state + + if (card.setting.type === 'link') { + window.open(card.setting.linkurl) + } else { + MKEmitter.emit('changeEditMenu', { + MenuID: card.setting.type === 'linkmenu' ? card.setting.linkMenuId : card.uuid, + copyMenuId: card.setting.type === 'menu' ? card.setting.copyMenuId : '', + MenuNo: card.setting.MenuNo || '', + MenuName: card.setting.name, + }) + } + } + + render() { + const { cards, offset } = this.props + const { card, visible, dict } = this.state + + let _style = {...card.style} + + if (_style.shadow) { + _style.boxShadow = '0 0 4px ' + _style.shadow + } + + _style = resetStyle(_style) + + return ( + <Col span={card.setting.width || 6} offset={offset || 0}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="edit" title="缂栬緫" type="edit" onClick={() => this.setState({visible: true})} /> + <CopyComponent type="menucell" card={card}/> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="plus" title="宸︾Щ" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> + <Icon className="close" title="鍙崇Щ" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> + </div> + } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}> + <Icon type="swap" id={card.uuid + 'swap'}/> + </Popover> + <Icon className="close" title="鍒犻櫎鑿滃崟" type="delete" onClick={() => this.props.deleteElement(card)} /> + </div> + } trigger="hover"> + <div className="menu-item" onDoubleClick={() => this.changeMenu()} style={_style}> + {card.setting.sign === 'icon' ? <div className="menu-sign"> + <Icon style={{ + fontSize: card.setting.iconFont || 20, + padding: card.setting.padding, + background: card.setting.background, + color: card.setting.color + }} type={card.setting.icon}/> + </div> : <div className="menu-sign"> + <img style={{width: card.setting.imgWidth, height: card.setting.imgWidth}} src={card.setting.url} alt=""/> + </div>} + <div className="menu-name">{card.setting.name}</div> + </div> + </Popover> + <Modal + wrapClassName="popview-modal" + title={'鑿滃崟璁剧疆'} + visible={visible} + width={800} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.settingSubmit} + onCancel={this.cancel} + destroyOnClose + > + <SettingForm + dict={dict} + cards={cards} + setting={card.setting} + inputSubmit={this.settingSubmit} + wrappedComponentRef={(inst) => this.settingRef = inst} + /> + </Modal> + </Col> + ) + } +} + +export default MenuBoxComponent \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/mob/components/menubar/normal-menubar/menucomponent/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/mob/components/menubar/normal-menubar/menucomponent/index.scss diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx new file mode 100644 index 0000000..b193269 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx @@ -0,0 +1,302 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Radio, Tooltip, Icon, Input, InputNumber, Select } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const { TextArea } = Input +const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) +const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) +const MkIcon = asyncComponent(() => import('@/components/mkIcon')) + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + cards: PropTypes.object, // 鍗$墖闆� + setting: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + type: this.props.setting.type, + sign: this.props.setting.sign, + menulist: [] + } + + UNSAFE_componentWillMount() { + let menulist = sessionStorage.getItem('appMenus') + + if (menulist) { + try { + menulist = JSON.parse(menulist) + } catch { + menulist = [] + } + } else { + menulist = [] + } + this.setState({menulist}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { setting } = this.props + const { getFieldDecorator } = this.props.form + const { menulist, type, sign } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menubar-menu-card-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="鑿滃崟鍚嶇О"> + {getFieldDecorator('name', { + initialValue: setting.name || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '鑿滃崟鍚嶇О!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鑿滃崟鍙傛暟"> + {getFieldDecorator('MenuNo', { + initialValue: setting.MenuNo || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '鑿滃崟鍙傛暟!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��"> + <Icon type="question-circle" /> + 鍗$墖瀹藉害 + </Tooltip> + }> + {getFieldDecorator('width', { + initialValue: setting.width || 24, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '瀹藉害!' + } + ] + })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鑿滃崟灞炴��"> + {getFieldDecorator('type', { + initialValue: type, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '绫诲瀷!' + } + ] + })( + <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({type: e.target.value})}> + <Radio value="menu">鑿滃崟</Radio> + <Radio value="linkmenu">鍏宠仈鑿滃崟</Radio> + <Radio value="link">閾炬帴</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {type === 'menu' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="澶嶅埗鑿滃崟浠呭湪褰撳墠鑿滃崟涓嶅瓨鍦ㄦ椂鏈夋晥銆�"> + <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> + 澶嶅埗鑿滃崟 + </Tooltip> + }> + {getFieldDecorator('copyMenuId', { + initialValue: setting.copyMenuId || '' + })( + <Select allowClear> + {menulist.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} + </Select> + )} + </Form.Item> + </Col> : null} + {type === 'linkmenu' ? <Col span={12}> + <Form.Item label="鍏宠仈鑿滃崟"> + {getFieldDecorator('linkMenuId', { + initialValue: setting.linkMenuId || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鍏宠仈鑿滃崟!' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {menulist.map(option => + <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> : null} + {type === 'link' ? <Col span={24} className="textarea"> + <Form.Item label="閾炬帴"> + {getFieldDecorator('linkurl', { + initialValue: setting.linkurl || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '閾炬帴!' + } + ] + })( <TextArea rows={2}/> )} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label="鏍囧織"> + {getFieldDecorator('sign', { + initialValue: sign, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鏍囧織!' + } + ] + })( + <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({sign: e.target.value})}> + <Radio value="icon">鍥炬爣</Radio> + <Radio value="image">鍥剧墖</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {sign === 'icon' ? <Col span={12}> + <Form.Item label="鍥炬爣"> + {getFieldDecorator('icon', { + initialValue: setting.icon || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鍥炬爣!' + } + ] + })( + <MkIcon /> + )} + </Form.Item> + </Col> : null} + {sign === 'icon' ? <Col span={12}> + <Form.Item label="瀛椾綋澶у皬"> + {getFieldDecorator('iconFont', { + initialValue: setting.iconFont || 20 + })( + <InputNumber min={12} max={200} precision={0} onPressEnter={this.handleSubmit}/> + )} + </Form.Item> + </Col> : null} + {sign === 'icon' ? <Col span={12}> + <Form.Item label="鍐呰竟璺�"> + {getFieldDecorator('padding', { + initialValue: setting.padding || 12 + })( + <InputNumber min={0} max={200} precision={0} onPressEnter={this.handleSubmit}/> + )} + </Form.Item> + </Col> : null} + {sign === 'icon' ? <Col span={12}> + <Form.Item label="瀛椾綋棰滆壊"> + {getFieldDecorator('color', { + initialValue: setting.color || '#ffffff' + })( + <ColorSketch /> + )} + </Form.Item> + </Col> : null} + {sign === 'icon' ? <Col span={12}> + <Form.Item label="鑳屾櫙鑹�"> + {getFieldDecorator('background', { + initialValue: setting.background || '#1890ff' + })( + <ColorSketch /> + )} + </Form.Item> + </Col> : null} + {sign === 'image' ? <Col span={12}> + <Form.Item label="鍥剧墖鍦板潃"> + {getFieldDecorator('url', { + initialValue: setting.url || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '鍥剧墖鍦板潃!' + } + ] + })( + <SourceComponent type="" placement="right"/> + )} + </Form.Item> + </Col> : null} + {sign === 'image' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鍥剧墖瀹藉害涓庨珮搴︾浉褰擄紝浣跨敤鐨勫浘鐗囨瘮渚嬪簲涓�1:1銆�"> + <Icon type="question-circle" /> + 鍥剧墖瀹藉害 + </Tooltip> + }> + {getFieldDecorator('imgWidth', { + initialValue: setting.imgWidth || 36 + })( + <InputNumber min={10} max={500} precision={0} onPressEnter={this.handleSubmit}/> + )} + </Form.Item> + </Col> : null} + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss new file mode 100644 index 0000000..91dfcf6 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss @@ -0,0 +1,25 @@ +.model-menubar-menu-card-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } + .textarea { + .ant-form-item-label { + width: 16%; + } + .ant-form-item-control-wrapper { + width: 84%; + } + } + .ant-radio-wrapper { + margin-right: 3px; + } + .color-sketch-block { + margin-top: 7px; + } +} \ No newline at end of file diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx b/src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx new file mode 100644 index 0000000..81346a6 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx @@ -0,0 +1,83 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import './index.scss' + +class DataSource extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + wrap: null + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({wrap: fromJS(config.wrap).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + editDataSource = () => { + this.setState({ + visible: true + }) + } + + verifySubmit = () => { + const { config } = this.props + + this.verifyRef.handleConfirm().then(res => { + + this.setState({ + wrap: res, + visible: false + }) + this.props.updateConfig({...config, wrap: res}) + }) + } + + render () { + const { config } = this.props + const { visible, dict, wrap } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} /> + <Modal + wrapClassName="popview-modal" + title={config.type === 'table' ? '琛ㄦ牸璁剧疆' : '鍗$墖璁剧疆'} + visible={visible} + width={800} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + wrap={wrap} + config={config} + inputSubmit={this.verifySubmit} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default DataSource \ No newline at end of file diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/index.scss b/src/mob/components/menubar/normal-menubar/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/wrapsetting/index.scss @@ -0,0 +1,7 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..e501fa1 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx @@ -0,0 +1,155 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + config: PropTypes.object, // 鍗$墖琛屼俊鎭� + wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + roleList: [], + } + + UNSAFE_componentWillMount () { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + this.setState({roleList}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { wrap } = this.props + const { getFieldDecorator } = this.props.form + const { roleList } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menubar-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="鏍囬"> + {getFieldDecorator('title', { + initialValue: wrap.title || '' + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�"> + <Icon type="question-circle" /> + 缁勪欢鍚嶇О + </Tooltip> + }> + {getFieldDecorator('name', { + initialValue: wrap.name, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��"> + <Icon type="question-circle" /> + 瀹藉害 + </Tooltip> + }> + {getFieldDecorator('width', { + initialValue: wrap.width || 24, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '瀹藉害!' + } + ] + })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="瀵归綈鏂瑰紡"> + {getFieldDecorator('float', { + initialValue: wrap.float || 'left' + })( + <Radio.Group style={{whiteSpace: 'nowrap'}}> + <Radio key="left" value="left"> 宸﹀榻� </Radio> + <Radio key="center" value="center"> 灞呬腑 </Radio> + <Radio key="right" value="right"> 鍙冲榻� </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="榛戝悕鍗�"> + {getFieldDecorator('blacklist', { + initialValue: wrap.blacklist || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {roleList.map(option => + <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..92283b8 --- /dev/null +++ b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menubar-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/index.jsx b/src/mob/components/navbar/normal-navbar/index.jsx new file mode 100644 index 0000000..3565e4a --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/index.jsx @@ -0,0 +1,187 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover } from 'antd' + +import asyncIconComponent from '@/utils/asyncIconComponent' + +import MKEmitter from '@/utils/events.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import './index.scss' + +const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) +const MenuComponent = asyncIconComponent(() => import('./menusetting')) +const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) + +class NormalNavbar extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + back: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + format: 'object', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 + pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� + switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + dataName: card.dataName || '', + width: card.width || 24, + name: card.name, + subtype: card.subtype, + setting: { interType: 'system' }, + wrap: { name: card.name, datatype: 'static', height: 50 }, + style: {borderTopColor: '#bcbcbc', borderTopWidth: '1px', paddingTop: '5px', fontSize: '13px' }, + menus: [], + columns: [], + scripts: [], + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.wrap.name = card.name + _card.style = config.style + } + + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (component) => { + this.setState({ + card: component + }) + + component.width = component.wrap.width + component.name = component.wrap.name + + this.props.updateConfig(component) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds[0] !== card.uuid) return + + let _card = {...card, style} + + this.setState({ + card: _card + }) + + this.props.updateConfig(_card) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding'], card.style) + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + changeMenu = (menu) => { + if (menu.property === 'link') { + window.open(menu.link) + } else { + MKEmitter.emit('changeEditMenu', { + MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, + copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', + MenuNo: menu.MenuNo, + MenuName: menu.name, + }) + } + } + + render() { + const { card } = this.state + + let _style = {...card.style} + if (_style.shadow) { + _style.boxShadow = '0 0 4px ' + _style.shadow + } + _style.height = card.wrap.height + + return ( + <div className="normal-navbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <MenuComponent config={card} updateConfig={this.updateComponent} /> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null} + {card.wrap.datatype === 'static' ? <Icon style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/> : null} + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + <div className="menu"> + {card.menus.map(menu => { + return ( + <div key={menu.MenuID} className="am-tab-bar-tab" onDoubleClick={() => this.changeMenu(menu)}> + {menu.icon ? <div className="am-tab-bar-tab-icon"> + <span className="am-badge am-tab-bar-tab-badge tab-badge"> + <Icon type={menu.icon} /> + {menu.tip ? <sup className="am-badge-text"></sup> : null} + </span> + </div> : null} + <p className="am-tab-bar-tab-title">{menu.name}</p> + </div> + ) + })} + </div> + </div> + ) + } +} + +export default NormalNavbar \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/index.scss b/src/mob/components/navbar/normal-navbar/index.scss new file mode 100644 index 0000000..cebf6d4 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/index.scss @@ -0,0 +1,111 @@ +.normal-navbar-edit-box { + position: absolute; + bottom: 0px; + left: 0px; + width: 100%; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 30px; + z-index: 3; + + .menu { + height: 100%; + display: flex; + font-size: inherit; + color: inherit; + .am-tab-bar-tab { + position: relative; + text-align: center; + flex: 1; + cursor: pointer; + .anticon { + font-size: 150%; + } + .am-badge-text { + position: absolute; + top: -2px; + height: 8px; + width: 8px; + border-radius: 100%; + background: #ff5b05; + z-index: 1; + } + p { + margin-bottom: 0; + } + } + } + + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + + .card-item { + overflow: hidden; + position: relative; + background-color: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 20px; + } + + .card-item:hover { + box-shadow: 0px 0px 2px #1890ff; + } + + .model-menu-card-cell-list .card-detail-row > .anticon-plus { + position: absolute; + right: -30px; + font-size: 16px; + } + .model-menu-action-list { + line-height: 40px; + .ant-row > .anticon-plus { + position: absolute; + right: -30px; + font-size: 16px; + } + } + .card-add-button { + text-align: right; + clear: left; + .anticon-plus { + font-size: 20px; + color: #26C281; + padding: 5px; + margin-right: 10px; + } + } + .ant-pagination { + float: right; + margin: 10px; + } + + .model-menu-action-list { + .page-card { + line-height: 55px; + } + } +} +.normal-navbar-edit-box::after { + display: block; + content: ' '; + clear: both; +} +.normal-navbar-edit-box:hover { + box-shadow: 0px 0px 4px #1890ff; +} +.top-menu-popover { + padding-top: 0!important; +} diff --git a/src/mob/components/navbar/normal-navbar/menusetting/index.jsx b/src/mob/components/navbar/normal-navbar/menusetting/index.jsx new file mode 100644 index 0000000..633fff4 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/menusetting/index.jsx @@ -0,0 +1,63 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import MenuTable from './menutable' +import './index.scss' + +class DataSource extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + verifySubmit = () => { + const { config } = this.props + let menus = this.mTable.state.data || [] + + this.props.updateConfig({...config, menus}) + this.setState({visible: false}) + } + + render () { + const { config } = this.props + const { visible, dict } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="menu" title="鑿滃崟" onClick={() => this.setState({ visible: true })}/> + <Modal + wrapClassName="popview-modal" + title="鑿滃崟缂栬緫" + visible={visible} + width={950} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <MenuTable + menus={config.menus} + cols={config.columns} + ref={(ref) => { this.mTable = ref }} + /> + </Modal> + </div> + ) + } +} + +export default DataSource \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/menusetting/index.scss b/src/mob/components/navbar/normal-navbar/menusetting/index.scss new file mode 100644 index 0000000..3a906d8 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/menusetting/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-menu { + color: purple; + } + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/menusetting/menuform/index.jsx b/src/mob/components/navbar/normal-navbar/menusetting/menuform/index.jsx new file mode 100644 index 0000000..2fafa7b --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/menusetting/menuform/index.jsx @@ -0,0 +1,222 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, Select } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const { TextArea } = Input +const MkIcon = asyncComponent(() => import('@/components/mkIcon')) + +class SettingForm extends Component { + static propTpyes = { + menu: PropTypes.object, // 鑿滃崟淇℃伅 + cols: PropTypes.array, // 瀛楁闆� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + property: this.props.menu.property || 'menu', + appMenus: [], + } + + UNSAFE_componentWillMount () { + let appMenus = sessionStorage.getItem('appMenus') + if (appMenus) { + try { + appMenus = JSON.parse(appMenus) + } catch { + appMenus = [] + } + } else { + appMenus = [] + } + + this.setState({appMenus}) + } + + componentDidMount() { + const { menu } = this.props + + if (!menu.MenuID) { + let _form = document.getElementById('name') + _form && _form.select() + } + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + changeProperty = (e) => { + let val = e.target.value + + this.setState({property: val}) + } + + render() { + const { menu, cols } = this.props + const { getFieldDecorator } = this.props.form + const { property, appMenus } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout} className="mob-menu-form"> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="鑿滃崟鍚嶇О"> + {getFieldDecorator('name', { + initialValue: menu.name, + rules: [ + { + required: true, + message: '璇疯緭鍏ヨ彍鍗曞悕绉�!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鑿滃崟鍙傛暟"> + {getFieldDecorator('MenuNo', { + initialValue: menu.MenuNo || '', + rules: [ + { + required: true, + message: '璇疯緭鍏ヨ彍鍗曞弬鏁�!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鍥炬爣"> + {getFieldDecorator('icon', { + initialValue: menu.icon || '' + })( + <MkIcon allowClear /> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="缁戝畾鎻愮ず瀛楁鍚庯紝浼氬湪鑿滃崟鍙充笂瑙掓樉绀烘彁绀轰俊鎭�傛敞锛氬湪娣诲姞鍥炬爣鏃舵湁鏁堛��"> + <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> + 鎻愮ず + </Tooltip> + }> + {getFieldDecorator('tip', { + initialValue: menu.tip || '' + })( + <Select allowClear> + {cols.map(item => <Select.Option key={item.uuid} value={item.field}>{item.label}</Select.Option>)} + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鑿滃崟灞炴��"> + {getFieldDecorator('property', { + initialValue: menu.property || 'menu' + })( + <Radio.Group onChange={this.changeProperty} style={{whiteSpace: 'nowrap'}}> + <Radio value="menu">鑿滃崟</Radio> + <Radio value="linkmenu">鍏宠仈鑿滃崟</Radio> + <Radio value="link">閾炬帴</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="闅愯棌"> + {getFieldDecorator('hidden', { + initialValue: menu.hidden || 'false' + })( + <Radio.Group> + <Radio value="false">鍚�</Radio> + <Radio value="true">鏄�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {property === 'link' ? <Col span={24}> + <Form.Item label="閾炬帴鍦板潃" className="textarea"> + {getFieldDecorator('link', { + initialValue: menu.link || '', + rules: [{ + required: true, + message: '璇疯緭鍏ラ摼鎺ュ湴鍧�!' + }] + })(<TextArea rows={2} />)} + </Form.Item> + </Col> : null} + {property === 'linkmenu' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鍏宠仈褰撳墠app涓凡鏈夌殑鑿滃崟銆�"> + <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> + 鍏宠仈鑿滃崟 + </Tooltip> + }> + {getFieldDecorator('linkMenuId', { + initialValue: menu.linkMenuId || '', + rules: [{ + required: true, + message: '璇烽�夋嫨鍏宠仈鑿滃崟!' + }] + })( + <Select> + {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} + </Select> + )} + </Form.Item> + </Col> : null} + {property === 'menu' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="澶嶅埗鑿滃崟浠呭湪褰撳墠鑿滃崟涓嶅瓨鍦ㄦ椂鏈夋晥銆�"> + <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> + 澶嶅埗鑿滃崟 + </Tooltip> + }> + {getFieldDecorator('copyMenuId', { + initialValue: menu.copyMenuId || '' + })( + <Select> + {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} + </Select> + )} + </Form.Item> + </Col> : null} + </Row> + </Form> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/menusetting/menuform/index.scss b/src/mob/components/navbar/normal-navbar/menusetting/menuform/index.scss new file mode 100644 index 0000000..b94aad3 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/menusetting/menuform/index.scss @@ -0,0 +1,10 @@ +.mob-menu-form { + .ant-form-item.textarea { + .ant-form-item-label { + width: 16%; + } + .ant-form-item-control-wrapper { + width: 84%; + } + } +} \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/menusetting/menutable/index.jsx b/src/mob/components/navbar/normal-navbar/menusetting/menutable/index.jsx new file mode 100644 index 0000000..b17ff7d --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/menusetting/menutable/index.jsx @@ -0,0 +1,198 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Table, Button, Modal, Icon } from 'antd' + +import MenuForm from '../menuform' +import Utils from '@/utils/utils.js' +// import MKEmitter from '@/utils/events.js' +import './index.scss' + +const { confirm } = Modal + +class MenuTable extends Component { + static propTpyes = { + menus: PropTypes.array, // 鍗$墖琛屼俊鎭� + cols: PropTypes.array, // 瀛楁闆� + } + + state = { + data: [], + editMenu: null, + columns: [ + { title: '鑿滃崟鍚嶇О', dataIndex: 'name', key: 'name' }, + { title: '鑿滃崟鍙傛暟', dataIndex: 'MenuNo', key: 'MenuNo' }, + { title: '鑿滃崟灞炴��', dataIndex: 'property', key: 'property', render: text => { + const trans = {menu: '鑿滃崟', link: '閾炬帴', linkmenu: '鍏宠仈鑿滃崟'} + + return trans[text] + }}, + { title: '鍥炬爣', dataIndex: 'icon', key: 'icon', render: (text, record) => { + return text ? <Icon type={text} /> : '' + }}, + { title: '鏄惁闅愯棌', dataIndex: 'hidden', key: 'hidden', render: (text, record) => { + const trans = {'true': '鏄�', 'false': '鍚�'} + return trans[text] || '鍚�' + }}, + { title: '鎿嶄綔', key: 'operation', align: 'center', width: '190px', render: (text, record) => + (<div> + <Button type="link" style={{padding: '0 5px', marginRight: '5px'}} onClick={() => this.editMenu(record)}>缂栬緫</Button> + <Button type="link" style={{color: '#ff4d4f', padding: '0 5px', marginRight: '5px'}} onClick={() => this.delMenu(record)}>鍒犻櫎</Button> + <Icon type="arrow-up" style={{color: '#26C281', cursor: 'pointer', padding: '0 5px', marginRight: '5px'}} onClick={() => this.moveUp(record)}/> + <Icon type="arrow-down" style={{color: '#ff4d4f', cursor: 'pointer', padding: '0 5px'}} onClick={() => this.moveDown(record)}/> + </div>) + } + ] + } + + UNSAFE_componentWillMount () { + const { menus } = this.props + + this.setState({data: fromJS(menus).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + moveUp = (record) => { + let data = fromJS(this.state.data).toJS() + + let dragIndex = data.findIndex(c => c.MenuID === record.MenuID) + let hoverIndex = dragIndex - 1 + + if (hoverIndex === -1) return + + data.splice(hoverIndex, 0, ...data.splice(dragIndex, 1)) + this.setState({data}) + } + + moveDown = (record) => { + let data = fromJS(this.state.data).toJS() + + let dragIndex = data.findIndex(c => c.MenuID === record.MenuID) + let hoverIndex = dragIndex + 1 + + if (hoverIndex === data.length) return + + data.splice(hoverIndex, 0, ...data.splice(dragIndex, 1)) + this.setState({data}) + } + + delMenu = (record) => { + const { data } = this.state + const _this = this + + confirm({ + title: '纭畾鍒犻櫎鍚楋紵', + content: '', + onOk() { + _this.setState({data: data.filter(item => item.MenuID !== record.MenuID)}) + }, + onCancel() {} + }) + } + + editMenu = (record) => { + this.setState({editMenu: record, visible: true}) + } + + plusMenu = () => { + let _menu = { + name: '鑿滃崟', + property: 'menu' + } + + this.setState({editMenu: _menu, visible: true}) + } + + menuSubmit = () => { + const { editMenu, data } = this.state + + this.menuRef.handleConfirm().then(res => { + let _menu = {...editMenu, ...res} + let _data = fromJS(data).toJS() + + if (!_menu.MenuID) { + _menu.MenuID = Utils.getuuid() + _data.push(_menu) + } else { + _data = _data.map(item => { + if (item.MenuID === _menu.MenuID) { + return _menu + } else { + return item + } + }) + } + + if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') { + const _this = this + confirm({ + content: '鑿滃崟灞炴�х敱鈥滆彍鍗曗�濆垏鎹㈣嚦鍏朵粬绫诲瀷鏃讹紝鑿滃崟灏嗚閲嶇疆锛屽嵆瑙i櫎涔嬪墠鑿滃崟鐨勭粦瀹氬叧绯伙紝纭畾淇敼鍚楋紵', + onOk() { + _data = _data.map(item => { + if (item.MenuID === _menu.MenuID) { + item.MenuID = Utils.getuuid() + } + return item + }) + _this.setState({data: _data, editMenu: null, visible: false}) + }, + onCancel() {} + }) + } else { + this.setState({data: _data, editMenu: null, visible: false}) + } + }) + } + + menuUpdate = (res) => { + const { data } = this.state + + this.setState({ + data: data.map(item => { + if (item.MenuID === res.MenuID) { + return res + } else { + return item + } + }) + }) + } + + render() { + const { cols } = this.props + const { columns, data, visible, editMenu } = this.state + + return ( + <div className="menu-control-wrap"> + <Button className="menu-plus mk-green" onClick={this.plusMenu}>娣诲姞</Button> + <Table + rowKey="MenuID" + columns={columns} + dataSource={data} + pagination={false} + /> + <Modal + title="缂栬緫" + visible={visible} + width={750} + maskClosable={false} + onOk={this.menuSubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <MenuForm + menu={editMenu} + cols={cols} + inputSubmit={this.menuSubmit} + wrappedComponentRef={(inst) => this.menuRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default MenuTable \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/menusetting/menutable/index.scss b/src/mob/components/navbar/normal-navbar/menusetting/menutable/index.scss new file mode 100644 index 0000000..725a1d5 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/menusetting/menutable/index.scss @@ -0,0 +1,23 @@ +.menu-control-wrap { + position: relative; + + .menu-plus { + float: right; + position: relative; + z-index: 1; + margin-bottom: 5px; + } + .ant-empty { + margin: 5px 0; + } + thead tr { + background: #fbfbfb; + } + tbody > tr { + background: #ffffff; + } + + .ant-table-body { + margin: 0!important; + } +} \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/wrapsetting/index.jsx b/src/mob/components/navbar/normal-navbar/wrapsetting/index.jsx new file mode 100644 index 0000000..a6785d0 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/wrapsetting/index.jsx @@ -0,0 +1,81 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import './index.scss' + +class DataSource extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + wrap: null + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({wrap: fromJS(config.wrap).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + editDataSource = () => { + this.setState({ + visible: true + }) + } + + verifySubmit = () => { + const { config } = this.props + + this.verifyRef.handleConfirm().then(res => { + + this.setState({ + wrap: res, + visible: false + }) + this.props.updateConfig({...config, wrap: res}) + }) + } + + render () { + const { visible, dict, wrap } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} /> + <Modal + wrapClassName="popview-modal" + title="鑿滃崟鏍忚缃�" + visible={visible} + width={800} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + wrap={wrap} + inputSubmit={this.verifySubmit} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default DataSource \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/wrapsetting/index.scss b/src/mob/components/navbar/normal-navbar/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/wrapsetting/index.scss @@ -0,0 +1,7 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx b/src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..debd0d8 --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx @@ -0,0 +1,118 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, InputNumber, Tooltip, Icon, Radio } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = {} + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { wrap } = this.props + const { getFieldDecorator } = this.props.form + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="瀵艰埅鏍忓悕绉�"> + {getFieldDecorator('name', { + initialValue: wrap.name, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '瀵艰埅鏍忓悕绉�!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鑿滃崟鍙傛暟"> + {getFieldDecorator('MenuNo', { + initialValue: wrap.MenuNo, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '鑿滃崟鍙傛暟!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��"> + <Icon type="question-circle" /> + 鏁版嵁鏉ユ簮 + </Tooltip> + }> + {getFieldDecorator('datatype', { + initialValue: wrap.datatype || 'static' + })( + <Radio.Group> + <Radio value="dynamic">鍔ㄦ��</Radio> + <Radio value="static">闈欐��</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="楂樺害"> + {getFieldDecorator('height', { + initialValue: wrap.height || 50, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '楂樺害!' + } + ] + })(<InputNumber min={30} max={200} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.scss b/src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..159130b --- /dev/null +++ b/src/mob/components/navbar/normal-navbar/wrapsetting/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/mob/components/topbar/normal-navbar/index.jsx b/src/mob/components/topbar/normal-navbar/index.jsx new file mode 100644 index 0000000..db75aed --- /dev/null +++ b/src/mob/components/topbar/normal-navbar/index.jsx @@ -0,0 +1,195 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover } from 'antd' + +import asyncIconComponent from '@/utils/asyncIconComponent' + +import MKEmitter from '@/utils/events.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import './index.scss' + +const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) + +class NormalNavbar extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + back: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + width: 24, + subtype: card.subtype, + wrap: { type: 'navbar', height: 50, title: 'NavBar', back: 'true', search: 'false', logout: 'false' }, + style: {borderBottomColor: '#bcbcbc', borderBottomWidth: '1px', paddingLeft: '10px', paddingRight: '10px', lineHeight: '2.8', fontSize: '18px' }, + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.style = config.style + } + + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + MKEmitter.addListener('submitSearch', this.getSearch) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + MKEmitter.removeListener('submitSearch', this.getSearch) + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (component) => { + this.setState({ + card: component + }) + + this.props.updateConfig(component) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds[0] !== card.uuid) return + + let _card = {...card, style} + + this.setState({ + card: _card + }) + + this.props.updateConfig(_card) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding', 'shadow'], card.style) + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + changeMenu = (menu) => { + if (menu.property === 'link') { + window.open(menu.link) + } else { + MKEmitter.emit('changeEditMenu', { + MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, + copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', + MenuNo: menu.MenuNo, + MenuName: menu.name, + }) + } + } + + getSearch = (config) => { + const { card } = this.state + + if (card.uuid !== config.uuid) return + + this.setState({ + card: config + }) + + this.props.updateConfig(config) + } + + setSearch = () => { + let card = fromJS(this.state.card).toJS() + + if (!card.search) { + card.search = { + floor: 1, + setting: { type: 'title', field: '', title: '', focus: 'true', btn: 'hidden' }, + groups: [], + fields: [] + } + } + this.props.updateConfig(card) + MKEmitter.emit('changeSearch', card) + } + + render() { + const { card } = this.state + + let _style = {...card.style} + if (_style.shadow) { + _style.boxShadow = '0 0 4px ' + _style.shadow + } + + return ( + <div className="normal-topbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + <div className="am-navbar"> + <div className="am-navbar-left"> + {card.wrap.back !== 'false' ? <Icon type="left" /> : null} + </div> + {card.wrap.type !== 'search' ? + <div className="am-navbar-title">{card.wrap.title || ''}</div> : + <div className="am-navbar-search" onDoubleClick={this.setSearch}><div className="search-bar"><Icon type="search" /></div></div> + } + <div className="am-navbar-right"> + {card.wrap.search === 'true' ? <Icon type="search" onDoubleClick={this.setSearch}/> : null} + {card.wrap.logout === 'true' ? <Icon type="ellipsis" /> : null} + </div> + </div> + </div> + ) + } +} + +export default NormalNavbar \ No newline at end of file diff --git a/src/mob/components/topbar/normal-navbar/index.scss b/src/mob/components/topbar/normal-navbar/index.scss new file mode 100644 index 0000000..c7cd342 --- /dev/null +++ b/src/mob/components/topbar/normal-navbar/index.scss @@ -0,0 +1,82 @@ +.normal-topbar-edit-box { + position: absolute; + top: 0px; + left: 0px; + width: 100%; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + height: 50px; + z-index: 3; + + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + color: rgba(0, 0, 0, 0.65); + } + .am-navbar { + height: 100%; + display: flex; + font-style: inherit; + font-weight: inherit; + .am-navbar-left { + width: 30px; + text-align: left; + color: #1890ff; + font-size: 20px; + line-height: 50px; + } + .am-navbar-title { + text-align: center; + font-style: inherit; + font-weight: inherit; + flex: 1; + } + .am-navbar-search { + flex: 1; + padding: 0 5px; + .search-bar { + height: 30px; + line-height: 30px; + padding: 0 10px; + color:rgba(0, 0, 0, 0.65); + border: 1px solid #E9EDF0; + background: #E9EDF0; + border-radius: 4px; + position: relative; + top: 50%; + transform: translateY(-50%); + cursor: pointer; + font-size: 18px; + } + } + .am-navbar-right { + text-align: right; + color: #1890ff; + min-width: 30px; + font-size: 20px; + line-height: 50px; + .anticon-search { + margin-right: 5px; + padding: 5px; + cursor: pointer; + } + } + } +} +.normal-topbar-edit-box::after { + display: block; + content: ' '; + clear: both; +} +.normal-topbar-edit-box:hover { + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/mob/components/topbar/normal-navbar/wrapsetting/index.jsx b/src/mob/components/topbar/normal-navbar/wrapsetting/index.jsx new file mode 100644 index 0000000..77c0894 --- /dev/null +++ b/src/mob/components/topbar/normal-navbar/wrapsetting/index.jsx @@ -0,0 +1,81 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import './index.scss' + +class DataSource extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + wrap: null + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({wrap: fromJS(config.wrap).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + editDataSource = () => { + this.setState({ + visible: true + }) + } + + verifySubmit = () => { + const { config } = this.props + + this.verifyRef.handleConfirm().then(res => { + + this.setState({ + wrap: res, + visible: false + }) + this.props.updateConfig({...config, wrap: res}) + }) + } + + render () { + const { visible, dict, wrap } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} /> + <Modal + wrapClassName="popview-modal" + title="瀵艰埅鏍忚缃�" + visible={visible} + width={750} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + wrap={wrap} + inputSubmit={this.verifySubmit} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default DataSource \ No newline at end of file diff --git a/src/mob/components/topbar/normal-navbar/wrapsetting/index.scss b/src/mob/components/topbar/normal-navbar/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/mob/components/topbar/normal-navbar/wrapsetting/index.scss @@ -0,0 +1,7 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.jsx b/src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..7656c0e --- /dev/null +++ b/src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.jsx @@ -0,0 +1,130 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Radio, Tooltip, Icon } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + type: this.props.wrap.type || 'navbar' + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { wrap } = this.props + const { getFieldDecorator } = this.props.form + const { type } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="绫诲瀷"> + {getFieldDecorator('type', { + initialValue: wrap.type || 'navbar' + })( + <Radio.Group onChange={(e) => this.setState({type: e.target.value})}> + <Radio value="navbar">瀵艰埅鏍�</Radio> + <Radio value="search">鎼滅储鏍�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="浣跨敤鎼滅储鏍忔椂锛屾爣棰樼敤浜庢悳绱㈡潯浠堕殣钘忔椂鏄剧ず銆�"> + <Icon type="question-circle" /> + 鏍囬 + </Tooltip> + }> + {getFieldDecorator('title', { + initialValue: wrap.title || '' + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="杩斿洖"> + {getFieldDecorator('back', { + initialValue: wrap.back || 'true' + })( + <Radio.Group> + <Radio value="true">鏄剧ず</Radio> + <Radio value="false">闅愯棌</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {type === 'navbar' ? <Col span={12}> + <Form.Item label="鎼滅储"> + {getFieldDecorator('search', { + initialValue: wrap.search || 'false' + })( + <Radio.Group> + <Radio value="true">鏄剧ず</Radio> + <Radio value="false">闅愯棌</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐐瑰嚮閫�鍑烘椂锛岃繑鍥炵涓�涓〉闈€��"> + <Icon type="question-circle" /> + 閫�鍑� + </Tooltip> + }> + {getFieldDecorator('logout', { + initialValue: wrap.logout || 'false' + })( + <Radio.Group> + <Radio value="true">鏄剧ず</Radio> + <Radio value="false">闅愯棌</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.scss b/src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..159130b --- /dev/null +++ b/src/mob/components/topbar/normal-navbar/wrapsetting/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/mob/header/index.jsx b/src/mob/header/index.jsx index 38c5863..5bf90ea 100644 --- a/src/mob/header/index.jsx +++ b/src/mob/header/index.jsx @@ -1,4 +1,5 @@ import React, {Component} from 'react' +import { Radio } from 'antd' import avatar from '@/assets/img/avatar.jpg' import MainLogo from '@/assets/img/main-logo.png' @@ -7,13 +8,26 @@ class MobHeader extends Component { state = { avatar: sessionStorage.getItem('CloudAvatar') || avatar, - userName: sessionStorage.getItem('CloudUserName') + userName: sessionStorage.getItem('CloudUserName'), + typename: sessionStorage.getItem('typename') + } + + changeView = (e) => { + let val = e.target.value + this.props.changeView(val) } render () { + const { typename } = this.state return ( <header className="mob-header-container"> <div className="header-logo"><img src={MainLogo} alt=""/></div> + {typename === 'pad' ? <div className="change-view"> + <Radio.Group defaultValue="vertical" onChange={this.changeView}> + <Radio value="vertical">绔栧睆</Radio> + <Radio value="horizontal">妯睆</Radio> + </Radio.Group> + </div> : null} <div className="header-user"> <img src={this.state.avatar} alt=""/> <span> diff --git a/src/mob/header/index.scss b/src/mob/header/index.scss index 40ac737..b4009e2 100644 --- a/src/mob/header/index.scss +++ b/src/mob/header/index.scss @@ -45,4 +45,12 @@ } } } + .change-view { + position: absolute; + left: calc(50% - 70px); + top: 12px; + .ant-radio-wrapper { + color: #ffffff; + } + } } \ No newline at end of file diff --git a/src/mob/home/index.jsx b/src/mob/home/index.jsx deleted file mode 100644 index dde5d1f..0000000 --- a/src/mob/home/index.jsx +++ /dev/null @@ -1,126 +0,0 @@ -import React, {Component} from 'react' -// import PropTypes from 'prop-types' -import { is, fromJS } from 'immutable' -import { Flex, WhiteSpace, Tabs } from 'antd-mobile' - -import zhCN from '@/locales/zh-CN/mob.js' -import enUS from '@/locales/en-US/mob.js' -import './index.scss' - -const PlaceHolder = ({ className = '', children = ''}) => ( - <div className={`${className} placeholder`}>{children ? children : 'Block'}</div> -) - -const tabs2 = [ - { title: '绠�浠�', sub: '1' }, - { title: '宸ヤ綔鍙�', sub: '2' }, - { title: '涓汉涓績', sub: '3' }, -] - -class MobHome extends Component { - // static propTpyes = { - // collapse: PropTypes.bool, - // } - state = { - dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, - } - - shouldComponentUpdate (nextProps, nextState) { - return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) - } - - render () { - - return ( - <div className="mob-home"> - <Tabs tabs={tabs2} - initialPage={1} - tabBarPosition="bottom" - renderTab={tab => <span>{tab.title}</span>} - > - <div className="home-tab"> - <div className="flex-container"> - <div className="sub-title">Basic</div> - <Flex> - <Flex.Item><PlaceHolder ><span> test</span></PlaceHolder></Flex.Item> - <Flex.Item><PlaceHolder /></Flex.Item> - </Flex> - <WhiteSpace size="lg" /> - <Flex> - <Flex.Item><PlaceHolder /></Flex.Item> - <Flex.Item><PlaceHolder /></Flex.Item> - <Flex.Item><PlaceHolder /></Flex.Item> - </Flex> - <WhiteSpace size="lg" /> - <Flex> - <Flex.Item><PlaceHolder /></Flex.Item> - <Flex.Item><PlaceHolder /></Flex.Item> - <Flex.Item><PlaceHolder /></Flex.Item> - <Flex.Item><PlaceHolder /></Flex.Item> - </Flex> - <WhiteSpace size="lg" /> - - <div className="sub-title">Wrap</div> - <Flex wrap="wrap"> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - </Flex> - <WhiteSpace size="lg" /> - - <div className="sub-title">Align</div> - <Flex justify="center"> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - </Flex> - <WhiteSpace /> - <Flex justify="end"> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - </Flex> - <WhiteSpace /> - <Flex justify="between"> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline" /> - </Flex> - - <WhiteSpace /> - <Flex align="start"> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline small" /> - <PlaceHolder className="inline" /> - </Flex> - <WhiteSpace /> - <Flex align="end"> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline small" /> - <PlaceHolder className="inline" /> - </Flex> - <WhiteSpace /> - <Flex align="baseline"> - <PlaceHolder className="inline" /> - <PlaceHolder className="inline small" /> - <PlaceHolder className="inline" /> - </Flex> - </div> - </div> - <div className="home-tab"> - Content of second tab - </div> - <div className="home-tab"> - Content of third tab - </div> - </Tabs> - </div> - ) - } -} - -export default MobHome \ No newline at end of file diff --git a/src/mob/home/index.scss b/src/mob/home/index.scss deleted file mode 100644 index 9b2141a..0000000 --- a/src/mob/home/index.scss +++ /dev/null @@ -1,38 +0,0 @@ -.mob-home { - width: 100%; - height: 100%; - overflow: hidden; - > .am-tabs { - > .am-tabs-tab-bar-wrap { - .am-tabs-default-bar-underline { - display: none; - } - .am-tabs-default-bar-tab { - cursor: pointer; - } - } - > .am-tabs-content-wrap { - > .am-tabs-pane-wrap { - .home-tab { - display: flex; - align-items: center; - justify-content: center; - } - } - > .am-tabs-pane-wrap::-webkit-scrollbar { - width: 4px; - } - > .am-tabs-pane-wrap::-webkit-scrollbar-thumb { - box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); - background: rgba(0, 0, 0, 0.13); - border-radius: 5px; - } - > .am-tabs-pane-wrap::-webkit-scrollbar-track { - box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); - border: 1px solid rgba(0, 0, 0, 0.07); - background: rgba(0, 0, 0, 0); - border-radius: 3px; - } - } - } -} \ No newline at end of file diff --git a/src/mob/mobshell/card.jsx b/src/mob/mobshell/card.jsx index 30225a7..9cd7402 100644 --- a/src/mob/mobshell/card.jsx +++ b/src/mob/mobshell/card.jsx @@ -5,8 +5,10 @@ import './index.scss' const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar')) -const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search')) +// const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search')) const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie')) +const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) +const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs')) const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) @@ -17,6 +19,12 @@ const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) +const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) +const NormalLogin = asyncComponent(() => import('@/pc/components/login/normal-login')) +const NormalNavbar = asyncComponent(() => import('@/mob/components/navbar/normal-navbar')) +const NormalTopbar = asyncComponent(() => import('@/mob/components/topbar/normal-navbar')) +const NormalMenuBar = asyncComponent(() => import('@/mob/components/menubar/normal-menubar')) +const Balcony = asyncComponent(() => import('@/menu/components/card/balcony')) const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { const originalIndex = findCard(id).index @@ -51,13 +59,34 @@ style = { opacity: 0.3} } + let col = 'ant-col-' + (card.width || 24) + if (card.type === 'login') { + let height = '' + if (card.wrap && card.wrap.height) { + // scaleview + height = card.wrap.height.replace(/\d+vw/ig, (word) => { + return parseFloat(word) * (window.GLOB.winWidth || 420) / 100 + 'px' + // return parseFloat(word) * 350 / 100 + 'px' + }).replace(/\d+vh/ig, (word) => { + return parseFloat(word) * (window.GLOB.winHeight || 738) / 100 + 'px' + // return parseFloat(word) * 615 / 100 + 'px' + }) + } + + style.minHeight = height + } + const getCardComponent = () => { if (card.type === 'bar' || card.type === 'line') { return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) - } else if (card.type === 'search') { - return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + // } else if (card.type === 'search') { + // return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'pie') { return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'dashboard') { + return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'scatter') { + return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'form') { return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'tabs') { @@ -78,12 +107,29 @@ return (<NormalGroup group={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'code') { return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'editor') { + return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'login') { + return (<NormalLogin card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'navbar') { + return (<NormalNavbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'topbar') { + return (<NormalTopbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'menubar') { + return (<NormalMenuBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'balcony') { + return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } } - return ( - <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}> - {getCardComponent()} - </div> - ) + + if (card.type === 'navbar' || card.type === 'topbar') { + return getCardComponent() + } else { + return ( + <div className={'ant-col mk-component-card ' + col} ref={node => drag(drop(node))} style={style}> + {getCardComponent()} + </div> + ) + } } export default Card diff --git a/src/mob/mobshell/index.jsx b/src/mob/mobshell/index.jsx index ee23621..5cdb407 100644 --- a/src/mob/mobshell/index.jsx +++ b/src/mob/mobshell/index.jsx @@ -19,6 +19,10 @@ handleList({...menu, components: _cards}) setCards(_cards) } + + if (menu.components.length > cards.length) { + setCards(menu.components) + } const findCard = id => { const card = cards.filter(c => `${c.uuid}` === id)[0] @@ -49,13 +53,16 @@ let uuids = MenuUtils.getDelButtonIds(card) confirm({ - title: `纭畾鍒犻櫎銆�${card.name}銆嬪悧锛焋, + title: `纭畾鍒犻櫎${card.name ? `銆�${card.name}銆媊 : '缁勪欢'}鍚楋紵`, content: hasComponent ? '褰撳墠缁勪欢涓惈鏈夊瓙缁勪欢锛�' : '', onOk() { - MKEmitter.emit('delButtons', uuids) const _cards = cards.filter(item => item.uuid !== card.uuid) handleList({...menu, components: _cards}) setCards(_cards) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -78,6 +85,24 @@ }) return } + } else if (item.component === 'navbar') { + if (cards.filter(card => card.type === 'navbar').length > 0) { + notification.warning({ + top: 92, + message: '鑿滃崟鏍忎笉鍙噸澶嶆坊鍔狅紒', + duration: 5 + }) + return + } + } else if (item.component === 'topbar') { + if (cards.filter(card => card.type === 'topbar').length > 0) { + notification.warning({ + top: 92, + message: '瀵艰埅鏍忎笉鍙噸澶嶆坊鍔狅紒', + duration: 5 + }) + return + } } let name = '' @@ -92,8 +117,12 @@ editor: '瀵屾枃鏈�', code: '鑷畾涔�', carousel: '杞挱', + dashboard: '浠〃鐩�', form: '琛ㄥ崟', - card: '鍗$墖' + card: '鍗$墖', + navbar: '瀵艰埅鏍�', + menubar: '鑿滃崟鏍�', + login: '鐧诲綍' } let i = 1 @@ -127,7 +156,25 @@ } const { index: overIndex } = findCard(`${targetId}`) - const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) + let _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) + let Topbar = null + let Navbar = null + _cards = _cards.filter(item => { + if (item.type === 'topbar') { + Topbar = item + } else if (item.type === 'navbar') { + Navbar = item + } + + return item.type !== 'topbar' && item.type !== 'navbar' + }) + + if (Topbar) { + _cards.unshift(Topbar) + } + if (Navbar) { + _cards.push(Navbar) + } handleList({...menu, components: _cards}) setCards(_cards) @@ -135,8 +182,8 @@ }) return ( - <div ref={drop} className="mob-shell-inner" id="menu-shell-inner" style={menu.style}> - <div className="ant-row"> + <div ref={drop} className="mob-shell-inner" id="menu-shell-inner"> + <div className="ant-row" style={menu.style}> {cards.map(card => ( <Card id={card.uuid} @@ -148,10 +195,10 @@ updateConfig={updateConfig} /> ))} + {cards.length === 0 ? + <Empty description="璇锋坊鍔犵粍浠�" /> : null + } </div> - {cards.length === 0 ? - <Empty description="璇锋坊鍔犵粍浠�" /> : null - } </div> ) } diff --git a/src/mob/mobshell/index.scss b/src/mob/mobshell/index.scss index 55dd022..cd21f50 100644 --- a/src/mob/mobshell/index.scss +++ b/src/mob/mobshell/index.scss @@ -1,8 +1,34 @@ .mob-shell-inner { + // scaleview + width: 120%; + height: 120%; + overflow-y: auto; + overflow-x: hidden; + background: #ffffff; + box-shadow: 0px 0px 2px #000000; + transform: scale(0.8333333333333334, 0.8333333333333334); + transform-origin: left top; .mk-component-card { position: relative; } - >.ant-empty { - padding-top: 150px; + >.ant-row { + min-height: 100%; + >.ant-empty { + padding-top: 150px; + } } +} +.mob-shell-inner::-webkit-scrollbar { + width: 2px; +} +.mob-shell-inner::-webkit-scrollbar-thumb { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); + background: rgba(0, 0, 0, 0.23); + border-radius: 5px; +} +.mob-shell-inner::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0); + border-radius: 3px; } \ No newline at end of file diff --git a/src/mob/modalconfig/controller.jsx b/src/mob/modalconfig/controller.jsx new file mode 100644 index 0000000..efd36d6 --- /dev/null +++ b/src/mob/modalconfig/controller.jsx @@ -0,0 +1,64 @@ +import React, {Component} from 'react' +import { is, fromJS } from 'immutable' + +import MKEmitter from '@/utils/events.js' +import ModalConfig from '@/mob/modalconfig' + +class ModalController extends Component { + state = { + btn: null, + config: null, + visible: false + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('changeModal', this.initConfig) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('changeModal', this.initConfig) + } + + initConfig = (config, btn) => { + this.setState({ + visible: true, + config: fromJS(config).toJS(), + btn: fromJS(btn).toJS() + }) + } + + handleBack = () => { + this.setState({ + visible: false, + config: null, + btn: null + }) + } + + handleSave = (modal) => { + const { config, btn } = this.state + MKEmitter.emit('submitModal', config, btn, modal) + } + + render () { + const { config, btn, visible } = this.state + + if (!visible) return null + + return ( + <ModalConfig btn={btn} componentConfig={config} handleBack={this.handleBack} handleSave={this.handleSave}/> + ) + } +} + +export default ModalController \ No newline at end of file diff --git a/src/mob/modalconfig/index.jsx b/src/mob/modalconfig/index.jsx new file mode 100644 index 0000000..fc634fd --- /dev/null +++ b/src/mob/modalconfig/index.jsx @@ -0,0 +1,466 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { DndProvider } from 'react-dnd' +import HTML5Backend from 'react-dnd-html5-backend' +import moment from 'moment' +import { Button, Modal, Collapse, notification, Switch, Icon } from 'antd' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import { getModalForm } from '@/templates/zshare/formconfig' + +import SourceElement from '@/templates/modalconfig/dragelement/source' +import SettingForm from '@/templates/modalconfig/settingform' +import asyncComponent from '@/utils/asyncComponent' +import { SearchItems } from './source' +import './index.scss' + +const { Panel } = Collapse +const { confirm } = Modal +const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS +const PasteComponent = asyncComponent(() => import('./pastecomponent')) +const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) +const DragElement = asyncComponent(() => import('@/mob/components/formdragelement')) +const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) + +class ComModalConfig extends Component { + static propTpyes = { + btn: PropTypes.object, + handleSave: PropTypes.func, + handleBack: PropTypes.func + } + + state = { + dict: CommonDict, // 瀛楀吀 + config: null, // 椤甸潰閰嶇疆锛屽寘鎷ā鏉跨被鍨嬨�佹ā鎬佹璁剧疆銆佹坊鍔犺〃鍚嶃�佽〃鍗曞垪琛� + visible: false, // 琛ㄥ崟缂栬緫妯℃�佹锛屾樉绀烘帶鍒� + formlist: null, // 琛ㄥ崟缂栬緫妯℃�佹锛屽彲缂栬緫瀛楁 + card: null, // 缂栬緫鍏冪礌 + settingVisible: false, // 鍏ㄥ眬閰嶇疆妯℃�佹 + originConfig: null, // 鍘熷鑿滃崟 + sqlVerifing: false, // sql楠岃瘉 + showField: false, // 鏄剧ず琛ㄥ崟瀛楁鍊� + standardform: null + } + + /** + * @description 鏁版嵁棰勫鐞� + */ + UNSAFE_componentWillMount () { + const { btn } = this.props + + let _config = btn.modal + _config.version = '1.0' + + this.setState({ + config: _config, + originConfig: fromJS(_config).toJS() + }) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + /** + * @description 琛ㄥ崟鍙樺寲 + * 1銆佽〃鍗曟嫋鎷芥坊鍔犳椂锛屾鏌ユ槸鍚﹀瓨鍦ㄧず渚嬭〃鍗曪紝濡傚瓨鍦ㄥ垯鍘婚櫎绀轰緥 + * 2銆佽〃鍗曠Щ鍔ㄥ悗锛屼繚瀛樼Щ鍔ㄥ悗鐨勯『搴� + * 3銆佹柊澧炶〃鍗曟椂锛岀洿鎺ユ墦寮�缂栬緫妗� + */ + handleList = (list, newcard) => { + let _config = fromJS(this.state.config).toJS() + + if (list.length > _config.fields.length) { + _config.fields = list.filter(item => !item.origin) + + this.setState({ + config: _config + }, () => { + this.handleForm(newcard) + }) + } else { + _config.fields = list + this.setState({config: _config}) + } + } + + /** + * @description 琛ㄥ崟缂栬緫 + * 1銆佹樉绀虹紪杈戝脊绐�-visible + * 2銆佷繚瀛樼紪杈戦」-card + * 3銆佽缃紪杈戝弬鏁伴」-formlist + */ + handleForm = (_card) => { + const { componentConfig } = this.props + const { config } = this.state + let card = fromJS(_card).toJS() + let _inputfields = [] + let _tabfields = [] + let _linkableFields = [] + let _linksupFields = [{ + value: '', + text: '绌�' + }] + let standardform = null + + _inputfields = config.fields.filter(item => item.type === 'text' || item.type === 'number' || item.type === 'textarea' || item.type === 'color') + _tabfields = config.fields.filter(item => card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) + _tabfields.unshift({field: '', text: '鍘熻〃鍗�'}) + + let uniq = new Map() + uniq.set(card.field, true) + let index = null + config.fields.forEach((item, i) => { + if (card.uuid === item.uuid) { + index = i + } + if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return + if (item.field && !uniq.has(item.field)) { + uniq.set(item.field, true) + + _linkableFields.push({ + value: item.field, + text: item.label + ' (琛ㄥ崟)' + }) + _linksupFields.push({ + value: item.field, + text: item.label + }) + } + }) + if (index !== null) { + if (index === 0) { + standardform = config.fields[index + 1] || null + } else { + standardform = config.fields[index - 1] || null + } + } + + componentConfig.columns.forEach(col => { + if (col.field && !uniq.has(col.field)) { + uniq.set(col.field, true) + + _linkableFields.push({ + value: col.field, + text: col.label + ' (鏄剧ず鍒�)' + }) + } + }) + + if (card.linkSubField && card.linkSubField.length > 0) { + let fields = _inputfields.map(item => item.field) + card.linkSubField = card.linkSubField.filter(item => fields.includes(item)) + } + + if (!card.span && standardform && standardform.span) { + card.span = standardform.span + card.labelwidth = standardform.labelwidth + } + + this.setState({ + standardform, + visible: true, + card: card, + formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields, !!this.props.editTab) + }) + } + + /** + * @description 缂栬緫鍚庢彁浜� + * 1銆佽幏鍙栫紪杈戝悗鐨勮〃鍗曚俊鎭� + * 2銆佸幓闄ゅ彲鑳藉瓨鍦ㄧ殑绀轰緥琛ㄥ崟 + * 3銆侀�氳繃loading鍒锋柊 + */ + handleSubmit = () => { + this.formRef.handleConfirm().then(res => { + let _config = fromJS(this.state.config).toJS() + let fieldrepet = false // 瀛楁閲嶅 + let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅 + + _config.fields = _config.fields.map(item => { + if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { + fieldrepet = true + } else if (res.label && item.uuid !== res.uuid && item.label === res.label) { + labelrepet = true + } + + if (item.uuid === res.uuid) { + return res + } else { + return item + } + }) + + if (fieldrepet) { + notification.warning({ + top: 92, + message: '瀛楁宸插瓨鍦紒', + duration: 10 + }) + return + } else if (labelrepet) { + notification.warning({ + top: 92, + message: '鍚嶇О宸插瓨鍦紒', + duration: 10 + }) + return + } + + _config.fields = _config.fields.filter(item => !item.origin) + + if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { + this.setState({ + sqlVerifing: true + }) + + let param = { + func: 's_debug_sql', + exec_type: 'y', + LText: res.dataSource + } + + param.LText = param.LText.replace(/@\$|\$@/ig, '') + + param.LText = Utils.formatOptions(param.LText) + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt('', param.timestamp) + + if (window.GLOB.mainSystemApi && res.database === 'sso') { + param.rduri = window.GLOB.mainSystemApi + } + + Api.getLocalConfig(param).then(result => { + if (result.status) { + this.setState({ + sqlVerifing: false, + config: _config, + card: null, + visible: false + }) + } else { + this.setState({sqlVerifing: false}) + + Modal.error({ + title: result.message + }) + } + }) + } else { + this.setState({ + config: _config, + card: null, + visible: false + }) + } + }) + } + + /** + * @description 琛ㄥ崟鍒犻櫎骞跺埛鏂� + */ + closeForm = (card) => { + let _this = this + + confirm({ + content: `纭畾鍒犻櫎${card.label ? `<<${card.label}>>` : ''}鍚楋紵`, + onOk() { + let _config = fromJS(_this.state.config).toJS() + _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid)) + + _this.setState({ + config: _config, + }) + }, + onCancel() {} + }) + } + + submitConfig = () => { + const { config } = this.state + + this.setState({originConfig: fromJS(config).toJS()}) + this.props.handleSave(config) + notification.success({ + top: 92, + message: '淇濆瓨鎴愬姛銆�', + duration: 2 + }) + } + + cancelConfig = () => { + const { config, originConfig } = this.state + + if (!is(fromJS(config), fromJS(originConfig))) { + let _this = this + confirm({ + content: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾杩斿洖鍚楋紵', + onOk() { + _this.props.handleBack() + }, + onCancel() {} + }) + } else { + this.props.handleBack() + } + } + + /** + * @description 鍏ㄥ眬璁剧疆妯℃�佹 + */ + changeSetting = () => { + this.setState({ + settingVisible: true + }) + } + + /** + * @description 淇濆瓨鍏ㄥ眬璁剧疆 + */ + settingSave = () => { + const {config} = this.state + this.settingRef.handleConfirm().then(res => { + this.setState({ + config: {...config, setting: res}, + settingVisible: false + }) + }) + } + + editModalCancel = () => { + const { config, card } = this.state + + if (card.focus) { + let _fields = config.fields.filter(item => item.uuid !== card.uuid) + let _config = {...config, fields: _fields} + + this.setState({ + card: null, + config: _config, + visible: false + }) + } else { + this.setState({ + card: null, + visible: false + }) + } + } + + /** + * @description 鏇存柊 + */ + updateConfig = (config) => { + this.setState({ + config + }) + } + + insert = (config) => { + this.setState({ + config + }, () => { + this.handleForm(config.fields[config.fields.length - 1]) + }) + } + + render () { + const { config, dict } = this.state + + return ( + <div className="mob-form-board"> + <DndProvider backend={HTML5Backend}> + <div className="tools"> + <Collapse accordion defaultActiveKey="1" bordered={false}> + <Panel header={dict['header.menu.form']} key="1"> + <div className="search-element"> + {SearchItems.map((item, index) => { + return (<SourceElement key={index} content={item}/>) + })} + </div> + <FieldsComponent + config={config} + type="form" + updatefield={this.updateConfig} + /> + </Panel> + </Collapse> + </div> + <div className="modal-control"> + <Button icon="setting" onClick={this.changeSetting}>璁剧疆</Button> + <Button type="primary" onClick={this.submitConfig}>淇濆瓨</Button> + <Button onClick={this.cancelConfig}>杩斿洖</Button> + <PasteComponent config={config} updateConfig={this.insert} /> + <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} /> + </div> + <div className="setting"> + <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}> + <div className="mob-shell-inner"> + <div className="am-navbar"> + <Icon type="close" /> + <div className="am-navbar-title">{config.setting.title}</div> + </div> + <DragElement + list={config.fields} + setting={config.setting} + showField={this.state.showField} + placeholder={this.state.dict['header.form.modal.placeholder']} + handleList={this.handleList} + handleForm={this.handleForm} + closeForm={this.closeForm} + /> + <Button className="modal-submit" type="primary">纭畾</Button> + </div> + </div> + </div> + </DndProvider> + <Modal + title={this.state.dict['model.edit']} + visible={this.state.visible} + width={850} + onCancel={this.editModalCancel} + onOk={this.handleSubmit} + confirmLoading={this.state.sqlVerifing} + destroyOnClose + > + <ModalForm + dict={this.state.dict} + card={this.state.card} + formlist={this.state.formlist} + inputSubmit={this.handleSubmit} + standardform={this.state.standardform} + wrappedComponentRef={(inst) => this.formRef = inst} + /> + </Modal> + <Modal + title={this.state.dict['model.edit']} + visible={this.state.settingVisible} + width={850} + maskClosable={false} + onOk={this.settingSave} + onCancel={() => { this.setState({ settingVisible: false }) }} + destroyOnClose + > + <SettingForm + config={config} + dict={this.state.dict} + isSubTab={!!this.props.editTab} + inputSubmit={this.settingSave} + wrappedComponentRef={(inst) => this.settingRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default ComModalConfig \ No newline at end of file diff --git a/src/mob/modalconfig/index.scss b/src/mob/modalconfig/index.scss new file mode 100644 index 0000000..02bdd82 --- /dev/null +++ b/src/mob/modalconfig/index.scss @@ -0,0 +1,321 @@ +.mob-form-board { + position: fixed; + z-index: 1070; + top: 48px; + left: 0px; + right: 0px; + bottom: 0px; + background: rgba(0, 0, 0, 1); + .tools { + position: absolute; + top: 0; + left: 0; + z-index: 1; + width: 235px; + background: #ffffff; + border-right: 1px solid #d9d9d9; + height: 100%; + overflow-y: auto; + padding-bottom: 30px; + .ant-collapse-borderless { + background-color: #ffffff; + } + .ant-collapse-item { + border: 0; + } + .ant-input-search { + margin-top: 10px; + } + .ant-collapse-item.ant-collapse-item-active { + border-bottom: 1px solid #d9d9d9; + } + .ant-collapse .ant-collapse-header { + padding: 11px 16px 10px 40px; + border-bottom: 1px solid #d9d9d9; + background: #1890ff; + color: #ffffff; + } + .ant-collapse-content-box { + .ant-form-item { + margin-bottom: 10px; + .ant-form-item-label { + text-align: left; + height: 25px; + line-height: 25px; + } + } + .ant-btn { + margin-bottom: 10px; + } + } + .search-element { + padding-top: 10px; + li { + padding: 0px 16px 10px; + div { + cursor: move; + } + } + } + .tables { + .ant-select-selection-selected-value { + opacity: 0.4!important; + } + } + .ant-list { + margin-top: 20px; + .ant-list-item { + display: -webkit-box; + padding-right: 20px; + position: relative; + padding-left: 5px; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + width: 100%; + .anticon { + position: absolute; + top: 0px; + right: 0px; + padding: 3px 3px 10px 10px; + cursor: pointer; + } + .bottom-mask { + position: absolute; + width: 100%; + height: 8px; + bottom: 0; + left: 0; + background: #ffffff; + border-radius: 8px; + } + } + } + } + .tools::-webkit-scrollbar { + width: 4px; + } + .tools::-webkit-scrollbar-thumb { + border-radius: 5px; + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08); + background: rgba(0, 0, 0, 0.08); + } + .tools::-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); + } + .modal-control { + position: absolute; + right: 0; + top: 0; + width: 120px; + height: 100vh; + padding: 20px 10px; + background: #ffffff; + z-index: 10; + transition: right 0.3s; + + div:not(.draw), button:not(.ant-switch) { + display: block!important; + margin-bottom: 15px; + width: 100%; + } + .ant-switch.big { + min-width: 60px; + height: 24px; + line-height: 24px; + margin-bottom: 15px; + .ant-switch-inner { + font-size: 14px; + } + } + .ant-switch.big:after { + width: 22px; + height: 22px; + } + } + .setting { + position: relative; + width: 100vw; + height: 100%; + background: #959595; + + .mob-shell { + margin: 0 auto; + background: #000000; + background-size: 100% 100%; + padding: 25px 13px 40px; + border-radius: 30px; + + .am-navbar { + height: 45px; + line-height: 45px; + position: relative; + border-bottom: 1px solid #f0f0f0; + margin-bottom: 10px; + .anticon-close { + position: absolute; + line-height: 45px; + font-size: 18px; + right: 10px; + } + .am-navbar-title { + font-size: 16px; + text-align: center; + } + } + .modal-submit { + width: 100%; + border-radius: 0; + opacity: 0.5; + cursor: default; + font-size: 18px; + height: 40px; + } + + .modal-fields-row { + min-height: calc(100% - 95px); + padding: 0 10px 35px; + } + + .modal-form { + padding: 0px 24px; + min-height: 87px; + .group-title { + position: relative; + min-height: 22px; + margin-bottom: 10px; + padding-top: 10px; + border-bottom: 1px solid #e8e8e8; + + span { + padding: 0 5px 5px; + } + } + > .ant-row { + min-height: 120px; + } + .ant-row .ant-col-6 { + padding: 0 12px!important; + } + .ant-row.ant-form-item .ant-col { + padding: 0; + } + .textarea2, .textarea4 { + padding-left: 7px; + } + .page-card { + position: relative; + background: #ffffff; + border-radius: 2px; + margin-bottom: 15px; + .ant-form-item { + cursor: move; + display: flex; + margin-bottom: 0px; + .ant-form-item-label { + overflow: visible; + position: relative; + height: 40px; + label { + width: 100%; + cursor: move; + overflow: hidden; + display: inline-block; + text-overflow: ellipsis; + white-space: nowrap; + } + } + .ant-form-item-control-wrapper { + position: relative; + .ant-select { + width: 100%; + margin-top: 4px; + } + .ant-calendar-picker { + width: 100%; + margin-top: 4px; + } + .ant-input-number { + width: 100%; + margin-top: 4px; + } + .normal-braft-editor { + border: 1px solid #d9d9d9; + border-radius: 4px; + } + } + .ant-form-item-control-wrapper::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0; + z-index: 1; + } + .ant-col-cuslabel { + width: 10.5%; + } + .ant-col-cuswrap { + width: 89.5%; + } + } + } + .ant-calendar-picker { + min-width: 100px!important; + } + } + } + } + .setting { + overflow-y: auto; + } + .setting::-webkit-scrollbar { + width: 7px; + } + .setting::-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); + } + .setting::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); + border-radius: 3px; + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0); + } +} + + +.modal-fields { + .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/mob/modalconfig/pastecomponent/index.jsx b/src/mob/modalconfig/pastecomponent/index.jsx new file mode 100644 index 0000000..03b2200 --- /dev/null +++ b/src/mob/modalconfig/pastecomponent/index.jsx @@ -0,0 +1,76 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Button, Modal, notification } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) + +class PasteController extends Component { + static propTpyes = { + config: PropTypes.object, // 缁勪欢閰嶇疆 + updateConfig: PropTypes.func + } + + state = { + visible: false + } + + pasteSubmit = () => { + const { config } = this.props + this.pasteFormRef.handleConfirm().then(res => { + if (res.copyType !== 'form') { + notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', duration: 5 }) + return + } + + let keys = config.fields.map(item => item.field ? item.field.toLowerCase() : '$emp_ty$') + + if (['multiselect', 'color', 'brafteditor'].includes(res.type)) { + res.type = 'text' + } + + if (res.field && keys.includes(res.field.toLowerCase())) { + notification.warning({ + top: 92, + message: '瀛楁宸插瓨鍦紒', + duration: 5 + }) + return + } + + this.props.updateConfig({...config, fields: [...config.fields, res]}) + this.setState({visible: false}) + + notification.success({ + top: 92, + message: '绮樿创鎴愬姛锛�', + duration: 2 + }) + }) + } + + render() { + const { visible } = this.state + + return ( + <div style={{display: 'inline-block'}}> + <Button icon="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} >绮樿创</Button> + <Modal + title="绮樿创" + visible={visible} + width={600} + maskClosable={false} + onOk={this.pasteSubmit} + onCancel={() => {this.setState({visible: false})}} + destroyOnClose + > + <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> + </Modal> + </div> + ) + } +} + +export default PasteController \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/mob/modalconfig/pastecomponent/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/mob/modalconfig/pastecomponent/index.scss diff --git a/src/mob/modalconfig/source.jsx b/src/mob/modalconfig/source.jsx new file mode 100644 index 0000000..3fed414 --- /dev/null +++ b/src/mob/modalconfig/source.jsx @@ -0,0 +1,104 @@ +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' + +const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS + +export const SearchItems = [ + { + type: 'form', + label: CommonDict['model.form.text'], + subType: 'text', + url: '' + }, + { + type: 'form', + label: CommonDict['model.form.number'], + subType: 'number', + url: '' + }, + { + type: 'form', + label: CommonDict['model.form.select'], + subType: 'select', + url: '' + }, + { + type: 'form', + label: CommonDict['model.form.link'], + subType: 'link', + url: '' + }, + { + type: 'form', + label: '寮�鍏�', + subType: 'switch', + url: '' + }, + { + type: 'form', + label: '澶氶�夋', + subType: 'checkbox', + url: '' + }, + { + type: 'form', + label: '鍗曢�夋', + subType: 'radio', + url: '' + }, + { + type: 'form', + label: '閫夐」鍗�', + subType: 'checkcard', + url: '' + }, + { + type: 'form', + label: CommonDict['header.form.fileupload'], + subType: 'fileupload', + url: '' + }, + { + type: 'form', + label: CommonDict['model.form.dateday'], + subType: 'date', + url: '' + }, + { + type: 'form', + label: CommonDict['model.form.datemonth'], + subType: 'datemonth', + url: '' + }, + { + type: 'form', + label: CommonDict['model.form.datetime'], + subType: 'datetime', + url: '' + }, + { + type: 'form', + label: CommonDict['model.form.textarea'], + subType: 'textarea', + url: '' + }, + { + type: 'form', + label: CommonDict['header.form.funcvar'], + subType: 'funcvar', + url: '' + }, + { + type: 'form', + label: '鎻愮ず', + subType: 'hint', + url: '' + }, + { + type: 'form', + label: '鍒嗗壊绾�', + subType: 'split', + url: '' + } +] + diff --git a/src/mob/modulesource/index.jsx b/src/mob/modulesource/index.jsx index f4705bf..f84cdd7 100644 --- a/src/mob/modulesource/index.jsx +++ b/src/mob/modulesource/index.jsx @@ -53,6 +53,7 @@ c_id: item.uuid, images: '', c_name: item.title, + typename: sessionStorage.getItem('appType') || '', long_param: '', del_type: 'Y' }).then(result => { diff --git a/src/mob/modulesource/option.jsx b/src/mob/modulesource/option.jsx index 6260773..417a095 100644 --- a/src/mob/modulesource/option.jsx +++ b/src/mob/modulesource/option.jsx @@ -9,22 +9,31 @@ import TableCard from '@/assets/mobimg/table-card.png' import NormalTable from '@/assets/mobimg/normal-table.png' import Pie from '@/assets/mobimg/pie.png' +import Editor from '@/assets/mobimg/editor.png' import SandBox from '@/assets/mobimg/sandbox.png' import Pie1 from '@/assets/mobimg/ring.png' import Pie2 from '@/assets/mobimg/nightingale.png' -import Mainsearch from '@/assets/mobimg/mainsearch.png' +// import Mainsearch from '@/assets/mobimg/mainsearch.png' import Navbar from '@/assets/mobimg/navbar-mob.png' import Carousel from '@/assets/mobimg/carousel.png' import Carousel1 from '@/assets/mobimg/carousel1.png' import form from '@/assets/mobimg/form.png' +import Login from '@/assets/mobimg/login.png' +// import dashboard from '@/assets/mobimg/dashboard.png' +import NavTop from '@/assets/mobimg/navtop-mob.png' +import scatter from '@/assets/mobimg/scatter.png' +import MenuBar from '@/assets/mobimg/menubar.png' // 缁勪欢閰嶇疆淇℃伅 export const menuOptions = [ - { type: 'menu', url: Navbar, component: 'navbar', subtype: 'mobnavbar', title: '瀵艰埅鏍�', width: 1200 }, + { type: 'menu', url: NavTop, component: 'topbar', subtype: 'topbar', title: '瀵艰埅鏍�' }, + { type: 'menu', url: Navbar, component: 'navbar', subtype: 'tabbar', title: '鑿滃崟鏍�' }, + { type: 'menu', url: MenuBar, component: 'menubar', subtype: 'menubar', title: '鑿滃崟' }, { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '鏍囩椤�', width: 24 }, - { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24 }, + // { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24 }, { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�', width: 24 }, { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '灞炴�у崱', width: 24 }, + { type: 'menu', url: card2, component: 'balcony', subtype: 'balcony', title: '鍙诞鍔ㄥ崱', width: 24 }, { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '琛ㄥ崟', width: 24 }, { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '杞挱-鍔ㄦ�佹暟鎹�', width: 24 }, { type: 'menu', url: Carousel1, component: 'carousel', subtype: 'propcard', title: '杞挱-闈欐�佹暟鎹�', width: 24 }, @@ -36,7 +45,11 @@ { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�', width: 24 }, { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '楗煎浘', width: 24 }, { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '鐜浘', width: 24 }, - { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 }, { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 24 }, + // { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '浠〃鐩�', width: 12 }, + { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '鏁g偣鍥�', width: 24 }, + { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '瀵屾枃鏈�', width: 24 }, + { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 }, { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24 }, + { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '鐧诲綍', width: 24 }, ] diff --git a/src/mob/searchconfig/controller.jsx b/src/mob/searchconfig/controller.jsx new file mode 100644 index 0000000..cd440c3 --- /dev/null +++ b/src/mob/searchconfig/controller.jsx @@ -0,0 +1,62 @@ +import React, {Component} from 'react' +import { is, fromJS } from 'immutable' + +import MKEmitter from '@/utils/events.js' +import SearchConfig from '@/mob/searchconfig' + +class SearchController extends Component { + state = { + config: null, + visible: false + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('changeSearch', this.initConfig) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('changeSearch', this.initConfig) + } + + initConfig = (config) => { + this.setState({ + visible: true, + config: fromJS(config).toJS() + }) + } + + handleBack = () => { + this.setState({ + visible: false, + config: null + }) + } + + handleSave = (search) => { + const { config } = this.state + + MKEmitter.emit('submitSearch', {...config, search}) + } + + render () { + const { config, visible } = this.state + + if (!visible) return null + + return ( + <SearchConfig config={config.search} handleBack={this.handleBack} handleSave={this.handleSave}/> + ) + } +} + +export default SearchController \ No newline at end of file diff --git a/src/mob/searchconfig/groupdragelement/card.jsx b/src/mob/searchconfig/groupdragelement/card.jsx new file mode 100644 index 0000000..b0e56e2 --- /dev/null +++ b/src/mob/searchconfig/groupdragelement/card.jsx @@ -0,0 +1,61 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon, Popover } from 'antd' + +import './index.scss' + +const Card = ({ id, card, moveCard, findCard, editCard, closeCard, changeGroup }) => { + 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) => { + const { id: draggedId } = item + + if (draggedId && draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + } + }) + const opacity = isDragging ? 0 : 1 + + const edit = () => { + editCard(id) + } + + const close = () => { + closeCard(id) + } + + const change = () => { + changeGroup(id) + } + + return ( + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="edit" type="edit" onClick={edit} /> + <Icon className="close" type="close" onClick={close} /> + </div> + } trigger="hover"> + <div className="page-card" onDoubleClick={change} style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + {card.wrap.icon ? <div className="icon"> + <Icon type={card.wrap.icon} /> + </div> : null} + <div className="name"> + {card.wrap.name} + </div> + </div> + </div> + </Popover> + ) +} +export default Card diff --git a/src/mob/searchconfig/groupdragelement/index.jsx b/src/mob/searchconfig/groupdragelement/index.jsx new file mode 100644 index 0000000..da4ac2e --- /dev/null +++ b/src/mob/searchconfig/groupdragelement/index.jsx @@ -0,0 +1,64 @@ +import React, { useState } from 'react' +import { is, fromJS } from 'immutable' +import update from 'immutability-helper' +import Card from './card' +import './index.scss' + +const Container = ({list, handleList, handleForm, closeForm, handleGroup }) => { + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + + if (!card) return + + const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) + + handleList(_cards) + } + + if (!is(fromJS(cards), fromJS(list))) { + setCards(list) + } + + const findCard = id => { + const card = cards.filter(c => `${c.uuid}` === id)[0] + return { + card, + index: cards.indexOf(card), + } + } + + const editCard = id => { + const { card } = findCard(id) + + handleForm(card) + } + + const closeCard = id => { + const { card } = findCard(id) + closeForm(card) + } + + const changeGroup = id => { + const { card } = findCard(id) + handleGroup(card) + } + + return ( + <div className="ant-row modal-search-groups-row"> + {cards.map(card => { + return <Card + id={card.uuid} + key={card.uuid} + card={card} + moveCard={moveCard} + editCard={editCard} + closeCard={closeCard} + changeGroup={changeGroup} + findCard={findCard} + /> + })} + </div> + ) +} +export default Container diff --git a/src/mob/searchconfig/groupdragelement/index.scss b/src/mob/searchconfig/groupdragelement/index.scss new file mode 100644 index 0000000..068d8d6 --- /dev/null +++ b/src/mob/searchconfig/groupdragelement/index.scss @@ -0,0 +1,27 @@ + +.modal-search-groups-row { + min-height: 20px!important; + padding-right: 30px; + margin-bottom: 15px; + .page-card { + float: left; + width: 13.333%; + text-align: center; + padding: 5px; + .icon { + background: #f0f0f0; + color: #000000; + border-radius: 30px; + width: 35px; + height: 35px; + line-height: 35px; + font-size: 18px; + margin: 0 auto 5px; + } + .name { + font-size: 13px; + white-space: nowrap; + color: rgba(0, 0, 0, 0.85); + } + } +} \ No newline at end of file diff --git a/src/mob/searchconfig/groupform/index.jsx b/src/mob/searchconfig/groupform/index.jsx new file mode 100644 index 0000000..44598bc --- /dev/null +++ b/src/mob/searchconfig/groupform/index.jsx @@ -0,0 +1,90 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input } from 'antd' +import { formRule } from '@/utils/option.js' +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const MkIcon = asyncComponent(() => import('@/components/mkIcon')) + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + config: PropTypes.object, // 琛ㄥ崟閰嶇疆淇℃伅 + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = {} + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { config } = this.props + const { getFieldDecorator } = this.props.form + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout} className="ant-advanced-search-form modal-setting-form"> + <Row gutter={24}> + <Col span={22}> + <Form.Item label="鍚嶇О"> + {getFieldDecorator('name', { + initialValue: config.wrap.name, + rules: [ + { + required: true, + message: '璇峰~鍐欏悕绉�!' + }, + { + max: formRule.input.max, + message: formRule.input.message + } + ] + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={22}> + <Form.Item label="鍥炬爣"> + {getFieldDecorator('icon', { + initialValue: config.wrap.icon + })( + <MkIcon allowClear/> + )} + </Form.Item> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/mob/searchconfig/groupform/index.scss b/src/mob/searchconfig/groupform/index.scss new file mode 100644 index 0000000..9a74987 --- /dev/null +++ b/src/mob/searchconfig/groupform/index.scss @@ -0,0 +1,18 @@ +.ant-advanced-search-form.modal-setting-form { + .textarea { + .ant-form-item-label { + width: 16.3%; + } + .ant-form-item-control-wrapper { + width: 83.33333333%; + } + } + .ant-input-number { + width: 100%; + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } +} \ No newline at end of file diff --git a/src/mob/searchconfig/index.jsx b/src/mob/searchconfig/index.jsx new file mode 100644 index 0000000..1d388a5 --- /dev/null +++ b/src/mob/searchconfig/index.jsx @@ -0,0 +1,574 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { DndProvider } from 'react-dnd' +import HTML5Backend from 'react-dnd-html5-backend' +import moment from 'moment' +import { Button, Modal, Collapse, notification, Switch, Icon } from 'antd' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import { getSearchForm } from '@/templates/zshare/formconfig' +import SourceElement from '@/templates/modalconfig/dragelement/source' +import SettingForm from './settingform' +import asyncComponent from '@/utils/asyncComponent' +import { SearchItems } from './source' +import './index.scss' + +const { Panel } = Collapse +const { confirm } = Modal +const SearchForm = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent/searchform')) +const PasteComponent = asyncComponent(() => import('./pastecomponent')) +const DragElement = asyncComponent(() => import('./searchdragelement')) +const GDragElement = asyncComponent(() => import('./groupdragelement')) +const GroupForm = asyncComponent(() => import('./groupform')) + +class ComModalConfig extends Component { + static propTpyes = { + btn: PropTypes.object, + handleSave: PropTypes.func, + handleBack: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, // 瀛楀吀 + config: null, // 椤甸潰閰嶇疆锛屽寘鎷ā鏉跨被鍨嬨�佹ā鎬佹璁剧疆銆佹坊鍔犺〃鍚嶃�佽〃鍗曞垪琛� + visible: false, // 琛ㄥ崟缂栬緫妯℃�佹锛屾樉绀烘帶鍒� + formlist: null, // 琛ㄥ崟缂栬緫妯℃�佹锛屽彲缂栬緫瀛楁 + card: null, // 缂栬緫鍏冪礌 + settingVisible: false, // 鍏ㄥ眬閰嶇疆妯℃�佹 + originConfig: null, // 鍘熷鑿滃崟 + sqlVerifing: false, // sql楠岃瘉 + showField: false, // 鏄剧ず琛ㄥ崟瀛楁鍊� + group: null, + editGroup: null + } + + /** + * @description 鏁版嵁棰勫鐞� + */ + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({ + group: fromJS(config).toJS(), + config: fromJS(config).toJS(), + originConfig: fromJS(config).toJS() + }) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + /** + * @description 琛ㄥ崟鍙樺寲 + */ + handleList = (list, newcard) => { + let _group = {...this.state.group, fields: list} + + this.setState({ + group: _group + }, () => { + if (newcard) { + this.handleForm(newcard) + } + }) + this.resetConfig(_group) + } + + /** + * @description 鍒嗙粍鍙樺寲 + */ + handleGroupList = (list) => { + let _group = {...this.state.group, groups: list} + + this.setState({ + group: _group + }) + this.resetConfig(_group) + } + + /** + * @description 琛ㄥ崟鍙樺寲 + */ + handleList = (list, newcard) => { + let _group = {...this.state.group, fields: list} + + this.setState({ + group: _group + }, () => { + if (newcard) { + this.handleForm(newcard) + } + }) + this.resetConfig(_group) + } + + resetConfig = (group) => { + let _config = fromJS(this.state.config).toJS() + if (group.floor === 1) { + _config = group + } else { + _config.groups = _config.groups.map(item => { + if (item.uuid === group.uuid) return group + return item + }) + } + + this.setState({ + config: _config + }) + } + + /** + * @description 琛ㄥ崟缂栬緫 + */ + handleForm = (_card) => { + let card = fromJS(_card).toJS() + + this.setState({ + visible: true, + card: card, + formlist: getSearchForm(card, []) + }) + } + + /** + * @description 缂栬緫鍚庢彁浜� + * 1銆佽幏鍙栫紪杈戝悗鐨勮〃鍗曚俊鎭� + * 2銆佸幓闄ゅ彲鑳藉瓨鍦ㄧ殑绀轰緥琛ㄥ崟 + * 3銆侀�氳繃loading鍒锋柊 + */ + handleSubmit = () => { + const { config } = this.state + this.formRef.handleConfirm().then(res => { + let _group = fromJS(this.state.group).toJS() + + _group.fields = _group.fields.map(item => { + if (item.uuid === res.uuid) { + return res + } else { + return item + } + }) + + let fieldrepet = false // 瀛楁閲嶅 + let lowerField = res.field.toLowerCase() + + if (config.setting.field) { + let m = config.setting.field.toLowerCase().split(',') + if (m.includes(lowerField)) { + fieldrepet = true + } + } + config.fields.forEach(item => { + if (item.uuid === res.uuid) return + if (res.type === 'date' && item.type === 'date') return + if (item.field.toLowerCase() === lowerField) { + fieldrepet = true + } + }) + + config.groups.forEach(group => { + if (group.setting.field) { + let m = group.setting.field.toLowerCase().split(',') + if (m.includes(lowerField)) { + fieldrepet = true + } + } + group.fields.forEach(item => { + if (item.uuid === res.uuid) return + if (res.type === 'date' && item.type === 'date') return + if (item.field.toLowerCase() === lowerField) { + fieldrepet = true + } + }) + }) + + if (fieldrepet) { + notification.warning({ + top: 92, + message: '瀛楁宸插瓨鍦紒', + duration: 10 + }) + return + } + + if (['checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { + this.setState({ + sqlVerifing: true + }) + + let param = { + func: 's_debug_sql', + exec_type: 'y', + LText: res.dataSource + } + + param.LText = param.LText.replace(/@\$|\$@/ig, '') + + param.LText = Utils.formatOptions(param.LText) + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt('', param.timestamp) + + if (window.GLOB.mainSystemApi && res.database === 'sso') { + param.rduri = window.GLOB.mainSystemApi + } + + Api.getLocalConfig(param).then(result => { + if (result.status) { + this.setState({ + sqlVerifing: false, + group: _group, + card: null, + visible: false + }) + this.resetConfig(_group) + } else { + this.setState({sqlVerifing: false}) + + Modal.error({ + title: result.message + }) + } + }) + } else { + this.setState({ + group: _group, + card: null, + visible: false + }) + this.resetConfig(_group) + } + }) + } + + /** + * @description 琛ㄥ崟鍒犻櫎骞跺埛鏂� + */ + closeForm = (card) => { + let _this = this + + confirm({ + content: `纭畾鍒犻櫎${card.label ? `<<${card.label}>>` : ''}鍚楋紵`, + onOk() { + let _group = fromJS(_this.state.group).toJS() + _group.fields = _group.fields.filter(item => item.uuid !== card.uuid) + + _this.setState({ + group: _group, + }) + _this.resetConfig(_group) + }, + onCancel() {} + }) + } + + submitConfig = () => { + const { config } = this.state + + this.setState({originConfig: fromJS(config).toJS()}) + this.props.handleSave(config) + notification.success({ + top: 92, + message: '淇濆瓨鎴愬姛銆�', + duration: 1 + }) + } + + cancelConfig = () => { + const { config, originConfig } = this.state + + if (!is(fromJS(config), fromJS(originConfig))) { + let _this = this + confirm({ + content: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾杩斿洖鍚楋紵', + onOk() { + _this.props.handleBack() + }, + onCancel() {} + }) + } else { + this.props.handleBack() + } + } + + /** + * @description 鍒嗙粍璁剧疆妯℃�佹 + */ + changeSetting = () => { + this.setState({ + settingVisible: true + }) + } + + /** + * @description 淇濆瓨鍒嗙粍璁剧疆 + */ + settingSave = () => { + const { config } = this.state + this.settingRef.handleConfirm().then(res => { + let _group = {...this.state.group, setting: res} + let lowers = _group.setting.field ? _group.setting.field.toLowerCase() : '' + + if (lowers) { + let fieldrepet = false // 瀛楁閲嶅 + lowers = lowers.split(',') + let length = lowers.length + + if (_group.floor !== 1 && config.setting.field) { + let m = config.setting.field.toLowerCase().split(',') + if (Array.from(new Set([...m, ...lowers])).length < m.length + length) { + fieldrepet = true + } + } + + config.fields.forEach(item => { + if (lowers.includes(item.field.toLowerCase())) { + fieldrepet = true + } + }) + + config.groups.forEach(group => { + if (_group.uuid === group.uuid) return + if (group.setting.field) { + let m = group.setting.field.toLowerCase().split(',') + if (Array.from(new Set([...m, ...lowers])).length < m.length + length) { + fieldrepet = true + } + } + group.fields.forEach(item => { + if (lowers.includes(item.field.toLowerCase())) { + fieldrepet = true + } + }) + }) + + if (fieldrepet) { + notification.warning({ + top: 92, + message: '瀛楁宸插瓨鍦紒', + duration: 10 + }) + return + } + } + + this.setState({ + group: _group, + settingVisible: false + }) + this.resetConfig(_group) + }) + } + + editModalCancel = () => { + const { group, card } = this.state + + if (card.focus) { + let _fields = group.fields.filter(item => item.uuid !== card.uuid) + let _group = {...group, fields: _fields} + + this.setState({ + card: null, + group: _group, + visible: false + }) + this.resetConfig(_group) + } else { + this.setState({ + card: null, + visible: false + }) + } + } + + plusGroup = () => { + let config = fromJS(this.state.config).toJS() + let _g = { + uuid: Utils.getuuid(), + wrap: { name: 'name', icon: '' }, + setting: { type: 'title', field: '', title: '', focus: 'true', btn: 'hidden' }, + fields: [] + } + + config.groups.push(_g) + + this.setState({config, group: config, editGroup: _g, gVisible: true}) + } + + handleGroupForm = (_g) => { + this.setState({editGroup: _g, gVisible: true}) + } + + /** + * @description 淇濆瓨鍒嗙粍璁剧疆 + */ + groupSave = () => { + this.gRef.handleConfirm().then(res => { + let _g = {...this.state.editGroup, wrap: res} + + let _group = fromJS(this.state.group).toJS() + _group.groups = _group.groups.map(item => { + if (item.uuid === _g.uuid) return _g + return item + }) + + this.setState({ + editGroup: null, + group: _group, + gVisible: false + }) + this.resetConfig(_group) + }) + } + + handleGroup = (g) => { + this.setState({ + group: g + }) + } + + closeGroup = (g) => { + const _this = this + let _group = fromJS(this.state.group).toJS() + _group.groups = _group.groups.filter(item => item.uuid !== g.uuid) + + confirm({ + content: `纭畾鍒犻櫎鍒嗙粍銆�${g.wrap.name}銆嬪悧锛焋, + onOk() { + _this.setState({ group: _group }) + _this.resetConfig(_group) + }, + onCancel() {} + }) + } + + returnUp = () => { + const { config } = this.state + + this.setState({ + group: config + }) + } + + render () { + const { dict, group, editGroup } = this.state + return ( + <div className="mob-search-board"> + <DndProvider backend={HTML5Backend}> + <div className="tools"> + <Collapse accordion defaultActiveKey="1" bordered={false}> + <Panel header={dict['header.menu.form']} key="1"> + <div className="search-element"> + {SearchItems.map((item, index) => { + return (<SourceElement key={index} content={item}/>) + })} + </div> + </Panel> + </Collapse> + </div> + <div className="modal-control"> + <Button type="primary" onClick={this.submitConfig}>淇濆瓨</Button> + <Button onClick={this.cancelConfig}>鍏抽棴</Button> + {!group.floor ? <Button onClick={this.returnUp}>杩斿洖涓婄骇</Button> : null} + <PasteComponent insert={this.insert} /> + <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} /> + </div> + <div className="setting"> + <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}> + <div className="mob-shell-inner"> + <Icon className="setting-group" onClick={this.changeSetting} type="setting" /> + {group.setting.type === 'title' ? <div className="am-navbar"> + <Icon type="left" /> + <div className="am-navbar-title">{group.setting.title}</div> + </div> : <div className="am-navbar"> + <Icon type="left" /> + <div className="search-bar"><Icon type="search" /></div> + </div>} + {group.floor === 1 ? <Icon className="plus-group" type="plus" onClick={this.plusGroup} /> : null} + <div style={{minHeight: 'calc(100% - 100px)'}}> + {group.floor === 1 && group.groups.length > 0 ? <GDragElement + list={group.groups} + handleList={this.handleGroupList} + handleForm={this.handleGroupForm} + handleGroup={this.handleGroup} + closeForm={this.closeGroup} + /> : null} + <DragElement + list={group.fields} + showField={this.state.showField} + handleList={this.handleList} + handleForm={this.handleForm} + closeForm={this.closeForm} + /> + </div> + {group.setting.btn !== 'hidden' ? <div className="search-btn"> + <Button className="reset">閲嶇疆</Button> + <Button className="submit" type="primary">纭畾</Button> + </div> : null} + </div> + </div> + </div> + </DndProvider> + <Modal + title={this.state.dict['model.edit']} + visible={this.state.visible} + width={850} + onCancel={this.editModalCancel} + onOk={this.handleSubmit} + confirmLoading={this.state.sqlVerifing} + destroyOnClose + > + <SearchForm + dict={this.state.dict} + card={this.state.card} + formlist={this.state.formlist} + inputSubmit={this.handleSubmit} + wrappedComponentRef={(inst) => this.formRef = inst} + /> + </Modal> + <Modal + title={this.state.dict['model.edit']} + visible={this.state.settingVisible} + width={850} + maskClosable={false} + onOk={this.settingSave} + onCancel={() => { this.setState({ settingVisible: false }) }} + destroyOnClose + > + <SettingForm + config={group} + inputSubmit={this.settingSave} + wrappedComponentRef={(inst) => this.settingRef = inst} + /> + </Modal> + <Modal + title={this.state.dict['model.edit']} + visible={this.state.gVisible} + width={600} + maskClosable={false} + onOk={this.groupSave} + onCancel={() => { this.setState({ gVisible: false }) }} + destroyOnClose + > + <GroupForm + config={editGroup} + inputSubmit={this.groupSave} + wrappedComponentRef={(inst) => this.gRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default ComModalConfig \ No newline at end of file diff --git a/src/mob/searchconfig/index.scss b/src/mob/searchconfig/index.scss new file mode 100644 index 0000000..fac4043 --- /dev/null +++ b/src/mob/searchconfig/index.scss @@ -0,0 +1,365 @@ +.mob-search-board { + position: fixed; + z-index: 1070; + top: 48px; + left: 0px; + right: 0px; + bottom: 0px; + background: rgba(0, 0, 0, 1); + .tools { + position: absolute; + top: 0; + left: 0; + z-index: 1; + width: 235px; + background: #ffffff; + border-right: 1px solid #d9d9d9; + height: 100%; + overflow-y: auto; + padding-bottom: 30px; + .ant-collapse-borderless { + background-color: #ffffff; + } + .ant-collapse-item { + border: 0; + } + .ant-input-search { + margin-top: 10px; + } + .ant-collapse-item.ant-collapse-item-active { + border-bottom: 1px solid #d9d9d9; + } + .ant-collapse .ant-collapse-header { + padding: 11px 16px 10px 40px; + border-bottom: 1px solid #d9d9d9; + background: #1890ff; + color: #ffffff; + } + .ant-collapse-content-box { + .ant-form-item { + margin-bottom: 10px; + .ant-form-item-label { + text-align: left; + height: 25px; + line-height: 25px; + } + } + .ant-btn { + margin-bottom: 10px; + } + } + .search-element { + padding-top: 10px; + li { + padding: 0px 16px 10px; + div { + cursor: move; + } + } + } + .tables { + .ant-select-selection-selected-value { + opacity: 0.4!important; + } + } + .ant-list { + margin-top: 20px; + .ant-list-item { + display: -webkit-box; + padding-right: 20px; + position: relative; + padding-left: 5px; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + width: 100%; + .anticon { + position: absolute; + top: 0px; + right: 0px; + padding: 3px 3px 10px 10px; + cursor: pointer; + } + .bottom-mask { + position: absolute; + width: 100%; + height: 8px; + bottom: 0; + left: 0; + background: #ffffff; + border-radius: 8px; + } + } + } + } + .tools::-webkit-scrollbar { + width: 4px; + } + .tools::-webkit-scrollbar-thumb { + border-radius: 5px; + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08); + background: rgba(0, 0, 0, 0.08); + } + .tools::-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); + } + .modal-control { + position: absolute; + right: 0; + top: 0; + width: 120px; + height: 100vh; + padding: 20px 10px; + background: #ffffff; + z-index: 10; + transition: right 0.3s; + + div:not(.draw), button:not(.ant-switch) { + display: block!important; + margin-bottom: 15px; + width: 100%; + } + .ant-switch.big { + min-width: 60px; + height: 24px; + line-height: 24px; + margin-bottom: 15px; + .ant-switch-inner { + font-size: 14px; + } + } + .ant-switch.big:after { + width: 22px; + height: 22px; + } + } + .setting { + position: relative; + width: 100vw; + height: 100%; + background: #959595; + + .mob-shell { + margin: 0 auto; + background: #000000; + background-size: 100% 100%; + padding: 25px 13px 40px; + border-radius: 30px; + + .am-navbar { + height: 45px; + line-height: 45px; + position: relative; + border-bottom: 1px solid #f0f0f0; + margin-bottom: 10px; + .anticon-close, .anticon-left { + position: absolute; + line-height: 45px; + font-size: 18px; + left: 10px; + } + .am-navbar-title { + font-size: 16px; + text-align: center; + color: #000000; + } + .search-bar { + height: 35px; + line-height: 35px; + padding: 0 10px; + color:rgba(0, 0, 0, 0.65); + border: 1px solid #E9EDF0; + background: #E9EDF0; + border-radius: 4px; + position: relative; + top: 50%; + transform: translateY(-50%); + margin: 0 30px 0 35px; + } + } + .search-btn { + .reset { + width: 30%; + border-radius: 0; + opacity: 0.5; + cursor: default; + font-size: 18px; + height: 45px; + } + .submit { + width: 70%; + border-radius: 0; + opacity: 0.5; + cursor: default; + font-size: 18px; + height: 45px; + } + } + + .setting-group { + position: absolute; + right: 0px; + top: 0px; + font-size: 18px; + padding: 5px; + cursor: pointer; + z-index: 1; + } + .plus-group { + color: #26C281; + position: absolute; + right: 0px; + top: 45px; + font-size: 18px; + padding: 5px; + cursor: pointer; + z-index: 2; + } + + .modal-search-fields-row { + min-height: 300px; + padding: 0 10px 35px; + } + + .modal-form { + padding: 0px 24px; + min-height: 87px; + .group-title { + position: relative; + min-height: 22px; + margin-bottom: 10px; + padding-top: 10px; + border-bottom: 1px solid #e8e8e8; + + span { + padding: 0 5px 5px; + } + } + > .ant-row { + min-height: 120px; + } + .ant-row .ant-col-6 { + padding: 0 12px!important; + } + .ant-row.ant-form-item .ant-col { + padding: 0; + } + .textarea2, .textarea4 { + padding-left: 7px; + } + .page-card { + position: relative; + background: #ffffff; + border-radius: 2px; + margin-bottom: 15px; + .ant-form-item { + cursor: move; + display: flex; + margin-bottom: 0px; + .ant-form-item-label { + overflow: visible; + position: relative; + height: 40px; + label { + width: 100%; + cursor: move; + overflow: hidden; + display: inline-block; + text-overflow: ellipsis; + white-space: nowrap; + } + } + .ant-form-item-control-wrapper { + position: relative; + .ant-select { + width: 100%; + margin-top: 4px; + } + .ant-calendar-picker { + width: 100%; + margin-top: 4px; + } + .ant-input-number { + width: 100%; + margin-top: 4px; + } + .normal-braft-editor { + border: 1px solid #d9d9d9; + border-radius: 4px; + } + } + .ant-form-item-control-wrapper::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0; + z-index: 1; + } + .ant-col-cuslabel { + width: 10.5%; + } + .ant-col-cuswrap { + width: 89.5%; + } + } + } + .ant-calendar-picker { + min-width: 100px!important; + } + } + } + } + .setting { + overflow-y: auto; + } + .setting::-webkit-scrollbar { + width: 7px; + } + .setting::-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); + } + .setting::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); + border-radius: 3px; + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0); + } +} + + +.modal-fields { + .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/mob/searchconfig/pastecomponent/index.jsx b/src/mob/searchconfig/pastecomponent/index.jsx new file mode 100644 index 0000000..ed81117 --- /dev/null +++ b/src/mob/searchconfig/pastecomponent/index.jsx @@ -0,0 +1,57 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Button, Modal, notification } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) + +class PasteController extends Component { + static propTpyes = { + updateConfig: PropTypes.func + } + + state = { + visible: false + } + + pasteSubmit = () => { + this.pasteFormRef.handleConfirm().then(res => { + if (res.copyType !== 'search') { + notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', duration: 5 }) + return + } + + if (['multiselect', 'color', 'brafteditor'].includes(res.type)) { + res.type = 'text' + } + + this.props.updateConfig(res) + this.setState({visible: false}) + }) + } + + render() { + const { visible } = this.state + + return ( + <div style={{display: 'inline-block'}}> + <Button icon="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} >绮樿创</Button> + <Modal + title="绮樿创" + visible={visible} + width={600} + maskClosable={false} + onOk={this.pasteSubmit} + onCancel={() => {this.setState({visible: false})}} + destroyOnClose + > + <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> + </Modal> + </div> + ) + } +} + +export default PasteController \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/mob/searchconfig/pastecomponent/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/mob/searchconfig/pastecomponent/index.scss diff --git a/src/mob/searchconfig/searchdragelement/card.jsx b/src/mob/searchconfig/searchdragelement/card.jsx new file mode 100644 index 0000000..5a4b632 --- /dev/null +++ b/src/mob/searchconfig/searchdragelement/card.jsx @@ -0,0 +1,132 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon, Popover, Form } from 'antd' +import { Range } from 'antd-mobile' +import moment from 'moment' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const CheckCard = asyncComponent(() => import('@/templates/modalconfig/checkCard')) + +const Card = ({ id, card, moveCard, findCard, editCard, closeCard, copyCard, showField }) => { + const originalIndex = findCard(id).index + const [{ isDragging }, drag] = useDrag({ + item: { type: 'search', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + const [, drop] = useDrop({ + accept: 'search', + canDrop: () => true, + drop: (item) => { + const { id: draggedId, originalIndex } = item + + if (originalIndex === undefined) { + item.dropTargetId = id + } else if (draggedId && draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + } + }) + const opacity = isDragging ? 0 : 1 + + const edit = () => { + editCard(id) + } + + const close = () => { + closeCard(id) + } + + const copy = () => { + copyCard(id) + } + + let formItem = null + if (card.type === 'date') { + formItem = (<div className="am-list-item"> + <div className="am-list-line"> + {card.labelShow !== 'false' ? <div className="am-input-label">{card.label}</div> : null} + <div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD') : '璇烽�夋嫨'}</div> + <div className="am-list-extra"><Icon type="right" /></div> + </div> + </div>) + } else if (card.type === 'datemonth') { + formItem = (<div className="am-list-item"> + <div className="am-list-line"> + {card.labelShow !== 'false' ? <div className="am-input-label">{card.label}</div> : null} + <div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'month').format('YYYY-MM') : '璇烽�夋嫨'}</div> + <div className="am-list-extra"><Icon type="right" /></div> + </div> + </div>) + } else if (card.type === 'range') { + let value = [(card.minValue || 0), (card.maxValue || 20)] + if (card.initval) { + value = card.initval.split(',') + value = [+value[0], +value[1]] + } + formItem = (<div className="am-list-item slider"> + <div className="am-list-line"> + {card.labelShow !== 'false' ? <div className="am-input-label">{card.label}</div> : null} + <div className="am-input-control"> + <Range + min={card.minValue || 0} + max={card.maxValue || 20} + value={value} + /> + </div> + </div> + </div>) + } else if (card.type === 'daterange') { + let value = '璇烽�夋嫨' + if (card.initval) { + try { + let _initval = JSON.parse(card.initval) + value = [moment().subtract(_initval[0], 'days').format('YYYY-MM-DD'), moment().subtract(_initval[1], 'days').format('YYYY-MM-DD')].join(' ~ ') + } catch { + value = '璇烽�夋嫨' + } + } + formItem = (<div className="am-list-item"> + <div className="am-list-line"> + {card.labelShow !== 'false' ? <div className="am-input-label">{card.label}</div> : null} + <div className="am-input-control">{value}</div> + <div className="am-list-extra"><Icon type="right" /></div> + </div> + </div>) + } else if (card.type === 'checkcard') { + formItem = (<div className="am-list-item check-card"> + <div className="am-list-line"> + {card.labelShow !== 'false' ? <div className="am-input-label">{card.label}</div> : null} + <div className="am-input-control"> + <CheckCard config={card} /> + </div> + </div> + </div>) + } + + return ( + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="edit" type="edit" onClick={edit} /> + <Icon className="copy" type="copy" onClick={copy} /> + <Icon className="close" type="close" onClick={close} /> + </div> + } trigger="hover"> + <div className="page-card" style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + {card.type === 'split' ? formItem : <Form.Item + className={'ant-form-item' + (card.required === 'true' ? ' required' : '') + (card.splitline === 'false' ? ' no-boder' : '')} + > + {formItem} + {showField ? <div className="field-name">{card.field}{card.hidden === 'true' ? '(闅愯棌)' : ''}</div> : ''} + </Form.Item>} + </div> + </div> + </Popover> + ) +} +export default Card diff --git a/src/mob/searchconfig/searchdragelement/index.jsx b/src/mob/searchconfig/searchdragelement/index.jsx new file mode 100644 index 0000000..10a535e --- /dev/null +++ b/src/mob/searchconfig/searchdragelement/index.jsx @@ -0,0 +1,123 @@ +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, handleList, handleForm, closeForm, showField }) => { + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + + if (!card) return + + const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) + + handleList(_cards) + } + + if (!is(fromJS(cards), fromJS(list))) { + setCards(list) + } + + const findCard = id => { + const card = cards.filter(c => `${c.uuid}` === id)[0] + return { + card, + index: cards.indexOf(card), + } + } + + const editCard = id => { + const { card } = findCard(id) + delete card.focus + handleForm(card) + } + + const closeCard = id => { + const { card } = findCard(id) + closeForm(card) + } + + const copyCard = id => { + const { card, index: overIndex } = findCard(id) + + let _card = fromJS(card).toJS() + _card.uuid = Utils.getuuid() + _card.focus = true + + // 澶嶅埗鍒板壀鍒囨澘 + let oInput = document.createElement('input') + let val = JSON.parse(JSON.stringify(_card)) + val.copyType = 'search' + + oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val))) + document.body.appendChild(oInput) + oInput.select() + document.execCommand('Copy') + oInput.className = 'oInput' + oInput.style.display = 'none' + document.body.removeChild(oInput) + + const _cards = update(cards, { $splice: [[overIndex + 1, 0, _card]] }) + + setCards(_cards) + + handleList(_cards, _card) + } + + const [, drop] = useDrop({ + accept: 'search', + drop(item) { + if (item.hasOwnProperty('originalIndex')) { + return + } + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.label = 'label' + newcard.type = item.subType + newcard.resourceType = '0' + newcard.options = [] + newcard.required = 'true' + newcard.focus = true + + let targetId = '' + + if (item.dropTargetId) { + targetId = item.dropTargetId + delete item.dropTargetId + } else if (cards.length > 0) { + targetId = cards[cards.length - 1].uuid + } + + const { index: overIndex } = findCard(`${targetId}`) // cards涓虹┖鏃� overIndex 涓� -1 + const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) + + setCards(_cards) + + handleList(_cards, newcard) + } + }) + + return ( + <div ref={drop} className="ant-row modal-search-fields-row"> + {cards.map(card => { + return <Card + id={card.uuid} + key={card.uuid} + card={card} + showField={showField} + moveCard={moveCard} + editCard={editCard} + closeCard={closeCard} + copyCard={copyCard} + findCard={findCard} + /> + })} + </div> + ) +} +export default Container diff --git a/src/mob/searchconfig/searchdragelement/index.scss b/src/mob/searchconfig/searchdragelement/index.scss new file mode 100644 index 0000000..357ef51 --- /dev/null +++ b/src/mob/searchconfig/searchdragelement/index.scss @@ -0,0 +1,149 @@ + +.modal-search-fields-row { + padding-bottom: 35px; + .mob-col.ant-col { + display: inline-block; + float: none; + vertical-align: top; + padding-left: 1.2%; + padding-right: 1.2%; + } + .am-list-item { + font-size: 16px; + padding-left: 10px; + position: relative; + display: flex; + height: 44px; + min-height: 44px; + background-color: #fff; + vertical-align: middle; + overflow: hidden; + transition: background-color 200ms; + align-items: center; + + .am-list-line { + align-items: center; + position: relative; + display: flex; + flex: 1 1; + align-self: stretch; + padding-right: 15px; + overflow: hidden; + .am-input-label { + width: 28%; + color: #000; + font-size: 16px; + margin-left: 0; + margin-right: 5px; + text-align: left; + white-space: nowrap; + overflow: hidden; + padding: 2px 0; + text-overflow: ellipsis; + } + .am-list-switch { + flex: 1; + text-align: right; + } + .am-input-control { + font-size: 16px; + flex: 1 1; + text-align: right; + } + .am-input-control.left { + text-align: left; + } + .am-list-extra { + display: block; + width: 15px; + height: 15px; + margin-left: 8px; + i { + vertical-align: top; + } + } + } + } + .am-list-item.check-card { + height: auto; + .am-list-line { + align-items: start; + display: block; + .check-card-edit-box { + margin-top: 0!important; + } + } + } + .am-list-item.hint { + height: auto; + .am-list-line { + align-items: start; + display: block; + .am-input-label { + line-height: 2; + } + .am-input-control { + font-size: 14px; + line-height: 1.5; + text-align: left; + padding-bottom: 5px; + } + } + } + .am-list-item.slider { + height: auto; + .am-list-line { + align-items: start; + display: block; + .am-input-control { + height: 25px; + padding-top: 10px; + padding-left: 12px; + } + } + } + + .check-card-edit-box .card-cell span { + line-height: 1.5; + } + .ant-form-item { + cursor: move; + margin-bottom: 0px; + .ant-form-item-control-wrapper::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0; + z-index: 1; + } + .field-name { + margin-left: 10px; + line-height: 1.5; + } + .ant-form-item-children { + vertical-align: top; + } + } + .ant-form-item.required { + .am-input-label::before { + display: inline-block; + margin-right: 4px; + color: #f5222d; + font-size: 14px; + font-family: SimSun, sans-serif; + line-height: 1; + content: '*'; + } + } + .ant-form-item.no-boder { + .am-list-line { + border-bottom: none; + } + } + .page-card { + margin-bottom: 10px; + } +} \ No newline at end of file diff --git a/src/mob/searchconfig/settingform/index.jsx b/src/mob/searchconfig/settingform/index.jsx new file mode 100644 index 0000000..c5a5443 --- /dev/null +++ b/src/mob/searchconfig/settingform/index.jsx @@ -0,0 +1,222 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Radio, Select, Tooltip, Icon } from 'antd' +import { formRule } from '@/utils/option.js' +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + config: PropTypes.object, // 琛ㄥ崟閰嶇疆淇℃伅 + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + roleList: [], + type: this.props.config.setting.type || 'title' + } + + UNSAFE_componentWillMount() { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + this.setState({roleList}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { config } = this.props + const { getFieldDecorator } = this.props.form + const { type, roleList } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout} className="mob-search-setting-form"> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="椤堕儴鏍峰紡"> + {getFieldDecorator('type', { + initialValue: type + })( + <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({type: e.target.value})}> + <Radio value="title">鏍囬鏍�</Radio> + <Radio value="search">鎼滅储鏍�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="浣跨敤鎼滅储鏍忔椂锛屾爣棰樼敤浜庢悳绱㈡潯浠堕殣钘忔椂鏄剧ず銆�"> + <Icon type="question-circle" /> + 鏍囬 + </Tooltip> + }> + {getFieldDecorator('title', { + initialValue: config.setting.title, + rules: [ + { + max: formRule.input.max, + message: formRule.input.message + } + ] + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + {type === 'search' ? <Col span={12}> + <Form.Item label="鎼滅储瀛楁"> + {getFieldDecorator('field', { + initialValue: config.setting.field, + rules: [ + { + required: true, + message: '璇峰~鍐欏瓧娈�!' + }, + { + max: formRule.input.max, + message: formRule.input.message + }, + { + pattern: formRule.field.multipattern, + message: formRule.field.message + } + ] + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> : null} + {type === 'search' ? <Col span={12}> + <Form.Item label="鍒濆鍊�"> + {getFieldDecorator('initval', { + initialValue: config.setting.initval, + rules: [ + { + max: formRule.input.max, + message: formRule.input.message + } + ] + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> : null} + {type === 'search' ? <Col span={12}> + <Form.Item label="鍖归厤鏂瑰紡"> + {getFieldDecorator('match', { + initialValue: config.setting.match || 'like' + })( + <Radio.Group> + <Radio value="like">like</Radio> + <Radio value="not like">not like</Radio> + <Radio value="=">=</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {type === 'search' ? <Col span={12}> + <Form.Item label="蹇呭~"> + {getFieldDecorator('required', { + initialValue: config.setting.required || 'false' + })( + <Radio.Group> + <Radio value="true">鏄�</Radio> + <Radio value="false">鍚�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {type === 'search' ? <Col span={12}> + <Form.Item label="闅愯棌"> + {getFieldDecorator('Hide', { + initialValue: config.setting.Hide || 'false' + })( + <Radio.Group> + <Radio value="true">鏄�</Radio> + <Radio value="false">鍚�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {type === 'search' ? <Col span={12}> + <Form.Item label="鑷姩鑱氱劍"> + {getFieldDecorator('focus', { + initialValue: config.setting.focus || 'true' + })( + <Radio.Group> + <Radio value="true">鏄�</Radio> + <Radio value="false">鍚�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label="鎼滅储鎸夐挳"> + {getFieldDecorator('btn', { + initialValue: config.setting.btn || 'hidden' + })( + <Radio.Group> + <Radio value="hidden">闅愯棌</Radio> + <Radio value="show">鏄剧ず</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {type === 'search' ? <Col span={12}> + <Form.Item label="榛戝悕鍗�"> + {getFieldDecorator('blacklist', { + initialValue: config.setting.blacklist || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {roleList.map(option => + <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> : null} + </Row> + </Form> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/mob/searchconfig/settingform/index.scss b/src/mob/searchconfig/settingform/index.scss new file mode 100644 index 0000000..f0d30ef --- /dev/null +++ b/src/mob/searchconfig/settingform/index.scss @@ -0,0 +1,23 @@ +.mob-search-setting-form { + .textarea { + .ant-form-item-label { + width: 16.3%; + } + .ant-form-item-control-wrapper { + width: 83.33333333%; + } + } + .ant-input-number { + width: 100%; + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .ant-col.ant-col-12 { + display: inline-block; + float: none; + vertical-align: top; + } +} \ No newline at end of file diff --git a/src/mob/searchconfig/source.jsx b/src/mob/searchconfig/source.jsx new file mode 100644 index 0000000..9d4684f --- /dev/null +++ b/src/mob/searchconfig/source.jsx @@ -0,0 +1,33 @@ +export const SearchItems = [ + { + type: 'search', + label: '鏁板�硷紙鍖洪棿锛�', + subType: 'range', + url: '' + }, + { + type: 'search', + label: '閫夐」鍗�', + subType: 'checkcard', + url: '' + }, + { + type: 'search', + label: '鏃ユ湡锛堝ぉ锛�', + subType: 'date', + url: '' + }, + { + type: 'search', + label: '鏃ユ湡锛堟湀锛�', + subType: 'datemonth', + url: '' + }, + { + type: 'search', + label: '鏃ユ湡锛堝尯闂达級', + subType: 'daterange', + url: '' + }, +] + diff --git a/src/pc/bgcontroller/index.jsx b/src/pc/bgcontroller/index.jsx index 67d98f5..b77b775 100644 --- a/src/pc/bgcontroller/index.jsx +++ b/src/pc/bgcontroller/index.jsx @@ -1,7 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Form, Icon } from 'antd' +import { Form, Icon, Select } from 'antd' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' @@ -11,6 +11,7 @@ const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) const StyleInput = asyncComponent(() => import('@/menu/stylecontroller/styleInput')) const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) +const { Option } = Select class MobController extends Component { static propTpyes = { @@ -22,6 +23,10 @@ dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, backgroundColor: '', backgroundImage: '', + backgroundSize: '', + backgroundRepeat: '', + backgroundPositon: '', + opacity: '', } UNSAFE_componentWillMount () { @@ -36,7 +41,10 @@ this.setState({ backgroundColor: config.style.backgroundColor, - backgroundImage: bgImg + backgroundImage: bgImg, + backgroundSize: config.style.backgroundSize || '100%', + backgroundRepeat: config.style.backgroundRepeat || 'repeat', + backgroundPositon: config.style.backgroundPositon || 'center' }) } @@ -84,9 +92,42 @@ this.props.updateConfig(config) } + backgroundSizeChange = (val) => { + this.setState({ + backgroundSize: val + }) + + let config = fromJS(this.props.config).toJS() + config.style.backgroundSize = val + + this.props.updateConfig(config) + } + + backgroundRepeatChange = (val) => { + this.setState({ + backgroundRepeat: val + }) + + let config = fromJS(this.props.config).toJS() + config.style.backgroundRepeat = val + + this.props.updateConfig(config) + } + + backgroundPositonChange = (val) => { + this.setState({ + backgroundPositon: val + }) + + let config = fromJS(this.props.config).toJS() + config.style.backgroundPositon = val + + this.props.updateConfig(config) + } + render () { const { config } = this.props - const { backgroundColor, backgroundImage } = this.state + const { backgroundColor, backgroundImage, backgroundSize, backgroundRepeat, backgroundPositon } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -113,6 +154,30 @@ <Form.Item colon={false} label="鑳屾櫙鍥�"> <SourceComponent value={backgroundImage} type="" placement="right" onChange={this.imgChange}/> </Form.Item> + <Form.Item colon={false} label="姣斾緥"> + <Select defaultValue={backgroundSize} onChange={this.backgroundSizeChange}> + <Option value="100%">100%</Option> + <Option value="100% 100%">100% 100%</Option> + <Option value="auto 100%">auto 100%</Option> + <Option value="contain">contain</Option> + <Option value="cover">cover</Option> + </Select> + </Form.Item> + <Form.Item colon={false} label="閲嶅"> + <Select defaultValue={backgroundRepeat} onChange={this.backgroundRepeatChange}> + <Option value="repeat">repeat</Option> + <Option value="no-repeat">no-repeat</Option> + <Option value="repeat-x">repeat-x</Option> + <Option value="repeat-y">repeat-y</Option> + </Select> + </Form.Item> + <Form.Item colon={false} label="浣嶇疆"> + <Select defaultValue={backgroundPositon} onChange={this.backgroundPositonChange}> + <Option value="center">center</Option> + <Option value="top">top</Option> + <Option value="bottom">bottom</Option> + </Select> + </Form.Item> <p style={{borderBottom: '1px solid #eaeaea', color: '#40a9ff'}}>鍐呰竟璺�</p> <Form.Item colon={false} diff --git a/src/pc/components/login/normal-login/index.jsx b/src/pc/components/login/normal-login/index.jsx new file mode 100644 index 0000000..028d757 --- /dev/null +++ b/src/pc/components/login/normal-login/index.jsx @@ -0,0 +1,170 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover } from 'antd' + +import asyncIconComponent from '@/utils/asyncIconComponent' +import asyncComponent from '@/utils/asyncComponent' + +import MKEmitter from '@/utils/events.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import { resetStyle } from '@/utils/utils-custom.js' +import './index.scss' + +const LoginForm = asyncComponent(() => import('./loginform')) +const WrapComponent = asyncIconComponent(() => import('../wrapsetting')) + +class PropCardEditComponent extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + back: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let ismob = sessionStorage.getItem('appType') === 'mob' + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + tabId: card.tabId || '', + parentId: card.parentId || '', + dataName: card.dataName || '', + width: card.width || 24, + name: card.name, + subtype: card.subtype, + wrap: { name: card.name, width: card.width || 24, loginWays: ['uname_pwd'] }, + style: { background: '#ffffff', width: '330px', borderRadius: '4px', marginLeft: '55vw'}, + loginWays: [ + {type: 'uname_pwd', label: '璐﹀彿瀵嗙爜', remember: 'true', labelStyle: {}, submitStyle: {}, submitLabel: '鐧诲綍'}, + {type: 'sms_vcode', label: '鐭俊楠岃瘉鐮�', labelStyle: {}, submitStyle: {}, submitLabel: '鐧诲綍'} + ] + } + + if (ismob) { + delete _card.style.width + delete _card.style.borderRadius + delete _card.style.marginLeft + + _card.style.paddingTop = '20px' + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.wrap.name = card.name + _card.style = config.style + } + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (component) => { + this.setState({ + card: component + }) + + component.width = component.wrap.width + component.name = component.wrap.name + + this.props.updateConfig(component) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['width', 'background', 'border', 'padding', 'margin'], card.style) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds.length !== 1 || comIds[0] !== card.uuid) return + + let _card = {...card, style} + + this.setState({ + card: _card + }) + + this.props.updateConfig(_card) + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + render() { + const { card, dict } = this.state + let style = resetStyle(card.style) + if (card.wrap.maxWidth) { + style.maxWidth = card.wrap.maxWidth + let left = style.marginLeft && style.marginLeft !== '0px' ? style.marginLeft : 'auto' + let right = style.marginRight && style.marginRight !== '0px' ? style.marginRight : 'auto' + style.margin = (style.marginTop || 0) + ' ' + right + ' ' + (style.marginBottom || 0) + ' ' + left + delete style.marginLeft + delete style.marginRight + delete style.marginTop + delete style.marginBottom + } + + return ( + <div className="login-edit-box" style={style} onClick={this.clickComponent} id={card.uuid}> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + <LoginForm loginWays={card.loginWays} wrap={card.wrap} menuId={card.uuid} dict={dict} /> + </div> + ) + } +} + +export default PropCardEditComponent \ No newline at end of file diff --git a/src/pc/components/login/normal-login/index.scss b/src/pc/components/login/normal-login/index.scss new file mode 100644 index 0000000..f87a9a8 --- /dev/null +++ b/src/pc/components/login/normal-login/index.scss @@ -0,0 +1,138 @@ +.login-edit-box { + display: inline-block; + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 100px; + + .card-control { + position: absolute; + top: 0px; + left: 0px; + .anticon-tool { + right: auto; + left: 1px; + padding: 1px; + } + } + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + .login-edit-form { + border-radius: inherit; + .ant-form-item { + font-size: 16px; + margin: 0 15px 15px; + .ant-input { + height: 35px; + background: transparent; + } + } + button:not(.vercode) { + width: 100%; + height: 40px; + line-height: 1; + font-size: 18px; + margin-bottom: 25px; + } + .ant-form-item:last-child { + margin-bottom: 0; + } + } + .login-way-wrap { + height: 50px; + line-height: 50px; + margin-bottom: 10px; + display: flex; + border-radius: inherit; + .login-way { + flex: 1; + width: 50%; + font-size: 17px; + text-align: center; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + padding: 0 16px; + transition: all 0.3s; + border: 1px solid transparent; + border-top: 0!important; + } + .login-way.active, .login-way:hover { + color: #1890ff; + } + .login-way:not(.active) { + cursor: pointer; + background: #fafafa; + border: 1px solid #e8e8e8; + } + .login-way:first-child { + border-left: 0; + border-top-left-radius: inherit; + } + .login-way:last-child { + border-right: 0; + border-top-right-radius: inherit; + } + } + .login-way-wrap.simple { + .login-way { + font-size: 18px; + text-align: left; + padding: 0 15px; + line-height: 60px; + } + } +} +.login-edit-box::after { + display: block; + content: ' '; + clear: both; +} +.login-edit-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} + +.mk-mob-view .login-edit-box { + display: block; + .login-way-wrap.simple { + display: none; + } + .login-way-wrap { + padding: 0 15px; + border-radius: 0; + .login-way { + border: 0; + background: transparent!important; + transition: all 0.3s; + border-bottom: 2px solid transparent; + } + .login-way.active, .login-way:hover { + color: #1890ff; + } + .login-way.active { + border-bottom: 2px solid #1890ff; + } + } + .ant-input { + border: 0; + border-radius: 0; + border-bottom: 1px solid #d9d9d9; + box-shadow: none!important; + } + .ant-input-group-addon { + border: 0; + border-radius: 0; + } +} diff --git a/src/pc/components/login/normal-login/loginform.jsx b/src/pc/components/login/normal-login/loginform.jsx new file mode 100644 index 0000000..20b96a4 --- /dev/null +++ b/src/pc/components/login/normal-login/loginform.jsx @@ -0,0 +1,139 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Form, Icon, Input, Button, Checkbox } from 'antd' + +import MKEmitter from '@/utils/events.js' +import './index.scss' + +class LoginTabForm extends Component { + static propTpyes = { + dict: PropTypes.object, + menuId: PropTypes.string, + loginWays: PropTypes.array, + wrap: PropTypes.array, + } + + state = { + activeWay: null, + loginWays: [], + } + + UNSAFE_componentWillMount () { + const { loginWays, wrap } = this.props + + let _loginWays = [] + loginWays.forEach(item => { + if (!wrap.loginWays || wrap.loginWays.includes(item.type)) { + _loginWays.push(item) + } + }) + + this.setState({ + loginWays: _loginWays, + activeWay: _loginWays[0], + }) + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { loginWays, wrap } = this.props + + if (!is(fromJS(wrap), fromJS(nextProps.wrap))) { + let _loginWays = [] + loginWays.forEach(item => { + if (!nextProps.wrap.loginWays || nextProps.wrap.loginWays.includes(item.type)) { + _loginWays.push(item) + } + }) + + this.setState({ + loginWays: _loginWays, + activeWay: _loginWays[0], + }) + } + } + + onChangeTab = (activeWay) => { + this.setState({activeWay}) + } + + changeMenu = () => { + const { wrap, menuId } = this.props + + MKEmitter.emit('changeEditMenu', { + MenuID: wrap.link === 'linkmenu' ? wrap.linkmenu : menuId, + copyMenuId: '', + MenuNo: '', + MenuName: '' + }) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + render() { + const { activeWay, loginWays } = this.state + + return ( + <Form className="login-edit-form"> + <div className={'login-way-wrap ' + (loginWays.length === 1 ? 'simple' : '')}> + {loginWays.map(item => ( + <div className={'login-way' + (activeWay.type === item.type ? ' active' : '')} onClick={() => this.onChangeTab(item)} key={item.type}>{item.label}</div> + ))} + </div> + {activeWay.type === 'uname_pwd' ? <div className="form-item-wrap"> + <Form.Item> + <Input + prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} + placeholder="鐢ㄦ埛鍚�" + autoComplete="off" + /> + </Form.Item> + <Form.Item> + <Input.Password placeholder="瀵嗙爜" prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} /> + </Form.Item> + <Form.Item className="minline"> + <Checkbox>璁颁綇瀵嗙爜</Checkbox> + </Form.Item> + <Form.Item className="btn-login"> + <Button type="primary" onDoubleClick={() => this.changeMenu()} className="login-form-button"> + 鐧诲綍 + </Button> + </Form.Item> + </div> : null} + {activeWay.type === 'sms_vcode' ? <div className="form-item-wrap"> + <Form.Item> + <Input + placeholder="鎵嬫満鍙�" + autoComplete="off" + /> + </Form.Item> + <Form.Item style={{marginBottom: '35px'}}> + <Input + addonAfter={ + <Button type="link" className="vercode" size="small"> + 鑾峰彇楠岃瘉鐮� + </Button> + } + placeholder="楠岃瘉鐮�" + autoComplete="off" + /> + </Form.Item> + <Form.Item className="btn-login"> + <Button type="primary" onDoubleClick={() => this.changeMenu()} className="login-form-button"> + 鐧诲綍 + </Button> + </Form.Item> + </div> : null} + </Form> + ) + } +} + +export default LoginTabForm \ No newline at end of file diff --git a/src/pc/components/login/wrapsetting/index.jsx b/src/pc/components/login/wrapsetting/index.jsx new file mode 100644 index 0000000..9c0ac72 --- /dev/null +++ b/src/pc/components/login/wrapsetting/index.jsx @@ -0,0 +1,81 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import './index.scss' + +class DataSource extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + wrap: null + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({wrap: fromJS(config.wrap).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + editDataSource = () => { + this.setState({ + visible: true + }) + } + + verifySubmit = () => { + const { config } = this.props + + this.verifyRef.handleConfirm().then(res => { + + this.setState({ + wrap: res, + visible: false + }) + this.props.updateConfig({...config, wrap: res}) + }) + } + + render () { + const { visible, dict, wrap } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} /> + <Modal + wrapClassName="popview-modal" + title="鐧诲綍璁剧疆" + visible={visible} + width={800} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + wrap={wrap} + inputSubmit={this.verifySubmit} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default DataSource \ No newline at end of file diff --git a/src/pc/components/login/wrapsetting/index.scss b/src/pc/components/login/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/pc/components/login/wrapsetting/index.scss @@ -0,0 +1,7 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/pc/components/login/wrapsetting/settingform/index.jsx b/src/pc/components/login/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..97042c8 --- /dev/null +++ b/src/pc/components/login/wrapsetting/settingform/index.jsx @@ -0,0 +1,270 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Tooltip, Icon, InputNumber, Select, Checkbox, notification, Radio } from 'antd' + +import StyleInput from '@/menu/stylecontroller/styleInput' +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + roleList: [], + msgTemps: [], + appMenus: [], + link: this.props.wrap.link || 'menu' + } + + UNSAFE_componentWillMount () { + let roleList = sessionStorage.getItem('sysRoles') + let msgTemps = sessionStorage.getItem('msgTemplate') + + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + if (msgTemps) { + try { + msgTemps = JSON.parse(msgTemps) + } catch { + msgTemps = [] + } + } else { + msgTemps = [] + } + + let appMenus = sessionStorage.getItem('appMenus') + if (appMenus) { + try { + appMenus = JSON.parse(appMenus) + } catch { + appMenus = [] + } + } else { + appMenus = [] + } + + this.setState({roleList, msgTemps, appMenus}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + if (values.loginWays.includes('sms_vcode') && !values.tempId) { + notification.warning({ + top: 92, + message: '浣跨敤鐭俊楠岃瘉鐮佺櫥褰曟椂锛岄渶瑕侀�夋嫨鐭俊妯℃澘锛�', + duration: 5 + }) + return + } + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { wrap } = this.props + const { getFieldDecorator } = this.props.form + const { roleList, msgTemps, appMenus, link } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�"> + <Icon type="question-circle" /> + 缁勪欢鍚嶇О + </Tooltip> + }> + {getFieldDecorator('name', { + initialValue: wrap.name, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="鐧诲綍鏂瑰紡"> + {getFieldDecorator('loginWays', { + initialValue: wrap.loginWays || [], + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鐧诲綍鏂瑰紡!' + } + ] + })( + <Checkbox.Group + options={[ + { label: '璐﹀彿瀵嗙爜', value: 'uname_pwd' }, + { label: '鐭俊楠岃瘉鐮�', value: 'sms_vcode' }, + ]} + /> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��"> + <Icon type="question-circle" /> + 瀹藉害 + </Tooltip> + }> + {getFieldDecorator('width', { + initialValue: wrap.width || 24, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '瀹藉害!' + } + ] + })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐧诲綍妗嗙殑鏈�澶у搴﹀�笺��"> + <Icon type="question-circle" /> + 鏈�澶у搴� + </Tooltip> + }> + {getFieldDecorator('maxWidth', { + initialValue: wrap.maxWidth || '' + })(<InputNumber min={100} max={2000} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="缁勪欢鍗犵敤鐨勬渶灏忛珮搴︼紝鐢ㄤ簬椤甸潰甯冨眬銆�"> + <Icon type="question-circle" /> + 楂樺害 + </Tooltip> + }> + {getFieldDecorator('height', { + initialValue: wrap.height + })(<StyleInput options={['px', 'vh', 'vw', '%']}/>)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="閾炬帴"> + {getFieldDecorator('link', { + initialValue: wrap.link || 'menu' + })( + <Radio.Group onChange={(e) => this.setState({link: e.target.value})}> + <Radio key="menu" value="menu"> 鑿滃崟 </Radio> + <Radio key="linkmenu" value="linkmenu"> 鍏宠仈鑿滃崟 </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {link === 'linkmenu' ? <Col span={12}> + <Form.Item label="鍏宠仈鑿滃崟"> + {getFieldDecorator('linkmenu', { + initialValue: wrap.linkmenu || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鑿滃崟!' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {appMenus.map(option => + <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> : null} + {/* $楠岃瘉鐮�$ $mob$ $send_type$ */} + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐭俊妯℃澘鍙湪绠$悊绯荤粺 HS-濂囦簯鐭俊妯℃澘 澶勬坊鍔犮��"> + <Icon type="question-circle" /> + 鐭俊妯℃澘 + </Tooltip> + }> + {getFieldDecorator('tempId', { + initialValue: wrap.tempId || '' + })( + <Select + showSearch + allowClear + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {msgTemps.map(option => + <Select.Option key={option.ID} value={option.ID}>{option.SignName + ' - ' + option.TemplateCode}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="榛戝悕鍗�"> + {getFieldDecorator('blacklist', { + initialValue: wrap.blacklist || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {roleList.map(option => + <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/pc/components/login/wrapsetting/settingform/index.scss b/src/pc/components/login/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..159130b --- /dev/null +++ b/src/pc/components/login/wrapsetting/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/pc/components/navbar/normal-navbar/index.jsx b/src/pc/components/navbar/normal-navbar/index.jsx index efa2b56..b70d77b 100644 --- a/src/pc/components/navbar/normal-navbar/index.jsx +++ b/src/pc/components/navbar/normal-navbar/index.jsx @@ -138,8 +138,11 @@ } changeMenu = (menu) => { + if (menu.property === 'link') { + window.open(menu.link) + return + } MKEmitter.emit('changeEditMenu', { - fixed: menu.property === 'menu', MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', MenuNo: menu.MenuNo, @@ -149,10 +152,15 @@ changeLogoMenu = () => { const { card } = this.state - - if (!card.wrap.logolink) return - - MKEmitter.emit('changeEditMenu', {MenuID: card.wrap.logolink}) + + if (card.wrap.property === 'linkmenu') { + MKEmitter.emit('changeEditMenu', { + MenuID: card.wrap.linkmenu, + copyMenuId: '', + MenuNo: '', + MenuName: '' + }) + } } render() { diff --git a/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx b/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx index 7fc5a87..1a29300 100644 --- a/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx +++ b/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx @@ -112,17 +112,6 @@ )} </Form.Item> </Col> - {property === 'link' ? <Col span={22}> - <Form.Item label="閾炬帴鍦板潃"> - {getFieldDecorator('link', { - initialValue: menu.link || '', - rules: [{ - required: true, - message: '璇疯緭鍏ラ摼鎺ュ湴鍧�!' - }] - })(<TextArea rows={2} />)} - </Form.Item> - </Col> : null} <Col span={22}> <Form.Item label="鎵撳紑鏂瑰紡"> {getFieldDecorator('open', { @@ -135,6 +124,17 @@ )} </Form.Item> </Col> + {property === 'link' ? <Col span={22}> + <Form.Item label="閾炬帴鍦板潃"> + {getFieldDecorator('link', { + initialValue: menu.link || '', + rules: [{ + required: true, + message: '璇疯緭鍏ラ摼鎺ュ湴鍧�!' + }] + })(<TextArea rows={2} />)} + </Form.Item> + </Col> : null} {property === 'linkmenu' ? <Col span={22}> <Form.Item label={ <Tooltip placement="topLeft" title="鍏宠仈褰撳墠app涓凡鏈夌殑鑿滃崟銆�"> diff --git a/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx b/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx index fad6b76..2206100 100644 --- a/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx +++ b/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx @@ -120,8 +120,8 @@ })( <Radio.Group onChange={this.changeProperty}> <Radio value="menu">鑿滃崟</Radio> - <Radio value="link">閾炬帴</Radio> <Radio value="linkmenu">鍏宠仈鑿滃崟</Radio> + <Radio value="link">閾炬帴</Radio> {menu.level === 1 || menu.level === 2 ? <Radio value="classify">鍒嗙被</Radio> : null} </Radio.Group> )} @@ -139,17 +139,6 @@ )} </Form.Item> </Col> - {property === 'link' ? <Col span={22}> - <Form.Item label="閾炬帴鍦板潃"> - {getFieldDecorator('link', { - initialValue: menu.link || '', - rules: [{ - required: true, - message: '璇疯緭鍏ラ摼鎺ュ湴鍧�!' - }] - })(<TextArea rows={2} />)} - </Form.Item> - </Col> : null} {property !== 'classify' ? <Col span={22}> <Form.Item label="鎵撳紑鏂瑰紡"> {getFieldDecorator('open', { @@ -160,6 +149,17 @@ <Radio value="self">褰撳墠绐楀彛</Radio> </Radio.Group> )} + </Form.Item> + </Col> : null} + {property === 'link' ? <Col span={22}> + <Form.Item label="閾炬帴鍦板潃"> + {getFieldDecorator('link', { + initialValue: menu.link || '', + rules: [{ + required: true, + message: '璇疯緭鍏ラ摼鎺ュ湴鍧�!' + }] + })(<TextArea rows={2} />)} </Form.Item> </Col> : null} {property === 'linkmenu' ? <Col span={22}> @@ -192,7 +192,7 @@ {getFieldDecorator('copyMenuId', { initialValue: menu.copyMenuId || '' })( - <Select> + <Select allowClear> {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} </Select> )} diff --git a/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx b/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx index 92d751b..8174d84 100644 --- a/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx +++ b/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx @@ -5,7 +5,7 @@ import MenuForm from '../menuform' import Utils from '@/utils/utils.js' -import MKEmitter from '@/utils/events.js' +// import MKEmitter from '@/utils/events.js' import './index.scss' const { confirm } = Modal @@ -97,7 +97,6 @@ let _data = _this.state.data.filter(item => item.MenuID !== record.MenuID) _this.setState({data: _data}) _this.props.menuUpdate({...menu, sublist: _data}) - MKEmitter.emit('delButtons', [record.MenuID]) }, onCancel() {} }) @@ -124,7 +123,7 @@ this.menuRef.handleConfirm().then(res => { let _menu = {...editMenu, ...res} - let _data = this.state.data + let _data = fromJS(this.state.data).toJS() if (!_menu.MenuID) { _menu.MenuID = Utils.getuuid() _data.push(_menu) @@ -137,8 +136,26 @@ } }) } - this.setState({data: _data, editMenu: null, visible: false}) - this.props.menuUpdate({...menu, sublist: _data}) + if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') { + const _this = this + confirm({ + content: '鑿滃崟灞炴�х敱鈥滆彍鍗曗�濆垏鎹㈣嚦鍏朵粬绫诲瀷鏃讹紝鑿滃崟灏嗚閲嶇疆锛屽嵆瑙i櫎涔嬪墠鑿滃崟鐨勭粦瀹氬叧绯伙紝纭畾淇敼鍚楋紵', + onOk() { + _data = _data.map(item => { + if (item.MenuID === _menu.MenuID) { + item.MenuID = Utils.getuuid() + } + return item + }) + _this.setState({data: _data, editMenu: null, visible: false}) + _this.props.menuUpdate({...menu, sublist: _data}) + }, + onCancel() {} + }) + } else { + this.setState({data: _data, editMenu: null, visible: false}) + this.props.menuUpdate({...menu, sublist: _data}) + } }) } @@ -263,12 +280,6 @@ let _data = _this.state.data.filter(item => item.MenuID !== record.MenuID) _this.setState({data: _data}) _this.props.menuUpdate({...menu, sublist: _data}) - - let uuids = [record.MenuID] - record.sublist && record.sublist.forEach(item => { - uuids.push(item.MenuID) - }) - MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -295,7 +306,7 @@ this.menuRef.handleConfirm().then(res => { let _menu = {...editMenu, ...res} - let _data = this.state.data + let _data = fromJS(this.state.data).toJS() if (!_menu.MenuID) { _menu.MenuID = Utils.getuuid() _data.push(_menu) @@ -308,8 +319,26 @@ } }) } - this.setState({data: _data, editMenu: null, visible: false}) - this.props.menuUpdate({...menu, sublist: _data}) + if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') { + const _this = this + confirm({ + content: '鑿滃崟灞炴�х敱鈥滆彍鍗曗�濆垏鎹㈣嚦鍏朵粬绫诲瀷鏃讹紝鑿滃崟灏嗚閲嶇疆锛屽嵆瑙i櫎涔嬪墠鑿滃崟鐨勭粦瀹氬叧绯伙紝纭畾淇敼鍚楋紵', + onOk() { + _data = _data.map(item => { + if (item.MenuID === _menu.MenuID) { + item.MenuID = Utils.getuuid() + } + return item + }) + _this.setState({data: _data, editMenu: null, visible: false}) + _this.props.menuUpdate({...menu, sublist: _data}) + }, + onCancel() {} + }) + } else { + this.setState({data: _data, editMenu: null, visible: false}) + this.props.menuUpdate({...menu, sublist: _data}) + } }) } @@ -444,16 +473,6 @@ content: '', onOk() { _this.setState({data: data.filter(item => item.MenuID !== record.MenuID)}) - - let uuids = [record.MenuID] - record.sublist && record.sublist.forEach(item => { - uuids.push(item.MenuID) - - item.sublist && item.sublist.forEach(cell => { - uuids.push(cell.MenuID) - }) - }) - MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -479,22 +498,38 @@ this.menuRef.handleConfirm().then(res => { let _menu = {...editMenu, ...res} + let _data = fromJS(data).toJS() if (!_menu.MenuID) { _menu.MenuID = Utils.getuuid() - this.setState({data: [...data, _menu], editMenu: null, visible: false}) + _data.push(_menu) } else { - this.setState({ - editMenu: null, - visible: false, - data: data.map(item => { - if (item.MenuID === _menu.MenuID) { - return _menu - } else { - return item - } - }) + _data = _data.map(item => { + if (item.MenuID === _menu.MenuID) { + return _menu + } else { + return item + } }) } + + if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') { + const _this = this + confirm({ + content: '鑿滃崟灞炴�х敱鈥滆彍鍗曗�濆垏鎹㈣嚦鍏朵粬绫诲瀷鏃讹紝鑿滃崟灏嗚閲嶇疆锛屽嵆瑙i櫎涔嬪墠鑿滃崟鐨勭粦瀹氬叧绯伙紝纭畾淇敼鍚楋紵', + onOk() { + _data = _data.map(item => { + if (item.MenuID === _menu.MenuID) { + item.MenuID = Utils.getuuid() + } + return item + }) + _this.setState({data: _data, editMenu: null, visible: false}) + }, + onCancel() {} + }) + } else { + this.setState({data: _data, editMenu: null, visible: false}) + } }) } diff --git a/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx b/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx index b5d097d..3d066a8 100644 --- a/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx +++ b/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx @@ -6,6 +6,7 @@ import './index.scss' const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) +const { TextArea } = Input class SettingForm extends Component { static propTpyes = { @@ -16,7 +17,8 @@ } state = { - appMenus: [] + appMenus: [], + property: '' } UNSAFE_componentWillMount () { @@ -31,7 +33,7 @@ appMenus = [] } - this.setState({appMenus}) + this.setState({appMenus, property: this.props.wrap.property || ''}) } handleConfirm = () => { @@ -58,7 +60,7 @@ render() { const { wrap } = this.props const { getFieldDecorator } = this.props.form - const { appMenus } = this.state + const { appMenus, property } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -141,22 +143,51 @@ </Form.Item> </Col> <Col span={12}> + <Form.Item label="logo灞炴��"> + {getFieldDecorator('property', { + initialValue: wrap.property || '' + })( + <Radio.Group onChange={(e) => this.setState({property: e.target.value})} style={{whiteSpace: 'nowrap'}}> + <Radio value="">绌�</Radio> + <Radio value="linkmenu">鍏宠仈鑿滃崟</Radio> + <Radio value="link">閾炬帴</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {property === 'linkmenu' ? <Col span={12}> <Form.Item label="logo閾炬帴"> - {getFieldDecorator('logolink', { - initialValue: wrap.logolink || '' + {getFieldDecorator('linkmenu', { + initialValue: wrap.linkmenu || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鍏宠仈鑿滃崟!' + } + ] })( <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} > - <Select.Option key="empty" intid={''} value={''}>鏃�</Select.Option> {appMenus.map(option => <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option> )} </Select> )} </Form.Item> - </Col> + </Col> : null} + {property === 'link' ? <Col span={24}> + <Form.Item label="logo閾炬帴" className="textarea"> + {getFieldDecorator('link', { + initialValue: wrap.link || '', + rules: [{ + required: true, + message: '璇疯緭鍏ラ摼鎺ュ湴鍧�!' + }] + })(<TextArea rows={2} />)} + </Form.Item> + </Col> : null} <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="瀛樺湪鐧诲綍涓斿彇鍒扮櫥褰曚俊鎭椂锛屾樉绀虹敤鎴峰ご鍍忋�佺敤鎴峰悕鍙婇��鍑恒��"> @@ -174,6 +205,23 @@ )} </Form.Item> </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="榛樿闅愯棌鑿滃崟鏍忥紝榧犳爣鍦ㄩ潬杩戦《閮ㄦ椂鏄剧ず銆�"> + <Icon type="question-circle" /> + 鎮诞鏄剧ず + </Tooltip> + }> + {getFieldDecorator('hover', { + initialValue: wrap.hover || 'false' + })( + <Radio.Group> + <Radio value="true">鍚敤</Radio> + <Radio value="false">涓嶅惎鐢�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> </Row> </Form> </div> diff --git a/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss b/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss index 159130b..25eecb7 100644 --- a/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss +++ b/src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss @@ -8,4 +8,12 @@ .ant-input-number { width: 100%; } + .ant-form-item.textarea { + .ant-form-item-label { + width: 16%; + } + .ant-form-item-control-wrapper { + width: 84%; + } + } } \ No newline at end of file diff --git a/src/pc/createview/index.jsx b/src/pc/createview/index.jsx new file mode 100644 index 0000000..9dd88d5 --- /dev/null +++ b/src/pc/createview/index.jsx @@ -0,0 +1,201 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Button, Modal, notification } from 'antd' +import moment from 'moment' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import Utils from '@/utils/utils.js' +import MenuUtils from '@/utils/utils-custom.js' +import SettingForm from './settingform' +import Api from '@/api' +import './index.scss' + +class CreateView extends Component { + static propTpyes = { + resetmenu: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + loading: false + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + verifySubmit = () => { + this.verifyRef.handleConfirm().then(res => { + this.setState({ + loading: true + }) + + let parMenuId = sessionStorage.getItem('kei_no') + sessionStorage.getItem('typename') + sessionStorage.getItem('lang') + let menuId = Utils.getuuid() + let config = { + version: 1.0, + uuid: menuId, + MenuID: menuId, + Template: 'webPage', + enabled: false, + MenuName: res.MenuName || '', + MenuNo: res.MenuNo || '', + tables: [], + components: [], + viewType: 'menu', + style: {} + } + + let param = { + func: 'sPC_TrdMenu_AddUpt', + FstID: parMenuId, + SndID: parMenuId, + ParentID: parMenuId, + MenuID: menuId, + MenuNo: res.MenuNo || '', + EasyCode: '', + Template: 'webPage', + TypeCharOne: sessionStorage.getItem('kei_no'), + Typename: sessionStorage.getItem('typename'), + MenuName: res.MenuName || '', + PageParam: JSON.stringify({Template: 'webPage'}), + open_edition: '', + LText: '', + LTexttb: '' + } + + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt('', param.timestamp) + + if (!res.copymenuId) { + param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config))) + + Api.getSystemConfig(param).then(result => { + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } else { + notification.success({ + top: 92, + message: '鍒涘缓鎴愬姛', + duration: 5 + }) + } + + this.setState({ + visible: false, + loading: false + }) + + this.props.resetmenu() + }) + } else { + Api.getSystemConfig({ + func: 'sPC_Get_LongParam', + TypeCharOne: sessionStorage.getItem('kei_no'), + typename: sessionStorage.getItem('typename') || 'pc', + MenuID: res.copymenuId + }).then(result => { + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + this.setState({ + loading: false + }) + return + } + + let _config = null + try { + _config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) + } catch (e) { + console.warn('Parse Failure') + _config = null + } + + if (!_config) { + notification.warning({ + top: 92, + message: '鏈幏鍙栧埌閰嶇疆淇℃伅锛�', + duration: 5 + }) + this.setState({ + loading: false + }) + return + } + + if (_config.components) { + config.components = MenuUtils.resetConfig(_config.components) + config.tables = _config.tables || [] + config.style = _config.style || {} + } + + param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config))) + + Api.getSystemConfig(param).then(result => { + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } else { + notification.success({ + top: 92, + message: '鍒涘缓鎴愬姛', + duration: 5 + }) + } + + this.setState({ + visible: false, + loading: false + }) + + this.props.resetmenu() + }) + }) + } + }) + } + + render () { + const { config } = this.props + const { visible, dict, loading } = this.state + + return ( + <div className="create-view"> + <Button icon="plus" className="mk-border-green" onClick={() => {this.setState({visible: true, loading: false})}}>鏂板缓椤甸潰</Button> + <Modal + title="鏂板缓椤甸潰" + visible={visible} + width={500} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + confirmLoading={loading} + destroyOnClose + > + <SettingForm + dict={dict} + config={config} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default CreateView \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/pc/createview/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/pc/createview/index.scss diff --git a/src/pc/createview/settingform/index.jsx b/src/pc/createview/settingform/index.jsx new file mode 100644 index 0000000..87ee449 --- /dev/null +++ b/src/pc/createview/settingform/index.jsx @@ -0,0 +1,107 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Select, Input } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + } + + state = { + appMenus: [] + } + + UNSAFE_componentWillMount () { + let appMenus = sessionStorage.getItem('appMenus') + if (appMenus) { + try { + appMenus = JSON.parse(appMenus) + } catch { + appMenus = [] + } + } else { + appMenus = [] + } + + this.setState({appMenus}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + render() { + const { getFieldDecorator } = this.props.form + const { appMenus } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={20}> + <Form.Item label="鑿滃崟鍚嶇О"> + {getFieldDecorator('MenuName', { + initialValue: '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '鑿滃崟鍚嶇О!' + } + ] + })(<Input placeholder="" autoComplete="off" />)} + </Form.Item> + </Col> + <Col span={20}> + <Form.Item label="鑿滃崟鍙傛暟"> + {getFieldDecorator('MenuNo', { + initialValue: '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '鑿滃崟鍙傛暟!' + } + ] + })(<Input placeholder="" autoComplete="off" />)} + </Form.Item> + </Col> + <Col span={20}> + <Form.Item label="澶嶅埗鑿滃崟"> + {getFieldDecorator('copymenuId', { + initialValue: '' + })( + <Select allowClear showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}> + {appMenus.map(option => + <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/pc/createview/settingform/index.scss b/src/pc/createview/settingform/index.scss new file mode 100644 index 0000000..159130b --- /dev/null +++ b/src/pc/createview/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/pc/menushell/card.jsx b/src/pc/menushell/card.jsx index 843c8c5..c3311f6 100644 --- a/src/pc/menushell/card.jsx +++ b/src/pc/menushell/card.jsx @@ -7,9 +7,12 @@ const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar')) const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search')) const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie')) +const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) +const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs')) const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) +const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) @@ -17,8 +20,10 @@ const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) const NormalNavbar = asyncComponent(() => import('@/pc/components/navbar/normal-navbar')) +const NormalLogin = asyncComponent(() => import('@/pc/components/login/normal-login')) const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) +const Balcony = asyncComponent(() => import('@/menu/components/card/balcony')) const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { const originalIndex = findCard(id).index @@ -53,8 +58,20 @@ style = { opacity: 0.3} } let col = ' ant-col ant-col-' + (card.width || 24) - if (card.type === 'navbar') { - col = '' + if (card.type === 'login') { + let height = '' + if (card.wrap && card.wrap.height) { + // scaleview + height = card.wrap.height.replace(/\d+vw/ig, (word) => { + return parseFloat(word) * (window.GLOB.winWidth || 420) / 100 + 'px' + // return parseFloat(word) * 350 / 100 + 'px' + }).replace(/\d+vh/ig, (word) => { + return parseFloat(word) * (window.GLOB.winHeight || 738) / 100 + 'px' + // return parseFloat(word) * 615 / 100 + 'px' + }) + } + + style.minHeight = height } const getCardComponent = () => { @@ -68,6 +85,12 @@ return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'pie') { return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'dashboard') { + return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'tree') { + return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'scatter') { + return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'tabs') { return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'card' && card.subtype === 'datacard') { @@ -88,12 +111,21 @@ return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'code') { return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'login') { + return (<NormalLogin card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'balcony') { + return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } } - return ( - <div className={`mk-component-card ${col}`} ref={node => drag(drop(node))} style={style}> - {getCardComponent()} - </div> - ) + + if (card.type === 'navbar') { + return getCardComponent() + } else { + return ( + <div className={`mk-component-card ${col}`} ref={node => drag(drop(node))} style={style}> + {getCardComponent()} + </div> + ) + } } export default Card diff --git a/src/pc/menushell/index.jsx b/src/pc/menushell/index.jsx index 29be748..24e3910 100644 --- a/src/pc/menushell/index.jsx +++ b/src/pc/menushell/index.jsx @@ -19,6 +19,10 @@ handleList({...menu, components: _cards}) setCards(_cards) } + + if (menu.components.length > cards.length) { + setCards(menu.components) + } const findCard = id => { const card = cards.filter(c => `${c.uuid}` === id)[0] @@ -49,13 +53,16 @@ let uuids = MenuUtils.getDelButtonIds(card) confirm({ - title: `纭畾鍒犻櫎銆�${card.name}銆嬪悧锛焋, + title: `纭畾鍒犻櫎${card.name ? `銆�${card.name}銆媊 : '缁勪欢'}鍚楋紵`, content: hasComponent ? '褰撳墠缁勪欢涓惈鏈夊瓙缁勪欢锛�' : '', onOk() { - MKEmitter.emit('delButtons', uuids) const _cards = cards.filter(item => item.uuid !== card.uuid) handleList({...menu, components: _cards}) setCards(_cards) + + if (uuids.length === 0) return + + MKEmitter.emit('delButtons', uuids) }, onCancel() {} }) @@ -102,7 +109,10 @@ code: '鑷畾涔�', navbar: '瀵艰埅鏍�', carousel: '杞挱', - card: '鍗$墖' + dashboard: '浠〃鐩�', + tree: '鏍戝舰鍒楄〃', + card: '鍗$墖', + login: '鐧诲綍' } let i = 1 diff --git a/src/pc/modulesource/index.jsx b/src/pc/modulesource/index.jsx index f4705bf..f84cdd7 100644 --- a/src/pc/modulesource/index.jsx +++ b/src/pc/modulesource/index.jsx @@ -53,6 +53,7 @@ c_id: item.uuid, images: '', c_name: item.title, + typename: sessionStorage.getItem('appType') || '', long_param: '', del_type: 'Y' }).then(result => { diff --git a/src/pc/modulesource/option.jsx b/src/pc/modulesource/option.jsx index 8e94aea..b7e6090 100644 --- a/src/pc/modulesource/option.jsx +++ b/src/pc/modulesource/option.jsx @@ -12,12 +12,18 @@ import Editor from '@/assets/mobimg/editor.png' import SandBox from '@/assets/mobimg/sandbox.png' import Pie1 from '@/assets/mobimg/ring.png' +import Pie3 from '@/assets/mobimg/nest.png' import Pie2 from '@/assets/mobimg/nightingale.png' import Mainsearch from '@/assets/mobimg/mainsearch.png' import Navbar from '@/assets/mobimg/navbar.png' import Carousel from '@/assets/mobimg/carousel.png' import Carousel1 from '@/assets/mobimg/carousel1.png' import form from '@/assets/mobimg/form.png' +import Login from '@/assets/mobimg/login.png' +import dashboard from '@/assets/mobimg/dashboard.png' +import ratioboard from '@/assets/mobimg/ratioboard.png' +import scatter from '@/assets/mobimg/scatter.png' +import tree from '@/assets/mobimg/tree.png' // 缁勪欢閰嶇疆淇℃伅 export const menuOptions = [ @@ -26,19 +32,26 @@ { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24 }, { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�', width: 24 }, { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '灞炴�у崱', width: 24 }, + { type: 'menu', url: card2, component: 'balcony', subtype: 'balcony', title: '鍙诞鍔ㄥ崱', width: 24 }, { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '琛ㄥ崟', width: 24 }, { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '杞挱-鍔ㄦ�佹暟鎹�', width: 24 }, { type: 'menu', url: Carousel1, component: 'carousel', subtype: 'propcard', title: '杞挱-闈欐�佹暟鎹�', width: 24 }, { type: 'menu', url: NormalTable, component: 'table', subtype: 'normaltable', title: '甯哥敤琛�', width: 24 }, { type: 'menu', url: TableCard, component: 'table', subtype: 'tablecard', title: '琛ㄦ牸', width: 12 }, + { type: 'menu', url: tree, component: 'tree', subtype: 'normaltree', title: '鏍戝舰鍒楄〃', width: 12 }, { type: 'menu', url: line, component: 'line', subtype: 'line', title: '鎶樼嚎鍥�', width: 24 }, { type: 'menu', url: line1, component: 'line', subtype: 'line1', title: '闃舵鎶樼嚎鍥�', width: 24 }, { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '鏌辩姸鍥�', width: 24 }, { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�', width: 24 }, { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '楗煎浘', width: 12 }, { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '鐜浘', width: 12 }, + { type: 'menu', url: Pie3, component: 'pie', subtype: 'nest', title: '宓屽楗煎浘', width: 12 }, + { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 }, + { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '浠〃鐩�', width: 12 }, + { type: 'menu', url: ratioboard, component: 'dashboard', subtype: 'ratioboard', title: '鍗犳瘮鍥�', width: 12 }, + { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '鏁g偣鍥�', width: 24 }, { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '瀵屾枃鏈�', width: 24 }, { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 }, - { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 }, { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24 }, + { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '鐧诲綍', width: 24 }, ] diff --git a/src/pc/quotecomponent/index.jsx b/src/pc/quotecomponent/index.jsx index 11426ac..a0bb263 100644 --- a/src/pc/quotecomponent/index.jsx +++ b/src/pc/quotecomponent/index.jsx @@ -51,7 +51,7 @@ Api.getSystemConfig({ func: 'sPC_Get_LongParam', TypeCharOne: sessionStorage.getItem('kei_no'), - typename: 'pc', + typename: sessionStorage.getItem('typename') || 'pc', MenuID: res.keys_id }).then(result => { if (!result.status) { diff --git a/src/pc/transfer/index.jsx b/src/pc/transfer/index.jsx new file mode 100644 index 0000000..d2fb44e --- /dev/null +++ b/src/pc/transfer/index.jsx @@ -0,0 +1,132 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Button, Modal, notification } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import Api from '@/api' +import './index.scss' + +class TransferWrap extends Component { + static propTpyes = { + MenuID: PropTypes.string + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + loading: false, + translist: [] + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + verifySubmit = () => { + const { MenuID } = this.props + + this.verifyRef.handleConfirm().then(res => { + let param = { + func: 's_sVersionDetail_CloudAdd', + kei_no: sessionStorage.getItem('kei_no'), + kei_no_detail: sessionStorage.getItem('typename'), + lang: sessionStorage.getItem('lang'), + BID: res.VersionName, + VType: 'mob_menu', + TrdMenuID: MenuID + } + + this.setState({ + loading: true + }) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛锛�', + duration: 3 + }) + this.setState({ + loading: false, + visible: false + }) + } else { + this.setState({ + loading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }, () => { + this.setState({ + loading: false + }) + }) + }) + } + + getTransList = () => { + let param = { + func: 's_get_sVersion', + dataM: 'Y', + PageSize: 9999, + PageIndex: 1, + OrderCol: 'ID desc' + } + + this.setState({ + visible: true, + loading: false + }) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + this.setState({ + translist: result.data + }) + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }) + } + + render () { + const { visible, dict, loading, translist } = this.state + + return ( + <div className="transfer-wrap"> + <Button icon="pull-request" className="mk-border-green" onClick={this.getTransList}>浼犺緭鍙�</Button> + <Modal + title="鍔犲叆浼犺緭鍙�" + visible={visible} + width={500} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + confirmLoading={loading} + destroyOnClose + > + <SettingForm + dict={dict} + translist={translist} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default TransferWrap \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/pc/transfer/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/pc/transfer/index.scss diff --git a/src/pc/transfer/settingform/index.jsx b/src/pc/transfer/settingform/index.jsx new file mode 100644 index 0000000..40d2fb0 --- /dev/null +++ b/src/pc/transfer/settingform/index.jsx @@ -0,0 +1,69 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Select } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, + translist: PropTypes.array, + } + + state = {} + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + render() { + const { getFieldDecorator } = this.props.form + const { translist } = this.props + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + + return ( + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={22}> + <Form.Item label="浼犺緭鍙�"> + {getFieldDecorator('VersionName', { + initialValue: '', + rules: [{ + required: true, + message: '璇烽�夋嫨浼犺緭鍙凤紒' + }] + })( + <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}> + {translist.map(option => + <Select.Option key={option.VersionName} value={option.VersionName}>{`${option.ProgramName}(${option.VersionName})`}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/pc/transfer/settingform/index.scss b/src/pc/transfer/settingform/index.scss new file mode 100644 index 0000000..159130b --- /dev/null +++ b/src/pc/transfer/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index 8f61de0..f496dec 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -18,6 +18,8 @@ const MenuDesign = asyncLoadComponent(() => import('@/views/menudesign')) const BillPrint = asyncLoadComponent(() => import('@/views/billprint')) const PrintT = asyncLoadComponent(() => import('@/views/printTemplate')) +const Interface = asyncLoadComponent(() => import('@/views/interface')) +const RoleManage = asyncLoadComponent(() => import('@/views/rolemanage')) const routers = [ {path: '/login', name: 'login', component: Login, auth: false}, @@ -31,7 +33,9 @@ {path: '/mobdesign/:param', name: 'mobdesign', component: MobDesign, auth: true}, {path: '/menudesign/:param', name: 'menudesign', component: MenuDesign, auth: true}, {path: '/billprint/:param', name: 'billprint', component: BillPrint, auth: true}, - {path: '/paramsmain/:param', name: 'pmain', component: Main, auth: true} + {path: '/paramsmain/:param', name: 'pmain', component: Main, auth: true}, + {path: '/role/:param', name: 'role', component: RoleManage, auth: true}, + {path: '/interface', name: 'interface', component: Interface, auth: true} ] export default class RouteConfig extends Component { @@ -56,28 +60,13 @@ _param.role_id && sessionStorage.setItem('role_id', _param.role_id) _param.dataM && sessionStorage.setItem('localRole_id', _param.dataM) _param.Member_Level && sessionStorage.setItem('Member_Level', _param.Member_Level) + _param.ThirdMenu && sessionStorage.setItem('ThirdMenu', _param.ThirdMenu) - if (_param.mainlogo) { - window.GLOB.mainlogo = _param.mainlogo - } - if (_param.navBar) { - window.GLOB.navBar = _param.navBar - } + window.GLOB.mainlogo = _param.mainlogo || '' + window.GLOB.navBar = _param.navBar || '' + if (_param.mstyle && styles[_param.mstyle]) { document.body.className = styles[_param.mstyle] - } - if (_param.MainMenu) { - sessionStorage.setItem('MainMenu', _param.MainMenu) - } - if (_param.SubMenu) { - sessionStorage.setItem('SubMenu', _param.SubMenu) - } - if (_param.ThirdMenu) { - sessionStorage.setItem('ThirdMenu', _param.ThirdMenu) - } - if (_param.param) { - _param.param.ThirdMenu = _param.ThirdMenu - sessionStorage.setItem('MenuParam', JSON.stringify(_param.param)) } } } catch { @@ -105,15 +94,7 @@ return ( <HashRouter> <Switch> - { - routers.map((item, index) => { - return ( - <Route key={index} path={item.path} name={item.name} exact render={ props => { - return this.controlRoute(item, props) - }}/> - ) - }) - } + {routers.map((item, index) => <Route key={index} path={item.path} name={item.name} exact render={ props => this.controlRoute(item, props)}/>)} <Redirect exact from="/" to="login"/> <Route component= {NotFound}/> </Switch> diff --git a/src/tabviews/calendar/index.jsx b/src/tabviews/calendar/index.jsx index 6141c25..b8b7c2a 100644 --- a/src/tabviews/calendar/index.jsx +++ b/src/tabviews/calendar/index.jsx @@ -48,6 +48,7 @@ visible: false, // 鏍囩椤垫帶鍒� triggerTime: '', // 鐐瑰嚮鏃堕棿 calendarYear: moment().format('YYYY'), // 鏃ュ巻骞翠唤 + hasReqFields: false } /** @@ -119,22 +120,17 @@ config.easyCode = _curUserConfig.easyCode || config.easyCode || '' } - // 瀛楁鏉冮檺榛戝悕鍗曘�佸繀濉�佸瓧娈甸�忚 - let valid = true - let roleId = sessionStorage.getItem('role_id') || '' + config.search = Utils.initSearchVal(config.search) + + // 瀛楁閫忚 + let hasReqFields = false config.search = config.search.map(item => { - item.oriInitval = item.initval - if (['text', 'select', 'link'].includes(item.type) && param && param.$searchkey === item.field) { + if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) { item.initval = param.$searchval } - if (item.required === 'true' && !item.initval) { - valid = false - } - - if (!item.blacklist || item.blacklist.length === 0) return item - if (item.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { - item.Hide = 'true' + if (item.required) { + hasReqFields = true } return item @@ -169,6 +165,27 @@ config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '') _customScript = _customScript.replace(/@\$|\$@/ig, '') } + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + let regs = [ + { reg: /@userName@/ig, value: `'${userName}'` }, + { reg: /@fullName@/ig, value: `'${fullName}'` }, + { reg: /@login_city@/ig, value: `'${city}'` } + ] + + regs.forEach(cell => { + config.setting.dataresource = config.setting.dataresource.replace(cell.reg, cell.value) + _customScript = _customScript.replace(cell.reg, cell.value) + }) + if (config.urlFields) { let _param = param || {} config.urlFields.forEach(field => { @@ -183,6 +200,7 @@ } this.setState({ + hasReqFields, BID: param && param.$BID ? param.$BID : '', loadingview: false, config: config, @@ -190,9 +208,9 @@ setting: config.setting, searchlist: config.search, arr_field: config.columns.map(item => item.field).join(','), - search: Utils.initMainSearch(config.search) // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級 + search: Utils.initMainSearch(config.search) }, () => { - if (config.setting.onload !== 'false' && valid) { // 鍒濆鍖栧彲鍔犺浇 + if (config.setting.onload !== 'false') { this.loadmaindata() } }) @@ -213,20 +231,15 @@ * @description 涓昏〃鏁版嵁鍔犺浇 */ async loadmaindata () { - const { setting, search, BID } = this.state + const { setting, search, BID, hasReqFields } = this.state let param = '' - let requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0)) - if (requireFields.length > 0) { - let labels = requireFields.map(item => item.label) - labels = Array.from(new Set(labels)) - - notification.warning({ - top: 92, - message: this.state.dict['form.required.input'] + labels.join('銆�') + ' !', - duration: 3 - }) - return + if (hasReqFields) { + let requireFields = search.filter(item => item.required && item.value === '') + + if (requireFields.length > 0) { + return + } } this.setState({ @@ -523,13 +536,13 @@ render() { const { menuType } = this.props - const { BID, searchlist, loadingview, viewlost, config, loading, data, triggerTime } = this.state + const { BID, setting, searchlist, loadingview, viewlost, config, loading, data, triggerTime } = this.state return ( <div className="calendar-page" id={this.state.ContainerId}> {loadingview && <Spin size="large" />} {searchlist && searchlist.length > 0 ? - <MainSearch BID={BID} searchlist={searchlist} menuType={menuType} refreshdata={this.refreshbysearch}/> : null + <MainSearch BID={BID} searchlist={searchlist} setting={setting} menuType={menuType} refreshdata={this.refreshbysearch}/> : null } {config && config.calendar ? <CalendarComponent calendar={config.calendar} loading={loading} data={data} triggerDate={this.triggerDate} changeDate={this.changeDate}/> : null} {menuType !== 'HS' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null} diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx index ce0938e..763405f 100644 --- a/src/tabviews/commontable/index.jsx +++ b/src/tabviews/commontable/index.jsx @@ -176,16 +176,17 @@ } let chartId = config.charts[0] ? config.charts[0].uuid : '' - // 瀛楁鏉冮檺榛戝悕鍗� + config.search = Utils.initSearchVal(config.search) + + // 瀛楁閫忚鍙婂繀濉爣蹇� + let hasReqFields = false config.search = config.search.map(item => { - item.oriInitval = item.initval if (['text', 'select', 'link'].includes(item.type) && param && param.$searchkey === item.field) { item.initval = param.$searchval } - if (!item.blacklist || item.blacklist.length === 0) return item - if (item.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { - item.Hide = 'true' + if (item.required) { + hasReqFields = true } return item @@ -223,8 +224,7 @@ if (!config.setting.execute) { // 榛樿sql 涓嶆墽琛屾椂 缃┖ config.setting.dataresource = '' - } - if (/\s/.test(config.setting.dataresource)) { + } else if (/\s/.test(config.setting.dataresource)) { config.setting.dataresource = '(' + config.setting.dataresource + ') tb' } @@ -237,6 +237,27 @@ config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '') config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '') } + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + let regs = [ + { reg: /@userName@/ig, value: `'${userName}'` }, + { reg: /@fullName@/ig, value: `'${fullName}'` }, + { reg: /@login_city@/ig, value: `'${city}'` } + ] + + regs.forEach(cell => { + config.setting.dataresource = config.setting.dataresource.replace(cell.reg, cell.value) + config.setting.customScript = config.setting.customScript.replace(cell.reg, cell.value) + }) + if (config.urlFields) { let _param = param || {} config.urlFields.forEach(field => { @@ -343,16 +364,6 @@ _columns.push(config.gridBtn) } - let valid = true // 鎼滅储鏉′欢蹇呭~楠岃瘉, 鍒濆鎼滅储鏉′欢, 濡傞�氳繃涓婄骇閫忚锛屽啓鍏ユ悳绱㈡潯浠� - let hasReqFields = false - config.search.forEach(item => { - if (item.required !== 'true') return - if (!item.initval) { - valid = false - } - hasReqFields = true - }) - this.setState({ loadingview: false, absFields, @@ -366,10 +377,10 @@ columns: _columns, arr_field: _arrField.join(','), BID: param && param.$BID ? param.$BID : '', - search: Utils.initMainSearch(config.search), // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級 + search: Utils.initMainSearch(config.search), hasReqFields }, () => { - if (config.setting.onload !== 'false' && valid) { // 鍒濆鍖栧彲鍔犺浇 + if (config.setting.onload !== 'false') { // 鍒濆鍖栧彲鍔犺浇 this.loadData() } this.setShortcut() @@ -430,11 +441,6 @@ loadData = () => { const { setting, search, BIDs, loadCustomApi, hasReqFields } = this.state - let requireFields = [] - - if (hasReqFields) { - requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0)) - } this.setState({ selectedData: [], @@ -445,17 +451,18 @@ } }) - if (requireFields.length > 0) { - let labels = requireFields.map(item => item.label) - labels = Array.from(new Set(labels)) + if (hasReqFields) { + let requireFields = search.filter(item => item.required && item.value === '') - notification.warning({ - top: 92, - message: this.state.dict['form.required.input'] + labels.join('銆�') + ' !', - duration: 3 - }) - return - } else if (window.GLOB.systemType === 'production' && setting.interType === 'custom' && !setting.proInterface) { + if (requireFields.length > 0) { + this.setState({ + loading: false + }) + return + } + } + + if (window.GLOB.systemType === 'production' && setting.interType === 'custom' && !setting.proInterface) { notification.warning({ top: 92, message: '鏈缃寮忕郴缁熷湴鍧�!', @@ -525,12 +532,12 @@ let mkey = result.mk_api_key || '' - delete result.mk_ex_invoke + delete result.mk_ex_invoke // 鏄惁缁х画鎵ц delete result.status delete result.message delete result.ErrCode delete result.ErrMesg - delete result.mk_api_key + delete result.mk_api_key // 褰撳墠璇锋眰鐨刱ey鍊硷紝鐢ㄤ簬鍥炶皟 let param = {} @@ -540,7 +547,7 @@ }) Api.directRequest(url, setting.method, param, setting.cross).then(res => { - if (typeof(res) !== 'object' || Array.isArray(res)) { + if (typeof(res) !== 'object') { let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒' if (typeof(res) === 'string') { @@ -555,6 +562,9 @@ this.customCallbackRequest(_result) } else { + if (Array.isArray(res)) { + res = { data: res } + } res.mk_api_key = mkey this.customCallbackRequest(res) } @@ -662,8 +672,13 @@ let result = await Api.genericInterface(param) this.getStatFieldsValue() - + if (result.status) { + let start = 1 + if (setting.laypage) { + start = pageSize * (pageIndex - 1) + 1 + } + this.setState({ data: result.data.map((item, index) => { if (absFields.length) { @@ -678,6 +693,7 @@ item.key = index item.$$uuid = item[setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = start + index + '' return item }), @@ -736,6 +752,7 @@ data = data.map(item => { if (item.$$uuid === _data.$$uuid) { _data.key = item.key + _data.$Index = item.$Index return _data } else { return item @@ -896,13 +913,13 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { MenuName, MenuID } = this.props const { arr_field, orderBy, search, setting} = this.state if (MenuID !== menuId) return - MKEmitter.emit('execExcelout', MenuID, btnId, { + MKEmitter.emit('returnModuleParam', MenuID, btnId, { arr_field: arr_field, orderBy: orderBy || setting.order, search: search, @@ -1019,7 +1036,7 @@ MKEmitter.addListener('reloadData', this.reloadData) MKEmitter.addListener('reloadMenuView', this.reloadMenuView) MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu) - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -1034,7 +1051,7 @@ MKEmitter.removeListener('reloadData', this.reloadData) MKEmitter.removeListener('reloadMenuView', this.reloadMenuView) MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu) - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -1046,7 +1063,7 @@ <div className="commontable" id={this.state.ContainerId}> {loadingview ? <Spin size="large" /> : null} {searchlist && searchlist.length ? - <MainSearch BID={BID} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null + <MainSearch BID={BID} searchlist={searchlist} setting={setting} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null } {setting ? <Row className="chart-view" gutter={16}> {/* 瑙嗗浘缁� */} @@ -1076,7 +1093,7 @@ </div> <div className="main-table-box"> {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && this.state.data && this.state.data.length > 0 ? - <Switch title="鏀惰捣" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={pickup} onChange={this.pickupChange} /> : null + <Switch title="鏀惰捣" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /> : null } <MainTable tableId="mainTable" diff --git a/src/tabviews/custom/components/card/balcony/index.jsx b/src/tabviews/custom/components/card/balcony/index.jsx new file mode 100644 index 0000000..879d8f5 --- /dev/null +++ b/src/tabviews/custom/components/card/balcony/index.jsx @@ -0,0 +1,301 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Spin, notification } from 'antd' + +import Api from '@/api' +// import Utils from '@/utils/utils.js' +import UtilsDM from '@/utils/utils-datamanage.js' +import asyncComponent from '@/utils/asyncComponent' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const CardCellComponent = asyncComponent(() => import('../cardcellList')) + +class BalconyComponent extends Component { + static propTpyes = { + BID: PropTypes.any, + menu: PropTypes.object, + data: PropTypes.array, + config: PropTypes.object, + menuType: PropTypes.any, + } + + state = { + BID: '', + config: null, + syncConfig: null, + loading: false, + sync: false, + data: {}, + show: true + } + + UNSAFE_componentWillMount () { + const { data, BID, menu } = this.props + let _config = fromJS(this.props.config).toJS() + let _cols = new Map() + + let _data = {} + let _sync = false + + if (_config.setting && _config.wrap.datatype !== 'static') { + _sync = _config.setting.sync === 'true' + + if (_sync && data) { + _data = data[_config.dataName] || {} + if (_data && Array.isArray(_data)) { + _data = _data[0] || {} + } + _sync = false + } + } else { + _data = {} + } + + if (_data) { + _data.$$BID = BID || '' + } + + _config.columns.forEach(item => { + _cols.set(item.field, item) + }) + + if (_config.wrap.position === 'fixed') { + _config.style.position = 'fixed' + _config.style.zIndex = 2 + _config.style.left = _config.wrap.left || '' + _config.style.right = _config.wrap.right || '' + _config.style.top = _config.wrap.top || '' + _config.style.bottom = _config.wrap.bottom || '' + _config.style.transform = _config.wrap.transform || '' + _config.style.width = _config.wrap.realwidth || '' + } + + let show = true + let syncConfig = null + if (_config.wrap.linkType === 'sync') { + _config.wrap.syncModule = _config.wrap.syncModule.pop() + + let filterComponent = (components) => { + components.forEach(item => { + if (syncConfig) return + if (item.type === 'tabs') { + item.subtabs.forEach(tab => { + filterComponent(tab.components) + }) + } else if (item.type === 'group') { + filterComponent(item.components) + } else if (_config.wrap.syncModule === item.uuid) { + syncConfig = { + uuid: item.uuid, + wrap: item.wrap, + setting: item.setting, + columns: item.columns + } + } + }) + } + + filterComponent(menu.components) + _config.elements = _config.elements.map(item => { + if (item.eleType === 'button') { + item.$syncModule = _config.wrap.syncModule + } + return item + }) + } else if (_config.wrap.linkType === 'sup') { + _config.wrap.supModule = _config.wrap.supModule.pop() + if (_config.wrap.supControl === 'hidden') { + show = false + } + } + + this.setState({ + show, + syncConfig, + sync: _sync, + data: _data, + BID: BID || '', + config: _config, + arr_field: _config.columns.map(col => col.field).join(','), + }, () => { + if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') { + this.loadData() + } + }) + } + + componentDidMount () { + MKEmitter.addListener('reloadData', this.reloadData) + MKEmitter.addListener('resetSelectLine', this.resetParentParam) + MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('reloadData', this.reloadData) + MKEmitter.removeListener('resetSelectLine', this.resetParentParam) + MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) + } + + /** + * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹� + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { sync, config, BID } = this.state + + if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) { + let _data = {} + if (nextProps.data && nextProps.data[config.dataName]) { + _data = nextProps.data[config.dataName] + if (_data && Array.isArray(_data)) { + _data = _data[0] + } + } + + if (_data) { + _data.$$BID = BID || '' + } + + this.setState({sync: false, data: _data}) + } + } + + /** + * @description 鎸夐挳鎵ц瀹屾垚鍚庨〉闈㈠埛鏂� + * @param {*} menuId // 鑿滃崟Id + * @param {*} position // 鍒锋柊浣嶇疆 + * @param {*} btn // 鎵ц鐨勬寜閽� + */ + refreshByButtonResult = (menuId, position, btn) => { + const { config, BID, syncConfig } = this.state + + if (config.uuid !== menuId) return + + this.loadData() // 鏁版嵁鍒锋柊 + + let supModule = config.wrap.supModule + + if (syncConfig) { + supModule = syncConfig.setting.supModule + + MKEmitter.emit('refreshByButtonResult', syncConfig.uuid, position, btn) + } + + if (btn.syncComponentId && btn.syncComponentId !== config.uuid && btn.syncComponentId !== supModule) { + MKEmitter.emit('reloadData', btn.syncComponentId) // 鍚岀骇鏍囩鍒锋柊 + } + + if (position === 'mainline' && supModule) { // 涓昏〃琛屽埛鏂� + MKEmitter.emit('reloadData', supModule, (BID || 'empty')) + } else if (position === 'popclose') { // 鏍囩鍏抽棴鍒锋柊 + supModule && MKEmitter.emit('reloadData', supModule, (BID || 'empty')) + btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId) + } + } + + resetParentParam = (MenuID, id) => { + const { config, syncConfig } = this.state + + if (syncConfig) { + if (!syncConfig.setting.supModule || syncConfig.setting.supModule !== MenuID) return + + if (id !== this.state.BID) { + this.setState({ BID: id }, () => { + this.loadData() + }) + } + } else { + if (!config.wrap.supModule || config.wrap.supModule !== MenuID) return + + if (config.wrap.supControl === 'hidden') { + this.setState({ show: id ? true : false }) + } + + if (id !== this.state.BID) { + this.setState({ BID: id }, () => { + this.loadData() + }) + } + } + } + + reloadData = (menuId) => { + const { config } = this.state + + if (menuId !== config.uuid) return + + this.loadData() + } + + async loadData () { + const { menuType } = this.props + const { config, arr_field, BID } = this.state + + if (config.wrap.datatype === 'static') { + this.setState({ + data: {$$BID: BID || ''}, + }) + return + } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� + this.setState({ + data: {$$BID: BID || ''}, + }) + return + } + + let searches = [] + + this.setState({ + loading: true + }) + + let _orderBy = config.setting.order || '' + let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID, menuType) + + let result = await Api.genericInterface(param) + if (result.status) { + let _data = result.data && result.data[0] ? result.data[0] : {} + _data.$$BID = BID || '' + + this.setState({ + data: _data, + loading: false + }) + } else { + this.setState({ + loading: false, + }) + notification.error({ + top: 92, + message: result.message, + duration: 10 + }) + } + } + + render() { + const { config, loading, data, show, syncConfig } = this.state + + return ( + <div className={'custom-balcony-box' + (!show ? ' hidden' : '')} style={config.style}> + {loading ? + <div className="loading-mask"> + <div className="ant-spin-blur"></div> + <Spin /> + </div> : null + } + <CardCellComponent data={data} cards={syncConfig || config} cardCell={config} elements={config.elements}/> + </div> + ) + } +} + +export default BalconyComponent \ No newline at end of file diff --git a/src/tabviews/custom/components/card/balcony/index.scss b/src/tabviews/custom/components/card/balcony/index.scss new file mode 100644 index 0000000..37c4a31 --- /dev/null +++ b/src/tabviews/custom/components/card/balcony/index.scss @@ -0,0 +1,65 @@ +.custom-balcony-box { + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + position: relative; + + .card-row-list::after { + content: ' '; + display: block; + clear: both; + } + + .card-row-list { + .card-item-box { + background-color: #ffffff; + transition: all 0.3s; + } + >.pointer { + cursor: pointer; + } + >.active >.card-item-box { + border-color: #1890ff!important; + box-shadow: 0 0 4px #1890ff; + } + } + + .card-item-box { + position: relative; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + transition: all 0.3s; + } + + .loading-mask { + position: absolute; + left: 40px; + top: 0; + right: 40px; + bottom: 0px; + display: flex; + align-items: center; + justify-content: center; + text-align: justify; + z-index: 1; + + .ant-spin-blur { + position: absolute; + width: 100%; + height: 100%; + opacity: 0.5; + background: #ffffff; + } + } +} +.custom-balcony-box.hidden { + display: none; +} + +.custom-balcony-box::after { + content: ' '; + display: block; + clear: both; +} diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx index 525c471..8b5fa84 100644 --- a/src/tabviews/custom/components/card/cardcellList/index.jsx +++ b/src/tabviews/custom/components/card/cardcellList/index.jsx @@ -21,10 +21,14 @@ const BarCode = asyncElementComponent(() => import('@/components/barcode')) const QrCode = asyncElementComponent(() => import('@/components/qrcode')) const Video = asyncComponent(() => import('@/components/video')) +const PicRadio = { + '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%', + '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%', + '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%' +} class CardCellComponent extends Component { static propTpyes = { - seq: PropTypes.any, // 搴忓彿 cards: PropTypes.object, // 鑿滃崟閰嶇疆淇℃伅 cardCell: PropTypes.object, data: PropTypes.object, @@ -260,13 +264,20 @@ } getContent = (card) => { - const { data, cards, seq } = this.props + const { data, cards } = this.props if (card.eleType === 'sequence') { + let _style = {} + if (card.marks) { + _style.width = card.innerHeight + _style.height = card.innerHeight + _style.lineHeight = card.innerHeight + 'px' + this.getMark(card.marks, _style) + } return ( <Col key={card.uuid} span={card.width}> <div style={card.style}> - <div className={'ant-mk-text'}>{seq}</div> + <div className="ant-mk-text"><span className="sequence-wrap" style={_style}>{data.$Index || ''}</span></div> </div> </Col> ) @@ -307,7 +318,7 @@ return ( <Col key={card.uuid} span={card.width}> <div style={_style} onClick={(e) => {this.openNewView(e, card)}}> - <div className={'ant-mk-text line' + card.height} style={{height: card.innerHeight || 'auto'}}>{val}</div> + <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight || 'auto'}}>{val}</div> </div> </Col> ) @@ -359,7 +370,7 @@ return ( <Col key={card.uuid} span={card.width}> <div style={_style}> - <div className={'ant-mk-text line' + card.height} style={{height: card.innerHeight || 'auto'}}>{val}</div> + <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight || 'auto'}}>{val}</div> </div> </Col> ) @@ -424,8 +435,17 @@ ) } else if (card.eleType === 'picture') { let _imagestyle = {} - let _style = card.style ? {...card.style} : {} + let _style = card.style ? {margin: '0 auto', ...card.style} : {} let url = '' + if (card.maxWidth) { + _style.maxWidth = card.maxWidth + if (_style.marginLeft === '0px') { + delete _style.marginLeft + } + if (_style.marginRight === '0px') { + delete _style.marginRight + } + } if (card.datatype === 'static') { url = card.url @@ -443,12 +463,8 @@ _imagestyle.borderRadius = _style.borderRadius } - if (card.lenWidRadio === '16:9') { - _imagestyle.paddingTop = '56.25%' - } else if (card.lenWidRadio === '3:2') { - _imagestyle.paddingTop = '66.67%' - } else if (card.lenWidRadio === '4:3') { - _imagestyle.paddingTop = '75%' + if (PicRadio[card.lenWidRadio]) { + _imagestyle.paddingTop = PicRadio[card.lenWidRadio] } else { _imagestyle.paddingTop = '100%' } @@ -534,128 +550,116 @@ </Col> ) } else if (card.eleType === 'button') { + let _data = data.$$type === 'extendCard' ? [] : [data] + if (['exec', 'prompt', 'pop'].includes(card.OpenType)) { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <NormalButton - BID={data.$$BID} - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - columns={cards.columns} - selectedData={[data]} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <NormalButton + BID={data.$$BID} + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + columns={cards.columns} + selectedData={_data} + /> </Col> ) } else if (card.OpenType === 'excelIn') { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <ExcelInButton - BID={data.$$BID} - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - selectedData={[data]} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <ExcelInButton + BID={data.$$BID} + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + selectedData={_data} + /> </Col> ) } else if (card.OpenType === 'excelOut') { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <ExcelOutButton - BID={data.$$BID} - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <ExcelOutButton + BID={data.$$BID} + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + /> </Col> ) } else if (card.OpenType === 'popview') { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <PopupButton - BID={data.$$BID} - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - selectedData={[data]} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <PopupButton + BID={data.$$BID} + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + selectedData={_data} + /> </Col> ) } else if (card.OpenType === 'tab') { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <TabButton - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - selectedData={[data]} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <TabButton + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + selectedData={_data} + /> </Col> ) } else if (card.OpenType === 'innerpage') { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <NewPageButton - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - selectedData={[data]} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <NewPageButton + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + selectedData={_data} + /> </Col> ) } else if (card.OpenType === 'funcbutton') { if (card.funcType === 'changeuser') { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <ChangeUserButton - BID={data.$$BID} - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - selectedData={[data]} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <ChangeUserButton + BID={data.$$BID} + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + selectedData={_data} + /> </Col> ) } else if (card.funcType === 'print') { return ( - <Col key={card.uuid} span={card.width}> - <div style={card.style}> - <PrintButton - BID={data.$$BID} - btn={card} - show={card.show} - style={card.btnstyle} - setting={cards.setting} - selectedData={[data]} - /> - </div> + <Col key={card.uuid} className="mk-cell-btn" span={card.width}> + <PrintButton + BID={data.$$BID} + btn={card} + show={card.show} + style={card.style} + setting={cards.setting} + selectedData={_data} + /> </Col> ) } } } + + return null } render() { diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss index 2684266..97c3ab3 100644 --- a/src/tabviews/custom/components/card/cardcellList/index.scss +++ b/src/tabviews/custom/components/card/cardcellList/index.scss @@ -1,11 +1,22 @@ .card-cell-list { position: relative; - + .ant-btn { + padding: 0; + } .ant-mk-text { font-style: inherit; font-weight: inherit; text-decoration: inherit; + .sequence-wrap { + display: inline-block; + width: 22px; + height: 22px; + line-height: 22px; + white-space: nowrap; + border-radius: 50%; + overflow: visible; + } } .ant-mk-text:not(.line1):not(.line) { word-break: break-word; @@ -46,9 +57,13 @@ .line10 { -webkit-line-clamp: 10; } - button { - height: auto; - min-height: 32px; + .mk-cell-btn { + > div {width: 100%;} + button { + width: 100%; + height: auto; + min-height: 32px; + } } .ant-mk-slider { box-sizing: border-box; diff --git a/src/tabviews/custom/components/card/data-card/index.jsx b/src/tabviews/custom/components/card/data-card/index.jsx index 59935cd..9272285 100644 --- a/src/tabviews/custom/components/card/data-card/index.jsx +++ b/src/tabviews/custom/components/card/data-card/index.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' import { connect } from 'react-redux' -import { Spin, Empty, notification, Col, Pagination } from 'antd' +import { Spin, Empty, notification, Row, Col, Pagination } from 'antd' import Api from '@/api' import Utils from '@/utils/utils.js' @@ -40,13 +40,39 @@ sync: false, // 鏄惁缁熶竴璇锋眰鏁版嵁 card: null, // 鍗$墖璁剧疆 data: null, // 鏁版嵁 - total: null + total: null, + precards: [], + nextcards: [], } UNSAFE_componentWillMount () { const { data, initdata, BID } = this.props let _config = fromJS(this.props.config).toJS() - let _card = _config.subcards[0] + + let _card = null + let precards = [] + let nextcards = [] + + _config.subcards.forEach(item => { + item.setting.$click = '' + if (item.setting.click === 'button') { + if (item.elements.filter(ele => ele.eleType === 'button').length < 2) { + item.setting.$click = ' trigger-button' + } + item.setting.click = '' + } + + if (item.$cardType !== 'extendCard') { + _card = item + } else if (!_card) { + precards.push(item) + } else { + nextcards.push(item) + } + }) + + _config.subcards = null + let _cols = new Map() let _data = null @@ -60,11 +86,26 @@ _sync = false } + if (_config.wrap.cardFloat && _config.wrap.cardFloat !== 'left') { + let _width = 0 + precards.forEach(card => { + _width += card.setting.width + }) + nextcards.forEach(card => { + _width += card.setting.width + }) + + _config.$offset = _width + } else { + _config.wrap.cardFloat = null + } + if (_data) { _data = _data.map((item, index) => { item.key = index item.$$uuid = item[_config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + 1 + '' return item }) } @@ -87,6 +128,8 @@ }) this.setState({ + precards, + nextcards, sync: _sync, data: _data, BID: BID || '', @@ -103,8 +146,9 @@ componentDidMount () { MKEmitter.addListener('reloadData', this.reloadData) + MKEmitter.addListener('getSyncData', this.getSyncData) MKEmitter.addListener('resetSelectLine', this.resetParentParam) - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -125,16 +169,15 @@ item.key = index item.$$uuid = item[config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + 1 + '' return item }) this.setState({sync: false, data: _data}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({pageIndex: 1}, () => { + this.loadData() + }) } } @@ -143,9 +186,18 @@ return } MKEmitter.removeListener('reloadData', this.reloadData) + MKEmitter.removeListener('getSyncData', this.getSyncData) MKEmitter.removeListener('resetSelectLine', this.resetParentParam) - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) + } + + getSyncData = (syncModule, btnId) => { + const { config, selectedData } = this.state + + if (config.uuid !== syncModule) return + + MKEmitter.emit('triggerBtnId', btnId, (selectedData || [])) } /** @@ -159,7 +211,15 @@ if (config.uuid !== menuId) return - this.loadData(btn) // 鏁版嵁鍒锋柊 + if (!btn || btn.resetPageIndex !== 'false') { + this.setState({ + pageIndex: 1 + }, () => { + this.loadData() + }) + } else { + this.loadData() + } if (btn.syncComponentId && btn.syncComponentId !== config.uuid && btn.syncComponentId !== config.setting.supModule) { MKEmitter.emit('reloadData', btn.syncComponentId) // 鍚岀骇鏍囩鍒锋柊 @@ -191,7 +251,7 @@ if (!config.setting.supModule || config.setting.supModule !== MenuID) return if (id !== this.state.BID) { - this.setState({ BID: id, BData: data }, () => { + this.setState({ BID: id, BData: data, pageIndex: 1 }, () => { this.loadData() }) } @@ -200,14 +260,14 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { mainSearch } = this.props const { arr_field, config, search } = this.state if (config.uuid !== menuId) return let searches = search ? fromJS(search).toJS() : [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { @@ -216,7 +276,7 @@ }) } - MKEmitter.emit('execExcelout', config.uuid, btnId, { + MKEmitter.emit('returnModuleParam', config.uuid, btnId, { arr_field: arr_field, orderBy: config.setting.order || '', search: searches, @@ -238,17 +298,23 @@ total: 0, loading: false }) + MKEmitter.emit('resetSelectLine', config.uuid, '', '') return } let searches = fromJS(search).toJS() - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { searches.push(item) } }) + } + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } this.setState({ @@ -260,6 +326,11 @@ let result = await Api.genericInterface(param) if (result.status) { + let start = 1 + if (config.setting.laypage) { + start = config.setting.pageSize * (pageIndex - 1) + 1 + } + this.setState({ activeKey: '', selectKeys: [], @@ -268,11 +339,13 @@ item.key = index item.$$uuid = item[config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + start + '' return item }), total: result.total, loading: false }) + MKEmitter.emit('resetSelectLine', config.uuid, '', '') } else { this.setState({ loading: false @@ -293,7 +366,7 @@ const { config, arr_field, pageIndex, search, BID } = this.state let searches = fromJS(search).toJS() - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { @@ -325,6 +398,7 @@ _data.key = item.key _data.$$uuid = _data[config.setting.primaryKey] || '' _data.$$BID = BID || '' + _data.$Index = item.$Index return _data } else { return item @@ -514,7 +588,7 @@ } render() { - const { config, loading, data, pageIndex, total, card, activeKey, BID, BData, selectedData, selectKeys } = this.state + const { config, precards, nextcards, loading, data, pageIndex, total, card, activeKey, BID, BData, selectedData, selectKeys } = this.state let _total = 0 let switchable = false @@ -523,9 +597,11 @@ switchable = true } let offset = 0 - if (config.wrap.cardFloat && config.wrap.cardFloat !== 'left') { - if (data && card.setting.width * data.length < 24) { - offset = 24 - card.setting.width * data.length + + if (config.wrap.cardFloat) { + let length = data ? data.length : 0 + if (card.setting.width * length + config.$offset < 24) { + offset = 24 - card.setting.width * length - config.$offset if (config.wrap.cardFloat === 'center') { offset = Math.floor(offset / 2) } @@ -533,7 +609,7 @@ } return ( - <div className="custom-data-card-box" style={{...config.style, minHeight: config.wrap.minHeight}}> + <div className="custom-data-card-box" style={config.style}> {loading ? <div className="loading-mask"> {data ? <div className="ant-spin-blur"></div> : null} @@ -549,20 +625,30 @@ actions={config.action} columns={config.columns} selectedData={selectedData} - refreshdata={this.refreshbyaction} /> : null } <div className={`data-zoom ${config.wrap.cardType || ''} ${config.wrap.scale || ''}`}> {switchable ? <div className={'prev-page ' + (pageIndex === 1 ? 'disabled' : '')} onClick={this.prevPage}><div><div><img src={preImg} alt=""/></div></div></div> : null} - {data && data.length > 0 ? <div className="card-row-list"> - {data.map((item, index) => ( - <Col className={(activeKey === index ? 'active' : (selectKeys.indexOf(index) > -1 ? 'selected' : '')) + (card.setting.click ? ' pointer' : '')} key={index} span={card.setting.width} offset={!index ? offset : 0} onClick={() => {this.changeCard(index, item)}}> + <Row className="card-row-list"> + {offset ? <Col span={offset} style={{height: '10px'}}> </Col> : null} + {precards.map((item, index) => ( + <Col key={'pre' + index} className={item.setting.$click} span={item.setting.width || 6}> + <CardItem card={item} cards={config} data={{$$BID: BID, $$type: 'extendCard'}}/> + </Col> + ))} + {data && data.map((item, index) => ( + <Col className={(activeKey === index ? ' active' : (selectKeys.indexOf(index) > -1 ? ' selected' : '')) + (card.setting.$click ? ' pointer' : '') + card.setting.$click} key={index} span={card.setting.width} onClick={() => {this.changeCard(index, item)}}> <CardItem card={card} cards={config} data={item}/> </Col> ))} - </div> : null} + {nextcards.map((item, index) => ( + <Col key={'next' + index} className={item.setting.$click} span={item.setting.width || 6}> + <CardItem card={item} cards={config} data={{$$BID: BID, $$type: 'extendCard'}}/> + </Col> + ))} + </Row> {switchable ? <div className={'prev-page ' + (total <= _total ? 'disabled' : '')} onClick={this.nextPage}><div><div><img src={nextImg} alt=""/></div></div></div> : null} - {!data || data.length === 0 ? <Empty description={false}/> : null} + {precards.length === 0 && nextcards.length === 0 && (!data || data.length === 0) ? <Empty description={false}/> : null} </div> {config.wrap.pagestyle !== 'switch' && config.setting.laypage && data ? <Pagination size="small" total={total} showTotal={t => `鍏� ${t} 鏉} pageSize={config.setting.pageSize} onChange={this.changePageIndex} current={pageIndex}/> : null} </div> diff --git a/src/tabviews/custom/components/card/data-card/index.scss b/src/tabviews/custom/components/card/data-card/index.scss index 49e69ef..9e0798f 100644 --- a/src/tabviews/custom/components/card/data-card/index.scss +++ b/src/tabviews/custom/components/card/data-card/index.scss @@ -125,6 +125,28 @@ margin: 10px; text-align: right; } + .trigger-button { + .card-item-box { + .card-cell-list { + position: unset; + .mk-cell-btn { + position: unset; + .ant-btn { + position: unset; + } + .ant-btn::after { + content: ' '; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + cursor: pointer; + } + } + } + } + } } .custom-card-box::after { diff --git a/src/tabviews/custom/components/card/prop-card/index.jsx b/src/tabviews/custom/components/card/prop-card/index.jsx index 0c85678..fc110d8 100644 --- a/src/tabviews/custom/components/card/prop-card/index.jsx +++ b/src/tabviews/custom/components/card/prop-card/index.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' import { connect } from 'react-redux' -import { Spin, notification, Col } from 'antd' +import { Spin, notification, Col, Row } from 'antd' import moment from 'moment' import Api from '@/api' @@ -73,6 +73,13 @@ let _width = 0 _config.subcards.forEach(card => { + card.setting.$click = '' + if (card.setting.click === 'button') { + if (card.elements.filter(ele => ele.eleType === 'button').length < 2) { + card.setting.$click = ' trigger-button' + } + card.setting.click = '' + } _width += card.setting.width card.elements = card.elements.map(item => { if (item.field && _cols.has(item.field)) { @@ -113,7 +120,7 @@ componentDidMount () { MKEmitter.addListener('reloadData', this.reloadData) MKEmitter.addListener('resetSelectLine', this.resetParentParam) - MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) + MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) this.handleTimer() } @@ -151,12 +158,10 @@ } this.setState({sync: false, data: _data}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.wrap.datatype !== 'static' && config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if ( config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -165,16 +170,7 @@ if (!config.timer) return - const _change = { - '15s': 15000, - '30s': 30000, - '1min': 60000, - '5min': 300000, - '10min': 600000, - '15min': 900000, - '30min': 1800000, - '1hour': 3600000 - } + const _change = { '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } let timer = _change[config.timer] @@ -270,25 +266,20 @@ if (config.wrap.datatype === 'static') { this.setState({ data: {$$BID: BID || ''}, - loading: false }) return } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� this.setState({ data: {$$BID: BID || ''}, - loading: false }) return } - let searches = [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 - let keys = searches.map(item => item.key) - mainSearch.forEach(item => { - if (!keys.includes(item.key)) { - searches.push(item) - } - }) + let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } if (!hastimer) { @@ -417,7 +408,7 @@ const { config, loading, data, activeKey } = this.state return ( - <div className="custom-prop-card-box" style={{...config.style, minHeight: config.wrap.minHeight}}> + <div className="custom-prop-card-box" style={config.style}> {loading ? <div className="loading-mask"> <div className="ant-spin-blur"></div> @@ -425,13 +416,13 @@ </div> : null } <NormalHeader config={config}/> - <div className={`card-row-list ${config.wrap.cardType || ''} ${config.wrap.scale || ''}`}> + <Row className={`card-row-list ${config.wrap.cardType || ''} ${config.wrap.scale || ''}`}> {config.subcards.map((item, index) => ( - <Col className={(activeKey === index ? 'active' : '') + (item.setting.click ? ' pointer' : '')} key={index} span={item.setting.width || 6} offset={item.offset || 0} onClick={() => {this.changeCard(index, item)}}> + <Col className={(activeKey === index ? 'active' : '') + (item.setting.click ? ' pointer' : '') + item.setting.$click} key={index} span={item.setting.width || 6} offset={item.offset || 0} onClick={() => {this.changeCard(index, item)}}> <CardItem card={item} cards={config} data={data}/> </Col> ))} - </div> + </Row> </div> ) } diff --git a/src/tabviews/custom/components/card/prop-card/index.scss b/src/tabviews/custom/components/card/prop-card/index.scss index 12c5e88..bb919f8 100644 --- a/src/tabviews/custom/components/card/prop-card/index.scss +++ b/src/tabviews/custom/components/card/prop-card/index.scss @@ -70,6 +70,28 @@ background: #ffffff; } } + .trigger-button { + .card-item-box { + .card-cell-list { + position: unset; + .mk-cell-btn { + position: unset; + .ant-btn { + position: unset; + } + .ant-btn::after { + content: ' '; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + cursor: pointer; + } + } + } + } + } } .custom-card-box::after { diff --git a/src/tabviews/custom/components/card/table-card/index.jsx b/src/tabviews/custom/components/card/table-card/index.jsx index a557611..609d46e 100644 --- a/src/tabviews/custom/components/card/table-card/index.jsx +++ b/src/tabviews/custom/components/card/table-card/index.jsx @@ -1,7 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Spin, notification, Col, Empty, Pagination } from 'antd' +import { Spin, notification, Row, Col, Empty, Pagination } from 'antd' import Api from '@/api' import Utils from '@/utils/utils.js' @@ -27,7 +27,6 @@ config: null, // 鍥捐〃閰嶇疆淇℃伅 loading: false, // 鏁版嵁鍔犺浇鐘舵�� search: null, // 鎼滅储鏉′欢 - preIndex: 0, // 寮�濮嬬储寮� pageIndex: 1, // 椤电爜 total: 0, // 鎬绘暟 sync: false, // 鏄惁缁熶竴璇锋眰鏁版嵁 @@ -59,6 +58,7 @@ item.key = index item.$$uuid = item[_config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + 1 + '' return item }) } @@ -69,9 +69,9 @@ } if (_config.setting.laypage) { - _config.wrap.contentHeight = _config.wrap.height - (showHeader ? 85 : 40) + _config.wrap.contentHeight = showHeader ? 'calc(100% - 85px)' : 'calc(100% - 40px)' } else { - _config.wrap.contentHeight = _config.wrap.height - (showHeader ? 45 : 0) + _config.wrap.contentHeight = showHeader ? 'calc(100% - 45px)' : '100%' } _config.columns.forEach(item => { @@ -104,7 +104,7 @@ componentDidMount () { MKEmitter.addListener('reloadData', this.reloadData) MKEmitter.addListener('resetSelectLine', this.resetParentParam) - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -118,7 +118,7 @@ } MKEmitter.removeListener('reloadData', this.reloadData) MKEmitter.removeListener('resetSelectLine', this.resetParentParam) - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -138,16 +138,15 @@ item.key = index item.$$uuid = item[config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + 1 + '' return item }) this.setState({sync: false, data: _data}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -181,7 +180,7 @@ if (!config.setting.supModule || config.setting.supModule !== MenuID) return if (id !== this.state.BID) { - this.setState({ BID: id }, () => { + this.setState({ BID: id, pageIndex: 1 }, () => { this.loadData() }) } @@ -198,14 +197,14 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { mainSearch } = this.props const { arr_field, config, search } = this.state if (config.uuid !== menuId) return let searches = search ? fromJS(search).toJS() : [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { @@ -214,7 +213,7 @@ }) } - MKEmitter.emit('execExcelout', config.uuid, btnId, { + MKEmitter.emit('returnModuleParam', config.uuid, btnId, { arr_field: arr_field, orderBy: config.setting.order || '', search: searches, @@ -229,20 +228,24 @@ if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� this.setState({ data: [], - total: 0, - preIndex: 0 + total: 0 }) return } let searches = search ? fromJS(search).toJS() : [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key) mainSearch.forEach(item => { if (!keys.includes(item.key)) { searches.push(item) } }) + } + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } this.setState({ @@ -254,9 +257,9 @@ let result = await Api.genericInterface(param) if (result.status) { - let _preIndex = 0 + let start = 1 if (config.setting.laypage) { - _preIndex = config.setting.pageSize * (pageIndex - 1) + start = config.setting.pageSize * (pageIndex - 1) + 1 } this.setState({ @@ -264,10 +267,10 @@ item.key = index item.$$uuid = item[config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + start + '' return item }), total: result.total, - preIndex: _preIndex, loading: false }) } else { @@ -290,7 +293,7 @@ }) } - getLines = (data, seq) => { + getLines = (data) => { const { config } = this.state let line = [] @@ -321,7 +324,7 @@ line.push( <Col key={index} span={24}> <div className="card-item-box" style={item.style}> - <CardCellComponent seq={seq} data={data} cards={config} cardCell={item} elements={item.elements}/> + <CardCellComponent data={data} cards={config} cardCell={item} elements={item.elements}/> </div> </Col> ) @@ -340,10 +343,10 @@ } render() { - const { config, loading, data, BID, pageIndex, preIndex, total } = this.state + const { config, loading, data, BID, pageIndex, total } = this.state return ( - <div className="custom-table-card-box" style={{...config.style, height: config.wrap.height}}> + <div className="custom-table-card-box" style={{...config.style}}> {loading ? <div className="loading-mask"> {data ? <div className="ant-spin-blur"></div> : null} @@ -351,9 +354,9 @@ </div> : null } <NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} /> - {data && data.length > 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}> - {data.map((item, index) => this.getLines(item, preIndex + index + 1))} - </div> : null} + {data && data.length > 0 ? <Row className="card-row-list" style={{height: config.wrap.contentHeight}}> + {data.map(item => this.getLines(item))} + </Row> : null} {data && data.length === 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}> <Empty description={false}/> </div> : null} diff --git a/src/tabviews/custom/components/carousel/data-card/index.jsx b/src/tabviews/custom/components/carousel/data-card/index.jsx index 1e6e1aa..e4c768a 100644 --- a/src/tabviews/custom/components/carousel/data-card/index.jsx +++ b/src/tabviews/custom/components/carousel/data-card/index.jsx @@ -92,7 +92,7 @@ componentDidMount () { MKEmitter.addListener('resetSelectLine', this.resetParentParam) - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -117,12 +117,10 @@ }) this.setState({sync: false, data: _data}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -131,7 +129,7 @@ return } MKEmitter.removeListener('resetSelectLine', this.resetParentParam) - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -174,15 +172,15 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { mainSearch } = this.props const { arr_field, config } = this.state if (config.uuid !== menuId) return - let searches = mainSearch ? fromJS(mainSearch).toJS() : [] + let searches = config.setting.useMSearch && mainSearch ? fromJS(mainSearch).toJS() : [] - MKEmitter.emit('execExcelout', config.uuid, btnId, { + MKEmitter.emit('returnModuleParam', config.uuid, btnId, { arr_field: arr_field, orderBy: config.setting.order || '', search: searches, @@ -202,7 +200,11 @@ return } - let searches = mainSearch ? fromJS(mainSearch).toJS() : [] + let searches = config.setting.useMSearch && mainSearch ? fromJS(mainSearch).toJS() : [] + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return + } this.setState({ loading: true @@ -315,7 +317,7 @@ const { config, loading, data, card } = this.state return ( - <div className="custom-data-carousel-box" style={{...config.style, minHeight: config.wrap.minHeight}}> + <div className="custom-data-carousel-box" style={config.style}> {loading ? <div className="loading-mask"> {data ? <div className="ant-spin-blur"></div> : null} diff --git a/src/tabviews/custom/components/carousel/data-card/index.scss b/src/tabviews/custom/components/carousel/data-card/index.scss index 15319b2..eabde18 100644 --- a/src/tabviews/custom/components/carousel/data-card/index.scss +++ b/src/tabviews/custom/components/carousel/data-card/index.scss @@ -4,6 +4,7 @@ background-repeat: no-repeat; background-size: cover; min-height: 30px; + overflow: hidden; .card-item-box { background-position: center center; diff --git a/src/tabviews/custom/components/carousel/prop-card/index.jsx b/src/tabviews/custom/components/carousel/prop-card/index.jsx index d519d08..8402eb6 100644 --- a/src/tabviews/custom/components/carousel/prop-card/index.jsx +++ b/src/tabviews/custom/components/carousel/prop-card/index.jsx @@ -133,12 +133,10 @@ } this.setState({sync: false, data: _data}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.wrap.datatype !== 'static' && config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -192,26 +190,21 @@ if (config.wrap.datatype === 'static') { this.setState({ - data: {$$BID: BID || ''}, - loading: false + data: {$$BID: BID || ''} }) return } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� this.setState({ - data: {$$BID: BID || ''}, - loading: false + data: {$$BID: BID || ''} }) return } - let searches = [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 - let keys = searches.map(item => item.key) - mainSearch.forEach(item => { - if (!keys.includes(item.key)) { - searches.push(item) - } - }) + let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } this.setState({ diff --git a/src/tabviews/custom/components/carousel/prop-card/index.scss b/src/tabviews/custom/components/carousel/prop-card/index.scss index b5e46e6..68b6eb3 100644 --- a/src/tabviews/custom/components/carousel/prop-card/index.scss +++ b/src/tabviews/custom/components/carousel/prop-card/index.scss @@ -5,6 +5,7 @@ background-size: cover; min-height: 30px; position: relative; + overflow: hidden; .card-item-box { position: relative; diff --git a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx index 01878f0..f279ed3 100644 --- a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx +++ b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx @@ -2,9 +2,8 @@ import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' import { Chart } from '@antv/g2' -import { connect } from 'react-redux' import DataSet from '@antv/data-set' -import { Spin, Empty, Select, notification } from 'antd' +import { Spin, Empty, notification } from 'antd' import moment from 'moment' import asyncComponent from './asyncButtonComponent' @@ -12,7 +11,6 @@ import Api from '@/api' import Utils from '@/utils/utils.js' import UtilsDM from '@/utils/utils-datamanage.js' -import { modifyTabview } from '@/store/action' import MKEmitter from '@/utils/events.js' import './index.scss' @@ -42,9 +40,6 @@ search: null, // 鎼滅储鏉′欢 vFields: [], // 鏁板�煎瓧娈� vstFields: null, // 缁熻鏁版嵁鍊煎瓧娈典俊鎭� - chartData: [], // 鍥捐〃鏁版嵁 - chartFields: [], // 缁熻鍥捐〃鐢熸垚瀛楁闆� - selectFields: [], // 缁熻鍥捐〃閫夋嫨瀛楁 } UNSAFE_componentWillMount () { @@ -65,6 +60,7 @@ let vstFields = null if (_config.plot.datatype === 'statistics') { + _config.plot.enabled = 'false' let _column = _config.columns.filter(col => _config.plot.InfoValue === col.field)[0] if (_column) { let decimal = 0 @@ -98,17 +94,22 @@ }) } - if (config.plot.title || config.search.length > 0) { - _config.plot.height = _config.plot.height - 80 - } else { - _config.plot.height = _config.plot.height - 30 + let padding = 0 + if (_config.style.paddingTop && !isNaN(parseInt(_config.style.paddingTop))) { + padding += parseInt(_config.style.paddingTop) + } + if (_config.style.paddingBottom && !isNaN(parseInt(_config.style.paddingBottom))) { + padding += parseInt(_config.style.paddingBottom) } - if (_config.style) { - _config.style = {..._config.style, minHeight: (config.plot.height || 400)} + let height = config.plot.height || 400 + if (config.plot.title || config.search.length > 0) { + _config.plot.height = height - 70 - padding } else { - _config.style = {minHeight: (config.plot.height || 400)} + _config.plot.height = height - 25 - padding } + + _config.style.height = height let transfield = {} _config.columns.forEach(col => { @@ -117,51 +118,180 @@ } }) - _config.plot.color = _config.plot.color || 'rgba(0, 0, 0, 0.85)' + _config.plot.color = _config.plot.color || 'rgba(0, 0, 0, 0.65)' + let bars = {} if (_config.plot.enabled === 'true' && _config.plot.customs && _config.plot.customs.length > 0) { - let colors = new Map() + let Bar_axis = [] + _config.plot.customs = _config.plot.customs.map(item => { + item.name = transfield[item.type] || item.type + item.chartType = item.shape ? (item.shape[0] || 'bar') : 'bar' + item.shape = item.shape ? (item.shape[1] || '') : '' + + if (item.chartType === 'bar') { + bars[item.type] = true + Bar_axis.push(item.type) + } + + return item + }) + + _config.plot.hasBar = Bar_axis.length > 0 + + if (_config.plot.mutilBar !== 'overlap') { + _config.plot.Bar_axis = Bar_axis + } + } else { + _config.plot.enabled = 'false' + } + + let colors = new Map() + + if (_config.plot.colors && _config.plot.colors.length > 0) { // 棰滆壊璁剧疆 + if (_config.plot.datatype === 'statistics') { + if (_config.plot.ramp === 'true') { + let _s = 'l(0) ' + if (_config.plot.chartType === 'bar' || (_config.plot.chartType === 'line' && _config.plot.rampDirection === 'vertical')) { + _s = 'l(90) ' + } + _config.plot.colors.forEach(item => { + if (!colors.has(item.type)) { + colors.set(item.type, _s + `0:${item.color} 1:${item.color1}`) + } + }) + } else { + _config.plot.colors.forEach(item => { + if (!colors.has(item.type)) { + colors.set(item.type, item.color) + } + }) + } + } else if (_config.plot.enabled === 'true') { + if (_config.plot.ramp === 'true') { + _config.plot.colors.forEach(item => { + let _type = transfield[item.type] || item.type + if (!colors.has(_type)) { + if (bars[item.type]) { + colors.set(_type, `l(90) 0:${item.color} 1:${item.color1}` ) + } else { + colors.set(_type, `l(0) 0:${item.color} 1:${item.color1}` ) + } + } + }) + } else { + _config.plot.colors.forEach(item => { + let _type = transfield[item.type] || item.type + if (!colors.has(_type)) { + colors.set(_type, item.color) + } + }) + } + } else { + if (_config.plot.ramp === 'true') { + let _s = 'l(0) ' + if (_config.plot.chartType === 'bar' || (_config.plot.chartType === 'line' && _config.plot.rampDirection === 'vertical')) { + _s = 'l(90) ' + } + _config.plot.colors.forEach(item => { + if (!transfield[item.type]) return + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], _s + `0:${item.color} 1:${item.color1}` ) + } + }) + } else { + _config.plot.colors.forEach(item => { + if (!transfield[item.type]) return + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], item.color) + } + }) + } + } + _config.plot.$colors = colors + } + + let xc = {label: { + formatter: (val) => { + if (!val || /^\s*$/.test(val)) return val + let _val = `${val}` + if (_val.length <= 11) return val + return _val.substring(0, 8) + '...' + }, + style: { fill: _config.plot.color } + }} + let yc = {label: { style: { fill: _config.plot.color } }} + if (_config.plot.grid === 'hidden') { + yc.grid = null + } + if (_config.plot.y_line === 'show') { + yc.line = {style: { stroke: '#D1D2CE' }} + } + if (_config.plot.lineColor) { + xc.tickLine = {style: { stroke: _config.plot.lineColor }} + xc.line = { style: { stroke: _config.plot.lineColor } } + if (yc.grid !== null) { + yc.grid = { line: { style: { stroke: _config.plot.lineColor } }} + } + if (yc.line) { + yc.line = { style: { stroke: _config.plot.lineColor } } + } + } + + _config.plot.$xc = xc + _config.plot.$yc = yc + + _config.plot.$paddingLeft = 30 + _config.plot.$paddingRight = 30 + + if (_config.plot.enabled === 'true') { let colorIndex = 0 let limit = chartColors.length - - if (_config.plot.colors && _config.plot.colors.length > 0) { - _config.plot.colors.forEach(item => { - if (!colors.has(item.type)) { - colors.set(item.type, item.color) - } - }) - } - let axisIndex = 0 - let hasBar = false let fields = [] let legends = [] _config.plot.customs.forEach(item => { - item.name = transfield[item.type] || item.type - item.chartType = item.shape ? (item.shape[0] || 'bar') : 'bar' - item.shape = item.shape ? (item.shape[1] || '') : '' - - if (colors.get(item.type)) { - item.color = colors.get(item.type) + if (colors.has(item.name)) { + item.color = colors.get(item.name) } else { item.color = chartColors[colorIndex % limit] colorIndex++ } - if (item.chartType === 'bar' && !hasBar) { - hasBar = true - } else if (item.chartType === 'bar') { - item.chartType = 'line' - item.shape = 'smooth' - } - if (item.axis === 'true' && axisIndex < 2) { if (axisIndex === 0) { - item.axis = { grid: {style: { fill: _config.plot.color }}, title: { style: { fill: _config.plot.color } }, label: {style: { fill: _config.plot.color }} } + item.axis = { label: {style: { fill: _config.plot.color }} } + if (item.title !== 'false') { + item.axis.title = { style: { fill: _config.plot.color } } + _config.plot.$paddingLeft = 50 + } + if (_config.plot.grid === 'hidden') { + item.axis.grid = null + } + if (_config.plot.y_line === 'show') { + item.axis.line = {style: { stroke: '#D1D2CE' }} + } + if (_config.plot.lineColor) { + if (item.axis.grid !== null) { + item.axis.grid = { line: { style: { stroke: _config.plot.lineColor } }} + } + if (item.axis.line) { + item.axis.line = { style: { stroke: _config.plot.lineColor } } + } + } fields.unshift(item) } else { - item.axis = { grid: null, title: {style: { fill: _config.plot.color }}, label: {style: { fill: _config.plot.color }} } + item.axis = { grid: null, label: {style: { fill: _config.plot.color }} } + if (item.title !== 'false') { + item.axis.title = { style: { fill: _config.plot.color } } + _config.plot.$paddingRight = 60 + } + if (_config.plot.y_line === 'show') { + item.axis.line = {style: { stroke: '#D1D2CE' }} + } + if (_config.plot.lineColor && item.axis.line) { + item.axis.line = { style: { stroke: _config.plot.lineColor } } + } fields.splice(1, 0, item) } axisIndex++ @@ -179,9 +309,7 @@ }) _config.plot.customs = fields _config.plot.legends = legends - _config.plot.hasBar = hasBar - } else { - _config.plot.enabled = 'false' + _config.plot.axisIndex = axisIndex } this.setState({ @@ -219,12 +347,10 @@ this.setState({sync: false, data: _data}, () => { this.handleData() }) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -235,7 +361,7 @@ componentDidMount () { MKEmitter.addListener('reloadData', this.reloadData) MKEmitter.addListener('resetSelectLine', this.resetParentParam) - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) this.handleTimer() } @@ -250,7 +376,7 @@ } MKEmitter.removeListener('reloadData', this.reloadData) MKEmitter.removeListener('resetSelectLine', this.resetParentParam) - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -259,16 +385,7 @@ if (!config.timer) return - const _change = { - '15s': 15000, - '30s': 30000, - '1min': 60000, - '5min': 300000, - '10min': 600000, - '15min': 900000, - '30min': 1800000, - '1hour': 3600000 - } + const _change = { '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } let timer = _change[config.timer] @@ -360,14 +477,14 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { mainSearch } = this.props const { arr_field, config, search } = this.state if (config.uuid !== menuId) return let searches = search ? fromJS(search).toJS() : [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { @@ -376,7 +493,7 @@ }) } - MKEmitter.emit('execExcelout', config.uuid, btnId, { + MKEmitter.emit('returnModuleParam', config.uuid, btnId, { arr_field: arr_field, orderBy: config.setting.order || '', search: searches, @@ -401,13 +518,18 @@ } let searches = search ? fromJS(search).toJS() : [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key) mainSearch.forEach(item => { if (!keys.includes(item.key)) { searches.push(item) } }) + } + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } if (!hastimer) { @@ -444,29 +566,11 @@ * @description 鏁版嵁棰勫鐞嗭紝缁熻鏁版嵁闇�瑕侀噸缃� */ handleData = () => { - const { data, plot } = this.state - - if (plot.datatype === 'statistics') { - let result = this.getStaticMsg(data) - - this.setState({ - chartData: result.data, - chartFields: result.chartFields, - selectFields: result.selectFields - }, () => { - let _element = document.getElementById(this.state.chartId) - if (_element) { - _element.innerHTML = '' - } - this.viewrender() - }) - } else { - let _element = document.getElementById(this.state.chartId) - if (_element) { - _element.innerHTML = '' - } - this.viewrender() + let _element = document.getElementById(this.state.chartId) + if (_element) { + _element.innerHTML = '' } + this.viewrender() } /** @@ -476,9 +580,9 @@ * 3銆佹煴鐘跺浘鏁版嵁琛ラ綈 */ getdata = () => { - const { data, plot, vFields } = this.state + const { data, plot, vFields, config } = this.state - if (!data) { + if (!data || data.length === 0) { this.setState({empty: true}) return [] } @@ -489,6 +593,8 @@ if (plot.repeat === 'average') { let _mdata = new Map() _cdata.forEach(item => { + if (!item[plot.Xaxis]) return + vFields.forEach(col => { if (typeof(item[col.field]) !== 'number') { item[col.field] = parseFloat(item[col.field]) @@ -501,10 +607,15 @@ } }) - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { + // dodge is not support linear attribute, please use category attribute! 鏃堕棿鏍煎紡 + if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { + item[plot.Xaxis] = ' ' + item[plot.Xaxis] + } + + if (!_mdata.has(item[plot.Xaxis])) { item.$count = 1 _mdata.set(item[plot.Xaxis], item) - } else if (item[plot.Xaxis]) { + } else { let _item = _mdata.get(item[plot.Xaxis]) _item.$count++ vFields.forEach(col => { @@ -521,11 +632,14 @@ item[col.field] = item[col.field].toFixed(col.decimal) item[col.field] = +item[col.field] }) + item.$$uuid = item[config.setting.primaryKey] || '' return item }) } else if (plot.repeat === 'cumsum') { let _mdata = new Map() _cdata.forEach(item => { + if (!item[plot.Xaxis]) return + vFields.forEach(col => { if (typeof(item[col.field]) !== 'number') { item[col.field] = parseFloat(item[col.field]) @@ -538,9 +652,13 @@ } }) - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { + if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { + item[plot.Xaxis] = ' ' + item[plot.Xaxis] + } + + if (!_mdata.has(item[plot.Xaxis])) { _mdata.set(item[plot.Xaxis], item) - } else if (item[plot.Xaxis]) { + } else { let _item = _mdata.get(item[plot.Xaxis]) vFields.forEach(col => { _item[col.field] += item[col.field] @@ -555,12 +673,19 @@ item[col.field] = item[col.field].toFixed(col.decimal) item[col.field] = +item[col.field] }) + item.$$uuid = item[config.setting.primaryKey] || '' return item }) } else { // plot.repeat === 'unrepeat' let _mdata = new Map() _cdata.forEach(item => { - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { + if (!item[plot.Xaxis]) return + + if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { + item[plot.Xaxis] = ' ' + item[plot.Xaxis] + } + + if (!_mdata.has(item[plot.Xaxis])) { vFields.forEach(col => { if (typeof(item[col.field]) !== 'number') { item[col.field] = parseFloat(item[col.field]) @@ -574,6 +699,8 @@ item[col.field] = item[col.field].toFixed(col.decimal) item[col.field] = +item[col.field] }) + + item.$$uuid = item[config.setting.primaryKey] || '' _mdata.set(item[plot.Xaxis], item) } }) @@ -586,36 +713,34 @@ } /** - * @description 缁熻鏁版嵁棰勫鐞嗭紝鍔ㄦ�佺敓鎴愮粺璁″瓧娈靛苟杩涜鏁版嵁杞崲 + * @description 缁熻鏁版嵁棰勫鐞� */ - getStaticMsg = (data) => { - const { plot, vstFields } = this.state + getStaticMsg = () => { + const { plot, vstFields, data } = this.state let percent = false - let decimal = 0 + let decimal = vstFields ? vstFields.decimal : 0 if (plot.show === 'percent') { percent = true } - if (vstFields) { - decimal = vstFields.decimal - } - if (!data) { + if (!data || data.length === 0) { this.setState({empty: true}) - return {data: [], chartFields: [], selectFields: []} + return [] } let _data = [] let _cdata = fromJS(data).toJS() - let _chartFields = [] - let _selectFields = [] if (plot.repeat === 'average') { let _mdata = new Map() _cdata.forEach(item => { if (!item[plot.InfoType] || !item[plot.Xaxis]) return - _chartFields.push(item[plot.InfoType]) + + if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { + item[plot.Xaxis] = ' ' + item[plot.Xaxis] + } item.$uuid = item[plot.InfoType] + item[plot.Xaxis] if (typeof(item[plot.InfoValue]) !== 'number') { @@ -651,7 +776,10 @@ let _mdata = new Map() _cdata.forEach(item => { if (!item[plot.InfoType] || !item[plot.Xaxis]) return - _chartFields.push(item[plot.InfoType]) + + if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { + item[plot.Xaxis] = ' ' + item[plot.Xaxis] + } item.$uuid = item[plot.InfoType] + item[plot.Xaxis] @@ -685,7 +813,10 @@ let _mdata = new Map() _cdata.forEach(item => { if (!item[plot.InfoType] || !item[plot.Xaxis]) return - _chartFields.push(item[plot.InfoType]) + + if (/^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(item[plot.Xaxis])) { + item[plot.Xaxis] = ' ' + item[plot.Xaxis] + } item.$uuid = item[plot.InfoType] + item[plot.Xaxis] @@ -710,31 +841,8 @@ _data = [..._mdata.values()] } - _chartFields = Array.from(new Set(_chartFields)) - - if (plot.InfoDefNumber >= _chartFields.length) { - _selectFields = _chartFields - } else { - _selectFields = _chartFields.slice(0, plot.InfoDefNumber) - } - - return {data: _data, chartFields: _chartFields, selectFields: _selectFields} - } - - /** - * @description 鑾峰彇缁熻鍥捐〃灞曠ず鏁版嵁锛岄�氳繃閫夋嫨绫诲瀷绛涢�� - */ - getStaticData = () => { - const { plot, chartData, chartFields, selectFields } = this.state - - let _data = [] - if (selectFields.length === chartFields.length) { - _data = chartData - } else { - _data = chartData.filter(item => selectFields.includes(item[plot.InfoType])) - } - this.setState({empty: _data.length === 0}) + return _data } @@ -760,37 +868,19 @@ let _data = [] let _valfield = 'value' let _typefield = 'key' - - let colors = new Map() let colorIndex = 0 if (plot.datatype === 'statistics') { _valfield = plot.InfoValue _typefield = plot.InfoType - if (plot.colors && plot.colors.length > 0) { // 棰滆壊璁剧疆 - plot.colors.forEach(item => { - if (!colors.has(item.type)) { - colors.set(item.type, item.color) - } - }) - } - - _data = this.getStaticData() + _data = this.getStaticMsg() } else { let data = this.getdata() if (plot.enabled === 'true') { this.customrender(data) return - } - - if (plot.colors && plot.colors.length > 0) { // 棰滆壊璁剧疆 - plot.colors.forEach(item => { - if (!colors.has(transfield[item.type])) { - colors.set(transfield[item.type], item.color) - } - }) } const ds = new DataSet() @@ -820,7 +910,7 @@ const chart = new Chart({ container: this.state.chartId, autoFit: true, - height: plot.height || 400 + height: plot.height }) chart.data(_data) @@ -830,25 +920,22 @@ range: [0, 1] }) } - chart.scale(_valfield, { + + let c = { nice: true, - range: [0, 0.93] - }) - - // 鍧愭爣杞存牸寮忓寲 - chart.axis(plot.Xaxis, { - label: { - formatter: (val) => { - if (!val || /^\s*$/.test(val)) return val - let _val = `${val}` - if (_val.length <= 11) return val - return _val.substring(0, 8) + '...' - }, - style: { fill: plot.color } - }, - line: { style: { fill: plot.color } } - }) - chart.axis(_valfield, { grid: { style: { fill: plot.color } }, label: { style: { fill: plot.color } } }) + range: [0, 0.9] + } + + if (plot.min || plot.min === 0) { + c.min = plot.min + } + if (plot.max || plot.max === 0) { + c.max = plot.max + } + chart.scale(_valfield, c) + + chart.axis(plot.Xaxis, plot.$xc) + chart.axis(_valfield, plot.$yc) if (!plot.legend || plot.legend === 'hidden') { chart.legend(false) @@ -889,20 +976,23 @@ } }) - if (plot.colors && plot.colors.length > 0) { + if (plot.$colors) { let limit = chartColors.length _chart.color(_typefield, (key) => { - if (colors.get(key)) { - return colors.get(key) + if (plot.$colors.has(key)) { + if (plot.area === 'true' && plot.rampDirection === 'vertical') { + return plot.$colors.get(key).replace(/l\(9?0\) 0:|\s1:.*/ig, '') + } + return plot.$colors.get(key) } else { - colors.set(key, chartColors[colorIndex % limit]) colorIndex++ + return chartColors[(colorIndex - 1) % limit] } }) } else { _chart.color(_typefield) } - if (plot.label === 'true') { + if (plot.label !== 'false') { _chart.label(_valfield, (value) => { if (plot.show === 'percent') { value = value + '%' @@ -916,28 +1006,57 @@ }) } - if (plot.point === 'true' && plot.colors && plot.colors.length > 0) { - let limit = chartColors.length - chart + if (plot.point === 'true') { + let _chart = chart .point() .position(`${plot.Xaxis}*${_valfield}`) - .color(_typefield, (key) => { - if (colors.get(key)) { - return colors.get(key) + .size(3) + .shape('circle') + + if (plot.$colors) { + let limit = chartColors.length + _chart.color(_typefield, (key) => { + if (plot.$colors.has(key)) { + return plot.$colors.get(key) } else { - colors.set(key, chartColors[colorIndex % limit]) colorIndex++ + return chartColors[(colorIndex - 1) % limit] } }) - .size(3) - .shape('circle') - } else if (plot.point === 'true') { - chart - .point() + } else { + _chart.color(_typefield) + } + } + + if (plot.area === 'true') { + let area = chart + .area() + // .shape(plot.shape || 'smooth') .position(`${plot.Xaxis}*${_valfield}`) - .color(_typefield) - .size(3) - .shape('circle') + .tooltip(false) + + if (plot.shape === 'smooth') { + area.shape('smooth') + } + if (plot.$colors) { + let limit = chartColors.length + area.color(_typefield, (key) => { + if (plot.$colors.has(key)) { + return plot.$colors.get(key) + } else { + colorIndex++ + return chartColors[(colorIndex - 1) % limit] + } + }) + } else { + area.color(_typefield) + } + } + + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) } chart.render() @@ -947,9 +1066,10 @@ * @description 鑷畾涔夋覆鏌� */ customrender = (data) => { - const { plot } = this.state + const { plot, transfield } = this.state const ds = new DataSet() const dv = ds.createView().source(data) + dv.transform({ type: 'map', callback(row) { @@ -960,46 +1080,26 @@ } }) + let padding = [10, 30, 30, 30] + + if (!plot.Bar_axis) { + padding = [10, plot.$paddingRight, 30, plot.$paddingLeft] + } + const chart = new Chart({ container: this.state.chartId, autoFit: true, - height: plot.height || 400 + height: plot.height }) - - let _data = dv.rows - // dodge is not support linear attribute, please use category attribute! 鏃堕棿鏍煎紡 - if (_data[0] && _data[0][plot.Xaxis] && /^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(_data[0][plot.Xaxis])) { - for (let i = 1; i < 12; i++) { - if (_data[i] && _data[i][plot.Xaxis] === _data[0][plot.Xaxis]) { - _data[i][plot.Xaxis] += ' ' - } else { - break; - } - } - _data[0][plot.Xaxis] += ' ' - } - - chart.data(_data) + + // 鍧愭爣杞存牸寮忓寲 + chart.axis(plot.Xaxis, plot.$xc) if (!plot.hasBar) { chart.scale(plot.Xaxis, { range: [0, 1] }) } - - // 鍧愭爣杞存牸寮忓寲 - chart.axis(plot.Xaxis, { - label: { - formatter: (val) => { - if (!val || /^\s*$/.test(val)) return val - let _val = `${val}` - if (_val.length <= 11) return val - return _val.substring(0, 8) + '...' - }, - style: { fill: plot.color } - }, - line: { style: { fill: plot.color } } - }) if (!plot.legend || plot.legend === 'hidden') { chart.legend(false) @@ -1020,16 +1120,215 @@ }) } - plot.customs.forEach((item, i) => { - chart.axis(item.name, item.axis) - - chart.scale(item.name, { - nice: true, - range: [0, 0.93] + chart.scale({ + nice: true + }) + + let lablecfg = { + position: 'top', + offset: 2, + style: { + fill: '#fff' + } + } + + if (plot.label === 'top') { + lablecfg.offset = -5 + lablecfg.style.textBaseline = 'top' + } else if (plot.label === 'middle') { + lablecfg.position = 'middle' + lablecfg.offset = 0 + } else if (plot.label === 'bottom') { + lablecfg.position = 'bottom' + lablecfg.offset = 0 + } else if (plot.label === 'true') { + lablecfg.style.fill = plot.color + } + + if (plot.Bar_axis) { + const view1 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + const dst = new DataSet() + const dvt = dst.createView().source(data) + + dvt.transform({ + type: 'fold', + fields: [...plot.Bar_axis], + key: 'key', + value: 'value' + }) + + dvt.transform({ + type: 'map', + callback(row) { + row.key = transfield[row.key] || row.key + return row + }, }) - if (item.chartType === 'bar') { - let _chart = chart + view1.data(dvt.rows) + + let c = { + nice: true, + range: [0, 0.9] + } + + if (plot.min || plot.min === 0) { + c.min = plot.min + } + if (plot.max || plot.max === 0) { + c.max = plot.max + } + view1.scale('value', c) + view1.axis('value', plot.$yc) + + view1.legend(false) + + let colorIndex = 0 + + if (plot.adjust !== 'stack') { + let _chart = view1 + .interval() + .position(`${plot.Xaxis}*value`) + .adjust([ + { + type: 'dodge', + marginRatio: 0 + } + ]) + .shape(plot.shape || 'rect') + .tooltip(`${plot.Xaxis}*value*key`, (name, value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: key, + value: value + } + }) + + if (plot.$colors) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (plot.$colors.has(key)) { + return plot.$colors.get(key) + } else { + colorIndex++ + return chartColors[(colorIndex - 1) % limit] + } + }) + } else { + _chart.color('key') + } + if (plot.label !== 'false') { + _chart.label('value*key', (value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + + if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { + lablecfg.style.fill = plot.$colors.get(key) + } + return { + content: value, + ...lablecfg + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } else if (plot.adjust === 'stack') { + let _chart = view1 + .interval() + .position(`${plot.Xaxis}*value`) + .adjust('stack') + .shape(plot.shape || 'rect') + .tooltip(`${plot.Xaxis}*value*key`, (name, value, type) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: type, + value: value + } + }) + + if (plot.$colors) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (plot.$colors.has(key)) { + return plot.$colors.get(key) + } else { + colorIndex++ + return chartColors[(colorIndex - 1) % limit] + } + }) + } else { + _chart.color('key') + } + if (plot.label !== 'false') { + _chart.label('value*key', (value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { + lablecfg.style.fill = plot.$colors.get(key) + } + return { + content: value, + ...lablecfg + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } + } + + const view2 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + + view2.data(dv.rows) + view2.legend(false) + + plot.customs.forEach((item, i) => { + if (item.chartType === 'bar' && !plot.Bar_axis) { + view2.axis(item.name, item.axis) + + let c = { + nice: true, + range: [0, 0.9] + } + + if (item.min || item.min === 0) { + c.min = item.min + } + if (item.max || item.max === 0) { + c.max = item.max + } + + view2.scale(item.name, c) + let _chart = view2 .interval() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) @@ -1044,21 +1343,43 @@ if (plot.barSize) { _chart.size(plot.barSize || 35) } - if (item.label === 'true') { + if (item.label !== 'false') { _chart.label(item.name, (value) => { if (plot.show === 'percent') { value = value + '%' } + if (plot.label === 'true' && plot.labelColor === 'custom' && item.color) { + lablecfg.style.fill = item.color + } return { content: value, - style: { - fill: plot.color - } + ...lablecfg } }) } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } } else if (item.chartType === 'line') { - let _chart = chart + if (!plot.Bar_axis) { + view2.axis(item.name, item.axis) + } else { + view2.axis(item.name, { grid: null, title: null, label: null }) + } + let c = { + nice: true, + range: [0, 0.9] + } + + if (item.min || item.min === 0) { + c.min = item.min + } + if (item.max || item.max === 0) { + c.max = item.max + } + + view2.scale(item.name, c) + let _chart = view2 .line() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) @@ -1095,6 +1416,14 @@ } }) + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + if (t === 'element-active' || t === 'element-highlight') { + chart.interaction(t) + } + }) + } + chart.render() } @@ -1102,42 +1431,24 @@ * @description 鏌辩姸鍥炬覆鏌� */ barrender = () => { - const { plot, transfield } = this.state + const { plot, transfield, config } = this.state let _data = [] let _valfield = 'value' let _typefield = 'key' - - let colors = new Map() let colorIndex = 0 if (plot.datatype === 'statistics') { _valfield = plot.InfoValue _typefield = plot.InfoType - if (plot.colors && plot.colors.length > 0) { // 棰滆壊璁剧疆 - plot.colors.forEach(item => { - if (!colors.has(item.type)) { - colors.set(item.type, item.color) - } - }) - } - - _data = this.getStaticData() + _data = this.getStaticMsg() } else { let data = this.getdata() if (plot.enabled === 'true') { this.customrender(data) return - } - - if (plot.colors && plot.colors.length > 0) { // 棰滆壊璁剧疆 - plot.colors.forEach(item => { - if (!colors.has(transfield[item.type])) { - colors.set(transfield[item.type], item.color) - } - }) } const ds = new DataSet() @@ -1166,42 +1477,26 @@ const chart = new Chart({ container: this.state.chartId, autoFit: true, - height: plot.height || 400 + height: plot.height }) - - // dodge is not support linear attribute, please use category attribute! 鏃堕棿鏍煎紡 - if (_data[0] && _data[0][plot.Xaxis] && /^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(_data[0][plot.Xaxis])) { - for (let i = 1; i < 12; i++) { - if (_data[i] && _data[i][plot.Xaxis] === _data[0][plot.Xaxis]) { - _data[i][plot.Xaxis] += ' ' - } else { - break; - } - } - _data[0][plot.Xaxis] += ' ' - } chart.data(_data) - chart.scale(_valfield, { + let c = { nice: true, - range: [0, 0.93] - }) + range: [0, 0.9] + } - // 鍧愭爣杞存牸寮忓寲 - chart.axis(plot.Xaxis, { - label: { - formatter: (val) => { - if (!val || /^\s*$/.test(val)) return val - let _val = `${val}` - if (_val.length <= 11) return val - return _val.substring(0, 8) + '...' - }, - style: { fill: plot.color } - }, - line: { style: { fill: plot.color } } - }) - chart.axis(_valfield, { grid: { style: { fill: plot.color } }, label: { style: { fill: plot.color } } }) + if (plot.min || plot.min === 0) { + c.min = plot.min + } + if (plot.max || plot.max === 0) { + c.max = plot.max + } + chart.scale(_valfield, c) + + chart.axis(plot.Xaxis, plot.$xc) + chart.axis(_valfield, plot.$yc) if (!plot.legend || plot.legend === 'hidden') { chart.legend(false) @@ -1221,8 +1516,44 @@ }) } + let lablecfg = { + position: 'top', + offset: 2, + style: { + fill: '#fff' + } + } + + if (plot.label === 'top') { + lablecfg.offset = -5 + lablecfg.style.textBaseline = 'top' + } else if (plot.label === 'middle') { + lablecfg.position = 'middle' + lablecfg.offset = 0 + } else if (plot.label === 'bottom') { + lablecfg.position = 'bottom' + lablecfg.offset = 0 + } else if (plot.label === 'true') { + lablecfg.style.fill = plot.color + } + if (plot.transpose === 'true') { chart.coordinate().transpose() + if (plot.label === 'top') { + delete lablecfg.style.textBaseline + lablecfg.position = 'right' + lablecfg.offset = -3 + lablecfg.style.textAlign = 'end' + } else if (plot.label === 'middle') { + lablecfg.position = 'middle' + lablecfg.offset = 0 + } else if (plot.label === 'bottom') { + lablecfg.position = 'left' + lablecfg.offset = 2 + } else if (plot.label === 'true') { + lablecfg.position = 'right' + lablecfg.offset = 2 + } } if (plot.coordinate === 'polar') { @@ -1250,35 +1581,50 @@ } }) - if (plot.colors && plot.colors.length > 0) { + if (plot.$colors) { let limit = chartColors.length _chart.color(_typefield, (key) => { - if (colors.get(key)) { - return colors.get(key) + if (plot.$colors.has(key)) { + return plot.$colors.get(key) } else { - colors.set(key, chartColors[colorIndex % limit]) colorIndex++ + return chartColors[(colorIndex - 1) % limit] } }) } else { _chart.color(_typefield) } - if (plot.label === 'true') { - _chart.label(_valfield, (value) => { + if (plot.label !== 'false') { + _chart.label(`${_valfield}*${_typefield}`, (value, key) => { if (plot.show === 'percent') { value = value + '%' } + + if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { + lablecfg.style.fill = plot.$colors.get(key) + } + return { content: value, - style: { - fill: plot.color - } + ...lablecfg } }) } if (plot.barSize || plot.correction) { _chart.size(plot.barSize || 35) + } + if (plot.selectColor) { + _chart.state({ + selected: { + style: { + fill: plot.selectColor, + } + } + }) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) } } else if (plot.adjust === 'stack') { let _chart = chart @@ -1293,29 +1639,32 @@ } }) - if (plot.colors && plot.colors.length > 0) { + if (plot.$colors) { let limit = chartColors.length _chart.color(_typefield, (key) => { - if (colors.get(key)) { - return colors.get(key) + if (plot.$colors.has(key)) { + return plot.$colors.get(key) } else { - colors.set(key, chartColors[colorIndex % limit]) colorIndex++ + return chartColors[(colorIndex - 1) % limit] } }) } else { _chart.color(_typefield) } - if (plot.label === 'true') { - _chart.label(_valfield, (value) => { + if (plot.label !== 'false') { + _chart.label(`${_valfield}*${_typefield}`, (value, key) => { if (plot.show === 'percent') { value = value + '%' } + + if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { + lablecfg.style.fill = plot.$colors.get(key) + } + return { content: value, - style: { - fill: plot.color - } + ...lablecfg } }) } @@ -1323,70 +1672,32 @@ if (plot.barSize || plot.correction) { _chart.size(plot.barSize || 35) } - } - - if (plot.linkmenu && plot.linkmenu.length > 0) { - let menu_id = plot.linkmenu.slice(-1)[0] - let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || '' - - chart.on('element:dblclick', (ev) => { - if (!menu) { - notification.warning({ - top: 92, - message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�', - duration: 5 - }) - return - } - - try { - let data = ev.data.data - let primaryId = '' - if (this.state.config.setting.primaryKey && data) { - primaryId = data[this.state.config.setting.primaryKey] || '' - } - - let newtab = { - ...menu, - selected: true, - param: { - $BID: primaryId + if (plot.selectColor) { + _chart.state({ + selected: { + style: { + fill: plot.selectColor, } } - - let tabs = this.props.tabviews.filter(tab => { - tab.selected = false - return tab.MenuID !== newtab.MenuID - }) - - if (this.props.tabviews.length > tabs.length) { - this.props.modifyTabview(fromJS(tabs).toJS()) - } - - this.setState({}, () => { - tabs.push(newtab) - this.props.modifyTabview(tabs) - }) - } catch { - console.warn('鑿滃崟鎵撳紑澶辫触锛�') - } + }) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } + + chart.on('element:click', (ev) => { + let data = ev.data.data + MKEmitter.emit('resetSelectLine', config.uuid, (data ? data.$$uuid : ''), null) + }) + + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) }) } chart.render() - } - - /** - * @description 缁熻鍥捐〃锛岀粺璁$被鍨嬪垏鎹� - */ - handleChange = (val) => { - this.setState({selectFields: val}, () => { - let _element = document.getElementById(this.state.chartId) - if (_element) { - _element.innerHTML = '' - } - this.viewrender() - }) } refreshSearch = (list) => { @@ -1396,7 +1707,7 @@ } render() { - const { config, loading, plot, empty, chartFields, selectFields, BID } = this.state + const { config, loading, empty, BID } = this.state return ( <div className="custom-line-chart-plot-box" style={config.style}> @@ -1432,19 +1743,8 @@ ) } })} - {plot.datatype === 'statistics' && chartFields.length > 0 ? <Select - mode="multiple" - showSearch - showArrow={true} - value={selectFields} - onChange={this.handleChange} - maxTagCount={0} - maxTagPlaceholder={(option) => <div className="type-label">{option.join('銆�')}</div>} - > - {chartFields.map((item, i) => <Select.Option key={i} value={item}>{item}</Select.Option>)} - </Select> : null} </div> - <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div> + <div className={'canvas' + (empty ? ' empty' : '')} style={{height: config.plot.height + 25}} id={this.state.chartId}></div> </div> {empty ? <Empty description={false}/> : null} </div> @@ -1452,17 +1752,4 @@ } } -const mapStateToProps = (state) => { - return { - tabviews: state.tabviews, - permMenus: state.permMenus, - } -} - -const mapDispatchToProps = (dispatch) => { - return { - modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews)) - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(LineChart) \ No newline at end of file +export default LineChart \ No newline at end of file diff --git a/src/tabviews/custom/components/chart/antv-bar-line/index.scss b/src/tabviews/custom/components/chart/antv-bar-line/index.scss index cd9f4ce..714a088 100644 --- a/src/tabviews/custom/components/chart/antv-bar-line/index.scss +++ b/src/tabviews/custom/components/chart/antv-bar-line/index.scss @@ -9,6 +9,7 @@ .canvas-wrap { margin: 0 0px; position: relative; + min-height: calc(100% - 45px); .chart-action { position: absolute; top: 0px; @@ -22,7 +23,7 @@ .canvas { margin: 0; - padding: 20px 15px 15px; + padding: 15px 10px 10px; letter-spacing: 0px; } .canvas.empty { @@ -45,6 +46,10 @@ top: 0; right: 0px; bottom: 0px; + display: flex; + align-items: center; + justify-content: center; + text-align: justify; z-index: 1; .ant-spin-blur { @@ -53,47 +58,6 @@ height: 100%; opacity: 0.5; background: #ffffff; - } - } - > .ant-select { - width: 150px; - float: right; - position: relative; - z-index: 1; - .ant-select-selection { - min-height: 24px; - height: 28px; - li { - background: unset; - border: 0; - width: 99%; - padding: 0; - margin-right: 0; - cursor: pointer; - - .type-label { - overflow: hidden; - word-break: break-word; - white-space: nowrap; - text-overflow: ellipsis; - } - } - li + li { - margin-top: 0; - width: 1%; - opacity: 0; - } - } - } - > .ant-select.ant-select-focused { - .ant-select-selection { - li { - width: 50%; - } - li + li { - width: 49%; - opacity: 1; - } } } .g2-tooltip-list{ diff --git a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx new file mode 100644 index 0000000..041e41d --- /dev/null +++ b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx @@ -0,0 +1,618 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Chart, registerShape } from '@antv/g2' +import { Spin, notification } from 'antd' +import moment from 'moment' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import asyncComponent from '@/utils/asyncComponent' +import UtilsDM from '@/utils/utils-datamanage.js' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader')) + +registerShape('point', 'pointer', { + draw(cfg, container) { + const group = container.addGroup({}); + // 鑾峰彇鏋佸潗鏍囩郴涓嬬敾甯冧腑蹇冪偣 + const center = this.parsePoint({ x: 0, y: 0 }); + // 缁樺埗鎸囬拡 + group.addShape('line', { + attrs: { + x1: center.x, + y1: center.y, + x2: cfg.x, + y2: cfg.y, + stroke: cfg.color, + lineWidth: 5, + lineCap: 'round', + }, + }); + group.addShape('circle', { + attrs: { + x: center.x, + y: center.y, + r: 9.75, + stroke: cfg.color, + lineWidth: 4.5, + fill: '#fff', + }, + }); + return group; + }, +}) + +registerShape('point', 'hidden', { + draw(cfg, container) { + return container.addGroup({}) + } +}) + +class DashboardChart extends Component { + static propTpyes = { + BID: PropTypes.any, // 鐖剁骇Id + data: PropTypes.array, // 缁熶竴鏌ヨ鏁版嵁 + config: PropTypes.object, // 缁勪欢閰嶇疆淇℃伅 + mainSearch: PropTypes.any, // 澶栧眰鎼滅储鏉′欢 + menuType: PropTypes.any, // 鑿滃崟绫诲瀷 + } + + state = { + BID: '', // 涓婄骇ID + config: null, // 鍥捐〃閰嶇疆淇℃伅 + loading: false, // 鏁版嵁鍔犺浇鐘舵�� + chartId: Utils.getuuid(), // 鍥捐〃Id + title: '', // 缁勪欢鏍囬 + sync: false, // 鏄惁缁熶竴璇锋眰鏁版嵁 + plot: null, // 鍥捐〃璁剧疆 + data: {}, // 鏁版嵁 + } + + UNSAFE_componentWillMount () { + const { config, data, initdata, BID } = this.props + let _config = fromJS(config).toJS() + + let _data = null + let _sync = _config.setting.sync === 'true' + + if (_sync && data) { + _data = data[config.dataName] || [] + _sync = false + } else if (_sync && initdata) { + _data = initdata || [] + _sync = false + } + + if (_config.subtype === 'ratioboard') { + _data = _data || [] + } else { + if (_data && Array.isArray(_data)) { + _data = _data[0] || {} + } else { + _data = {} + } + } + + let height = config.plot.height || 400 + if (config.plot.title) { + _config.plot.height = height - 75 + } else { + _config.plot.height = height - 30 + } + _config.style.height = height + + this.setState({ + config: _config, + data: _data, + BID: BID || '', + arr_field: _config.columns.map(col => col.field).join(','), + plot: _config.plot, + sync: _sync, + title: config.plot.title + }, () => { + if (config.setting.sync !== 'true' && config.setting.onload === 'true') { + this.loadData() + } else if (config.setting.sync === 'true') { + this.handleData() + } + }) + } + + /** + * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹� + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { sync, config } = this.state + + if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) { + let _data = null + + if (config.subtype === 'ratioboard') { + _data = [] + if (nextProps.data && nextProps.data[config.dataName]) { + _data = nextProps.data[config.dataName] || [] + } + } else { + _data = {} + if (nextProps.data && nextProps.data[config.dataName]) { + _data = nextProps.data[config.dataName] || {} + } + if (_data.hasOwnProperty(config.plot.valueField)) { + _data.value = _data[config.plot.valueField] + } + } + + this.setState({sync: false, data: _data}, () => { + this.handleData() + }) + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('reloadData', this.reloadData) + MKEmitter.addListener('resetSelectLine', this.resetParentParam) + this.handleTimer() + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + clearTimeout(this.timer) + this.setState = () => { + return + } + MKEmitter.removeListener('reloadData', this.reloadData) + MKEmitter.removeListener('resetSelectLine', this.resetParentParam) + } + + handleTimer = () => { + const { config } = this.state + + if (!config.timer) return + + const _change = { '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } + + let timer = _change[config.timer] + + if (!timer) return + + let _param = { + func: 's_get_timers_role', + LText: `select '${window.GLOB.appkey || ''}','${config.uuid}'`, + timer_type: config.timer, + component_id: config.uuid + } + + _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') // 鏃堕棿鎴� + _param.LText = Utils.formatOptions(_param.LText) // 鍏抽敭瀛楃鏇挎崲锛宐ase64鍔犲瘑 + _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp) // md5瀵嗛挜 + + Api.getSystemConfig(_param).then(result => { + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + return + } else if (result.run_type) { + this.setState({timer}) + this.timer = setTimeout(() => { + this.timerTask() + }, timer) + } + }) + } + + timerTask = () => { + const { timer } = this.state + if (!timer) return + + this.loadData(true) + + this.timer = setTimeout(() => { + this.timerTask() + }, timer) + } + + reloadData = (menuId) => { + const { config } = this.state + + if (config.uuid !== menuId) return + + this.loadData() + } + + resetParentParam = (MenuID, id) => { + const { config } = this.state + + if (!config.setting.supModule || config.setting.supModule !== MenuID) return + if (id !== this.state.BID) { + this.setState({ BID: id }, () => { + this.loadData() + }) + } + } + + handleData = () => { + let _element = document.getElementById(this.state.chartId) + if (_element) { + _element.innerHTML = '' + } + this.viewrender() + } + + async loadData (hastimer) { + const { mainSearch, menuType } = this.props + const { config, arr_field, BID } = this.state + + if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� + this.setState({ + data: {} + }, () => { + this.handleData() + }) + return + } + + let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return + } + + if (!hastimer) { + this.setState({ + loading: true + }) + } + + let _orderBy = config.setting.order || '' + let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID, menuType) + + let result = await Api.genericInterface(param) + if (result.status) { + let data = null + if (config.subtype === 'ratioboard') { + data = result.data || [] + } else { + data = {} + if (result.data && result.data[0] && result.data[0].hasOwnProperty(config.plot.valueField)) { + data.value = result.data[0][config.plot.valueField] + } + } + + this.setState({ + data, + loading: false + }, () => { + this.handleData() + }) + } else { + this.setState({ + loading: false, + timer: null + }) + notification.error({ + top: 92, + message: result.message, + duration: 10 + }) + } + } + + viewrender = () => { + const { config } = this.state + if (config.subtype === 'ratioboard') { + this.ratioboardrender() + } else { + this.dashboardrender() + } + } + + getratiodata = () => { + const { data, plot } = this.state + + let colors = {} + if (plot.colors && plot.colors.length > 0) { + plot.colors.forEach(item => { + colors[item.tick] = item.color + }) + } + + return data.map(item => { + let val = +item[plot.valueField] + let type = item[plot.labelField] || '' + if (isNaN(val)) { + val = 0 + } + return { + type: type, + value: val, + $percent: val / plot.maxValue, + $color: colors[type] || '#1890ff' + } + }) + } + + ratioboardrender = () => { + const { plot, chartId } = this.state + const data = this.getratiodata() + + const chart = new Chart({ + container: chartId, + autoFit: true, + height: plot.height, + }) + + chart.data(data) + chart.coordinate('polar', { + startAngle: -Math.PI / 2, + endAngle: 3 * Math.PI / 2, + radius: (plot.radius || 75) / 100 + }) + chart.scale('$percent', { + min: 0, + max: 1, + tickInterval: 1, + }) + chart.axis(false) + chart.facet('rect', { + fields: ['type'], + showTitle: false, + eachView: function eachView(view, facet) { + const data = facet.data[0] + + view.point().position('').shape('hidden') + + view.annotation().arc({ + top: false, + start: [0, 1], + end: [0.9999, 1], + style: { + stroke: plot.backColor, + lineWidth: 10 + } + }) + + let _tick = data.$percent + if (_tick >= 1) { + _tick = 0.9999 + } + + view.annotation().arc({ + start: [0, 1], + end: [_tick, 1], + style: { + stroke: data.$color, + lineWidth: 10, + } + }) + // 浠〃鐩樹俊鎭� + let text = '' + if (plot.percent === 'true') { + text = +(data.$percent * 100).toFixed(2) + '%' + } else { + text = data.value + } + + view.annotation().text({ + position: ['50%', '45%'], + content: data.type, + style: { + fontSize: plot.fontSize * 0.8, + fill: plot.labelColor, + fontWeight: 300, + textAlign: 'center' + }, + offsetX: 0 + }) + view.annotation().text({ + position: ['50%', '55%'], + content: text, + style: { + fontSize: plot.fontSize, + fill: plot.labelColor, + fontWeight: 500, + textAlign: 'center' + }, + offsetX: 0, + offsetY: 10 + }) + } + }) + chart.render() + } + + /** + * @description 浠〃鐩樻覆鏌� + */ + dashboardrender = () => { + const { plot, chartId, data } = this.state + + let _data = fromJS(data).toJS() + + if (_data.hasOwnProperty('value')) { + if (_data.value === '' || _data.value === null) { + delete _data.value + } else { + _data.value = +_data.value + + if (isNaN(_data.value)) { + delete _data.value + } else if (_data.value > plot.maxValue) { + _data.value = plot.maxValue + } + } + } + + const chart = new Chart({ + container: chartId, + autoFit: true, + height: plot.height, + padding: [0, 0, 0, 0], + }) + chart.data([_data]) + chart.scale('value', { + min: 0, + max: plot.maxValue, + tickInterval: plot.tickInterval, + }) + chart.coordinate('polar', { + startAngle: (-9 / 8) * Math.PI, + endAngle: (1 / 8) * Math.PI, + radius: 0.75, + }) + + chart.axis('1', false) + chart.axis('value', { + line: null, + label: { + offset: -36, + style: { + fontSize: 18, + fill: plot.tickColor, + textAlign: 'center', + textBaseline: 'middle', + }, + }, + tickLine: { + length: -24, + style: { + stroke: plot.tickColor + } + }, + grid: null, + }) + chart.legend(false) + chart.tooltip(false) + chart + .point() + .position('value*1') + .shape('pointer') + .color('value', (val) => { + if (!val && val !== 0) return 'transparent' + let _color = '#1890FF' + if (plot.colors && plot.colors.length > 0) { + _color = plot.colors[plot.colors.length - 1].color || '#1890FF' + plot.colors.some(item => { + if (item.tick > val) { + _color = item.color + return true + } + return false + }) + } + return _color + }) + .animate({ + appear: { + animation: 'fade-in' + } + }) + + // 缁樺埗浠〃鐩樿儗鏅� + chart.annotation().arc({ + top: false, + start: [0, 1], + end: [plot.maxValue, 1], + style: { + stroke: '#CBCBCB', + lineWidth: 18, + lineDash: null, + }, + }) + + if (!plot.colors || plot.colors.length === 0) { + chart.annotation().arc({ + start: [0, 1], + end: [plot.maxValue, 1], + style: { + stroke: '#1890FF', + lineWidth: 18, + lineDash: null, + }, + }) + } else { + let start = 0 + plot.colors.forEach(item => { + chart.annotation().arc({ + start: [start, 1], + end: [item.tick, 1], + style: { + stroke: item.color, + lineWidth: 18, + lineDash: null, + }, + }) + start = item.tick + }) + } + + if (plot.label) { + chart.annotation().text({ + position: ['50%', '85%'], + content: plot.label, + style: { + fontSize: 20, + fill: plot.labelColor, + textAlign: 'center', + }, + }) + } + + if (data.hasOwnProperty('value')) { + let val = data.value + if (plot.percent !== 'false' && plot.maxValue) { + val = +(val / plot.maxValue * 100).toFixed(2) + ' %' + } + + chart.annotation().text({ + position: ['50%', '90%'], + content: val, + style: { + fontSize: 36, + fill: plot.labelColor, + textAlign: 'center', + }, + offsetY: 15, + }) + } + + chart.render() + } + + render() { + const { config, loading, empty } = this.state + + return ( + <div className="custom-dashboard-plot-box" style={config.style}> + {loading ? + <div className="loading-mask"> + <div className="ant-spin-blur"></div> + <Spin /> + </div> : null + } + <NormalHeader config={config} /> + <div className="canvas-wrap"> + <div className={'canvas' + (empty ? ' empty' : '')} style={{height: config.plot.height + 30}} id={this.state.chartId}></div> + </div> + </div> + ) + } +} + +export default DashboardChart \ No newline at end of file diff --git a/src/tabviews/custom/components/chart/antv-dashboard/index.scss b/src/tabviews/custom/components/chart/antv-dashboard/index.scss new file mode 100644 index 0000000..d9f3566 --- /dev/null +++ b/src/tabviews/custom/components/chart/antv-dashboard/index.scss @@ -0,0 +1,110 @@ +.custom-dashboard-plot-box { + position: relative; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 100px; + + .canvas-wrap { + margin: 0 0px; + position: relative; + min-height: calc(100% - 45px); + .chart-action { + position: absolute; + top: 2px; + right: 5px; + z-index: 1; + } + .chart-action.with-title { + top: 35px; + } + } + + .canvas { + margin: 0; + padding: 15px; + letter-spacing: 0px; + } + .canvas.empty { + div { + opacity: 0; + } + } + .ant-empty { + position: absolute; + top: calc(50% - 34px); + left: calc(50% - 92px); + + .ant-empty-image { + height: 60px; + } + } + .loading-mask { + position: absolute; + left: 0px; + top: 0; + right: 0px; + bottom: 0px; + display: flex; + align-items: center; + justify-content: center; + text-align: justify; + z-index: 1; + + .ant-spin-blur { + position: absolute; + width: 100%; + height: 100%; + opacity: 0.5; + background: #ffffff; + } + } + > .ant-select { + width: 150px; + float: right; + position: relative; + z-index: 1; + .ant-select-selection { + min-height: 24px; + height: 28px; + li { + background: unset; + border: 0; + width: 99%; + padding: 0; + margin-right: 0; + cursor: pointer; + + .type-label { + overflow: hidden; + word-break: break-word; + white-space: nowrap; + text-overflow: ellipsis; + } + } + li + li { + margin-top: 0; + width: 1%; + opacity: 0; + } + } + } + > .ant-select.ant-select-focused { + .ant-select-selection { + li { + width: 50%; + } + li + li { + width: 49%; + opacity: 1; + } + } + } + .g2-tooltip-list{ + display: none; + } + .g2-tooltip-title + .g2-tooltip-list{ + display: block; + } +} diff --git a/src/tabviews/custom/components/chart/antv-pie/index.jsx b/src/tabviews/custom/components/chart/antv-pie/index.jsx index c7fbd33..002b51b 100644 --- a/src/tabviews/custom/components/chart/antv-pie/index.jsx +++ b/src/tabviews/custom/components/chart/antv-pie/index.jsx @@ -3,7 +3,7 @@ import { is, fromJS } from 'immutable' import { Chart } from '@antv/g2' import { connect } from 'react-redux' -import DataSet from '@antv/data-set' +import DataSet, { DataView } from '@antv/data-set' import { Spin, Empty, notification } from 'antd' import moment from 'moment' @@ -55,17 +55,23 @@ _sync = false } + let height = config.plot.height || 400 if (config.plot.title || config.search.length > 0) { - _config.plot.height = _config.plot.height - 80 + _config.plot.height = height - 75 } else { - _config.plot.height = _config.plot.height - 30 + _config.plot.height = height - 30 } - if (_config.style) { - _config.style = {..._config.style, minHeight: (config.plot.height || 400)} - } else { - _config.style = {minHeight: (config.plot.height || 400)} - } + _config.style.height = height + + let decimal = 0 + _config.columns.forEach(col => { + if (_config.plot.Yaxis === col.field && /Decimal/ig.test(col.datatype)) { + decimal = +col.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '') + } + }) + + _config.plot.$decimal = decimal this.setState({ config: _config, @@ -100,12 +106,10 @@ this.setState({sync: false, data: _data}, () => { this.handleData() }) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -136,16 +140,7 @@ if (!config.timer) return - const _change = { - '15s': 15000, - '30s': 30000, - '1min': 60000, - '5min': 300000, - '10min': 600000, - '15min': 900000, - '30min': 1800000, - '1hour': 3600000 - } + const _change = { '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } let timer = _change[config.timer] @@ -210,11 +205,18 @@ } handleData = () => { - let _element = document.getElementById(this.state.chartId) + const { plot, chartId } = this.state + + let _element = document.getElementById(chartId) if (_element) { _element.innerHTML = '' } - this.pierender() + + if (plot.shape === 'nest') { + this.nestrender() + } else { + this.pierender() + } } async loadData (hastimer) { @@ -231,13 +233,18 @@ } let searches = fromJS(search).toJS() - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key) mainSearch.forEach(item => { if (!keys.includes(item.key)) { searches.push(item) } }) + } + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } if (!hastimer) { @@ -277,19 +284,12 @@ * 3銆佹煴鐘跺浘鏁版嵁琛ラ綈 */ getdata = () => { - const { data, plot, config } = this.state + const { data, plot } = this.state if (!data) { this.setState({empty: true}) return [] } - - let decimal = 0 - config.columns.forEach(col => { - if (plot.Yaxis === col.field && /Decimal/ig.test(col.datatype)) { - decimal = +col.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '') - } - }) let _data = [] let _cdata = fromJS(data).toJS() @@ -300,14 +300,16 @@ if (typeof(item[plot.Yaxis]) !== 'number') { item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) if (isNaN(item[plot.Yaxis])) { - item[plot.Yaxis] = 0 + return } + } else if (!item[plot.Xaxis]) { + return } - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { + if (!_mdata.has(item[plot.Xaxis])) { item.$count = 1 _mdata.set(item[plot.Xaxis], item) - } else if (item[plot.Xaxis]) { + } else { let _item = _mdata.get(item[plot.Xaxis]) _item.$count++ _item[plot.Yaxis] += item[plot.Yaxis] @@ -318,8 +320,7 @@ _data = [..._mdata.values()] _data = _data.map(item => { item[plot.Yaxis] = item[plot.Yaxis] / item.$count - item[plot.Yaxis] = item[plot.Yaxis].toFixed(decimal) - item[plot.Yaxis] = +item[plot.Yaxis] + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) return item }) @@ -329,13 +330,15 @@ if (typeof(item[plot.Yaxis]) !== 'number') { item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) if (isNaN(item[plot.Yaxis])) { - item[plot.Yaxis] = 0 + return } + } else if (!item[plot.Xaxis]) { + return } - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { + if (!_mdata.has(item[plot.Xaxis])) { _mdata.set(item[plot.Xaxis], item) - } else if (item[plot.Xaxis]) { + } else { let _item = _mdata.get(item[plot.Xaxis]) _item[plot.Yaxis] += item[plot.Yaxis] _mdata.set(item[plot.Xaxis], _item) @@ -344,34 +347,390 @@ _data = [..._mdata.values()] _data = _data.map(item => { - item[plot.Yaxis] = item[plot.Yaxis].toFixed(decimal) - item[plot.Yaxis] = +item[plot.Yaxis] + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) return item }) } else { // plot.repeat === 'unrepeat' let _mdata = new Map() _cdata.forEach(item => { - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { - - if (typeof(item[plot.Yaxis]) !== 'number') { - item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) - if (isNaN(item[plot.Yaxis])) { - item[plot.Yaxis] = 0 - } - } - - item[plot.Yaxis] = item[plot.Yaxis].toFixed(decimal) - item[plot.Yaxis] = +item[plot.Yaxis] - - _mdata.set(item[plot.Xaxis], item) + if (!item[plot.Xaxis] || _mdata.has(item[plot.Xaxis])) { + return } + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } + + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + + _mdata.set(item[plot.Xaxis], item) }) _data = [..._mdata.values()] } this.setState({empty: _data.length === 0}) + return _data + } + + getnestdata = () => { + const { data, plot } = this.state + + if (!data) { + this.setState({empty: true}) + return [] + } + + let _data = [] + let _cdata = fromJS(data).toJS() + + if (plot.repeat === 'average') { + let _mdata = new Map() + let map = new Map() + let sort = 1 + _cdata.forEach(item => { + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } else if (!item[plot.Xaxis] || !item[plot.type]) { + return + } + + let sign = item[plot.type] + item[plot.Xaxis] + + if (!_mdata.has(sign)) { + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + + item.$count = 1 + item.$sort = _sort + _mdata.set(sign, item) + } else { + let _item = _mdata.get(sign) + _item.$count++ + _item[plot.Yaxis] += item[plot.Yaxis] + _mdata.set(sign, _item) + } + }) + + _data = [..._mdata.values()] + _data = _data.map(item => { + item[plot.Yaxis] = item[plot.Yaxis] / item.$count + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + + return item + }) + } else if (plot.repeat === 'cumsum') { + let _mdata = new Map() + let map = new Map() + let sort = 1 + _cdata.forEach(item => { + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } else if (!item[plot.Xaxis] || !item[plot.type]) { + return + } + + let sign = item[plot.type] + item[plot.Xaxis] + + if (!_mdata.has(sign)) { + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + + item.$sort = _sort + _mdata.set(sign, item) + } else { + let _item = _mdata.get(sign) + _item[plot.Yaxis] += item[plot.Yaxis] + _mdata.set(sign, _item) + } + }) + + _data = [..._mdata.values()] + _data = _data.map(item => { + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + return item + }) + } else { // plot.repeat === 'unrepeat' + let _mdata = new Map() + let map = new Map() + let sort = 1 + _cdata.forEach(item => { + let sign = item[plot.type] + item[plot.Xaxis] + if (!item[plot.Xaxis] || !item[plot.type] || _mdata.has(sign)) { + return + } + + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } + + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + + item.$sort = _sort + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + + _mdata.set(sign, item) + }) + + _data = [..._mdata.values()] + } + + this.setState({empty: _data.length === 0}) + + return _data + } + + nestrender = () => { + const { plot, chartId } = this.state + + let X_axis = plot.Xaxis + let Y_axis = plot.Yaxis + let type = plot.type + let color = plot.color + + let colors = new Map() + let colorIndex = 0 + + if (plot.colors && plot.colors.length > 0) { + plot.colors.forEach(item => { + if (!colors.has(item.label)) { + colors.set(item.label, item.color) + } + }) + } + + let _data = this.getnestdata() + + const dvx = new DataView().source(_data) + + dvx.transform({ + type: 'sort-by', + fields: ['$sort'] + }) + + let data = dvx.rows + + // 閫氳繃 DataSet 璁$畻鐧惧垎姣� + const dv = new DataView() + dv.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: type, + as: '$percent' + }) + + const dv1 = new DataView() + dv1.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: X_axis, + as: '$percent', + }) + + const chart = new Chart({ + container: chartId, + autoFit: true, + height: plot.height, + padding: 0, + }) + + chart.data(dv.rows) + + if (plot.show !== 'value') { + chart.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + + Y_axis = '$percent' + } + let radius = plot.radius / 100 + let innerRadius = plot.innerRadius / 100 + + chart.coordinate('theta', { + innerRadius: innerRadius, + radius: innerRadius + (radius - innerRadius) / 2, + }) + chart.tooltip({ + showTitle: false, + showMarkers: false, + }) + chart.legend(false) + let chart1 = chart + .interval() + .adjust('stack') + .position(Y_axis) + .tooltip(`${type}*${Y_axis}`, (type, percent) => { + if (plot.show !== 'value') { + percent = (percent * 100).toFixed(2) + '%' + } + return { + name: type, + value: percent, + } + }) + if (plot.splitLine) { + chart1.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, + }) + } + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + chart1.color(type, (_type) => { + if (colors.has(_type)) { + return colors.get(_type) + } else { + let _c = chartColors[colorIndex % limit] + colors.set(type, _c) + colorIndex++ + return _c + } + }) + } else { + chart1.color(type) + } + + if (plot.label !== 'false') { + chart1.label(type, { + offset: -10, + }) + } + + const outterView = chart.createView() + + outterView.data(dv1.rows) + + if (plot.show !== 'value') { + outterView.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + } + outterView.coordinate('theta', { + innerRadius: (innerRadius + (radius - innerRadius) / 2) / radius, + radius: radius + }) + let chart2 = outterView + .interval() + .adjust('stack') + .position(Y_axis) + .tooltip(`${X_axis}*${Y_axis}`, (name, value) => { + if (plot.show !== 'value') { + value = (value * 100).toFixed(2) + '%' + } + return { + name: name, + value: value + } + }) + + if (plot.splitLine) { + chart2.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, + }) + } + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + chart2.color(X_axis, (type) => { + if (colors.has(type)) { + return colors.get(type) + } else { + let _c = chartColors[colorIndex % limit] + colors.set(type, _c) + colorIndex++ + return _c + } + }) + } else { + chart2.color(X_axis) + } + + if (plot.label !== 'false') { + if (plot.label === 'inner') { + chart2.label(Y_axis, { + offset: -30, + content: (data) => { + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + return _val + }, + style: { + textAlign: 'center', + fontSize: 16, + shadowBlur: 2, + shadowColor: 'rgba(0, 0, 0, .45)', + fill: '#fff', + } + }) + } else { + chart2.label(Y_axis, { + layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' }, + labelHeight: 20, + content: (data) => { + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + + return `${data[X_axis]}: ${_val}` + }, + labelLine: { + style: { + lineWidth: 0.5, + }, + }, + style: { + fill: color + } + }) + } + } + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) + } + chart.render() } /** @@ -379,12 +738,13 @@ */ pierender = () => { const { plot, chartId } = this.state - let color = plot.color || 'rgba(0, 0, 0, 0.85)' - let X_axis = plot.Xaxis || 'x' - let Y_axis = plot.Yaxis || 'y' + let color = plot.color - let data = this.getdata(X_axis, Y_axis) + let X_axis = plot.Xaxis + let Y_axis = plot.Yaxis + + let data = this.getdata() const ds = new DataSet() const dv = ds.createView().source(data) @@ -392,7 +752,7 @@ const chart = new Chart({ container: chartId, autoFit: true, - height: plot.height || 400 + height: plot.height }) if (plot.shape !== 'nightingale' && plot.show !== 'value') { @@ -479,14 +839,23 @@ value: value } }) + + if (plot.splitLine) { + _chart.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, + }) + } if (plot.colors && plot.colors.length > 0) { let limit = chartColors.length _chart.color(X_axis, (type) => { - if (colors.get(type)) { + if (colors.has(type)) { return colors.get(type) } else { - colors.set(type, chartColors[colorIndex % limit]) + let _c = chartColors[colorIndex % limit] + colors.set(type, _c) colorIndex++ + return _c } }) } else { @@ -515,7 +884,7 @@ }) } else { _chart.label(Y_axis, { - layout: { type: 'pie-spider' }, + layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' }, labelHeight: 20, content: (data) => { let _val = '' @@ -538,10 +907,8 @@ }) } } - chart.interaction('element-active') } else { chart.axis(false) - chart.interaction('element-highlight') let _chart = chart .interval() .position(`${X_axis}*${Y_axis}`) @@ -549,11 +916,13 @@ if (plot.colors && plot.colors.length > 0) { let limit = chartColors.length _chart.color(X_axis, (type) => { - if (colors.get(type)) { + if (colors.has(type)) { return colors.get(type) } else { - colors.set(type, chartColors[colorIndex % limit]) + let _c = chartColors[colorIndex % limit] + colors.set(type, _c) colorIndex++ + return _c } }) } else { @@ -570,9 +939,11 @@ } _chart.label(X_axis, _label) - .style({ - lineWidth: 1, - stroke: '#fff', + } + if (plot.splitLine) { + _chart.style({ + lineWidth: plot.splitLine, + stroke: plot.splitColor, }) } } @@ -624,7 +995,11 @@ } }) } - + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) + } chart.render() } @@ -647,7 +1022,7 @@ } <NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} /> <div className="canvas-wrap"> - <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div> + <div className={'canvas' + (empty ? ' empty' : '')} style={{height: config.plot.height + 30}} id={this.state.chartId}></div> </div> {empty ? <Empty description={false}/> : null} </div> diff --git a/src/tabviews/custom/components/chart/antv-pie/index.scss b/src/tabviews/custom/components/chart/antv-pie/index.scss index 3839a61..3360ffe 100644 --- a/src/tabviews/custom/components/chart/antv-pie/index.scss +++ b/src/tabviews/custom/components/chart/antv-pie/index.scss @@ -9,6 +9,7 @@ .canvas-wrap { margin: 0 0px; position: relative; + min-height: calc(100% - 45px); .chart-action { position: absolute; top: 2px; @@ -45,6 +46,10 @@ top: 0; right: 0px; bottom: 0px; + display: flex; + align-items: center; + justify-content: center; + text-align: justify; z-index: 1; .ant-spin-blur { diff --git a/src/tabviews/custom/components/chart/antv-scatter/asyncButtonComponent.jsx b/src/tabviews/custom/components/chart/antv-scatter/asyncButtonComponent.jsx new file mode 100644 index 0000000..5fb9c1a --- /dev/null +++ b/src/tabviews/custom/components/chart/antv-scatter/asyncButtonComponent.jsx @@ -0,0 +1,34 @@ +import React, {Component} from 'react' +import { Button } from 'antd' + +/** + * @description 寮傛鍔犺浇妯″潡 + * @param {*} importComponent + */ +export default function asyncComponent(importComponent) { + return class extends Component { + constructor(props) { + super(props) + + this.state = { + component: null + } + } + + async componentDidMount() { + const {default: component} = await importComponent() + + this.setState({component}) + } + + // <Button className="loading-skeleton" disabled={true}></Button> // 楠ㄦ灦鎸夐挳 + render() { + const C = this.state.component + const btn = this.props.btn || {} + + return C ? + <C {...this.props} /> : + <Button icon={btn.OpenType === 'excelOut' ? 'download' : 'upload'} disabled={true} title={btn.label} style={{border: 0, background: 'transparent'}}></Button> + } + } +} \ No newline at end of file diff --git a/src/tabviews/custom/components/chart/antv-scatter/index.jsx b/src/tabviews/custom/components/chart/antv-scatter/index.jsx new file mode 100644 index 0000000..742617f --- /dev/null +++ b/src/tabviews/custom/components/chart/antv-scatter/index.jsx @@ -0,0 +1,432 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Chart } from '@antv/g2' +import { Spin, Empty, notification } from 'antd' +import moment from 'moment' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import asyncComponent from '@/utils/asyncComponent' +import asyncBtnComponent from './asyncButtonComponent' +import UtilsDM from '@/utils/utils-datamanage.js' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader')) +const ExcelOutButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton')) +const ExcelInButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/excelInbutton')) + +class ScatterChart extends Component { + static propTpyes = { + BID: PropTypes.any, // 鐖剁骇Id + data: PropTypes.array, // 缁熶竴鏌ヨ鏁版嵁 + config: PropTypes.object, // 缁勪欢閰嶇疆淇℃伅 + mainSearch: PropTypes.any, // 澶栧眰鎼滅储鏉′欢 + menuType: PropTypes.any, // 鑿滃崟绫诲瀷 + } + + state = { + BID: '', // 涓昏〃ID + config: null, // 鍥捐〃閰嶇疆淇℃伅 + empty: true, // 鍥捐〃鏁版嵁涓虹┖ + loading: false, // 鏁版嵁鍔犺浇鐘舵�� + chartId: Utils.getuuid(), // 鍥捐〃Id + sync: false, // 鏄惁缁熶竴璇锋眰鏁版嵁 + plot: null, // 鍥捐〃璁剧疆 + data: null, // 鏁版嵁 + search: null, // 鎼滅储鏉′欢 + } + + UNSAFE_componentWillMount () { + const { config, data, initdata, BID } = this.props + let _config = fromJS(config).toJS() + let _data = null + let _sync = config.setting.sync === 'true' + + if (config.setting.sync === 'true' && data) { + _data = data[config.dataName] || [] + _sync = false + } else if (config.setting.sync === 'true' && initdata) { + _data = initdata || [] + _sync = false + } + + let height = config.plot.height || 400 + if (config.plot.title || config.search.length > 0) { + _config.plot.height = height - 70 + } else { + _config.plot.height = height - 25 + } + + _config.style.height = height + + this.setState({ + config: _config, + data: _data, + BID: BID || '', + empty: !_data, + arr_field: _config.columns.map(col => col.field).join(','), + plot: _config.plot, + sync: _sync, + search: Utils.initMainSearch(config.search), + }, () => { + if (config.setting.sync !== 'true' && config.setting.onload === 'true') { + this.loadData() + } else if (config.setting.sync === 'true' && _data) { + this.handleData() + } + }) + } + + /** + * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹� + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { sync, config } = this.state + + if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) { + let _data = [] + if (nextProps.data && nextProps.data[config.dataName]) { + _data = nextProps.data[config.dataName] || [] + } + + this.setState({sync: false, data: _data, empty: !_data,}, () => { + this.handleData() + }) + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('reloadData', this.reloadData) + MKEmitter.addListener('resetSelectLine', this.resetParentParam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) + MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) + this.handleTimer() + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + clearTimeout(this.timer) + this.setState = () => { + return + } + MKEmitter.removeListener('reloadData', this.reloadData) + MKEmitter.removeListener('resetSelectLine', this.resetParentParam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) + MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) + } + + handleTimer = () => { + const { config } = this.state + + if (!config.timer) return + + const _change = { '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } + + let timer = _change[config.timer] + + if (!timer) return + + let _param = { + func: 's_get_timers_role', + LText: `select '${window.GLOB.appkey || ''}','${config.uuid}'`, + timer_type: config.timer, + component_id: config.uuid + } + + _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') // 鏃堕棿鎴� + _param.LText = Utils.formatOptions(_param.LText) // 鍏抽敭瀛楃鏇挎崲锛宐ase64鍔犲瘑 + _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp) // md5瀵嗛挜 + + Api.getSystemConfig(_param).then(result => { + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + return + } else if (result.run_type) { + this.setState({timer}) + this.timer = setTimeout(() => { + this.timerTask() + }, timer) + } + }) + } + + timerTask = () => { + const { timer } = this.state + if (!timer) return + + this.loadData(true) + + this.timer = setTimeout(() => { + this.timerTask() + }, timer) + } + + /** + * @description 鎸夐挳鎵ц瀹屾垚鍚庨〉闈㈠埛鏂� + * @param {*} menuId // 鑿滃崟Id + * @param {*} position // 鍒锋柊浣嶇疆 + * @param {*} btn // 鎵ц鐨勬寜閽� + */ + refreshByButtonResult = (menuId, position, btn) => { + const { config, BID } = this.state + + if (config.uuid !== menuId) return + + this.loadData() // 鏁版嵁鍒锋柊 + + if (btn.syncComponentId && btn.syncComponentId !== config.uuid && btn.syncComponentId !== config.setting.supModule) { + MKEmitter.emit('reloadData', btn.syncComponentId) // 鍚岀骇鏍囩鍒锋柊 + } + + if (position === 'mainline' && config.setting.supModule) { // 涓昏〃琛屽埛鏂� + MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty')) + } + } + + reloadData = (menuId) => { + const { config } = this.state + + if (config.uuid !== menuId) return + + this.loadData() + } + + resetParentParam = (MenuID, id) => { + const { config } = this.state + + if (!config.setting.supModule || config.setting.supModule !== MenuID) return + if (id !== this.state.BID) { + this.setState({ BID: id }, () => { + this.loadData() + }) + } + } + + /** + * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� + */ + queryModuleParam = (menuId, btnId) => { + const { mainSearch } = this.props + const { arr_field, config, search } = this.state + + if (config.uuid !== menuId) return + + let searches = search ? fromJS(search).toJS() : [] + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + let keys = searches.map(item => item.key.toLowerCase()) + mainSearch.forEach(item => { + if (!keys.includes(item.key.toLowerCase())) { + searches.push(item) + } + }) + } + + MKEmitter.emit('returnModuleParam', config.uuid, btnId, { + arr_field: arr_field, + orderBy: config.setting.order || '', + search: searches, + menuName: config.name + }) + } + + /** + * @description 鏁版嵁鍔犺浇 + */ + async loadData (hastimer) { + const { mainSearch, menuType } = this.props + const { config, arr_field, BID, search } = this.state + + if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� + this.setState({ + data: [], + empty: false, + }, () => { + this.handleData() + }) + return + } + + let searches = search ? fromJS(search).toJS() : [] + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + let keys = searches.map(item => item.key) + mainSearch.forEach(item => { + if (!keys.includes(item.key)) { + searches.push(item) + } + }) + } + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return + } + + if (!hastimer) { + this.setState({ + loading: true + }) + } + + let _orderBy = config.setting.order || '' + let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID, menuType) + + let result = await Api.genericInterface(param) + if (result.status) { + this.setState({ + data: result.data, + empty: false, + loading: false + }, () => { + this.handleData() + }) + } else { + this.setState({ + loading: false, + timer: null + }) + notification.error({ + top: 92, + message: result.message, + duration: 10 + }) + } + } + + /** + * @description 鏁版嵁棰勫鐞嗭紝缁熻鏁版嵁闇�瑕侀噸缃� + */ + handleData = () => { + let _element = document.getElementById(this.state.chartId) + if (_element) { + _element.innerHTML = '' + } + this.scatterrender() + } + + /** + * @description 鏁g偣鍥炬覆鏌� + */ + scatterrender = () => { + const { plot, data, chartId } = this.state + const chart = new Chart({ + container: chartId, + autoFit: true, + height: plot.height + }) + + chart.data(data); + chart.scale({ + [plot.Xaxis]: { nice: true }, + [plot.Yaxis]: { nice: true }, + }) + + chart.axis(plot.Xaxis, { label: { style: { fill: plot.color } } }) + chart.axis(plot.Yaxis, { label: { style: { fill: plot.color } } }) + chart.legend({ + position: 'bottom', + itemName: { style: { fill: plot.color } } + }) + + if (plot.tooltip !== 'true') { + chart.tooltip(false) + } else { + chart.tooltip({ + showTitle: false, + showCrosshairs: true, + crosshairs: { + type: 'xy', + } + }) + } + + chart + .point() + .position(`${plot.Xaxis}*${plot.Yaxis}`) + .color(plot.gender) + .shape(plot.shape) + .tooltip(`${plot.gender}*${plot.Xaxis}*${plot.Yaxis}`, (gender, height, weight) => { + return { + name: gender, + value: height + (plot.Xunit ? `(${plot.Xunit}), ` : ', ') + weight + (plot.Yunit ? `(${plot.Yunit})` : '') + }; + }) + .style({ + fillOpacity: 0.85 + }) + if (plot.interaction && plot.interaction.length) { + plot.interaction.forEach(t => { + chart.interaction(t) + }) + } + chart.render() + } + + refreshSearch = (list) => { + this.setState({search: list}, () => { + this.loadData() + }) + } + + render() { + const { config, loading, empty, BID } = this.state + + return ( + <div className="custom-scatter-plot-box" style={config.style}> + {loading ? + <div className="loading-mask"> + <div className="ant-spin-blur"></div> + <Spin /> + </div> : null + } + <NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} /> + <div className="canvas-wrap"> + <div className="chart-action"> + {config.action.map(item => { + if (item.OpenType === 'excelOut') { + return ( + <ExcelOutButton + key={item.uuid} + BID={BID} + btn={item} + show="icon" + setting={config.setting} + /> + ) + } else { + return ( + <ExcelInButton + key={item.uuid} + BID={BID} + btn={item} + show="icon" + setting={config.setting} + /> + ) + } + })} + </div> + <div className={'canvas' + (empty ? ' empty' : '')} style={{height: config.plot.height + 25}} id={this.state.chartId}></div> + </div> + {empty ? <Empty description={false}/> : null} + </div> + ) + } +} + +export default ScatterChart \ No newline at end of file diff --git a/src/tabviews/custom/components/chart/antv-scatter/index.scss b/src/tabviews/custom/components/chart/antv-scatter/index.scss new file mode 100644 index 0000000..c9ad16c --- /dev/null +++ b/src/tabviews/custom/components/chart/antv-scatter/index.scss @@ -0,0 +1,70 @@ +.custom-scatter-plot-box { + position: relative; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 100px; + + .canvas-wrap { + margin: 0 0px; + position: relative; + min-height: calc(100% - 45px); + .chart-action { + position: absolute; + top: 0px; + right: 5px; + z-index: 1; + .ant-btn { + float: right; + } + } + } + + .canvas { + margin: 0; + padding: 15px 10px 10px; + letter-spacing: 0px; + } + .canvas.empty { + div { + opacity: 0; + } + } + .ant-empty { + position: absolute; + top: calc(50% - 34px); + left: calc(50% - 92px); + + .ant-empty-image { + height: 60px; + } + } + .loading-mask { + position: absolute; + left: 0px; + top: 0; + right: 0px; + bottom: 0px; + display: flex; + align-items: center; + justify-content: center; + text-align: justify; + z-index: 1; + + .ant-spin-blur { + position: absolute; + width: 100%; + height: 100%; + opacity: 0.5; + background: #ffffff; + } + } + + .g2-tooltip-list{ + display: none; + } + .g2-tooltip-title + .g2-tooltip-list{ + display: block; + } +} diff --git a/src/tabviews/custom/components/code/sand-box/index.jsx b/src/tabviews/custom/components/code/sand-box/index.jsx index 204c9f7..1fd9fa9 100644 --- a/src/tabviews/custom/components/code/sand-box/index.jsx +++ b/src/tabviews/custom/components/code/sand-box/index.jsx @@ -106,12 +106,10 @@ this.setState({sync: false, data: _data}, () => { this.renderView() }) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.wrap.datatype !== 'static' && config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -141,9 +139,11 @@ return } - let searches = [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 - searches = mainSearch + let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } this.setState({ diff --git a/src/tabviews/custom/components/editor/braft-editor/index.jsx b/src/tabviews/custom/components/editor/braft-editor/index.jsx index 5691f35..8b7c537 100644 --- a/src/tabviews/custom/components/editor/braft-editor/index.jsx +++ b/src/tabviews/custom/components/editor/braft-editor/index.jsx @@ -100,12 +100,10 @@ } this.setState({sync: false, data: _data}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.wrap.datatype !== 'static' && config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } } @@ -135,9 +133,11 @@ return } - let searches = [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 - searches = mainSearch + let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } this.setState({ diff --git a/src/tabviews/custom/components/form/normal-form/index.jsx b/src/tabviews/custom/components/form/normal-form/index.jsx index 8d3fc08..f8bb190 100644 --- a/src/tabviews/custom/components/form/normal-form/index.jsx +++ b/src/tabviews/custom/components/form/normal-form/index.jsx @@ -3,7 +3,6 @@ import { is, fromJS } from 'immutable' import { connect } from 'react-redux' import { Spin, notification, Button } from 'antd' -// import moment from 'moment' import Api from '@/api' import Utils from '@/utils/utils.js' @@ -33,7 +32,6 @@ BID: '', // 涓婄骇ID config: null, // 鍥捐〃閰嶇疆淇℃伅 loading: false, // 鏁版嵁鍔犺浇鐘舵�� - activeKey: '', // 閫変腑鏁版嵁 sync: false, // 鏄惁缁熶竴璇锋眰鏁版嵁 data: null, // 鏁版嵁 group: null, @@ -41,7 +39,8 @@ } UNSAFE_componentWillMount () { - const { data, BID, config } = this.props + const { data, BID } = this.props + let config = fromJS(this.props.config).toJS() let _data = null let _sync = false @@ -60,15 +59,31 @@ _data = {} } + if (!config.wrap.groupLabel) { + if (config.subcards.length > 1) { + config.wrap.groupLabel = 'show' + } else { + config.wrap.groupLabel = 'hidden' + } + } + let roleId = sessionStorage.getItem('role_id') || '' config.subcards = config.subcards.map(group => { group.subButton.uuid = group.uuid group.subButton.$menuId = group.uuid group.subButton.Ot = 'requiredSgl' - group.subButton.btnstyle = group.subButton.style + group.subButton.$forbid = true group.subButton.OpenType = 'formSubmit' group.subButton.execError = 'never' + + if (group.subButton.enable === 'false') { + group.subButton.style.display = 'none' + } + + if (group.prevButton.enable === 'false' && group.subButton.enable === 'false' && group.nextButton.enable === 'false') { + group.$button = 'no-button' + } group.fields = group.fields.map(cell => { // 鏁版嵁婧恠ql璇彞锛岄澶勭悊锛屾潈闄愰粦鍚嶅崟瀛楁璁剧疆涓洪殣钘忚〃鍗� @@ -117,6 +132,7 @@ } componentDidMount () { + MKEmitter.addListener('reloadData', this.reloadData) MKEmitter.addListener('mkFormSubmit', this.mkFormSubmit) MKEmitter.addListener('resetSelectLine', this.resetParentParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) @@ -130,6 +146,7 @@ this.setState = () => { return } + MKEmitter.removeListener('reloadData', this.reloadData) MKEmitter.removeListener('mkFormSubmit', this.mkFormSubmit) MKEmitter.removeListener('resetSelectLine', this.resetParentParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) @@ -157,13 +174,19 @@ } this.setState({sync: false, data: _data, group: _group, step: _group.sort - 1,}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.wrap.datatype !== 'static' && config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.loadData() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) } + } + + reloadData = (menuId, id) => { + const { config } = this.state + + if (config.uuid !== menuId) return + + this.loadData(null, 'refresh') } /** @@ -180,6 +203,26 @@ if (btn.syncComponentId && btn.syncComponentId !== config.uuid && btn.syncComponentId !== config.setting.supModule) { MKEmitter.emit('reloadData', btn.syncComponentId) // 鍚岀骇鏍囩鍒锋柊 } + + if (config.wrap.datatype !== 'static' && config.setting) { + this.loadData(btn) + } else { + this.execSuccess(btn) + } + } + + resetParentParam = (MenuID, id) => { + const { config } = this.state + if (config.wrap.datatype === 'static' || !config.setting.supModule || config.setting.supModule !== MenuID) return + if (id !== this.state.BID) { + this.setState({ BID: id }, () => { + this.loadData() + }) + } + } + + execSuccess = (btn) => { + const { config, group } = this.state if (config.subcards.length > group.sort) { let _group = config.subcards.filter(item => item.sort === (group.sort + 1))[0] @@ -218,36 +261,24 @@ } } - resetParentParam = (MenuID, id) => { - const { config } = this.state - if (config.wrap.datatype === 'static' || !config.setting.supModule || config.setting.supModule !== MenuID) return - if (id !== this.state.BID) { - this.setState({ BID: id }, () => { - this.loadData() - }) - } - } - - async loadData () { + async loadData (btn, type) { const { mainSearch, menuType } = this.props const { config, arr_field, BID, group } = this.state if (config.wrap.datatype === 'static' || (config.setting.supModule && !BID)) { this.setState({ - data: {}, - loading: false + data: {} }) + btn && this.execSuccess(btn) return } - let searches = [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 - let keys = searches.map(item => item.key) - mainSearch.forEach(item => { - if (!keys.includes(item.key)) { - searches.push(item) - } - }) + let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + btn && this.execSuccess(btn) + return } this.setState({ @@ -260,20 +291,34 @@ let result = await Api.genericInterface(param) if (result.status) { let _data = result.data && result.data[0] ? result.data[0] : {} - let _group = group - if (config.wrap.statusControl && _data[config.wrap.statusControl]) { - let _status = _data[config.wrap.statusControl] - let _groups = config.subcards.filter(item => item.setting.status === _status)[0] - _group = _groups || _group - } - this.setState({ - group: _group, - step: _group.sort - 1, - activeKey: '', - data: _data || {}, - loading: false - }) + if (btn) { + this.setState({ + data: _data || {}, + loading: false + }) + this.execSuccess(btn) + } else { + let _group = group + + if (type === 'refresh') { + _group = config.subcards[0] + } + + if (config.wrap.statusControl && _data[config.wrap.statusControl]) { + let _status = _data[config.wrap.statusControl] + let _groups = config.subcards.filter(item => item.setting.status === _status)[0] + _group = _groups || _group + } + this.setState({ + group: null, + step: _group.sort - 1, + data: _data || {}, + loading: false + }, () => { + this.setState({group: _group}) + }) + } } else { this.setState({ loading: false, @@ -283,6 +328,7 @@ message: result.message, duration: 10 }) + btn && this.execSuccess(btn) } } @@ -327,7 +373,7 @@ <Spin /> </div> : null } - {config.subcards.length > 1 ? <div className="mk-normal-form-title"> + {config.wrap.groupLabel !== 'hidden' ? <div className="mk-normal-form-title"> {config.subcards.map(card => ( <div key={card.uuid} className={'form-title' + (card.sort <= step ? ' active' : '')}> <span className="form-sort" style={{background: config.wrap.color}}>{card.sort}</span> @@ -345,8 +391,8 @@ inputSubmit={this.handleOk} wrappedComponentRef={(inst) => this.formRef = inst} /> : null} - {group && data ? <div className="mk-form-action"> - {group.sort !== 1 ? <Button type="link" className="prev" onClick={this.prevStep} style={group.prevButton.style}>{group.prevButton.label}</Button> : null} + {group && data ? <div className={'mk-form-action ' + (group.$button || '')}> + {group.sort !== 1 && group.prevButton.enable !== 'false' ? <Button type="link" className="prev" onClick={this.prevStep} style={group.prevButton.style}>{group.prevButton.label}</Button> : null} <NormalButton BID={BID} position="form" diff --git a/src/tabviews/custom/components/form/normal-form/index.scss b/src/tabviews/custom/components/form/normal-form/index.scss index 285b505..7547391 100644 --- a/src/tabviews/custom/components/form/normal-form/index.scss +++ b/src/tabviews/custom/components/form/normal-form/index.scss @@ -78,6 +78,10 @@ right: 5px; } } + .mk-form-action.no-button { + padding: 0; + height: 0; + } .loading-mask { position: absolute; diff --git a/src/tabviews/custom/components/group/normal-group/index.jsx b/src/tabviews/custom/components/group/normal-group/index.jsx index d814a27..0ffbce3 100644 --- a/src/tabviews/custom/components/group/normal-group/index.jsx +++ b/src/tabviews/custom/components/group/normal-group/index.jsx @@ -2,24 +2,32 @@ import PropTypes from 'prop-types' import { connect } from 'react-redux' import { is, fromJS } from 'immutable' -import { Col, Empty, notification, Button } from 'antd' -import moment from 'moment' -import md5 from 'md5' +import { Col, Empty, notification, Button, Row } from 'antd' import Api from '@/api' -import options from '@/store/options.js' import asyncComponent from '@/utils/asyncComponent' +import { + getStructuredParams, + getStructDefaultParam +} from '@/utils/utils-datamanage.js' import Utils from '@/utils/utils.js' import './index.scss' // 閫氱敤缁勪欢 const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line')) const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie')) +const AntvDashboard = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-dashboard')) +const AntvScatter = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-scatter')) const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card')) const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card')) +const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table')) const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card')) const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor')) const SandBox = asyncComponent(() => import('@/tabviews/custom/components/code/sand-box')) +const NormalForm = asyncComponent(() => import('@/tabviews/custom/components/form/normal-form')) +const NormalTree = asyncComponent(() => import('@/tabviews/custom/components/tree/antd-tree')) +const CarouselDataCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/data-card')) +const CarouselPropCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/prop-card')) class TabTransfer extends Component { static propTpyes = { @@ -41,7 +49,6 @@ // 鑾峰彇涓绘悳绱㈡潯浠� let _mainSearch = mainSearch ? fromJS(mainSearch).toJS() : [] - let params = [] config.components.forEach(item => { if (item.type === 'tabs') return @@ -50,8 +57,25 @@ if (!item.format) return if (item.dataName && (!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') { - let param = this.getDefaultParam(item, _mainSearch) - params.push(param) + let searchlist = [] + if (item.search && item.search.length > 0) { + searchlist = Utils.initMainSearch(item.search) + } + if (item.setting.useMSearch) { + let keys = searchlist.map(item => item.key) + _mainSearch.forEach(item => { + if (!keys.includes(item.key)) { + searchlist.push(item) + } + }) + } + + if (searchlist.filter(cell => cell.required && cell.value === '').length > 0) { + item.setting.sync = 'false' + item.setting.onload = 'false' + } else { + params.push(getStructDefaultParam(item, searchlist)) + } } else { item.setting.sync = 'false' } @@ -71,137 +95,10 @@ } /** - * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鐨勫弬鏁� - */ - getDefaultParam = (component, mainSearch) => { - const { columns, search, setting, dataName, format } = component - - let searchlist = [] - if (search && search.length > 0) { - searchlist = Utils.initMainSearch(search) - } - - if (setting.useMSearch === 'true') { - let keys = searchlist.map(item => item.key) - mainSearch.forEach(item => { - if (!keys.includes(item.key)) { - searchlist.push(item) - } - }) - } - - let arr_field = columns.map(col => col.field) - let _dataresource = setting.dataresource - let _customScript = setting.customScript - - if (setting.queryType === 'statistics' || _customScript) { - let allSearch = Utils.getAllSearchOptions(searchlist) - let regoptions = allSearch.map(item => { - return { - reg: new RegExp('@' + item.key + '@', 'ig'), - value: `'${item.value}'` - } - }) - - regoptions.forEach(item => { - if (_dataresource && setting.queryType === 'statistics') { - _dataresource = _dataresource.replace(item.reg, item.value) - } - if (_customScript) { - _customScript = _customScript.replace(item.reg, item.value) - } - }) - } - - let _search = '' - if (setting.queryType !== 'statistics' && _dataresource) { - _search = Utils.joinMainSearchkey(searchlist) - _search = _search ? 'where ' + _search : '' - } - - if (setting.order && _dataresource) { - _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows ` - } else if (_dataresource) { - _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} ` - } - - // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞 - if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) { - _customScript && console.info(`${_dataresource ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) - _dataresource && console.info(_dataresource) - } - - return { - name: dataName, - columns: columns, - par_tablename: '', - type: format === 'array' ? format : '', - primaryKey: setting.primaryKey || '', - foreign_key: '', - sql: _dataresource, - script: _customScript - } - } - - /** * @description 涓昏〃鏁版嵁鍔犺浇 */ loadmaindata = (params) => { - const { config } = this.props - let LText_field = [] - let diffUser = false - let userName = sessionStorage.getItem('User_Name') || '' - let fullName = sessionStorage.getItem('Full_Name') || '' - let city = sessionStorage.getItem('city') || '' - - if (sessionStorage.getItem('isEditState') === 'true') { - userName = sessionStorage.getItem('CloudUserName') || '' - fullName = sessionStorage.getItem('CloudFullName') || '' - } - - let _LText = params.map((item, index) => { - let _script = item.script - - if (index === 0) { - _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50) - select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}' - ${_script} - ` - } - if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) { - diffUser = true - } - - item.columns.forEach(cell => { - LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`) - }) - return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort` - }) - - let param = { - func: 'sPC_Get_structured_data', - LText: _LText.join(' union all '), - LText_field: LText_field.join(' union all ') - } - - let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText) - - param.LText1 = LText1 - param.LText = LText - param.LText2 = LText2 - param.LText_field = Utils.formatOptions(param.LText_field) - - if (config.cacheUseful === 'true') { - param.time_type = config.timeUnit - param.time_limit = config.cacheTime - if (diffUser) { - param.userid = sessionStorage.getItem('UserID') - } - param.data_md5 = md5(JSON.stringify(param)) - } - - param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - param.secretkey = Utils.encrypt(param.LText, param.timestamp) + let param = getStructuredParams(params, this.props.config) Api.getLocalConfig(param).then(result => { if (result.status) { @@ -252,6 +149,36 @@ <AntvPie data={data} config={item} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> </Col> ) + } else if (item.type === 'dashboard') { + return ( + <Col span={item.width} key={item.uuid}> + <AntvDashboard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'form') { + return ( + <Col span={item.width} key={item.uuid}> + <NormalForm config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'scatter') { + return ( + <Col span={item.width} key={item.uuid}> + <AntvScatter config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'carousel' && item.subtype === 'datacard') { + return ( + <Col span={item.width} key={item.uuid}> + <CarouselDataCard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'carousel' && item.subtype === 'propcard') { + return ( + <Col span={item.width} key={item.uuid}> + <CarouselPropCard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) } else if (item.type === 'card' && item.subtype === 'datacard') { return ( <Col span={item.width} key={item.uuid}> @@ -268,6 +195,18 @@ return ( <Col span={item.width} key={item.uuid}> <TableCard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'table' && item.subtype === 'normaltable') { + return ( + <Col span={item.width} key={item.uuid}> + <NormalTable config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'tree') { + return ( + <Col span={item.width} key={item.uuid}> + <NormalTree config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> </Col> ) } else if (item.type === 'editor') { @@ -366,7 +305,7 @@ return ( <div className="normal-group-wrap" id={config.uuid} style={config.style}> {config.setting && config.setting.print === 'true' ? <Button className="print-button" icon="printer" loading={printing} onClick={this.print}></Button> : null} - {this.getComponents()} + <Row>{this.getComponents()}</Row> </div> ) } diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx index f471844..2d53f40 100644 --- a/src/tabviews/custom/components/share/normalTable/index.jsx +++ b/src/tabviews/custom/components/share/normalTable/index.jsx @@ -15,7 +15,11 @@ const { Paragraph } = Typography const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList')) - +const PicRadio = { + '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%', + '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%', + '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%' +} class BodyRow extends React.Component { shouldComponentUpdate (nextProps, nextState) { return !is(fromJS(this.props.data), fromJS(nextProps.data)) || !is(fromJS(this.props.className), fromJS(nextProps.className)) @@ -187,7 +191,7 @@ content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)} ${content.substr(11, 2)}:${content.substr(14, 2)}:${content.substr(17, 2)}` } - content = col.prefix + content + col.postfix + content = (col.prefix || '') + content + (col.postfix || '') } if (col.marks) { @@ -272,12 +276,8 @@ let cols = 24 / (col.picSort || 1) let paddingTop = '100%' - if (col.lenWidRadio === '16:9') { - paddingTop = '56.25%' - } else if (col.lenWidRadio === '3:2') { - paddingTop = '66.67%' - } else if (col.lenWidRadio === '4:3') { - paddingTop = '75%' + if (PicRadio[col.lenWidRadio]) { + paddingTop = PicRadio[col.lenWidRadio] } resProps.children = ( @@ -350,6 +350,10 @@ ) } else if (col.type === 'custom') { style.padding = '0px' + if (col.style) { + style = {...style, ...col.style} + } + resProps.children = ( <CardCellComponent data={record} cards={config} elements={col.elements}/> ) @@ -423,7 +427,10 @@ if (item.rowspan === 'true') { rowspans.push(item.field) } - if (_format && !Math.floor(Math.random() * radio)) { + if (item.type === 'index') { + item.field = '$Index' + item.type = 'text' + } else if (_format && !Math.floor(Math.random() * radio)) { item.blur = true } @@ -803,12 +810,13 @@ } return ( - <div className={'normal-custom-table ' + setting.tableHeader} id={tableId}> + <div className={`normal-custom-table ${setting.tableHeader || ''} ${setting.mode || ''}`} id={tableId}> {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 ? - <Switch title="鏀惰捣" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={pickup} onChange={this.pickupChange} /> : null + <Switch title="鏀惰捣" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /> : null } <Table components={components} + style={setting.style} size={setting.size || 'middle'} bordered={setting.bordered !== 'false'} rowSelection={rowSelection} diff --git a/src/tabviews/custom/components/share/normalTable/index.scss b/src/tabviews/custom/components/share/normalTable/index.scss index 19301ac..489c533 100644 --- a/src/tabviews/custom/components/share/normalTable/index.scss +++ b/src/tabviews/custom/components/share/normalTable/index.scss @@ -8,11 +8,15 @@ } .normal-table-footer.pagination { position: absolute; - bottom: 40px; + bottom: 10px; } >.ant-table-wrapper { position: relative; z-index: 1; + } + .ant-table { + color: inherit; + font-size: inherit; } table { @@ -163,6 +167,34 @@ display: none; } } +.normal-custom-table.ghost { + .main-pickup { + display: none; + } + .ant-table-thead > tr { + > th { + color: inherit; + background: transparent; + .ant-table-column-sorter .ant-table-column-sorter-inner { + color: inherit; + } + } + > th:hover { + background: transparent; + } + } + .ant-table-body { + overflow-x: auto; + tr { + td { + background: transparent!important; + } + } + tr:hover td { + background: transparent!important; + } + } +} .image-scale-modal { width: 70vw; min-height: 80vh; diff --git a/src/tabviews/custom/components/share/normalheader/index.jsx b/src/tabviews/custom/components/share/normalheader/index.jsx index 9643142..570a190 100644 --- a/src/tabviews/custom/components/share/normalheader/index.jsx +++ b/src/tabviews/custom/components/share/normalheader/index.jsx @@ -46,7 +46,7 @@ if (!title && !show) return null return ( - <div className="normal-header" style={config.headerStyle}> + <div className={'normal-header' + (show ? ' header-search' : '')} style={config.headerStyle}> <span className="title">{title}</span> {show ? <SearchComponent config={config} BID={BID} menuType={menuType} refreshdata={this.props.refresh}/> : null} </div> diff --git a/src/tabviews/custom/components/share/normalheader/index.scss b/src/tabviews/custom/components/share/normalheader/index.scss index c58253d..3939c9a 100644 --- a/src/tabviews/custom/components/share/normalheader/index.scss +++ b/src/tabviews/custom/components/share/normalheader/index.scss @@ -5,13 +5,14 @@ border-bottom: 1px solid #e8e8e8; overflow: hidden; letter-spacing: 0px; + line-height: 45px; .title { text-decoration: inherit; font-weight: inherit; font-style: inherit; float: left; - line-height: 45px; + line-height: inherit; margin-left: 10px; position: relative; z-index: 1; @@ -22,6 +23,7 @@ font-weight: normal; font-style: normal; letter-spacing: 0px; + flex: 1; >.ant-row { >.ant-col { height: 45px; @@ -36,6 +38,9 @@ } } } +.header-search.normal-header { + display: flex; +} .normal-header.hidden { display: none; } \ No newline at end of file diff --git a/src/tabviews/custom/components/share/tabtransfer/index.jsx b/src/tabviews/custom/components/share/tabtransfer/index.jsx index 03cbe65..62512b7 100644 --- a/src/tabviews/custom/components/share/tabtransfer/index.jsx +++ b/src/tabviews/custom/components/share/tabtransfer/index.jsx @@ -3,12 +3,13 @@ import { connect } from 'react-redux' import { is, fromJS } from 'immutable' import { Row, Col, Empty, notification } from 'antd' -import moment from 'moment' -import md5 from 'md5' import Api from '@/api' -import options from '@/store/options.js' import asyncComponent from '@/utils/asyncComponent' +import { + getStructuredParams, + getStructDefaultParam +} from '@/utils/utils-datamanage.js' import Utils from '@/utils/utils.js' import './index.scss' @@ -16,13 +17,20 @@ const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line')) const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch')) const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie')) +const AntvDashboard = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-dashboard')) const AntvTabs = asyncComponent(() => import('@/tabviews/custom/components/tabs/antv-tabs')) const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card')) +const AntvScatter = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-scatter')) const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card')) +const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table')) const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card')) const NormalGroup = asyncComponent(() => import('@/tabviews/custom/components/group/normal-group')) const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor')) const SandBox = asyncComponent(() => import('@/tabviews/custom/components/code/sand-box')) +const NormalForm = asyncComponent(() => import('@/tabviews/custom/components/form/normal-form')) +const NormalTree = asyncComponent(() => import('@/tabviews/custom/components/tree/antd-tree')) +const CarouselDataCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/data-card')) +const CarouselPropCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/prop-card')) class TabTransfer extends Component { static propTpyes = { @@ -63,8 +71,25 @@ if (!item.format) return if (item.dataName && (!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') { - let param = this.getDefaultParam(item, _mainSearch) - params.push(param) + let searchlist = [] + if (item.search && item.search.length > 0) { + searchlist = Utils.initMainSearch(item.search) + } + if (item.setting.useMSearch) { + let keys = searchlist.map(item => item.key) + _mainSearch.forEach(item => { + if (!keys.includes(item.key)) { + searchlist.push(item) + } + }) + } + + if (searchlist.filter(cell => cell.required && cell.value === '').length > 0) { + item.setting.sync = 'false' + item.setting.onload = 'false' + } else { + params.push(getStructDefaultParam(item, searchlist)) + } } else { item.setting.sync = 'false' } @@ -86,137 +111,10 @@ } /** - * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鐨勫弬鏁� - */ - getDefaultParam = (component, mainSearch) => { - const { columns, search, setting, dataName, format } = component - - let searchlist = [] - if (search && search.length > 0) { - searchlist = Utils.initMainSearch(search) - } - - if (setting.useMSearch === 'true') { - let keys = searchlist.map(item => item.key) - mainSearch.forEach(item => { - if (!keys.includes(item.key)) { - searchlist.push(item) - } - }) - } - - let arr_field = columns.map(col => col.field) - let _dataresource = setting.dataresource - let _customScript = setting.customScript - - if (setting.queryType === 'statistics' || _customScript) { - let allSearch = Utils.getAllSearchOptions(searchlist) - let regoptions = allSearch.map(item => { - return { - reg: new RegExp('@' + item.key + '@', 'ig'), - value: `'${item.value}'` - } - }) - - regoptions.forEach(item => { - if (_dataresource && setting.queryType === 'statistics') { - _dataresource = _dataresource.replace(item.reg, item.value) - } - if (_customScript) { - _customScript = _customScript.replace(item.reg, item.value) - } - }) - } - - let _search = '' - if (setting.queryType !== 'statistics' && _dataresource) { - _search = Utils.joinMainSearchkey(searchlist) - _search = _search ? 'where ' + _search : '' - } - - if (setting.order && _dataresource) { - _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows ` - } else if (_dataresource) { - _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} ` - } - - // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞 - if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) { - _customScript && console.info(`${_dataresource ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) - _dataresource && console.info(_dataresource) - } - - return { - name: dataName, - columns: columns, - par_tablename: '', - type: format === 'array' ? format : '', - primaryKey: setting.primaryKey || '', - foreign_key: '', - sql: _dataresource, - script: _customScript - } - } - - /** * @description 涓昏〃鏁版嵁鍔犺浇 */ loadmaindata = (params) => { - const { config } = this.props - let LText_field = [] - let diffUser = false - let userName = sessionStorage.getItem('User_Name') || '' - let fullName = sessionStorage.getItem('Full_Name') || '' - let city = sessionStorage.getItem('city') || '' - - if (sessionStorage.getItem('isEditState') === 'true') { - userName = sessionStorage.getItem('CloudUserName') || '' - fullName = sessionStorage.getItem('CloudFullName') || '' - } - - let _LText = params.map((item, index) => { - let _script = item.script - - if (index === 0) { - _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50) - select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}' - ${_script} - ` - } - if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) { - diffUser = true - } - - item.columns.forEach(cell => { - LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`) - }) - return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort` - }) - - let param = { - func: 'sPC_Get_structured_data', - LText: _LText.join(' union all '), - LText_field: LText_field.join(' union all ') - } - - let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText) - - param.LText1 = LText1 - param.LText = LText - param.LText2 = LText2 - param.LText_field = Utils.formatOptions(param.LText_field) - - if (config.cacheUseful === 'true') { - param.time_type = config.timeUnit - param.time_limit = config.cacheTime - if (diffUser) { - param.userid = sessionStorage.getItem('UserID') - } - param.data_md5 = md5(JSON.stringify(param)) - } - - param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - param.secretkey = Utils.encrypt(param.LText, param.timestamp) + let param = getStructuredParams(params, this.props.config) Api.getLocalConfig(param).then(result => { if (result.status) { @@ -271,10 +169,22 @@ <AntvPie data={data} config={item} BID={BID} mainSearch={mainSearch} menuType={menuType} /> </Col> ) + } else if (item.type === 'dashboard') { + return ( + <Col span={item.width} key={item.uuid}> + <AntvDashboard config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'scatter') { + return ( + <Col span={item.width} key={item.uuid}> + <AntvScatter config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) } else if (item.type === 'search') { return ( <Col span={item.width} key={item.uuid}> - <MainSearch config={item} mainSearch={mainSearch} menuType={menuType} refreshdata={this.resetSearch} /> + <MainSearch config={item} menuType={menuType} refreshdata={this.resetSearch} /> </Col> ) } else if (item.type === 'tabs') { @@ -295,18 +205,48 @@ <PropCard config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> </Col> ) + } else if (item.type === 'carousel' && item.subtype === 'datacard') { + return ( + <Col span={item.width} key={item.uuid}> + <CarouselDataCard config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'carousel' && item.subtype === 'propcard') { + return ( + <Col span={item.width} key={item.uuid}> + <CarouselPropCard config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) } else if (item.type === 'table' && item.subtype === 'tablecard') { return ( <Col span={item.width} key={item.uuid}> <TableCard config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> </Col> ) + } else if (item.type === 'table' && item.subtype === 'normaltable') { + return ( + <Col span={item.width} key={item.uuid}> + <NormalTable config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) } else if (item.type === 'group' && item.subtype === 'normalgroup') { return ( <Col span={item.width} key={item.uuid}> <NormalGroup config={item} bids={bids} mainSearch={mainSearch} menuType={menuType} /> </Col> ) + } else if (item.type === 'form') { + return ( + <Col span={item.width} key={item.uuid}> + <NormalForm config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'tree') { + return ( + <Col span={item.width} key={item.uuid}> + <NormalTree config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) } else if (item.type === 'editor') { return ( <Col span={item.width} key={item.uuid}> diff --git a/src/tabviews/custom/components/table/normal-table/index.jsx b/src/tabviews/custom/components/table/normal-table/index.jsx index 86035b3..2c432a8 100644 --- a/src/tabviews/custom/components/table/normal-table/index.jsx +++ b/src/tabviews/custom/components/table/normal-table/index.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types' import {connect} from 'react-redux' import { is, fromJS } from 'immutable' -import { notification } from 'antd' +import { notification, Collapse } from 'antd' import Api from '@/api' import Utils from '@/utils/utils.js' @@ -18,6 +18,8 @@ const MainAction = asyncComponent(() => import('@/tabviews/zshare/actionList')) const MainTable = asyncComponent(() => import('@/tabviews/custom/components/share/normalTable')) const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader')) + +const { Panel } = Collapse class NormalTable extends Component { static propTpyes = { @@ -46,7 +48,6 @@ pageSize: 10, // 姣忛〉鏁版嵁鏉℃暟 orderBy: '', // 鎺掑簭 search: '', // 鎼滅储鏉′欢鏁扮粍锛屼娇鐢ㄦ椂闇�鍒嗗満鏅鐞� - statFields: [], // 鍚堣瀛楁 statFValue: [] // 鍚堣鍊� } @@ -74,6 +75,7 @@ item.key = index item.$$uuid = item[_config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + 1 + '' return item }) } @@ -95,13 +97,25 @@ } }) + let setting = {..._config.setting, ..._config.wrap, style: {}} + if (setting.color) { + setting.style.color = setting.color + } + if (setting.fontSize) { + setting.style.fontSize = setting.fontSize + } + + if (_config.wrap.collapse === 'true') { + _config.wrap.title = _config.wrap.title || ' ' + } + this.setState({ BID: BID || '', title: _config.wrap.title, sync: _sync, data: _data, config: _config, - setting: {..._config.setting, ..._config.wrap}, + setting: setting, searchlist: _config.search, actions: _config.action, columns: _config.cols, @@ -110,6 +124,8 @@ }, () => { if (_config.setting.sync !== 'true' && _config.setting.onload === 'true') { this.loadmaindata() + this.getStatFieldsValue() + } else if (_config.setting.onload === 'true') { this.getStatFieldsValue() } }) @@ -123,7 +139,6 @@ async loadmaindata (reset, repage) { const { mainSearch } = this.props const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize } = this.state - let requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0)) if (setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� this.setState({ @@ -135,26 +150,20 @@ reset && MKEmitter.emit('resetTable', config.uuid, repage) // 鍒楄〃閲嶇疆 return } - if (requireFields.length > 0) { - let labels = requireFields.map(item => item.label) - labels = Array.from(new Set(labels)) - - notification.warning({ - top: 92, - message: this.state.dict['form.required.input'] + labels.join('銆�') + ' !', - duration: 3 - }) - return - } let searches = fromJS(search).toJS() - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { searches.push(item) } }) + } + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return } this.setState({ @@ -173,11 +182,17 @@ MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲 reset && MKEmitter.emit('resetTable', config.uuid, repage) // 鍒楄〃閲嶇疆 + let start = 1 + if (setting.laypage) { + start = pageSize * (pageIndex - 1) + 1 + } + this.setState({ data: result.data.map((item, index) => { item.key = index item.$$uuid = item[setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = start + index + '' return item }), selectedData: [], @@ -204,7 +219,7 @@ const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize } = this.state let searches = fromJS(search).toJS() - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { @@ -236,6 +251,7 @@ data = data.map(item => { if (item.$$uuid === _data.$$uuid) { _data.key = item.key + _data.$Index = item.$Index return _data } else { return item @@ -274,7 +290,7 @@ */ getStatFieldsValue = () => { const { mainSearch } = this.props - const { setting, config, search, BID, orderBy, statFields } = this.state + const { setting, config, search, BID, orderBy } = this.state if (setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� this.setState({ @@ -283,15 +299,10 @@ return } - if (statFields.length === 0 || setting.interType !== 'system' || !setting.dataresource) return - - let requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0)) - if (requireFields.length > 0) { - return - } + if (config.statFields.length === 0 || setting.interType !== 'system' || !setting.dataresource) return let searches = fromJS(search).toJS() - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { @@ -299,9 +310,13 @@ } }) } + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return + } let _orderBy = orderBy || setting.order - let param = UtilsDM.getStatQueryDataParams(setting, statFields, searches, _orderBy, BID, this.props.menuType) + let param = UtilsDM.getStatQueryDataParams(setting, config.statFields, searches, _orderBy, BID, this.props.menuType) if (param.func === 'sPC_Get_TableData') { param.menuname = config.name || '' @@ -313,7 +328,7 @@ let values = [] if (_data) { - statFields.forEach(item => { + config.statFields.forEach(item => { if (_data[item.field] || _data[item.field] === 0) { let val = +_data[item.field] if (isNaN(val)) { @@ -408,14 +423,14 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { mainSearch } = this.props const { arr_field, config, orderBy, search, setting} = this.state if (config.uuid !== menuId) return let searches = search ? fromJS(search).toJS() : [] - if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 + if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢 let keys = searches.map(item => item.key.toLowerCase()) mainSearch.forEach(item => { if (!keys.includes(item.key.toLowerCase())) { @@ -424,7 +439,7 @@ }) } - MKEmitter.emit('execExcelout', config.uuid, btnId, { + MKEmitter.emit('returnModuleParam', config.uuid, btnId, { arr_field: arr_field, orderBy: orderBy || setting.order, search: searches, @@ -486,6 +501,14 @@ } } + getSyncData = (syncModule, btnId) => { + const { config, selectedData } = this.state + + if (config.uuid !== syncModule) return + + MKEmitter.emit('triggerBtnId', btnId, (selectedData || [])) + } + UNSAFE_componentWillReceiveProps(nextProps) { const { sync, config, BID } = this.state @@ -498,16 +521,15 @@ item.key = index item.$$uuid = item[config.setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = index + 1 + '' return item }) this.setState({sync: false, data: _data}) - } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { - if (config.setting.syncRefresh === 'true') { - this.setState({}, () => { - this.reloadtable() - }) - } + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({pageIndex: 1}, () => { + this.reloadtable() + }) } } @@ -517,8 +539,9 @@ componentDidMount () { MKEmitter.addListener('reloadData', this.reloadData) + MKEmitter.addListener('getSyncData', this.getSyncData) MKEmitter.addListener('resetSelectLine', this.resetParentParam) - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -530,8 +553,9 @@ return } MKEmitter.removeListener('reloadData', this.reloadData) + MKEmitter.removeListener('getSyncData', this.getSyncData) MKEmitter.removeListener('resetSelectLine', this.resetParentParam) - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -540,33 +564,64 @@ return ( <div className="custom-normal-table" style={config.style}> - <NormalHeader config={config}/> - {searchlist && searchlist.length ? - <MainSearch BID={BID} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null - } - <MainAction - BID={BID} - setting={setting} - actions={actions} - BData={this.state.BData} - columns={config.columns} - selectedData={selectedData} - /> - <div className={'main-table-box ' + (!actions || actions.length === 0 ? 'no-action' : '')}> - <MainTable + {config.wrap.collapse === 'true' ? <Collapse bordered={false} defaultActiveKey="1" expandIconPosition="right"> + <Panel forceRender={true} header={<NormalHeader config={config}/>} key="1"> + {searchlist && searchlist.length ? + <MainSearch BID={BID} setting={config.wrap} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null + } + <MainAction + BID={BID} + setting={setting} + actions={actions} + BData={this.state.BData} + columns={config.columns} + selectedData={selectedData} + /> + <div className={'main-table-box ' + (!actions || actions.length === 0 ? 'no-action' : '')}> + <MainTable + setting={setting} + columns={columns} + MenuID={config.uuid} + data={this.state.data} + fields={config.columns} + total={this.state.total} + lineMarks={config.lineMarks} + loading={this.state.loading} + refreshdata={this.refreshbytable} + statFValue={this.state.statFValue} + chgSelectData={(selects) => this.setState({selectedData: selects})} + /> + </div> + </Panel> + </Collapse> : <> + <NormalHeader config={config}/> + {searchlist && searchlist.length ? + <MainSearch BID={BID} setting={config.wrap} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null + } + <MainAction + BID={BID} setting={setting} - columns={columns} - MenuID={config.uuid} - data={this.state.data} - fields={config.columns} - total={this.state.total} - lineMarks={config.lineMarks} - loading={this.state.loading} - refreshdata={this.refreshbytable} - statFValue={this.state.statFValue} - chgSelectData={(selects) => this.setState({selectedData: selects})} + actions={actions} + BData={this.state.BData} + columns={config.columns} + selectedData={selectedData} /> - </div> + <div className={'main-table-box ' + (!actions || actions.length === 0 ? 'no-action' : '')}> + <MainTable + setting={setting} + columns={columns} + MenuID={config.uuid} + data={this.state.data} + fields={config.columns} + total={this.state.total} + lineMarks={config.lineMarks} + loading={this.state.loading} + refreshdata={this.refreshbytable} + statFValue={this.state.statFValue} + chgSelectData={(selects) => this.setState({selectedData: selects})} + /> + </div> + </>} </div> ) } diff --git a/src/tabviews/custom/components/table/normal-table/index.scss b/src/tabviews/custom/components/table/normal-table/index.scss index 05a3b2e..1207f33 100644 --- a/src/tabviews/custom/components/table/normal-table/index.scss +++ b/src/tabviews/custom/components/table/normal-table/index.scss @@ -60,4 +60,32 @@ float: right; } } + .ant-collapse { + background-color: transparent; + border-radius: 0px; + > .ant-collapse-item { + border: 0; + >.ant-collapse-header { + padding: 0; + .normal-header { + padding-right: 40px; + } + } + } + .ant-collapse-item:last-child > .ant-collapse-content { + border-radius: 0; + .ant-collapse-content-box { + padding: 0; + >.button-list.toolbar-button { + padding: 0; + line-height: 55px; + padding-right: 60px; + button { + margin-right: 0px; + margin-bottom: 0px; + } + } + } + } + } } \ No newline at end of file diff --git a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx index 1e004a5..5cff8f8 100644 --- a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx +++ b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx @@ -10,7 +10,7 @@ const TabTransfer = asyncComponent(() => import('../../share/tabtransfer')) const { TabPane } = Tabs -class antvBarLineChart extends Component { +class antvTabs extends Component { static propTpyes = { bids: PropTypes.any, // 鐖剁骇Id闆� config: PropTypes.object, // 缁勪欢閰嶇疆淇℃伅 @@ -79,4 +79,4 @@ } } -export default antvBarLineChart \ No newline at end of file +export default antvTabs \ No newline at end of file diff --git a/src/tabviews/custom/components/tree/antd-tree/index.jsx b/src/tabviews/custom/components/tree/antd-tree/index.jsx new file mode 100644 index 0000000..7cfd7c8 --- /dev/null +++ b/src/tabviews/custom/components/tree/antd-tree/index.jsx @@ -0,0 +1,452 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Spin, Empty, notification, Input, Tree, Icon } from 'antd' +import moment from 'moment' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import UtilsDM from '@/utils/utils-datamanage.js' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const { TreeNode } = Tree +const { Search } = Input + +class NormalTree extends Component { + static propTpyes = { + BID: PropTypes.any, // 鐖剁骇Id + data: PropTypes.array, // 缁熶竴鏌ヨ鏁版嵁 + config: PropTypes.object, // 缁勪欢閰嶇疆淇℃伅 + mainSearch: PropTypes.any, // 澶栧眰鎼滅储鏉′欢 + menuType: PropTypes.any, // 鑿滃崟绫诲瀷 + } + + state = { + BID: '', // 涓昏〃ID + config: null, // 鍥捐〃閰嶇疆淇℃伅 + loading: false, // 鏁版嵁鍔犺浇鐘舵�� + sync: false, // 鏄惁缁熶竴璇锋眰鏁版嵁 + data: null, // 鏁版嵁 + searchkey: null, // 杩囨护鏉′欢 + treedata: null, // 鍒楄〃鏁版嵁闆� + treeNodes: null, // 鍒楄〃鏁版嵁闆� + expandedKeys: [], // 灞曞紑鐨勬爲鑺傜偣 + selectedKeys: [], // 閫変腑鐨勬爲鑺傜偣 + } + + UNSAFE_componentWillMount () { + const { config, data, initdata, BID } = this.props + let _config = fromJS(config).toJS() + let _data = null + let _sync = config.setting.sync === 'true' + + if (config.setting.sync === 'true' && data) { + _data = data[config.dataName] || [] + _sync = false + } else if (config.setting.sync === 'true' && initdata) { + _data = initdata || [] + _sync = false + } + + this.setState({ + config: _config, + data: _data, + BID: BID || '', + arr_field: _config.columns.map(col => col.field).join(','), + sync: _sync + }, () => { + if (config.setting.sync !== 'true' && config.setting.onload === 'true') { + this.loadData() + } else if (config.setting.sync === 'true' && _data) { + this.handleData() + } + }) + } + + /** + * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹� + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { sync, config } = this.state + + if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) { + let _data = [] + if (nextProps.data && nextProps.data[config.dataName]) { + _data = nextProps.data[config.dataName] || [] + } + + this.setState({sync: false, data: _data}, () => { + this.handleData() + }) + } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { + this.setState({}, () => { + this.loadData() + }) + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('reloadData', this.reloadData) + MKEmitter.addListener('resetSelectLine', this.resetParentParam) + this.handleTimer() + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + clearTimeout(this.timer) + this.setState = () => { + return + } + MKEmitter.removeListener('reloadData', this.reloadData) + MKEmitter.removeListener('resetSelectLine', this.resetParentParam) + } + + handleTimer = () => { + const { config } = this.state + + if (!config.timer) return + + const _change = { '15s': 15000, '30s': 30000, '1min': 60000, '5min': 300000, '10min': 600000, '15min': 900000, '30min': 1800000, '1hour': 3600000 } + + let timer = _change[config.timer] + + if (!timer) return + + let _param = { + func: 's_get_timers_role', + LText: `select '${window.GLOB.appkey || ''}','${config.uuid}'`, + timer_type: config.timer, + component_id: config.uuid + } + + _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') // 鏃堕棿鎴� + _param.LText = Utils.formatOptions(_param.LText) // 鍏抽敭瀛楃鏇挎崲锛宐ase64鍔犲瘑 + _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp) // md5瀵嗛挜 + + Api.getSystemConfig(_param).then(result => { + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + return + } else if (result.run_type) { + this.setState({timer}) + this.timer = setTimeout(() => { + this.timerTask() + }, timer) + } + }) + } + + timerTask = () => { + const { timer } = this.state + if (!timer) return + + this.loadData(true) + + this.timer = setTimeout(() => { + this.timerTask() + }, timer) + } + + reloadData = (menuId) => { + const { config } = this.state + + if (config.uuid !== menuId) return + + this.loadData() + } + + resetParentParam = (MenuID, id) => { + const { config } = this.state + + if (!config.setting.supModule || config.setting.supModule !== MenuID) return + if (id !== this.state.BID) { + this.setState({ BID: id }, () => { + this.loadData() + }) + } + } + + /** + * @description 鏁版嵁鍔犺浇 + */ + async loadData (hastimer) { + const { mainSearch, menuType } = this.props + const { config, arr_field, BID } = this.state + + if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇� + this.setState({ + data: [] + }, () => { + this.handleData() + }) + return + } + + let searches = config.setting.useMSearch && mainSearch ? mainSearch : [] + + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + return + } + + if (!hastimer) { + this.setState({ + loading: true + }) + } + + let _orderBy = config.setting.order || '' + let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID, menuType) + + let result = await Api.genericInterface(param) + if (result.status) { + this.setState({ + data: result.data, + loading: false + }, () => { + this.handleData() + }) + } else { + this.setState({ + loading: false, + timer: null + }) + notification.error({ + top: 92, + message: result.message, + duration: 10 + }) + } + } + + handleData = () => { + const { data, searchkey, config } = this.state + if (!data || data.length === 0) { + this.setState({ + treedata: [], + treeNodes: [], + }) + return + } + let parentNodes = [] + let _options = [] + let logMap = new Map() + + data.forEach(item => { + let pval = item[config.wrap.parentField] + let val = item[config.wrap.valueField] + + if (!val || logMap.has(val)) return + + logMap.set(val, true) + if (pval === config.wrap.mark) { + parentNodes.push({ + // ...item, + $title: item[config.wrap.labelField] || '', + $key: val, + $parentId: '' + }) + } else if (pval) { + _options.push({ + // ...item, + $title: item[config.wrap.labelField] || '', + $key: val, + $parentId: pval + }) + } + }) + let _treedata = this.getTree(parentNodes, _options) + + let _treeNodes = [] + + if (!searchkey) { + _treeNodes = fromJS(_treedata).toJS() + } else { + _treeNodes = this.getFilterTree(fromJS(_treedata).toJS(), searchkey.toLowerCase()) + } + + this.setState({ + treedata: _treedata, + treeNodes: _treeNodes, + }) + } + + treeFilter = (value) => { + const { treedata } = this.state + + let _treeNodes = [] + + if (!value) { + _treeNodes = fromJS(treedata).toJS() + } else { + _treeNodes = this.getFilterTree(fromJS(treedata).toJS(), value.toLowerCase()) + } + + this.setState({ + searchkey: value, + treeNodes: _treeNodes + }) + } + + /** + * @description 鑾峰彇缁撴瀯鏍戜俊鎭� + */ + getFilterTree = (parents, searchkey) => { + return parents.filter(node => { + if (!node.children) { + return (node.$title.toLowerCase().indexOf(searchkey) >= 0 || node.$key.toLowerCase().indexOf(searchkey) >= 0) + } else { + if (node.$title.toLowerCase().indexOf(searchkey) >= 0 || node.$key.toLowerCase().indexOf(searchkey) >= 0) { + return true + } + + node.children = this.getFilterTree(node.children, searchkey) + if (node.children.length === 0) { + return false + } else { + return true + } + } + }) + } + + /** + * @description 鑾峰彇缁撴瀯鏍戜俊鎭� + */ + getTree = (parents, options) => { + parents.forEach(parent => { + parent.children = [] + // 娣诲姞鑿滃崟鐨勫瓙鍏冪礌 + options = options.filter(option => { + if (option.$parentId === parent.$key) { + parent.children.push(option) + return false + } + return true + }) + + if (parent.children.length === 0) { + parent.children = null + } else { + parent.children = this.getTree(parent.children, options) + } + }) + return parents + } + + /** + * @description 鑾峰彇鏍戣妭鐐� + */ + renderTreeNodes = (nodes) => { + return nodes.map(item => { + if (item.children) { + return ( + <TreeNode icon={<span><Icon type="folder-open" /><Icon type="folder" /></span>} title={item.$title} key={item.$key} dataRef={item}> + {this.renderTreeNodes(item.children)} + </TreeNode> + ) + } + return <TreeNode icon={<Icon type="file" />} key={item.$key} title={item.$title} dataRef={item} isLeaf /> + }) + } + + changeExpandedKeys = (expandedKeys) => { + this.setState({ + expandedKeys: expandedKeys + }) + } + + // 鍙抽敭灞曞紑鑺傜偣涓嬬殑鍏ㄩ儴鍒嗘敮 + changeExpandedAllKeys = ({event, node}) => { + const { expandedKeys } = this.state + let _node = node.props.dataRef + event.stopPropagation() + + let keys = [] + this.getExpandKeys(_node, keys) + + this.setState({ + expandedKeys: Array.from(new Set([...keys, ...expandedKeys])), + }) + } + + getExpandKeys = (node, keys) => { + if (node.children) { + keys.push(node.$key) + node.children.forEach(_node => { + this.getExpandKeys(_node, keys) + }) + } + } + + selectTreeNode = (selectedKeys, {selected, node}) => { + const { config } = this.state + let _expandedKeys = fromJS(this.state.expandedKeys).toJS() + let _data = fromJS(node.props.dataRef).toJS() + + if (_expandedKeys.indexOf(_data.$key) >= 0) { + _expandedKeys = _expandedKeys.filter(key => key !== _data.$key) + } else { + if (_data.children) { + _expandedKeys.push(_data.$key) + _expandedKeys = Array.from(new Set(_expandedKeys)) + } + } + + if (selected) { + MKEmitter.emit('resetSelectLine', config.uuid, (_data ? _data.$key : ''), _data) + } + + this.setState({ + expandedKeys: _expandedKeys, + selectedKeys: [_data.$key] + }) + } + + render() { + const { config, loading, treeNodes, expandedKeys, selectedKeys } = this.state + + return ( + <div className="custom-tree-box" style={config.style}> + {loading ? + <div className="loading-mask"> + <div className="ant-spin-blur"></div> + <Spin /> + </div> : null + } + {config.wrap.title || config.wrap.searchable === 'true' ? <div className="tree-header" style={config.headerStyle}> + <span className="title">{config.wrap.title}</span> + {config.wrap.searchable === 'true' ? <Search allowClear onSearch={this.treeFilter} /> : null} + </div> : null} + {treeNodes && treeNodes.length > 0 ? <div className="tree-box"> + <Tree + blockNode + onSelect={this.selectTreeNode} + expandedKeys={expandedKeys} + selectedKeys={selectedKeys} + onRightClick={this.changeExpandedAllKeys} + onExpand={this.changeExpandedKeys} + showIcon={config.wrap.showIcon === 'true'} + showLine={config.wrap.showLine === 'true'} + > + {this.renderTreeNodes(treeNodes)} + </Tree> + </div> : null} + {treeNodes && treeNodes.length === 0 ? <Empty description={false}/> : null} + </div> + ) + } +} + +export default NormalTree \ No newline at end of file diff --git a/src/tabviews/custom/components/tree/antd-tree/index.scss b/src/tabviews/custom/components/tree/antd-tree/index.scss new file mode 100644 index 0000000..13f499c --- /dev/null +++ b/src/tabviews/custom/components/tree/antd-tree/index.scss @@ -0,0 +1,97 @@ +.custom-tree-box { + position: relative; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 100px; + + .tree-header { + position: relative; + height: 45px; + padding-right: 8px; + border-bottom: 1px solid #e8e8e8; + overflow: hidden; + letter-spacing: 0px; + + .title { + text-decoration: inherit; + font-weight: inherit; + font-style: inherit; + float: left; + line-height: 45px; + margin-left: 10px; + position: relative; + z-index: 1; + } + .ant-input-search.ant-input-affix-wrapper { + width: calc(100% - 140px); + max-width: 130px; + margin-top: 6px; + float: right; + height: 30px; + border-radius: 20px; + border: 1px solid #d9d9d9; + opacity: 0.6; + input { + border: none; + border-radius: 20px; + height: 28px; + } + } + } + .tree-box { + overflow-x: auto; + padding-bottom: 10px; + + .ant-tree-node-content-wrapper-close > span > span > .anticon-folder-open { + display: none; + } + .ant-tree-node-content-wrapper-open > span > span > .anticon-folder { + display: none; + } + } + .tree-box::-webkit-scrollbar { + height: 10px; + } + .tree-box::-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); + } + .tree-box::-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-empty { + position: absolute; + top: calc(50% - 34px); + left: calc(50% - 92px); + + .ant-empty-image { + height: 60px; + } + } + .loading-mask { + position: absolute; + left: 0px; + top: 0; + right: 0px; + bottom: 0px; + display: flex; + align-items: center; + justify-content: center; + text-align: justify; + z-index: 1; + + .ant-spin-blur { + position: absolute; + width: 100%; + height: 100%; + opacity: 0.5; + background: #ffffff; + } + } +} diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx index 97b6365..8cf4cc6 100644 --- a/src/tabviews/custom/index.jsx +++ b/src/tabviews/custom/index.jsx @@ -3,15 +3,13 @@ import { connect } from 'react-redux' import { is, fromJS } from 'immutable' import { notification, Spin, Row, Col } from 'antd' -import moment from 'moment' -import md5 from 'md5' import Api from '@/api' import options from '@/store/options.js' import zhCN from '@/locales/zh-CN/main.js' import enUS from '@/locales/en-US/main.js' import Utils from '@/utils/utils.js' -import UtilsDM from '@/utils/utils-datamanage.js' +import UtilsDM, { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js' import asyncComponent from '@/utils/asyncComponent' import MKEmitter from '@/utils/events.js' import NotFount from '@/components/404' @@ -21,6 +19,8 @@ const AntvBarAndLine = asyncComponent(() => import('./components/chart/antv-bar-line')) const AntvPie = asyncComponent(() => import('./components/chart/antv-pie')) const AntvTabs = asyncComponent(() => import('./components/tabs/antv-tabs')) +const AntvDashboard = asyncComponent(() => import('./components/chart/antv-dashboard')) +const AntvScatter = asyncComponent(() => import('./components/chart/antv-scatter')) const DataCard = asyncComponent(() => import('./components/card/data-card')) const PropCard = asyncComponent(() => import('./components/card/prop-card')) const NormalForm = asyncComponent(() => import('./components/form/normal-form')) @@ -32,6 +32,8 @@ const NormalGroup = asyncComponent(() => import('./components/group/normal-group')) const BraftEditor = asyncComponent(() => import('./components/editor/braft-editor')) const SandBox = asyncComponent(() => import('./components/code/sand-box')) +const NormalTree = asyncComponent(() => import('./components/tree/antd-tree')) +const Balcony = asyncComponent(() => import('./components/card/balcony')) const SettingComponent = asyncComponent(() => import('@/tabviews/zshare/settingcomponent')) const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage')) @@ -167,9 +169,9 @@ } let regs = [ - { reg: /@userName@/ig, value: userName }, - { reg: /@fullName@/ig, value: fullName }, - { reg: /@login_city@/ig, value: city } + { reg: /@userName@/ig, value: `'${userName}'` }, + { reg: /@fullName@/ig, value: `'${fullName}'` }, + { reg: /@login_city@/ig, value: `'${city}'` } ] if (window.GLOB.externalDatabase !== null) { @@ -182,7 +184,7 @@ config.urlFields.forEach(field => { let val = `'${param ? (param[field] || '') : ''}'` regs.push({ - reg: new RegExp(field, 'ig'), + reg: new RegExp('@' + field + '@', 'ig'), value: val }) }) @@ -336,7 +338,7 @@ }) Api.directRequest(url, setting.method, param, setting.cross).then(res => { - if (typeof(res) !== 'object' || Array.isArray(res)) { + if (typeof(res) !== 'object') { let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒' if (typeof(res) === 'string') { @@ -351,6 +353,9 @@ this.customCallbackRequest(_result, setting, inters) } else { + if (Array.isArray(res)) { + res = { data: res } + } res.mk_api_key = mkey this.customCallbackRequest(res, setting, inters) } @@ -462,7 +467,7 @@ tab.components.forEach(comp => { if (comp.type === 'tabs' && comp.parentIds) { supIds.push(...comp.parentIds) - } else if (comp.setting.supModule) { + } else if (comp.setting && comp.setting.supModule) { supIds.push(comp.setting.supModule) } }) @@ -477,14 +482,14 @@ } item.components = this.filterComponent(item.components, roleId, permAction, permMenus) - } else if (item.type === 'pie' || item.type === 'bar' || item.type === 'line') { + } else if (['pie', 'bar', 'line', 'dashboard', 'scatter'].includes(item.type)) { if ( item.plot.blacklist && item.plot.blacklist.length > 0 && item.plot.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0 ) { return false } - } else { + } else if (item.wrap) { if ( item.wrap.blacklist && item.wrap.blacklist.length > 0 && item.wrap.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0 @@ -492,21 +497,50 @@ return false } } - // 鎼滅储榛戝悕鍗曡繃婊� + + // 鎼滅储鏉′欢鍒濆鍖� if (item.search && item.search.length > 0) { - item.search = item.search.map(cell => { - cell.oriInitval = cell.initval - - if (!cell.blacklist || cell.blacklist.length === 0) return cell - if (cell.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { - cell.Hide = 'true' - } - - return item - }) + item.search = Utils.initSearchVal(item.search) } + if (item.type === 'table' && item.subtype === 'normaltable') { - item.cols = this.getCols(item.cols, roleId, permMenus) + let statFields = [] + let getCols = (cols) => { + return cols.filter(col => { + if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { + return false + } else if (col.Hide === 'true') { + return false + } + if (col.type === 'number' && col.sum === 'true' && !statFields.includes(col.field)) { + statFields.push(col) + } else if (col.type === 'colspan') { + col.subcols = getCols(col.subcols || []) + if (col.subcols.length === 0) { + return false + } + } else if (col.type === 'custom') { + col.elements = col.elements.map(cell => { + if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height) { + cell.innerHeight = 'auto' + } + return cell + }) + } + + if (col.linkmenu && col.linkmenu.length > 0) { + let menu_id = col.linkmenu.pop() + col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || '' + } else { + col.linkThdMenu = '' + } + + return true + }) + } + + item.cols = getCols(item.cols) + item.statFields = statFields } // 鏉冮檺杩囨护 @@ -516,20 +550,26 @@ item.action = item.action.filter(cell => { cell.logLabel = item.name + '-' + cell.label cell.ContainerId = this.state.ContainerId - cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : '' + cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : '' cell.$menuId = item.uuid cell.$tabId = tabId - cell.$type = 'CustomPage' + cell.$view = 'CustomPage' if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃� cell = this.getPrinter(cell, item.uuid) } + if (cell.btnstyle) { // 鍏煎 + cell.style = cell.style || {} + cell.style = {...cell.style, ...cell.btnstyle} + } + return isHS || permAction[cell.uuid] }) } + if (item.type === 'card') { - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { let _hasheight = card.style.height && card.style.height !== 'auto' if (card.style.shadow) { // 鍗$墖闃村奖 @@ -542,13 +582,17 @@ cell.logLabel = item.name + '-' + cell.label cell.Ot = 'requiredSgl' cell.ContainerId = this.state.ContainerId - cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : '' + cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : '' cell.$menuId = item.uuid cell.$tabId = tabId - cell.$type = 'CustomPage' + cell.$view = 'CustomPage' if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃� cell = this.getPrinter(cell, item.uuid) + } + if (card.btnstyle) { // 鍏煎 + card.style = card.style || {} + card.style = {...card.style, ...card.btnstyle} } } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height && _hasheight) { cell.innerHeight = 'auto' @@ -561,13 +605,17 @@ cell.logLabel = item.name + '-' + cell.label cell.Ot = 'requiredSgl' cell.ContainerId = this.state.ContainerId - cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : '' + cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : '' cell.$menuId = item.uuid cell.$tabId = tabId - cell.$type = 'CustomPage' + cell.$view = 'CustomPage' if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃� cell = this.getPrinter(cell, item.uuid) + } + if (card.btnstyle) { // 鍏煎 + card.style = card.style || {} + card.style = {...card.style, ...card.btnstyle} } } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height && _hasheight) { cell.innerHeight = 'auto' @@ -575,21 +623,45 @@ return cell.eleType !== 'button' || isHS || permAction[cell.uuid] }) }) + } else if (item.type === 'balcony') { + item.elements = item.elements.filter(cell => { + if (cell.eleType === 'button') { + cell.logLabel = item.name + '-' + cell.label + cell.ContainerId = this.state.ContainerId + cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : '' + cell.$menuId = item.uuid + cell.$tabId = tabId + cell.$view = 'CustomPage' + + if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃� + cell = this.getPrinter(cell, item.uuid) + } + } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height) { + cell.innerHeight = 'auto' + } + + return cell.eleType !== 'button' || isHS || permAction[cell.uuid] + }) } else if ((item.type === 'table' && item.subtype === 'tablecard') || item.type === 'carousel') { - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { let _hasheight = card.style.height && card.style.height !== 'auto' card.elements = card.elements.filter(cell => { if (cell.eleType === 'button') { cell.logLabel = item.name + '-' + cell.label cell.Ot = 'requiredSgl' cell.ContainerId = this.state.ContainerId - cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : '' + cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : '' cell.$menuId = item.uuid cell.$tabId = tabId - cell.$type = 'CustomPage' + cell.$view = 'CustomPage' if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃� cell = this.getPrinter(cell, item.uuid) + } + + if (card.btnstyle) { // 鍏煎 + card.style = card.style || {} + card.style = {...card.style, ...card.btnstyle} } } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height && _hasheight) { cell.innerHeight = 'auto' @@ -604,13 +676,18 @@ cell.logLabel = item.name + '-' + cell.label cell.Ot = 'requiredSgl' cell.ContainerId = this.state.ContainerId - cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : '' + cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : '' cell.$menuId = item.uuid cell.$tabId = tabId - cell.$type = 'CustomPage' + cell.$view = 'CustomPage' if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃� cell = this.getPrinter(cell, item.uuid) + } + + if (cell.btnstyle) { // 鍏煎 + cell.style = cell.style || {} + cell.style = {...cell.style, ...cell.btnstyle} } return isHS || permAction[cell.uuid] @@ -656,31 +733,6 @@ return item } - getCols = (cols, roleId, permMenus) => { - return cols.filter(col => { - if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { - return false - } else if (col.Hide === 'true') { - return false - } - if (col.type === 'colspan') { - col.subcols = this.getCols(col.subcols || [], roleId, permMenus) - if (col.subcols.length === 0) { - return false - } - } - - if (col.linkmenu && col.linkmenu.length > 0) { - let menu_id = col.linkmenu.pop() - col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || '' - } else { - col.linkThdMenu = '' - } - - return true - }) - } - // 鏍煎紡鍖栭粯璁よ缃� formatSetting = (components, params, mainSearch, inherit, regs) => { return components.map(component => { @@ -697,12 +749,19 @@ return component } - if (['propcard', 'brafteditor', 'sandbox', 'stepform'].includes(component.subtype) && component.wrap.datatype === 'static') { - component.format = '' + if (component.setting) { + component.setting.useMSearch = component.setting.useMSearch === 'true' + component.setting.syncRefresh = (component.setting.useMSearch && component.setting.syncRefresh === 'true') } - if (!component.setting) return component // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂 - if (!component.format) return component // 娌℃湁鍔ㄦ�佹暟鎹� 鏁版嵁鏍煎紡 array 鎴� object + if (component.wrap && component.wrap.datatype === 'static') { + component.format = '' + component.setting = component.setting || {} + component.setting.useMSearch = false + component.setting.syncRefresh = false + } + + if (!component.setting || !component.format) return component // 1銆佷笉浣跨敤绯荤粺鍑芥暟鏃讹紱2銆� 娌℃湁鍔ㄦ�佹暟鎹� 鏁版嵁鏍煎紡 array 鎴� object if (component.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂 component.setting.sync = 'false' component.setting.laypage = component.setting.laypage === 'true' @@ -718,7 +777,7 @@ } }) delete component.scripts - + component.setting.$name = component.name || '' component.setting.execute = component.setting.execute !== 'false' // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡 component.setting.laypage = component.setting.laypage === 'true' // 鏄惁鍒嗛〉锛岃浆涓篵oolean 缁熶竴鏍煎紡 @@ -750,8 +809,25 @@ // dataName 绯荤粺鐢熸垚鐨勬暟鎹簮鍚嶇О // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ if (component.floor === 1 && component.dataName && (!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true' && component.setting.sync === 'true') { - let param = this.getDefaultParam(component, mainSearch) - params.push(param) + let searchlist = [] + if (component.search && component.search.length > 0) { + searchlist = Utils.initMainSearch(component.search) + } + if (component.setting.useMSearch) { + let keys = searchlist.map(item => item.key) + mainSearch.forEach(item => { + if (!keys.includes(item.key)) { + searchlist.push(item) + } + }) + } + + if (searchlist.filter(item => item.required && item.value === '').length > 0) { + component.setting.sync = 'false' + component.setting.onload = 'false' + } else { + params.push(getStructDefaultParam(component, searchlist)) + } } else if (component.floor === 1) { component.setting.sync = 'false' } @@ -761,138 +837,10 @@ } /** - * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鐨勫弬鏁� - */ - getDefaultParam = (component, mainSearch) => { - const { columns, search, setting, dataName, format } = component - - let searchlist = [] - if (search && search.length > 0) { - searchlist = Utils.initMainSearch(search) - } - - if (setting.useMSearch === 'true') { - let keys = searchlist.map(item => item.key) - mainSearch.forEach(item => { - if (!keys.includes(item.key)) { - searchlist.push(item) - } - }) - } - - let arr_field = columns.map(col => col.field) - let _dataresource = setting.dataresource - let _customScript = setting.customScript - - - if (setting.queryType === 'statistics' || _customScript) { - let allSearch = Utils.getAllSearchOptions(searchlist) - let regoptions = allSearch.map(item => { - return { - reg: new RegExp('@' + item.key + '@', 'ig'), - value: `'${item.value}'` - } - }) - - regoptions.forEach(item => { - if (_dataresource && setting.queryType === 'statistics') { - _dataresource = _dataresource.replace(item.reg, item.value) - } - _customScript = _customScript.replace(item.reg, item.value) - }) - } - - let _search = '' - if (setting.queryType !== 'statistics' && _dataresource) { - _search = Utils.joinMainSearchkey(searchlist) - _search = _search ? 'where ' + _search : '' - } - - if (setting.order && _dataresource) { - _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows ` - } else if (_dataresource) { - _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} ` - } - - // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞 - if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) { - _customScript && console.info(`${_dataresource ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) - _dataresource && console.info(_dataresource) - } - - return { - name: dataName, - columns: columns, - par_tablename: '', - type: format === 'array' ? format : '', - primaryKey: setting.primaryKey || '', - foreign_key: '', - sql: _dataresource, - script: _customScript - } - } - - /** * @description 涓昏〃鏁版嵁鍔犺浇 */ loadmaindata = (params) => { - const { config } = this.state - let LText_field = [] - let diffUser = false - let userName = sessionStorage.getItem('User_Name') || '' - let fullName = sessionStorage.getItem('Full_Name') || '' - let city = sessionStorage.getItem('city') || '' - - if (sessionStorage.getItem('isEditState') === 'true') { - userName = sessionStorage.getItem('CloudUserName') || '' - fullName = sessionStorage.getItem('CloudFullName') || '' - } - - let _LText = params.map((item, index) => { - let _script = item.script - - if (index === 0) { - _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50) - select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}' - ${_script} - ` - } - if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) { - diffUser = true - } - - item.columns.forEach(cell => { - LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`) - }) - return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort` - }) - - // 鎶婂ぇ鎺ュ彛sPC_Get_structured_data鐨刲text鎷嗘垚涓変唤锛岀涓�娈碉細@LText1锛岀浜屾@LText锛岀涓夋@LText2 - let param = { - func: 'sPC_Get_structured_data', - LText: _LText.join(' union all '), - LText_field: LText_field.join(' union all '), - BID: this.state.BID || '' - } - - let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText) - - param.LText1 = LText1 - param.LText = LText - param.LText2 = LText2 - param.LText_field = Utils.formatOptions(param.LText_field) - - if (config.cacheUseful === 'true') { - param.time_type = config.timeUnit - param.time_limit = config.cacheTime - if (diffUser) { - param.userid = sessionStorage.getItem('UserID') - } - param.data_md5 = md5(JSON.stringify(param)) - } - - param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - param.secretkey = Utils.encrypt(param.LText, param.timestamp) + let param = getStructuredParams(params, this.state.config, this.state.BID) this.setState({loading: true, loadingview: false}) @@ -1005,6 +953,18 @@ <AntvPie config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> </Col> ) + } else if (item.type === 'scatter') { + return ( + <Col span={item.width} key={item.uuid}> + <AntvScatter config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'dashboard') { + return ( + <Col span={item.width} key={item.uuid}> + <AntvDashboard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) } else if (item.type === 'form') { return ( <Col span={item.width} key={item.uuid}> @@ -1014,7 +974,7 @@ } else if (item.type === 'search') { return ( <Col span={item.width} key={item.uuid}> - <MainSearch config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} refreshdata={this.resetSearch} /> + <MainSearch config={item} BID={BID} menuType={menuType} refreshdata={this.resetSearch} /> </Col> ) } else if (item.type === 'tabs') { @@ -1033,6 +993,12 @@ return ( <Col span={item.width} key={item.uuid}> <PropCard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) + } else if (item.type === 'balcony') { + return ( + <Col span={item.width} key={item.uuid}> + <Balcony menu={config} config={item} data={data} BID={_bid} menuType={menuType} /> </Col> ) } else if (item.type === 'carousel' && item.subtype === 'datacard') { @@ -1071,6 +1037,12 @@ <BraftEditor config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> </Col> ) + } else if (item.type === 'tree') { + return ( + <Col span={item.width} key={item.uuid}> + <NormalTree config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> + </Col> + ) } else if (item.type === 'code') { return ( <Col span={item.width} key={item.uuid}> diff --git a/src/tabviews/custom/index.scss b/src/tabviews/custom/index.scss index 4e7b7e6..a0314f1 100644 --- a/src/tabviews/custom/index.scss +++ b/src/tabviews/custom/index.scss @@ -43,6 +43,12 @@ .ant-btn-link:hover { opacity: 0.8; } + .button-list.toolbar-button { + button { + height: auto; + min-height: 32px; + } + } } .custom-page-wrap.loading { .ant-spin-spinning:not(.view-spin) { diff --git a/src/tabviews/formtab/formgroup/index.jsx b/src/tabviews/formtab/formgroup/index.jsx index aed3d1a..e03fbc1 100644 --- a/src/tabviews/formtab/formgroup/index.jsx +++ b/src/tabviews/formtab/formgroup/index.jsx @@ -4,7 +4,6 @@ import { Form, Row, Col, Input, InputNumber, Select, DatePicker, notification, Collapse } from 'antd' import moment from 'moment' import { formRule } from '@/utils/option.js' -import Utils from '@/utils/utils.js' import FileUpload from '@/tabviews/zshare/fileupload' import './index.scss' @@ -71,24 +70,6 @@ _fieldsvalue[key] = _val } else if (datatype[key] === 'fileupload') { let _val = nextProps.data[key] ? nextProps.data[key] : '' - - if (_val) { - try { - _val = _val.split(',').map((url, index) => { - return { - uid: `${index}`, - name: url.slice(url.lastIndexOf('/') + 1), - status: 'done', - url: url, - origin: true - } - }) - } catch { - _val = [] - } - } else { - _val = [] - } _fieldsvalue[key] = _val } else if (datatype[key] === 'text' || datatype[key] === 'textarea') { @@ -521,30 +502,11 @@ </Col> ) } else if (item.type === 'fileupload') { - let filelist = this.props.data ? this.props.data[item.field] : item.initval - if (filelist && this.state.readin[item.field]) { - try { - filelist = filelist.split(',').map((url, index) => { - return { - uid: `${index}`, - name: url.slice(url.lastIndexOf('/') + 1), - status: 'done', - url: url, - origin: true - } - }) - } catch { - filelist = [] - } - } else { - filelist = [] - } - fields.push( <Col span={24 / cols} key={index}> <Form.Item label={item.label}> {getFieldDecorator(item.field, { - initialValue: filelist, + initialValue: item.initval, rules: [ { required: item.required === 'true', @@ -552,7 +514,7 @@ } ] })( - <FileUpload /> + <FileUpload config={item}/> )} </Form.Item> </Col> @@ -674,19 +636,8 @@ _value = values[key] ? values[key].join(',') : '' } else if (this.state.datatype[key] === 'fileupload') { - let vals = [] + _value = values[key] - if (values[key] && values[key].length > 0) { - values[key].forEach(_val => { - if (_val.origin && _val.url) { - vals.push(_val.url) - } else if (!_val.origin && _val.status === 'done' && _val.response) { - vals.push(Utils.getrealurl(_val.response)) - } - }) - } - - _value = vals.join(',') } else if (this.state.datatype[key] === 'text' || this.state.datatype[key] === 'textarea') { _value = values[key].replace(/\t*|\v*/g, '') // 鍘婚櫎鍒惰〃绗� diff --git a/src/tabviews/home/index.jsx b/src/tabviews/home/index.jsx index 26fbcd0..dfb3f7d 100644 --- a/src/tabviews/home/index.jsx +++ b/src/tabviews/home/index.jsx @@ -1,5 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' +import { connect } from 'react-redux' import { notification, Spin } from 'antd' import Api from '@/api' @@ -17,11 +18,25 @@ state = { loading: true, background: sessionStorage.getItem('home_background'), + waiting: true, view: '' } componentDidMount () { this.loadHomeConfig() + if (this.props.permMenus.length > 0 && JSON.stringify(this.props.permAction) !== '{}') { + this.setState({ + waiting: false + }) + } + } + + UNSAFE_componentWillReceiveProps (nextProps) { + if (nextProps.permMenus.length > 0 && JSON.stringify(nextProps.permAction) !== '{}') { + this.setState({ + waiting: false + }) + } } loadHomeConfig = () => { @@ -39,6 +54,7 @@ } else { this.setState({ loading: false, + waiting: false, view: 'default' }) } @@ -57,9 +73,9 @@ } render() { - const { loading, view, background } = this.state + const { loading, waiting, view, background } = this.state - if (loading) { + if (loading || waiting) { return (<div className="home-loading-view" style={{background: background}}><Spin className="home-box-spin" size="large" /></div>) } else if (view === 'custom') { return (<CustomPage MenuID={this.props.MenuID}/>) @@ -69,4 +85,15 @@ } } -export default Home \ No newline at end of file +const mapStateToProps = (state) => { + return { + permAction: state.permAction, + permMenus: state.permMenus + } +} + +const mapDispatchToProps = () => { + return {} +} + +export default connect(mapStateToProps, mapDispatchToProps)(Home) \ No newline at end of file diff --git a/src/tabviews/scriptmanage/config.jsx b/src/tabviews/scriptmanage/config.jsx index e9ccbfc..493937d 100644 --- a/src/tabviews/scriptmanage/config.jsx +++ b/src/tabviews/scriptmanage/config.jsx @@ -15,7 +15,7 @@ }, tables: [{"TbName":"s_custom_script","Remark":"鑷畾涔夎剼鏈�"}], search: [ - {"label":"鎻忚堪","field":"Remark","type":"text","initval":"","match":"like","required":"false","ratio":6,"blacklist":[],"uuid":"1587005744706mppigfhf206gciiivf9"} + {"label":"鎻忚堪","field":"Remark","type":"text","initval":"","oriInitval":"", "match":"like","required": false,"ratio":6,"blacklist":[],"uuid":"1587005744706mppigfhf206gciiivf9"} ], action:[ {"label":"娣诲姞","OpenType":"pop","intertype":"inner","innerFunc":"s_custom_script_adduptdel","position":"toolbar","Ot":"notRequired","execSuccess":"grid","execError":"never","icon":"","class":"green","sql":"s_custom_script","sqlType":"insert","uuid":"1587006129803057fs8mb9q151ae6165"}, diff --git a/src/tabviews/scriptmanage/index.jsx b/src/tabviews/scriptmanage/index.jsx index 68a4ce8..868fc97 100644 --- a/src/tabviews/scriptmanage/index.jsx +++ b/src/tabviews/scriptmanage/index.jsx @@ -135,7 +135,6 @@ if (result.status) { this.setState({ data: result.data.map((item, index) => { - // item.LongParam = this.UnformatOptions(item.LongParam) item.key = index item.$$uuid = item[setting.primaryKey] || '' return item @@ -154,75 +153,6 @@ }) } } - - // UnformatOptions = (value) => { - // if (!value) return '' - // let salt = 'minKe' // 鐩愬�� - // let _value = '' - // const formatKeys = [ - // { 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 ' } - // ] - - // try { - // try { - // _value = JSON.parse(window.decodeURIComponent(window.atob(value))) - // } catch { - // _value = '' - // } - - // if (!_value) { - // _value = window.atob(value) - // _value = _value.replace(salt, '') - // _value = window.decodeURIComponent(window.atob(_value)) - - // _value = _value.replace(/\smpercent\s/g, '%') - - // formatKeys.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 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鐨勫弬鏁� diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx index b31d3b2..f917266 100644 --- a/src/tabviews/subtable/index.jsx +++ b/src/tabviews/subtable/index.jsx @@ -141,16 +141,17 @@ config.action = config.action.filter(item => permAction[item.uuid]) } - let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID - // 瀛楁鏉冮檺榛戝悕鍗� - config.search = config.search.map(item => { - item.oriInitval = item.initval - if (!item.blacklist || item.blacklist.length === 0) return item - if (item.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { - item.Hide = 'true' + config.search = Utils.initSearchVal(config.search) + + let hasReqFields = false + config.search.forEach(field => { + if (field.required) { + hasReqFields = true } - return item }) + + // 瀛楁鏉冮檺榛戝悕鍗� + let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID config.columns = config.columns.map(col => { if (!col.blacklist || col.blacklist.length === 0) return col @@ -260,16 +261,6 @@ _columns.push(config.gridBtn) } - let valid = true // 鎼滅储鏉′欢蹇呭~楠岃瘉 - let hasReqFields = false - config.search.forEach(field => { - if (field.required !== 'true') return - hasReqFields = true - if (!field.initval) { - valid = false - } - }) - config.setting.tabType = 'sub' // 鏁版嵁婧愪俊鎭澶勭悊 config.setting.laypage = config.setting.laypage !== 'false' // 鏄惁鍒嗛〉锛岃浆涓篵oolean 缁熶竴鏍煎紡 @@ -306,6 +297,26 @@ config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '') config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '') } + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + let regs = [ + { reg: /@userName@/ig, value: `'${userName}'` }, + { reg: /@fullName@/ig, value: `'${fullName}'` }, + { reg: /@login_city@/ig, value: `'${city}'` } + ] + + regs.forEach(cell => { + config.setting.dataresource = config.setting.dataresource.replace(cell.reg, cell.value) + config.setting.customScript = config.setting.customScript.replace(cell.reg, cell.value) + }) } this.setState({ @@ -319,10 +330,10 @@ actions: _actions, columns: _columns, arr_field: _arrField.join(','), - search: Utils.initMainSearch(config.search), // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級 + search: Utils.initMainSearch(config.search), hasReqFields }, () => { - if (config.setting.onload !== 'false' && (!Tab.supMenu || BID || Tab.isTreeNode) && valid) { // 鍒濆鍖栧彲鍔犺浇 + if (config.setting.onload !== 'false' && (!Tab.supMenu || BID || Tab.isTreeNode)) { // 鍒濆鍖栧彲鍔犺浇 this.loadData() } }) @@ -350,23 +361,17 @@ searches = [...mainSearch, ...searches] } - let requireFields = [] if (hasReqFields) { - requireFields = searches.filter(item => item.required && (!item.value || item.value.length === 0)) + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + this.setState({ + loading: false + }) + return + } } - if (requireFields.length > 0) { - let prex = this.props.Tab && this.props.Tab.label ? this.props.Tab.label + '-' : '' - let labels = requireFields.map(item => item.label) - labels = Array.from(new Set(labels)) - - notification.warning({ - top: 92, - message: prex + this.state.dict['form.required.input'] + labels.join('銆�') + ' !', - duration: 3 - }) - return - } else if (this.props.Tab.supMenu && !BID) { // 涓昏〃ID涓嶅瓨鍦ㄦ椂锛屼笉鏌ヨ瀛愯〃 + if (this.props.Tab.supMenu && !BID) { // 涓昏〃ID涓嶅瓨鍦ㄦ椂锛屼笉鏌ヨ瀛愯〃 this.setState({ data: [], selectedData: [], @@ -466,7 +471,7 @@ }) Api.directRequest(url, setting.method, param, setting.cross).then(res => { - if (typeof(res) !== 'object' || Array.isArray(res)) { + if (typeof(res) !== 'object') { let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒' if (typeof(res) === 'string') { @@ -481,6 +486,9 @@ this.customCallbackRequest(_result) } else { + if (Array.isArray(res)) { + res = { data: res } + } res.mk_api_key = mkey this.customCallbackRequest(res) } @@ -596,6 +604,11 @@ this.getStatFieldsValue(searches) if (result.status) { + let start = 1 + if (setting.laypage) { + start = pageSize * (pageIndex - 1) + 1 + } + this.setState({ data: result.data.map((item, index) => { if (absFields.length) { @@ -609,6 +622,7 @@ item.key = index item.$$uuid = item[setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = start + index + '' return item }), @@ -676,6 +690,7 @@ data = data.map(item => { if (item.$$uuid === _data.$$uuid) { _data.key = item.key + _data.$Index = item.$Index return _data } else { return item @@ -813,7 +828,7 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { Tab, mainSearch, MenuID } = this.props const { arr_field, orderBy, search, setting} = this.state @@ -824,7 +839,7 @@ searches = [...mainSearch, ...search] } - MKEmitter.emit('execExcelout', MenuID, btnId, { + MKEmitter.emit('returnModuleParam', MenuID, btnId, { arr_field: arr_field, orderBy: orderBy || setting.order, search: searches, @@ -920,7 +935,7 @@ componentDidMount () { MKEmitter.addListener('reloadData', this.reloadData) - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -932,7 +947,7 @@ return } MKEmitter.removeListener('reloadData', this.reloadData) - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -943,7 +958,7 @@ <div className="subtable" id={'subtable' + this.props.MenuID}> {loadingview && <Spin />} {searchlist && searchlist.length ? - <SubSearch BID={this.props.BID} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null + <SubSearch BID={this.props.BID} setting={setting} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null } {config ? <Row className="chart-view" gutter={16}> {/* 瑙嗗浘缁� */} @@ -973,7 +988,7 @@ </div> <div className="subtable-box"> {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && this.state.data && this.state.data.length > 0 ? - <Switch title="鏀惰捣" className="subtable-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={pickup} onChange={this.pickupChange} /> : null + <Switch title="鏀惰捣" className="subtable-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /> : null } <SubTable tableId={this.props.Tab.uuid} diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx index 7cda524..fdc900d 100644 --- a/src/tabviews/subtabtable/index.jsx +++ b/src/tabviews/subtabtable/index.jsx @@ -136,17 +136,17 @@ config.action = config.action.filter(item => permAction[item.uuid]) } - let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID - // 瀛楁鏉冮檺榛戝悕鍗� - config.search = config.search.filter(item => { - item.oriInitval = item.initval - if (!item.blacklist || item.blacklist.length === 0) return item - if (item.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { - item.Hide = 'true' - } + config.search = Utils.initSearchVal(config.search) - return item + let hasReqFields = false + config.search.forEach(field => { + if (field.required) { + hasReqFields = true + } }) + + // 瀛楁鏉冮檺榛戝悕鍗� + let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID config.columns = config.columns.map(col => { if (!col.blacklist || col.blacklist.length === 0) return col @@ -235,16 +235,6 @@ _columns.push(config.gridBtn) } - let valid = true // 鎼滅储鏉′欢蹇呭~楠岃瘉 - let hasReqFields = false - config.search.forEach(field => { - if (field.required !== 'true') return - hasReqFields = true - if (!field.initval) { - valid = false - } - }) - config.setting.tabType = 'subtab' // 鏁版嵁婧愪俊鎭澶勭悊 config.setting.laypage = config.setting.laypage !== 'false' // 鏄惁鍒嗛〉锛岃浆涓篵oolean 缁熶竴鏍煎紡 @@ -281,6 +271,26 @@ config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '') config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '') } + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + let regs = [ + { reg: /@userName@/ig, value: `'${userName}'` }, + { reg: /@fullName@/ig, value: `'${fullName}'` }, + { reg: /@login_city@/ig, value: `'${city}'` } + ] + + regs.forEach(cell => { + config.setting.dataresource = config.setting.dataresource.replace(cell.reg, cell.value) + config.setting.customScript = config.setting.customScript.replace(cell.reg, cell.value) + }) } this.setState({ @@ -297,7 +307,7 @@ search: Utils.initMainSearch(config.search), // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級 hasReqFields }, () => { - if (config.setting.onload !== 'false' && valid) { // 鍒濆鍖栧彲鍔犺浇 + if (config.setting.onload !== 'false') { // 鍒濆鍖栧彲鍔犺浇 this.loadData() } }) @@ -323,23 +333,17 @@ searches = [...mainSearch, ...searches] } - let requireFields = [] - if (hasReqFields) { - requireFields = searches.filter(item => item.required && (!item.value || item.value.length === 0)) + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + this.setState({ + loading: false + }) + return + } } - if (requireFields.length > 0) { - let labels = requireFields.map(item => item.label) - labels = Array.from(new Set(labels)) - - notification.warning({ - top: 92, - message: this.state.dict['form.required.input'] + labels.join('銆�') + ' !', - duration: 3 - }) - return - } else if (window.GLOB.systemType === 'production' && setting.interType === 'custom' && !setting.proInterface) { + if (window.GLOB.systemType === 'production' && setting.interType === 'custom' && !setting.proInterface) { notification.warning({ top: 92, message: '鏈缃寮忕郴缁熷湴鍧�!', @@ -428,7 +432,7 @@ }) Api.directRequest(url, setting.method, param, setting.cross).then(res => { - if (typeof(res) !== 'object' || Array.isArray(res)) { + if (typeof(res) !== 'object') { let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒' if (typeof(res) === 'string') { @@ -443,6 +447,9 @@ this.customCallbackRequest(_result) } else { + if (Array.isArray(res)) { + res = { data: res } + } res.mk_api_key = mkey this.customCallbackRequest(res) } @@ -559,6 +566,11 @@ this.getStatFieldsValue(searches) if (result.status) { + let start = 1 + if (setting.laypage) { + start = pageSize * (pageIndex - 1) + 1 + } + this.setState({ data: result.data.map((item, index) => { if (absFields.length) { @@ -572,6 +584,7 @@ item.key = index item.$$uuid = item[setting.primaryKey] || '' item.$$BID = BID || '' + item.$Index = start + index + '' return item }), @@ -702,7 +715,7 @@ /** * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁� */ - getexceloutparam = (menuId, btnId) => { + queryModuleParam = (menuId, btnId) => { const { Tab, mainSearch, MenuID } = this.props const { arr_field, orderBy, search, setting} = this.state @@ -713,7 +726,7 @@ searches = [...mainSearch, ...search] } - MKEmitter.emit('execExcelout', MenuID, btnId, { + MKEmitter.emit('returnModuleParam', MenuID, btnId, { arr_field: arr_field, orderBy: orderBy || setting.order, search: searches, @@ -753,7 +766,7 @@ } componentDidMount () { - MKEmitter.addListener('getexceloutparam', this.getexceloutparam) + MKEmitter.addListener('queryModuleParam', this.queryModuleParam) MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -764,7 +777,7 @@ this.setState = () => { return } - MKEmitter.removeListener('getexceloutparam', this.getexceloutparam) + MKEmitter.removeListener('queryModuleParam', this.queryModuleParam) MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult) } @@ -775,7 +788,7 @@ <div className="subtabtable" id={'subtabtable' + this.props.MenuID}> {loadingview && <Spin />} {searchlist && searchlist.length ? - <SubSearch BID={this.props.BID} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null + <SubSearch BID={this.props.BID} setting={setting} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null } {config ? <Row className="chart-view" gutter={16}> {/* 瑙嗗浘缁� */} diff --git a/src/tabviews/tabmanage/index.jsx b/src/tabviews/tabmanage/index.jsx index 7be8cb2..5d37c1d 100644 --- a/src/tabviews/tabmanage/index.jsx +++ b/src/tabviews/tabmanage/index.jsx @@ -49,9 +49,9 @@ return { uuid: temp.MenuID, value: temp.MenuID, - MenuName: temp.MenuName, + MenuName: temp.MenuName || '', type: temp.Template, - MenuNo: temp.MenuNo, + MenuNo: temp.MenuNo || '', Remark: temp.Remark } }) @@ -504,7 +504,7 @@ let _tabviews = [] if (tabviews) { - _tabviews = tabviews.filter(tab => tab.MenuName.toLowerCase().indexOf(searchKey.toLowerCase()) >= 0) + _tabviews = tabviews.filter(tab => tab.MenuName.toLowerCase().indexOf(searchKey.toLowerCase()) >= 0 || tab.MenuNo.toLowerCase().indexOf(searchKey.toLowerCase()) >= 0) } return ( diff --git a/src/tabviews/treepage/index.jsx b/src/tabviews/treepage/index.jsx index 5590efc..835e4a3 100644 --- a/src/tabviews/treepage/index.jsx +++ b/src/tabviews/treepage/index.jsx @@ -171,6 +171,26 @@ config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '') config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '') } + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + let regs = [ + { reg: /@userName@/ig, value: `'${userName}'` }, + { reg: /@fullName@/ig, value: `'${fullName}'` }, + { reg: /@login_city@/ig, value: `'${city}'` } + ] + + regs.forEach(cell => { + config.setting.dataresource = config.setting.dataresource.replace(cell.reg, cell.value) + config.setting.customScript = config.setting.customScript.replace(cell.reg, cell.value) + }) } this.setState({ diff --git a/src/tabviews/verupmanage/config.jsx b/src/tabviews/verupmanage/config.jsx index 37a7348..60948bb 100644 --- a/src/tabviews/verupmanage/config.jsx +++ b/src/tabviews/verupmanage/config.jsx @@ -13,7 +13,7 @@ queryType: 'query', }, search:[ - {label: '浼犺緭鍙�', field:'VersionName', type: 'text', initval:'',match: 'like', uuid: '1581736007223d84ddmht4gdfb1850nh'} + {label: '浼犺緭鍙�', field: 'VersionName', type: 'text', initval:'', oriInitval: '', required: false, match: 'like', uuid: '1581736007223d84ddmht4gdfb1850nh'} ], action:[ {label:'娣诲姞',OpenType:'pop',intertype:'outer',innerFunc:'',sysInterface:'true',outerFunc:'s_get_sVersiondetail_Up',interface:'http://cloud.mk9h.cn/webapi/dostars',callbackFunc:'s_sVersion_Local_add',position:'toolbar',Ot:'notRequired',execSuccess:'grid',execError:'never',icon:'',class:'green',uuid:'1583979660949vpssdb2p2lsqff9abkr'}, @@ -99,7 +99,7 @@ onload:'true' }, search:[ - {label:'缁煎悎鏌ヨ',field:'Remark,KeyWords,TypeName',type:'text',initval:'',match:'like','ratio':6,uuid:'1583983588787acl55md59fu9kpb52db'} + {label:'缁煎悎鏌ヨ',field:'Remark,KeyWords,TypeName',type:'text',initval:'', oriInitval: '', required: false,match:'like','ratio':6,uuid:'1583983588787acl55md59fu9kpb52db'} ], action:[ {label:'鎵ц',OpenType:'pop',intertype:'outer',innerFunc:'',sysInterface:'true',outerFunc:'s_get_sVersionDetail_Ltext',interface:'http://cloud.mk9h.cn/webapi/dostars',callbackFunc:'s_sDataDictb_TBBack',position:'toolbar',execSuccess:'grid',execError:'never',icon:'',class:'primary',Ot:'required',uuid:'1583983849299g1qfd28g3c9n9e0e57a',verify:null}, @@ -144,7 +144,7 @@ onload:'true' }, search:[ - {label:'缁煎悎鏌ヨ',field:'Remark,KeyWords,TypeName',type:'text',initval:'',match:'like',uuid:'15839847143720ggaaukqtfhp3mirsuc'} + {label:'缁煎悎鏌ヨ',field:'Remark,KeyWords,TypeName',type:'text',initval:'', oriInitval: '', required: false,match:'like',uuid:'15839847143720ggaaukqtfhp3mirsuc'} ], action:[], columns:[ diff --git a/src/tabviews/zshare/actionList/asyncButtonComponent.jsx b/src/tabviews/zshare/actionList/asyncButtonComponent.jsx index 1d48bf6..30d70ed 100644 --- a/src/tabviews/zshare/actionList/asyncButtonComponent.jsx +++ b/src/tabviews/zshare/actionList/asyncButtonComponent.jsx @@ -27,19 +27,11 @@ const btn = this.props.btn || {} let style = {} - if (!C && btn.btnstyle) { - if (btn.btnstyle.marginRight) { - style.marginRight = btn.btnstyle.marginRight - } - if (btn.btnstyle.marginLeft) { - style.marginLeft = btn.btnstyle.marginLeft - } - if (btn.btnstyle.marginTop) { - style.marginTop = btn.btnstyle.marginTop - } - if (btn.btnstyle.marginBottom) { - style.marginBottom = btn.btnstyle.marginBottom - } + if (!C && btn.style) { + style.marginRight = btn.style.marginRight || '' + style.marginLeft = btn.style.marginLeft || '' + style.marginTop = btn.style.marginTop || '' + style.marginBottom = btn.style.marginBottom || '' } return C ? diff --git a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx index 584b9e2..12ee0f4 100644 --- a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx +++ b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx @@ -23,7 +23,23 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + disabled: false, loading: false + } + + UNSAFE_componentWillMount () { + const { btn, selectedData } = this.props + let disabled = false + + if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + this.setState({disabled}) + } } shouldComponentUpdate (nextProps, nextState) { @@ -35,6 +51,24 @@ if (position === 'toolbar') { MKEmitter.addListener('triggerBtnId', this.actionTrigger) + } + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { btn, selectedData } = this.props + + if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) { + let disabled = false + + if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + nextProps.selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + } + this.setState({disabled}) } } @@ -160,13 +194,14 @@ render() { const { btn, show } = this.props - const { loading } = this.state + const { loading, disabled } = this.state if (show === 'actionList') { return ( <Button icon={btn.icon} loading={loading} + disabled={disabled} className={'mk-btn mk-' + btn.class} onClick={(e) => {e.stopPropagation(); this.actionTrigger()}} >{btn.label}</Button> @@ -177,7 +212,8 @@ type="link" title={show === 'icon' ? btn.label : ''} loading={loading} - style={btn.btnstyle} + disabled={disabled} + style={btn.style} icon={show === 'text' ? '' : (btn.icon || '')} onClick={(e) => {e.stopPropagation(); this.actionTrigger()}} >{show === 'icon' && btn.icon ? '' : btn.label}</Button> diff --git a/src/tabviews/zshare/actionList/excelInbutton/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/index.jsx index 0d53a35..2fc88ba 100644 --- a/src/tabviews/zshare/actionList/excelInbutton/index.jsx +++ b/src/tabviews/zshare/actionList/excelInbutton/index.jsx @@ -28,7 +28,23 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, loading: false, + disabled: false, primaryId: '', + } + + UNSAFE_componentWillMount () { + const { btn, selectedData } = this.props + let disabled = false + + if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + this.setState({disabled}) + } } shouldComponentUpdate (nextProps, nextState) { @@ -40,6 +56,24 @@ if (position === 'toolbar') { MKEmitter.addListener('triggerBtnId', this.actionTrigger) + } + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { btn, selectedData } = this.props + + if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) { + let disabled = false + + if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + nextProps.selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + } + this.setState({disabled}) } } @@ -74,7 +108,7 @@ if ((triggerId && btn.uuid !== triggerId) || loading) return - if (Tab && Tab.supMenu && !BID) { + if (((Tab && Tab.supMenu) || setting.supModule) && !BID) { notification.warning({ top: 92, message: '闇�瑕佷笂绾т富閿�硷紒', @@ -103,7 +137,7 @@ } let primaryId = '' // 瀵煎叆鏃惰Id - if (btn.Ot === 'requiredSgl') { + if (btn.Ot === 'requiredSgl' && setting.primaryKey) { primaryId = data[0][setting.primaryKey] || '' } @@ -408,13 +442,14 @@ render() { const { btn, show } = this.props - const { loading } = this.state + const { loading, disabled } = this.state if (show === 'actionList') { return <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}> <Button icon={btn.icon} loading={loading} + disabled={disabled} className={'mk-btn mk-' + btn.class} onClick={() => {this.actionTrigger()}} >{btn.label}</Button> @@ -426,7 +461,8 @@ type="link" title={show === 'icon' ? btn.label : ''} loading={loading} - style={btn.btnstyle} + disabled={disabled} + style={btn.style} icon={show === 'text' ? '' : (show === 'icon' ? (btn.icon || 'upload') : (btn.icon || ''))} onClick={() => {this.actionTrigger()}} >{show === 'icon' ? '' : btn.label}</Button> diff --git a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx index 121fc6f..2bd9686 100644 --- a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx +++ b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx @@ -42,7 +42,7 @@ if (position === 'toolbar') { MKEmitter.addListener('triggerBtnId', this.actionTrigger) } - MKEmitter.addListener('execExcelout', this.triggerExcelout) + MKEmitter.addListener('returnModuleParam', this.triggerExcelout) } componentWillUnmount () { @@ -50,7 +50,7 @@ return } MKEmitter.removeListener('triggerBtnId', this.actionTrigger) - MKEmitter.removeListener('execExcelout', this.triggerExcelout) + MKEmitter.removeListener('returnModuleParam', this.triggerExcelout) } /** @@ -78,7 +78,7 @@ if ((triggerId && btn.uuid !== triggerId) || loading) return - if (Tab && Tab.supMenu && !BID) { + if (((Tab && Tab.supMenu) || setting.supModule) && !BID) { notification.warning({ top: 92, message: '闇�瑕佷笂绾т富閿�硷紒', @@ -110,7 +110,7 @@ return } - MKEmitter.emit('getexceloutparam', btn.$menuId, btn.uuid) + MKEmitter.emit('queryModuleParam', btn.$menuId, btn.uuid) if (window.GLOB.systemType === 'production') { MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '瀵煎嚭Excel'}) } @@ -130,9 +130,7 @@ if (btn.search === 'true' && viewParam.search && viewParam.search.length > 0) { let valid = false viewParam.search.forEach(item => { - if (Array.isArray(item.value) && item.value.length > 0) { - valid = true - } else if (item.value || item.value === 0) { + if (item.value || item.value === 0) { valid = true } }) @@ -430,31 +428,77 @@ const { btn } = this.props try { - let _header = [] - let _topRow = {} - let colwidth = [] - let abses = [] + let imgCol = btn.verify.columns.filter(col => col.type === 'image')[0] - btn.verify.columns.forEach(col => { - if (_topRow[col.Column]) return + if (imgCol) { + const column = btn.verify.columns.map(item => { + let col = { + title: item.Text, + key: item.Column, + type: 'text', + width: (item.Width || 20) * 10 + } + if (item.type === 'image') { + col.type = 'image' + col.height = col.width + } + return col + }) - _header.push(col.Column) - _topRow[col.Column] = col.Text + let table = [] - if (col.abs === 'true') { - abses.push(col.Column) + data && data.forEach((item, index) => { + let _row = {} + + item.$Index = index + 1 + '' + + btn.verify.columns.forEach((col, i) => { + if (item[col.Column] && col.abs === 'true') { + _row[col.Column] = Math.abs(item[col.Column]) + } else { + _row[col.Column] = item[col.Column] + } + }) + + table.push(_row) + }) + + this.table2excel(column, table, this.state.excelName.replace(/\.xlsx/ig, '.xls')) + + if (btn.verify && btn.verify.enable === 'true' && btn.verify.script) { + this.execCustomScript() + } else { + this.execSuccess({ErrCode: 'S', ErrMesg: '瀵煎嚭鎴愬姛锛�'}) } - colwidth.push({width: col.Width || 20}) - }) - - let table = [] - - table.push(_topRow) - - if (data && abses.length > 0) { - data.forEach(item => { + } else { + let _header = [] + let _topRow = {} + let colwidth = [] + let abses = [] + + btn.verify.columns.forEach(col => { + if (_topRow[col.Column]) return + + _header.push(col.Column) + _topRow[col.Column] = col.Text + + if (col.abs === 'true') { + abses.push(col.Column) + } + + colwidth.push({width: col.Width || 20}) + }) + + let table = [] + + table.push(_topRow) + + data && data.forEach((item, index) => { let _row = {} + + item.$Index = index + 1 + '' + _header.forEach(field => { if (item[field] && abses.includes(field)) { _row[field] = Math.abs(item[field]) @@ -465,35 +509,67 @@ table.push(_row) }) - } else if (data) { - data.forEach(item => { - let _row = {} - _header.forEach(field => { - _row[field] = item[field] - }) - table.push(_row) - }) - } - - const ws = XLSX.utils.json_to_sheet(table, {header: _header, skipHeader: true}) - - ws['!cols'] = colwidth - - const wb = XLSX.utils.book_new() - XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') - - XLSX.writeFile(wb, this.state.excelName) - - if (btn.verify && btn.verify.enable === 'true' && btn.verify.script) { - this.execCustomScript() - } else { - this.execSuccess({ErrCode: 'S', ErrMesg: '瀵煎嚭鎴愬姛锛�'}) + const ws = XLSX.utils.json_to_sheet(table, {header: _header, skipHeader: true}) + + ws['!cols'] = colwidth + + const wb = XLSX.utils.book_new() + XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') + + XLSX.writeFile(wb, this.state.excelName) + + if (btn.verify && btn.verify.enable === 'true' && btn.verify.script) { + this.execCustomScript() + } else { + this.execSuccess({ErrCode: 'S', ErrMesg: '瀵煎嚭鎴愬姛锛�'}) + } } } catch { this.execError({ErrCode: 'N', message: 'Excel鐢熸垚澶辫触锛�'}) } } + + table2excel = (column, data, excelName) => { + let thead = column.reduce((result, item) => { + return result + `<th>${item.title}</th>` + }, '') + + thead = `<thead><tr>${thead}</tr></thead>` + + let tbody = data.reduce((result, row) => { + const temp = column.reduce((tds, col) => { + let cell = '<td></td>' + if (col.type !== 'image' || !row[col.key]) { + cell = `<td style="width: ${col.width}px;">${row[col.key]}</td>` + } else if (col.type === 'image') { + cell = `<td style="width: ${col.width}px;height: ${col.height}px;"><img src="${row[col.key]}" width="${col.width * 0.75}"></td>` + } + return tds + cell + }, '') + return result + `<tr>${temp}</tr>` + }, '') + + tbody = `<tbody>${tbody}</tbody>` + + const table = thead + tbody + + let html = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>" + html += '<head><meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">' + html += '<xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>Sheet1</x:Name><x:WorksheetOptions><x:Print><x:ValidPrinterInfo/></x:Print></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml></head>' + html += `<body><table>${table}</table></body>` + html += '</html>' + + let url = 'data:application/vnd.ms-excel;charset=utf-8,' + encodeURIComponent(html) + // let url = 'data:application/vnd.ms-excel;base64,' + window.btoa(unescape(encodeURIComponent(html))) + let link = document.createElement('a') + link.href = url + link.download = excelName + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + } + /** * @description 鎵ц鑷畾涔夎剼鏈� @@ -606,20 +682,21 @@ if (this.props.BID) { param.BID = this.props.BID } + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } let _dataresource = setting.dataresource let regoptions = null if (setting.queryType === 'statistics' || param.custom_script) { let allSearch = Utils.getAllSearchOptions(search) - let userName = sessionStorage.getItem('User_Name') || '' - let fullName = sessionStorage.getItem('Full_Name') || '' - let city = sessionStorage.getItem('city') || '' - - if (sessionStorage.getItem('isEditState') === 'true') { - userName = sessionStorage.getItem('CloudUserName') || '' - fullName = sessionStorage.getItem('CloudFullName') || '' - } regoptions = allSearch.map(item => { return { @@ -665,7 +742,7 @@ } if (param.custom_script) { - param.custom_script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000) select @ErrorCode='',@retmsg ='' + param.custom_script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50) select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}' ${param.custom_script} ` regoptions.forEach(item => { @@ -798,7 +875,7 @@ type="link" title={show === 'icon' ? btn.label : ''} loading={loading} - style={btn.btnstyle} + style={btn.style} icon={show === 'text' ? '' : (show === 'icon' ? (btn.icon || 'download') : (btn.icon || ''))} onClick={(e) => {e.stopPropagation(); this.actionTrigger()}} >{show === 'icon' ? '' : btn.label}</Button> diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx index dcf07e8..2ff034c 100644 --- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx +++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx @@ -21,7 +21,23 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + disabled: false, visible: false + } + + UNSAFE_componentWillMount () { + const { btn, selectedData } = this.props + let disabled = false + + if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + this.setState({disabled}) + } } shouldComponentUpdate (nextProps, nextState) { @@ -33,6 +49,24 @@ if (position === 'toolbar') { MKEmitter.addListener('triggerBtnId', this.actionTrigger) + } + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { btn, selectedData } = this.props + + if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) { + let disabled = false + + if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + nextProps.selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + } + this.setState({disabled}) } } @@ -69,14 +103,6 @@ duration: 5 }) return - } else if (btn.Ot !== 'notRequired' && !setting.primaryKey) { - // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾槸鍚﹁缃富閿� - notification.warning({ - top: 92, - message: '鏈缃富閿紒', - duration: 5 - }) - return } else if (!btn.pageTemplate) { notification.warning({ top: 92, @@ -91,7 +117,7 @@ let MenuNo = '' let Remark = '' if (btn.Ot === 'requiredSgl' && data[0]) { - Id = data[0][setting.primaryKey] || '' + Id = setting.primaryKey ? (data[0][setting.primaryKey] || '') : '' name = data[0].PrintTempName || '' MenuNo = data[0].PrintTempNO || '' Remark = data[0].Remark || '' @@ -103,7 +129,7 @@ _name = '鍗曟嵁鎵撳嵃' if (btn.Ot === 'required' && data && data.length > 0) { data.forEach((item, i) => { - let _id = item[setting.primaryKey] || '' + let _id = setting.primaryKey ? (item[setting.primaryKey] || '') : '' let url = '#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: _id, tempId: btn.printTemp, dataM: sessionStorage.getItem('dataM') }))) window.open(url) }) @@ -164,12 +190,14 @@ render() { const { btn, show } = this.props + const { disabled } = this.state if (show === 'actionList') { return ( <Button className={'mk-btn mk-' + btn.class} icon={btn.icon} + disabled={disabled} onClick={(e) => {e.stopPropagation(); this.actionTrigger()}} >{btn.label}</Button> ) @@ -178,7 +206,8 @@ <Button type="link" title={show === 'icon' ? btn.label : ''} - style={btn.btnstyle} + style={btn.style} + disabled={disabled} icon={show === 'text' ? '' : (btn.icon || '')} onClick={(e) => {e.stopPropagation(); this.actionTrigger()}} >{show === 'icon' && btn.icon ? '' : btn.label}</Button> diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx index 076f844..952fd74 100644 --- a/src/tabviews/zshare/actionList/normalbutton/index.jsx +++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx @@ -3,7 +3,7 @@ import moment from 'moment' import {connect} from 'react-redux' import { is, fromJS } from 'immutable' -import { Button, Modal, notification, message } from 'antd' +import { Button, Modal, notification, message, Drawer } from 'antd' import Api from '@/api' import Utils, { getSysDefaultSql } from '@/utils/utils.js' @@ -42,7 +42,25 @@ btnconfig: null, loading: false, loadingNumber: '', + disabled: false, checkParam: null + } + + moduleParams = null + + UNSAFE_componentWillMount () { + const { btn, selectedData } = this.props + let disabled = false + + if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + this.setState({disabled}) + } } shouldComponentUpdate (nextProps, nextState) { @@ -52,10 +70,28 @@ componentDidMount () { const { position } = this.props - if (position === 'toolbar') { - MKEmitter.addListener('triggerBtnId', this.actionTrigger) - } else if (position === 'form') { + MKEmitter.addListener('triggerBtnId', this.actionTrigger) + if (position === 'form') { MKEmitter.addListener('triggerFormSubmit', this.actionSubmit) + } + MKEmitter.addListener('returnModuleParam', this.resetModuleParam) + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { btn, selectedData } = this.props + + if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) { + let disabled = false + + if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + nextProps.selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + } + this.setState({disabled}) } } @@ -65,6 +101,7 @@ } MKEmitter.removeListener('triggerBtnId', this.actionTrigger) MKEmitter.removeListener('triggerFormSubmit', this.actionSubmit) + MKEmitter.removeListener('returnModuleParam', this.resetModuleParam) } actionSubmit = (res) => { @@ -77,6 +114,14 @@ }) this.execSubmit(this.state.tabledata, () => {}, res.form) + } + + resetModuleParam = (menuId, btnId, param) => { + const { btn } = this.props + + if (btn.$menuId !== menuId || btn.uuid !== btnId || !param) return + + this.moduleParams = param } /** @@ -99,17 +144,22 @@ * @description 瑙﹀彂鎸夐挳鎿嶄綔 */ actionTrigger = (triggerId, record) => { - const { setting, Tab, BID, btn, selectedData } = this.props + const { Tab, BID, btn, selectedData, setting } = this.props const { loading } = this.state if ((triggerId && btn.uuid !== triggerId) || loading) return - if (Tab && Tab.supMenu && !BID) { + if (((Tab && Tab.supMenu) || setting.supModule) && !BID) { notification.warning({ top: 92, message: '闇�瑕佷笂绾т富閿�硷紒', duration: 5 }) + return + } + + if (btn.$syncModule && !triggerId) { + MKEmitter.emit('getSyncData', btn.$syncModule, btn.uuid) return } @@ -129,14 +179,6 @@ notification.warning({ top: 92, message: this.state.dict['main.action.confirm.selectSingleLine'], - duration: 5 - }) - return - } else if (btn.OpenType !== 'formSubmit' && !setting.primaryKey) { - // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾槸鍚﹁缃富閿� - notification.warning({ - top: 92, - message: '鏈缃富閿紒', duration: 5 }) return @@ -258,7 +300,7 @@ let primaryId = '' - if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') { + if ((btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') && setting.primaryKey) { let ids = data.map(d => { return d[setting.primaryKey] || ''}) ids = ids.filter(Boolean) primaryId = ids.join(',') @@ -268,11 +310,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, retmsg) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -310,11 +352,11 @@ param.ID = primaryId || Utils.getguid() if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -342,11 +384,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -404,11 +446,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, retmsg) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -437,11 +479,11 @@ param.ID = Utils.getguid() if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -460,11 +502,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -512,13 +554,15 @@ let primaryId = '' - if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') { + if ((btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') && setting.primaryKey) { let ids = data.map(d => { return d[setting.primaryKey] || ''}) ids = ids.filter(Boolean) primaryId = ids.join(',') } - param[setting.primaryKey] = primaryId // 璁剧疆涓婚敭鍙傛暟 + if (setting.primaryKey) { + param[setting.primaryKey] = primaryId // 璁剧疆涓婚敭鍙傛暟 + } if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit') { // 琛ㄥ崟 formdata.forEach(_data => { @@ -559,7 +603,9 @@ param[_data.key] = _data.value }) } - param[setting.primaryKey] = primaryId + if (setting.primaryKey) { + param[setting.primaryKey] = primaryId + } if (this.props.menuType === 'HS' && param.func === 's_sDataDictb_TBBack' && param.LTextOut) { // 鍑芥暟 s_sDataDictb_TBBack 浜戠楠岃瘉 param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') @@ -578,6 +624,30 @@ * @description 鎸夐挳鎻愪氦鎵ц */ execSubmit = (data, _resolve, formdata) => { + const { setting, btn } = this.props + this.moduleParams = null + + if ( + (btn.intertype === 'system' || (btn.intertype === 'custom' && btn.procMode === 'system')) && + btn.sqlType !== 'insert' && btn.Ot !== 'notRequired' && btn.verify && btn.verify.invalid === 'true' && + setting.dataresource + ) { + MKEmitter.emit('queryModuleParam', btn.$menuId, btn.uuid) + setTimeout(() => { + if (this.moduleParams) { + this.execRealSubmit(data, _resolve, formdata) + } else { + setTimeout(() => { + this.execRealSubmit(data, _resolve, formdata) + }, 100) + } + }, 50) + } else { + this.execRealSubmit(data, _resolve, formdata) + } + } + + execRealSubmit = (data, _resolve, formdata) => { const { setting, btn } = this.props if (btn.intertype === 'system' || btn.intertype === 'inner') { // 绯荤粺鎺ュ彛 let params = [] @@ -800,7 +870,7 @@ }) Api.directRequest(url, btn.method, param, btn.cross).then(res => { - if (typeof(res) !== 'object' || Array.isArray(res)) { + if (typeof(res) !== 'object') { let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒' if (typeof(res) === 'string') { @@ -815,6 +885,9 @@ this.customCallbackRequest(params, result, record, _resolve) } else { + if (Array.isArray(res)) { + res = { data: res } + } res.mk_api_key = mkey this.customCallbackRequest(params, res, record, _resolve) } @@ -872,6 +945,9 @@ subObjs.push(val) } } else { + if (typeof(val) === 'string') { + val = val.replace(/'/ig, '"') + } keys.push(key) vals.push(`'${val}'`) } @@ -1252,6 +1328,7 @@ let _param = { templatecode: verify.noteCode, // 妯℃澘缂栫爜 TypeCharOne: verify.noteTemp, // N涓嶅悓鍐呭锛孻鐩稿悓鍐呭 + ID: verify.noteId || '' // 妯℃澘Id锛屾殏鏃舵湭浣跨敤 } _param.submitdate = res.submitdate @@ -1316,10 +1393,12 @@ _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp) - _param.rduri = 'http://sso.mk9h.cn/webapi/dostar' - _param.appkey = window.GLOB.appkey || '' + _param.rduri = 'http://sso.mk9h.cn/webapi/dostars' - Api.dostarInterface(_param).then(result => { + _param.userid = 'bh0bapabtd45epsgra79segbch6c1ibk' + _param.LoginUID = 'bh0bapabtd45epsgra79segbch6c1ibk' + + Api.getLocalConfig(_param).then(result => { if (!result.status) { notification.warning({ top: 92, @@ -1578,13 +1657,19 @@ _initval = '' } + let _type = item.type + + if (['date', 'datemonth', 'datetime'].includes(_type) && item.declareType === 'nvarchar(50)') { + _type = 'text' + } + result.push({ key: item.field, readonly: item.readonly === 'true', readin: _readin, fieldlen: _fieldlen, writein: item.writein !== 'false', - type: item.type, + type: _type, value: _initval }) }) @@ -1613,51 +1698,87 @@ let title = btnconfig.setting.title let width = btnconfig.setting.width + 'vw' - let clickouter = false - let container = document.body + let clickouter = btnconfig.setting.clickouter === 'close' - if ( - (setting.tabType === 'main' && btnconfig.setting.container === 'tab' && this.props.ContainerId) || - (btnconfig.setting.container === 'tab' && btn.ContainerId) - ) { - width = btnconfig.setting.width + '%' - container = () => document.getElementById(this.props.ContainerId || btn.ContainerId) + if (btnconfig.setting.display === 'drawer') { + let height = '100vh' + if (btnconfig.setting.placement === 'top' || btnconfig.setting.placement === 'bottom') { + width = '100vw' + height = btnconfig.setting.width + 'vh' + } + return ( + <Drawer + title={title} + width={width} + height={height} + maskClosable={clickouter} + onClose={this.handleCancel} + visible={visible} + placement={btnconfig.setting.placement || 'right'} + bodyStyle={{ paddingBottom: 80 }} + destroyOnClose + > + <MutilForm + BID={BID} + dict={this.state.dict} + menuType={this.props.menuType} + action={btnconfig} + inputSubmit={this.handleOk} + data={this.state.tabledata[0]} + BData={this.props.BData} + wrappedComponentRef={(inst) => this.formRef = inst} + /> + <div style={{ position: 'absolute', zIndex: 1, right: 0, bottom: 0, width: '100%', borderTop: '1px solid #e9e9e9', padding: '10px 16px', background: '#fff', textAlign: 'right'}}> + <Button onClick={this.handleCancel} style={{ marginRight: 8 }}> + 鍙栨秷 + </Button> + <Button onClick={this.handleOk} loading={this.state.confirmLoading} type="primary"> + 纭畾 + </Button> + </div> + </Drawer> + ) + } else { + let container = document.body + + if ( + (setting.tabType === 'main' && btnconfig.setting.container === 'tab' && this.props.ContainerId) || + (btnconfig.setting.container === 'tab' && btn.ContainerId) + ) { + width = btnconfig.setting.width + '%' + container = () => document.getElementById(this.props.ContainerId || btn.ContainerId) + } + return ( + <Modal + title={title} + maskClosable={clickouter} + getContainer={container} + wrapClassName='action-modal' + visible={visible} + width={width} + onOk={this.handleOk} + confirmLoading={this.state.confirmLoading} + onCancel={this.handleCancel} + destroyOnClose + > + <MutilForm + BID={BID} + dict={this.state.dict} + menuType={this.props.menuType} + action={btnconfig} + inputSubmit={this.handleOk} + data={this.state.tabledata[0]} + BData={this.props.BData} + wrappedComponentRef={(inst) => this.formRef = inst} + /> + </Modal> + ) } - - if (btnconfig.setting.clickouter === 'close') { - clickouter = true - } - - return ( - <Modal - title={title} - maskClosable={clickouter} - getContainer={container} - wrapClassName='action-modal' - visible={visible} - width={width} - onOk={this.handleOk} - confirmLoading={this.state.confirmLoading} - onCancel={this.handleCancel} - destroyOnClose - > - <MutilForm - BID={BID} - dict={this.state.dict} - menuType={this.props.menuType} - action={btnconfig} - inputSubmit={this.handleOk} - data={this.state.tabledata[0]} - BData={this.props.BData} - wrappedComponentRef={(inst) => this.formRef = inst} - /> - </Modal> - ) } render() { const { btn, show, style } = this.props - const { loadingNumber, loading, visible } = this.state + const { loadingNumber, loading, disabled } = this.state if (show === 'actionList') { return <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}> @@ -1665,10 +1786,11 @@ style={style} icon={btn.icon} loading={loading} + disabled={disabled} className={'mk-btn mk-' + btn.class} onClick={() => {this.actionTrigger()}} >{(loadingNumber ? `(${loadingNumber})` : '') + btn.label}</Button> - {visible ? this.getModels() : null} + {this.getModels()} </div> } else if (show && show.indexOf('plus') > -1) { return <div className="mk-btn-wrap"> @@ -1679,7 +1801,7 @@ style={{fontSize: show.substring(4) + 'px'}} onClick={() => {this.actionTrigger()}} ></Button> - {visible ? this.getModels() : null} + {this.getModels()} </div> } else { // icon銆乼ext銆� all 鍗$墖 return <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}> @@ -1687,11 +1809,12 @@ type="link" title={show === 'icon' ? btn.label : ''} loading={loading} - style={btn.btnstyle || style} + disabled={disabled} + style={btn.style || style} icon={show === 'text' ? '' : (btn.icon || '')} onClick={() => {this.actionTrigger()}} >{show === 'icon' && btn.icon ? '' : btn.label}</Button> - {visible ? this.getModels() : null} + {this.getModels()} </div> } } diff --git a/src/tabviews/zshare/actionList/popupbutton/index.jsx b/src/tabviews/zshare/actionList/popupbutton/index.jsx index 539e70c..c519a94 100644 --- a/src/tabviews/zshare/actionList/popupbutton/index.jsx +++ b/src/tabviews/zshare/actionList/popupbutton/index.jsx @@ -31,7 +31,23 @@ visible: false, popData: null, primaryId: '', + disabled: false, loading: false, + } + + UNSAFE_componentWillMount () { + const { btn, selectedData } = this.props + let disabled = false + + if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + this.setState({disabled}) + } } shouldComponentUpdate (nextProps, nextState) { @@ -46,6 +62,24 @@ } MKEmitter.addListener('openNewTab', this.openNewTab) MKEmitter.addListener('refreshPopButton', this.refreshPopButton) + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { btn, selectedData } = this.props + + if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) { + let disabled = false + + if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + nextProps.selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + } + this.setState({disabled}) + } } componentWillUnmount () { @@ -75,7 +109,7 @@ if (btn.uuid !== tabId) return - if (btn.$type === 'CustomPage') { + if (btn.$view === 'CustomPage') { if (btn.popClose !== 'never') { MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn) } @@ -94,7 +128,7 @@ if ((triggerId && btn.uuid !== triggerId) || loading) return - if (Tab && Tab.supMenu && !BID) { + if (((Tab && Tab.supMenu) || setting.supModule) && !BID) { notification.warning({ top: 92, message: '闇�瑕佷笂绾т富閿�硷紒', @@ -113,14 +147,6 @@ duration: 5 }) return - } else if (!setting.primaryKey) { - // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾槸鍚﹁缃富閿� - notification.warning({ - top: 92, - message: '鏈缃富閿紒', - duration: 5 - }) - return } else if (setting.tabType === 'subtab') { notification.warning({ top: 92, @@ -133,7 +159,7 @@ let _data = null let primaryId = '' - if (btn.Ot === 'requiredSgl') { + if (btn.Ot === 'requiredSgl' && setting.primaryKey) { _data = data[0] primaryId = _data[setting.primaryKey] || '' } @@ -168,13 +194,14 @@ render() { const { btn, show } = this.props - const { loading, popData, primaryId } = this.state + const { loading, popData, primaryId, disabled } = this.state return ( <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}> {show === 'actionList' ? <Button className={'mk-btn mk-' + btn.class} icon={btn.icon} + disabled={disabled} onClick={() => {this.actionTrigger()}} loading={loading} >{btn.label}</Button> : null} @@ -182,12 +209,13 @@ type="link" title={show === 'icon' ? btn.label : ''} loading={loading} - style={btn.btnstyle} + disabled={disabled} + style={btn.style} icon={show === 'text' ? '' : (btn.icon || '')} onClick={() => {this.actionTrigger()}} >{show === 'icon' && btn.icon ? '' : btn.label}</Button> : null} <Modal - className={'popview-modal ' + (btn.$type === 'CustomPage' ? 'custom-popview' : '')} + className={'popview-modal ' + (btn.$view === 'CustomPage' ? 'custom-popview' : '')} title={btn.label} width={'85vw'} maskClosable={false} @@ -198,14 +226,14 @@ ]} destroyOnClose > - {btn.$type !== 'CustomPage' ? <SubTabTable + {btn.$view !== 'CustomPage' ? <SubTabTable Tab={btn} MenuID={btn.linkTab} SupMenuID={this.props.MenuID} BID={popData ? primaryId : this.props.BID} BData={popData || this.props.BData} /> : null} - {btn.$type === 'CustomPage' ? <CustomPage Tab={btn} MenuID={btn.uuid} param={{BID: (popData ? primaryId : this.props.BID), data: (popData || this.props.BData)}} /> : null} + {btn.$view === 'CustomPage' ? <CustomPage Tab={btn} MenuID={btn.uuid} param={{$BID: (popData ? primaryId : this.props.BID), ...(popData || this.props.BData || {})}} /> : null} </Modal> </div> ) diff --git a/src/tabviews/zshare/actionList/printbutton/index.jsx b/src/tabviews/zshare/actionList/printbutton/index.jsx index 323d5ab..fb45054 100644 --- a/src/tabviews/zshare/actionList/printbutton/index.jsx +++ b/src/tabviews/zshare/actionList/printbutton/index.jsx @@ -40,7 +40,23 @@ tabledata: null, btnconfig: null, loading: false, + disabled: false, loadingNumber: '' + } + + UNSAFE_componentWillMount () { + const { btn, selectedData } = this.props + let disabled = false + + if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + this.setState({disabled}) + } } shouldComponentUpdate (nextProps, nextState) { @@ -52,6 +68,24 @@ if (position === 'toolbar') { MKEmitter.addListener('triggerBtnId', this.actionTrigger) + } + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { btn, selectedData } = this.props + + if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) { + let disabled = false + + if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + nextProps.selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + } + this.setState({disabled}) } } @@ -81,12 +115,12 @@ * @description 瑙﹀彂鎸夐挳鎿嶄綔 */ actionTrigger = (triggerId, record) => { - const { setting, Tab, BID, btn, selectedData } = this.props + const { Tab, BID, btn, selectedData, setting } = this.props const { loading } = this.state if ((triggerId && btn.uuid !== triggerId) || loading) return - if (Tab && Tab.supMenu && !BID) { + if (((Tab && Tab.supMenu) || setting.supModule) && !BID) { notification.warning({ top: 92, message: '闇�瑕佷笂绾т富閿�硷紒', @@ -111,14 +145,6 @@ notification.warning({ top: 92, message: this.state.dict['main.action.confirm.selectSingleLine'], - duration: 5 - }) - return - } else if (!setting.primaryKey) { - // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾槸鍚﹁缃富閿� - notification.warning({ - top: 92, - message: '鏈缃富閿紒', duration: 5 }) return @@ -276,6 +302,7 @@ let errorMsg = '' let _temps = {} + let images = [] result.forEach(res => { if (res.status && !errorMsg) { @@ -289,6 +316,7 @@ status: false } } else { + images = [...images, ..._temp.imgs] _temps[res.tempId] = _temp } } else if (!errorMsg) { @@ -297,7 +325,38 @@ }) if (!errorMsg) { - this.execPrint(printlist, _temps, formdata) + if (images.length > 0) { + let errorUrls = [] + images.forEach(url => { + let img = new Image() + img.onerror = () => { + errorUrls.push(url) + } + img.src = url + }) + + setTimeout(() => { + if (errorUrls.length > 0) { + notification.warning({ + top: 92, + message: '妯℃澘涓浘鐗� ' + errorUrls.join('锛�') + ' 宸插け鏁堬紒', + duration: 5 + }) + Object.keys(_temps).forEach(key => { + _temps[key].config.ReportHeader.Control = _temps[key].config.ReportHeader.Control.map(item => { + if (item.Type === 'image' && errorUrls.includes(item.Value)) { + item.Value = '' + } + return item + }) + }) + } + + this.execPrint(printlist, _temps, formdata) + }, 500) + } else { + this.execPrint(printlist, _temps, formdata) + } } else { this.execError(errorMsg) } @@ -358,17 +417,21 @@ let _param = { ...param, ...formdata } params.push(_param) } else if (btn.Ot === 'requiredSgl') { - param[setting.primaryKey] = data[0][setting.primaryKey] + if (setting.primaryKey) { + param[setting.primaryKey] = data[0][setting.primaryKey] + } let _param = { ...param, ...formdata } params.push(_param) } else if (btn.Ot === 'requiredOnce') { - let ids = data.map(d => { return d[setting.primaryKey]}) - ids = ids.filter(Boolean) - ids = ids.join(',') - - param[setting.primaryKey] = ids + if (setting.primaryKey) { + let ids = data.map(d => { return d[setting.primaryKey]}) + ids = ids.filter(Boolean) + ids = ids.join(',') + + param[setting.primaryKey] = ids + } let _param = { ...param, ...formdata } @@ -376,7 +439,10 @@ } else if (btn.Ot === 'required') { params = data.map((cell, index) => { let _param = { ...param } - _param[setting.primaryKey] = cell[setting.primaryKey] + + if (setting.primaryKey) { + _param[setting.primaryKey] = cell[setting.primaryKey] + } formlist.forEach(_data => { if (index !== 0 && _data.readin && cell.hasOwnProperty(_data.key)) { @@ -568,6 +634,7 @@ let _configparam = '' // 鎵撳嵃閰嶇疆淇℃伅 let fields = [] // 妯℃澘涓墍闇�瀛楁 let nonEFields = [] // 闈炵┖瀛楁 + let imgs = [] if (!res.ConfigParam) { error = '鏈幏鍙栧埌鎵撳嵃妯℃澘淇℃伅锛�' @@ -581,7 +648,6 @@ if (!configParam) { error = '鎵撳嵃妯℃澘瑙f瀽閿欒锛�' } else { - let control = configParam.elements.map(element => { let _field = element.field @@ -628,6 +694,12 @@ item.ImageWidth = element.imgWidth item.ImageHeight = element.imgHeight item.Trimming = '' + if (element.productValue && window.GLOB.systemType === 'production') { + item.Value = element.productValue + imgs.push(item.Value) + } else if (item.Value) { + imgs.push(item.Value) + } } else if (item.Type === 'text') { item.FontFamily = element.fontFamily item.FontSize = element.fontSize @@ -688,7 +760,8 @@ error: error, config: _configparam, fields: fields, - nonEFields: nonEFields + nonEFields: nonEFields, + imgs: imgs } } @@ -1251,13 +1324,14 @@ render() { const { btn, show } = this.props - const { loadingNumber, loading } = this.state + const { loadingNumber, loading, disabled } = this.state if (show === 'actionList') { return <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}> <Button icon={btn.icon} loading={loading} + disabled={disabled} className={'mk-btn mk-' + btn.class} onClick={() => {this.actionTrigger()}} >{loadingNumber ? `(${loadingNumber})` : '' + btn.label}</Button> @@ -1269,7 +1343,8 @@ type="link" title={show === 'icon' ? btn.label : ''} loading={loading} - style={btn.btnstyle} + disabled={disabled} + style={btn.style} icon={show === 'text' ? '' : (btn.icon || '')} onClick={() => {this.actionTrigger()}} >{show === 'icon' && btn.icon ? '' : btn.label}</Button> diff --git a/src/tabviews/zshare/actionList/tabbutton/index.jsx b/src/tabviews/zshare/actionList/tabbutton/index.jsx index 28bf3f2..fdb9d78 100644 --- a/src/tabviews/zshare/actionList/tabbutton/index.jsx +++ b/src/tabviews/zshare/actionList/tabbutton/index.jsx @@ -22,7 +22,23 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + disabled: false, primaryId: '' + } + + UNSAFE_componentWillMount () { + const { btn, selectedData } = this.props + let disabled = false + + if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + this.setState({disabled}) + } } shouldComponentUpdate (nextProps, nextState) { @@ -34,6 +50,24 @@ if (position === 'toolbar') { MKEmitter.addListener('triggerBtnId', this.actionTrigger) + } + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { btn, selectedData } = this.props + + if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) { + let disabled = false + + if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒� + nextProps.selectedData.forEach(item => { + let s = item[btn.controlField] + '' + if (s === btn.controlVal || (btn.controlVal && btn.controlVal.split(',').includes(s))) { + disabled = true + } + }) + } + this.setState({disabled}) } } @@ -62,19 +96,11 @@ duration: 5 }) return - } else if (!setting.primaryKey) { - // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾槸鍚﹁缃富閿� - notification.warning({ - top: 92, - message: '鏈缃富閿紒', - duration: 5 - }) - return } let primaryId = '' - if (btn.Ot === 'requiredSgl') { + if (btn.Ot === 'requiredSgl' && setting.primaryKey) { primaryId = data[0][setting.primaryKey] || '' } @@ -156,12 +182,14 @@ render() { const { btn, show } = this.props + const { disabled } = this.state if (show === 'actionList') { return ( <Button className={'mk-btn mk-' + btn.class} icon={btn.icon} + disabled={disabled} onClick={(e) => {e.stopPropagation(); this.actionTrigger()}} >{btn.label}</Button> ) @@ -170,7 +198,8 @@ <Button type="link" title={show === 'icon' ? btn.label : ''} - style={btn.btnstyle} + style={btn.style} + disabled={disabled} icon={show === 'text' ? '' : (btn.icon || '')} onClick={(e) => {e.stopPropagation(); this.actionTrigger()}} >{show === 'icon' && btn.icon ? '' : btn.label}</Button> diff --git a/src/tabviews/zshare/dategroup/index.jsx b/src/tabviews/zshare/dategroup/index.jsx deleted file mode 100644 index 64a37cf..0000000 --- a/src/tabviews/zshare/dategroup/index.jsx +++ /dev/null @@ -1,229 +0,0 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' -import { DatePicker, Tooltip, Icon } from 'antd' -import moment from 'moment' - -import Utils from '@/utils/utils.js' -import QuarterPicker from './quarterpicker' -import YearPicker from './yearpicker' -import './index.scss' - -const { MonthPicker, WeekPicker, RangePicker } = DatePicker - -class DateGroup extends Component { - static propTpyes = { - card: PropTypes.object, // 鎼滅储鏉′欢 - position: PropTypes.number, // 绱㈠紩锛岀敤浜庢帶鍒跺搴﹀拰骞寸殑灞曞紑鏂瑰悜 - onGroupChange: PropTypes.func // 鎼滅储鍐呭鍒囨崲 - } - - state = { - active: '', - quarterId: Utils.getuuid(), - yearId: Utils.getuuid(), - dateRange: '', - initDateRange: '', - initType: '', - placement: this.props.position % 4 !== 3 ? 'bottomLeft' : 'bottomRight' - } - - UNSAFE_componentWillMount() { - const { card } = this.props - - if (card.initval && card.initval[0]) { - let _type = card.initval[0] - let _val = card.initval[1] - let _dateRange = null - - if (_type === 'day') { - _dateRange = [moment().subtract(_val, 'days').format('YYYY-MM-DD'), - moment().subtract(_val, 'days').format('YYYY-MM-DD')] - } else if (_type === 'week') { - _dateRange = [moment().subtract(_val * 7, 'days').startOf('week').format('YYYY-MM-DD'), - moment().subtract(_val * 7, 'days').endOf('week').format('YYYY-MM-DD')] - } else if (_type === 'month') { - _dateRange = [moment().subtract(_val, 'month').startOf('month').format('YYYY-MM-DD'), - moment().subtract(_val, 'month').endOf('month').format('YYYY-MM-DD')] - } else if (_type === 'quarter') { - let _differ = parseInt(moment().format('MM')) % 3 - let _pdiffer = 0 - let _ndiffer = 0 - - // 宸�艰绠� - switch(_differ) { - case 0: - _pdiffer = 2 - _ndiffer = 0 - break - case 1: - _pdiffer = 0 - _ndiffer = -2 - break - case 2: - _pdiffer = 1 - _ndiffer = -1 - break - default: - } - _dateRange = [moment().subtract(_pdiffer + _val * 3, 'month').startOf('month').format('YYYY-MM-DD'), - moment().subtract(_ndiffer + _val * 3, 'month').endOf('month').format('YYYY-MM-DD')] - } else if (_type === 'year') { - let _year = parseInt(moment().format('YYYY')) - _val - _dateRange = [_year + '-01-01', _year + '-12-31'] - } else if (_type === 'customized') { - try { - _val = JSON.parse(_val) - } catch { - _val = [0, 0] - } - _dateRange = [moment().subtract(_val[0], 'days').format('YYYY-MM-DD'), - moment().subtract(_val[1], 'days').format('YYYY-MM-DD')] - } - this.setState({ - active: card.initval[0], - dateRange: _dateRange, - initDateRange: _dateRange, - initType: card.initval[0] - }) - } - } - - onChange = (date, type) => { - let values = [] - if (type === 'day') { - values = [moment(date).format('YYYY-MM-DD'), moment(date).format('YYYY-MM-DD')] - } else if (type === 'week') { - values = [moment(date).startOf('week').format('YYYY-MM-DD'), moment(date).endOf('week').format('YYYY-MM-DD')] - } else if (type === 'month') { - values = [moment(date).startOf('month').format('YYYY-MM-DD'), moment(date).endOf('month').format('YYYY-MM-DD')] - } else if (type === 'quarter') { - values = date - document.getElementById(this.state.quarterId).click() - } else if (type === 'year') { - values = date - document.getElementById(this.state.yearId).click() - } else if (type === 'customized') { - values = [moment(date[0]).format('YYYY-MM-DD'), moment(date[1]).format('YYYY-MM-DD')] - } - - this.setState({ - active: type, - dateRange: values - }, () => { - this.props.onGroupChange() - }) - } - - clearTime = () => { - this.setState({ - active: '', - dateRange: '' - }, () => { - this.props.onGroupChange() - }) - } - - reset = () => { - const { initDateRange, initType } = this.state - - this.setState({ - active: initType, - dateRange: initDateRange - }) - } - - getSearchItems = () => { - const { card } = this.props - const { dateRange, active } = this.state - let items = [] - - items.push({ - type: 'daterange', - key: card.datefield, - value: dateRange, - label: card.label, - match: 'between', - required: card.required === 'true' - }) - - if (card.transfer === 'true') { - items.push({ - type: card.type, - key: card.field, - value: active, - label: card.label, - match: '=', - forbid: true, - required: card.required === 'true' - }) - } - - return items - } - - render() { - const { card } = this.props - const { active, quarterId, yearId, dateRange, placement } = this.state - let tabs = {day: '鏃�', week: '鍛�', month: '鏈�', quarter: '瀛�', year: '骞�', customized: '鑷畾涔�'} - - return ( - <div className="table-search-date-group"> - {card.items.map(tab => { - if (tab === 'day') { - return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > - {tabs[tab]} - <DatePicker allowClear={false} onChange={(date) => this.onChange(date, tab)} /> - </span>) - } else if (tab === 'week') { - return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > - {tabs[tab]} - <WeekPicker dropdownClassName="group-week-picker" allowClear={false} onChange={(date) => this.onChange(date, tab)} /> - </span>) - } else if (tab === 'month') { - return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > - {tabs[tab]} - <MonthPicker allowClear={false} onChange={(date) => this.onChange(date, tab)} /> - </span>) - } else if (tab === 'quarter') { - return ( - <Tooltip key={tab} placement={placement} overlayClassName={'quarter-picker-tooltip ' + placement} trigger="click" title={ - <div> - <QuarterPicker card={card} onChange={(date) => this.onChange(date, tab)}/> - </div> - }> - <span id={quarterId} className={'ant-tag ant-tag-quarter ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > - {tabs[tab]} - </span> - </Tooltip> - ) - } else if (tab === 'year') { - return ( - <Tooltip key={tab} placement={placement} overlayClassName={'year-picker-tooltip ' + placement} trigger="click" title={ - <div> - <YearPicker card={card} onChange={(date) => this.onChange(date, tab)}/> - </div> - }> - <span id={yearId} className={'ant-tag ant-tag-quarter ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > - {tabs[tab]} - </span> - </Tooltip> - ) - } else { - return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > - {tabs[tab]} - <RangePicker allowClear={false} onChange={(date) => this.onChange(date, tab)} /> - </span>) - } - })} - - {dateRange ? <div className="table-search-date-group-value"> - {dateRange.join(' ~ ')} - <Icon type="close-circle" onClick={this.clearTime} className="ant-calendar-picker-clear" /> - </div> : null} - {!dateRange && card.required === 'true' ? <div className="ant-form-explain">璇烽�夋嫨{card.label}!</div> : null} - </div> - ) - } -} - -export default DateGroup \ No newline at end of file diff --git a/src/tabviews/zshare/fileupload/index.jsx b/src/tabviews/zshare/fileupload/index.jsx index df0cf6f..32ecbc4 100644 --- a/src/tabviews/zshare/fileupload/index.jsx +++ b/src/tabviews/zshare/fileupload/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { fromJS } from 'immutable' +import { is, fromJS } from 'immutable' import moment from 'moment' import { Upload, Button, Icon, Progress, notification } from 'antd' import SparkMD5 from 'spark-md5' @@ -16,23 +16,74 @@ class FileUpload extends Component { static propTpyes = { - value: PropTypes.array, // 鏂囦欢鏁扮粍 - accept: PropTypes.any, // 鏂囦欢鏍煎紡 - maxFile: PropTypes.any, // 鏈�澶ф枃浠舵暟 - fileType: PropTypes.string // 鏂囦欢鏄剧ず绫诲瀷 + config: PropTypes.object, // 琛ㄥ崟淇℃伅 + onChange: PropTypes.func, // 琛ㄥ崟鍙樺寲 } state = { percent: 0, + accept: '', + accepts: null, + maxFile: null, + rduri: '', + limit: 2, + compress: false, + fileType: 'text', showprogress: false, filelist: [] } UNSAFE_componentWillMount () { - const { value } = this.props - if (!value) return + const { config } = this.props - this.setState({filelist: fromJS(value).toJS()}) + let filelist = [] + if (config.initval) { + try { + filelist = config.initval.split(',').map((url, index) => { + return { + uid: `${index}`, + name: url.slice(url.lastIndexOf('/') + 1), + status: 'done', + url: url, + origin: true + } + }) + } catch { + filelist = [] + } + } + + let accept = '' + let accepts = null + let compress = false + if (config.compress === 'true') { + compress = true + accepts = ['.jpg', '.png', '.gif', '.jpeg'] + accept = accepts.join(',') + } else if (config.suffix) { + accepts = config.suffix.split(',') + accept = config.suffix + } + let rduri = config.rduri || '' + + if (window.GLOB.systemType === 'production') { + rduri = config.proRduri || '' + } + + this.setState({ + rduri, + accept, + accepts, + filelist, + compress, + limit: config.limit || 2, + maxFile: config.maxfile && config.maxfile > 0 ? config.maxfile : null, + fileType: config.fileType || 'text' + }) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) } onChange = ({ fileList }) => { @@ -44,14 +95,24 @@ }) this.setState({filelist: fileList}) - this.props.onChange(fileList) } onRemove = file => { const files = this.state.filelist.filter(v => v.uid !== file.uid) this.setState({filelist: files}) - this.props.onChange(files) + + let vals = [] + + files.forEach(item => { + if (item.origin && item.url) { + vals.push(item.url) + } else if (!item.origin && item.status === 'done' && item.response) { + vals.push(item.response) + } + }) + + this.props.onChange(vals.join(',')) } onUpdate = (url) => { @@ -63,19 +124,31 @@ filelist[filelist.length -1].origin = false } + filelist = filelist.filter(item => !!(item.url || item.response)) + + let vals = [] + + filelist.forEach(item => { + if (item.origin && item.url) { + vals.push(item.url) + } else if (!item.origin && item.status === 'done' && item.response) { + vals.push(item.response) + } + }) + this.setState({filelist}) - this.props.onChange(filelist) + this.props.onChange(vals.join(',')) } - onDelete = (msg) => { + onFail = (msg) => { let filelist = this.state.filelist.map(item => { if (!item.url && !item.response && !item.status) { item.status = 'error' } return item }) - this.setState({filelist, showprogress: false}) - this.props.onChange(filelist) + + this.setState({filelist, showprogress: false, percent: 0}) notification.warning({ top: 92, @@ -97,6 +170,7 @@ form.append('fileExt', params.file.fileType) form.append('shardingCnt', param.chunks) form.append('shardingNo', param.chunk) + form.append('LoginUID', sessionStorage.getItem('LoginUID') || '') Api.getLargeFileUpload(form).then(res => { if (res.status) { @@ -109,7 +183,7 @@ if (res.urlPath) { this.onUpdate(res.urlPath) } else { - this.onDelete() + this.onFail() } this.setState({ percent: 100 @@ -123,7 +197,7 @@ }) } } else { - this.onDelete(res.message) + this.onFail(res.message) } }) } @@ -139,12 +213,11 @@ } beforeUpload = (file) => { - const { accept } = this.props + const { accepts, compress, limit, rduri } = this.state - if (accept && file.name) { - let types = accept.split(',') + if (accepts && file.name) { let pass = false - types.forEach(type => { + accepts.forEach(type => { if (new RegExp(type + '$', 'ig').test(file.name)) { pass = true } @@ -164,6 +237,89 @@ showprogress: true, percent: 0 }) + + if (compress) { + let reader = new FileReader() + let fileSize = file.size / 1024 / 1024 + let compressRate = 0.9 + + if (fileSize / limit > 5) { + compressRate = 0.4 + } else if (fileSize / limit > 4) { + compressRate = 0.5 + } else if (fileSize / limit > 3) { + compressRate = 0.6 + } else if (fileSize / limit > 2) { + compressRate = 0.7 + } else if (fileSize > limit) { + compressRate = 0.8 + } + + reader.onload = (e) => { + let img = new Image() + let maxW = 640 + + img.onload = () => { + let cvs = document.createElement( 'canvas') + let ctx = cvs.getContext( '2d') + + if (img.width > maxW) { + img.height *= maxW / img.width + img.width = maxW + } + + cvs.width = img.width + cvs.height = img.height + + ctx.clearRect(0, 0, cvs.width, cvs.height) + ctx.drawImage(img, 0, 0, img.width, img.height) + + let param = {Base64Img: cvs.toDataURL('image/jpeg', compressRate)} + + if (rduri) { + param.rduri = rduri + } + + Api.fileuploadbase64(param).then(result => { + if (result.status && result.Images) { + let url = service + result.Images + + if (rduri) { + url = rduri.replace(/webapi(.*)$/, '') + result.Images + } + + this.onUpdate(url) + + this.setState({ + percent: 100 + }, () => { + setTimeout(() => { + this.setState({ + showprogress: false, + percent: 0 + }) + }, 200) + }) + } else { + this.onFail(result.message) + } + }) + } + + img.onerror = () => { + this.onFail('鍥剧墖璇诲彇澶辫触锛�') + } + + img.src = e.target.result + } + + reader.onerror = () => { + this.onFail('鏂囦欢璇诲彇澶辫触锛�') + } + + reader.readAsDataURL(file) + return false + } // 鍏煎鎬х殑澶勭悊 let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice @@ -233,11 +389,10 @@ } chunkFileReader.onerror = () => { - this.onDelete() - console.warn('File reading failed.') + this.onFail('鏂囦欢璇诲彇澶辫触锛�') } totalFileReader.onerror = () => { - this.onDelete() + this.onFail('鏂囦欢璇诲彇澶辫触锛�') } let loadNext = () => { @@ -269,12 +424,11 @@ } render() { - const { maxFile, fileType, accept } = this.props - const { showprogress, percent, filelist } = this.state + const { showprogress, percent, filelist, maxFile, fileType, accept } = this.state let uploadable = 'fileupload-form-container ' - if (maxFile && maxFile > 0 && filelist.length >= maxFile) { + if (maxFile && filelist.length >= maxFile) { uploadable += 'limit-fileupload' } @@ -284,7 +438,7 @@ listType: fileType, fileList: filelist, action: null, - accept: accept || '', + accept: accept, method: 'post', multiple: false, onChange: this.onChange, diff --git a/src/tabviews/zshare/fileupload/index.scss b/src/tabviews/zshare/fileupload/index.scss index 5841f7b..6b612d6 100644 --- a/src/tabviews/zshare/fileupload/index.scss +++ b/src/tabviews/zshare/fileupload/index.scss @@ -4,6 +4,12 @@ bottom: -20px; left: 0px; } + + .ant-upload-select-picture-card { + .ant-progress-small.ant-progress-line { + bottom: 0px; + } + } .ant-upload-list-picture-card .ant-upload-list-item { width: 90px; @@ -12,6 +18,12 @@ .ant-upload.ant-upload-select-picture-card { width: 90px; height: 90px; + } + a[href^="data"] { + pointer-events: none; + .anticon-eye-o { + display: none; + } } } .fileupload-form-container.limit-fileupload { @@ -26,4 +38,7 @@ } } } + > .ant-upload-select-picture-card { + display: none; + } } \ No newline at end of file diff --git a/src/tabviews/zshare/imgScale/index.jsx b/src/tabviews/zshare/imgScale/index.jsx new file mode 100644 index 0000000..dc4c542 --- /dev/null +++ b/src/tabviews/zshare/imgScale/index.jsx @@ -0,0 +1,65 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon } from 'antd' + +import './index.scss' + +class ImgScale extends Component { + static propTpyes = { + data: PropTypes.object + } + + state = { + list: [], + index: 0 + } + + UNSAFE_componentWillMount() { + const { data } = this.props + + this.setState({ + list: data.list || [], + index: data.index || 0 + }) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + reduce = () => { + const { index } = this.state + + this.setState({index: index - 1}) + } + + plus = () => { + const { index } = this.state + + this.setState({index: index + 1}) + } + + render() { + const { list, index } = this.state + + return ( + <div className="img-scale-wrap"> + <img src={list[index]} alt="" /> + {index > 0 ? <Icon type="left" onClick={this.reduce} /> : null} + {index < list.length -1 ? <Icon type="right" onClick={this.plus} /> : null} + </div> + ) + } +} + +export default ImgScale \ No newline at end of file diff --git a/src/tabviews/zshare/imgScale/index.scss b/src/tabviews/zshare/imgScale/index.scss new file mode 100644 index 0000000..db4944e --- /dev/null +++ b/src/tabviews/zshare/imgScale/index.scss @@ -0,0 +1,20 @@ +.img-scale-wrap { + position: relative; + img { + max-width: 100%; + } + + .anticon { + position: absolute; + top: calc(50% - 25px); + font-size: 30px; + padding: 10px; + } + + .anticon-left { + left: 20px; + } + .anticon-right { + right: 20px; + } +} diff --git a/src/tabviews/zshare/mutilform/checkCard/index.jsx b/src/tabviews/zshare/mutilform/checkCard/index.jsx index c8ceec6..fd825fa 100644 --- a/src/tabviews/zshare/mutilform/checkCard/index.jsx +++ b/src/tabviews/zshare/mutilform/checkCard/index.jsx @@ -2,6 +2,7 @@ import PropTypes from 'prop-types' import { Col, Row } from 'antd' +import MKEmitter from '@/utils/events.js' import './index.scss' class CheckCard extends Component { @@ -29,10 +30,12 @@ } changeCard = (item) => { - const { multiple } = this.props.card + const { card } = this.props const { selectKeys } = this.state - if (multiple === 'true') { + if (card.readonly) return + + if (card.multiple === 'true') { let keys = [] if (selectKeys.includes(item.$value)) { keys = selectKeys.filter(key => key !== item.$value) @@ -45,7 +48,13 @@ }, () => { this.props.onChange && this.props.onChange(keys.join(',')) }) - } else if (multiple !== 'true' && selectKeys !== item.$value) { + } else if (selectKeys !== item.$value) { + card.linkFields && card.linkFields.forEach((m, i) => { + setTimeout(() => { + MKEmitter.emit('mkSP', m.uuid, item.$value, 0) + }, (i + 1) * 10) + }) + this.setState({ selectKeys: item.$value }, () => { @@ -55,7 +64,7 @@ } getCards = () => { - const { display, width, options, fields, ratio, multiple } = this.props.card + const { display, width, options, fields, ratio, multiple, backgroundColor, borderColor } = this.props.card const { selectKeys } = this.state let paddingTop = '100%' @@ -67,12 +76,16 @@ paddingTop = '56.25%' } + let style = borderColor ? {borderColor} : {} + let _style = backgroundColor ? {backgroundColor} : null + if (!options || options.length === 0) { return null } else if (display !== 'picture') { if (!fields || fields.length === 0) { return null } + return options.map(item => { let _active = false if (multiple === 'true' && selectKeys.includes(item.$value)) { @@ -82,7 +95,8 @@ } return <Col span={width} key={item.key}> - <div className={'card-cell ' + (_active ? 'active' : '')} onClick={() => this.changeCard(item)}> + <div className={'card-cell' + (_active ? ' active' : '') + (_style ? ' bg-control' : '')} style={style} onClick={() => this.changeCard(item)}> + <div className="bg-mask" style={_style}></div> {fields.map(col => { return <span key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span> })} @@ -99,7 +113,7 @@ } return <Col span={width} key={item.key}> - <div className={'card-pic-cell ' + (_active ? 'active' : '')} onClick={() => this.changeCard(item)} style={{paddingTop, backgroundImage: `url(${item.$url})`}}> + <div className={'card-pic-cell ' + (_active ? 'active' : '')} onClick={() => this.changeCard(item)} style={{...style, paddingTop, backgroundImage: `url(${item.$url})`}}> </div> </Col> }) @@ -107,8 +121,9 @@ } render() { + const { card } = this.props return ( - <div className="check-card-form-box"> + <div className={'check-card-form-box' + (card.readonly ? ' readonly' : '')}> <Row gutter={12}>{this.getCards()}</Row> </div> ) diff --git a/src/tabviews/zshare/mutilform/checkCard/index.scss b/src/tabviews/zshare/mutilform/checkCard/index.scss index 3d87dc7..ae18860 100644 --- a/src/tabviews/zshare/mutilform/checkCard/index.scss +++ b/src/tabviews/zshare/mutilform/checkCard/index.scss @@ -2,28 +2,48 @@ margin-top: 10px; margin-bottom: -10px; .card-cell { + position: relative; border: 1px solid #bcbcbc; border-radius: 4px; padding: 6px; margin-bottom: 12px; line-height: 1.5; - transition: all 0.3s; cursor: pointer; + transition: all 0.3s; span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + position: relative; + z-index: 1; + } + .bg-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0.3; + border-radius: 4px; + background-color: transparent; + transition: opacity 0.3s; } } - .card-cell:hover, .card-cell.active { + .card-cell:not(.bg-control).active { border-color: #1890ff; background: #1890ff; span { color: #ffffff!important; } } + .card-cell.bg-control.active { + .bg-mask { + opacity: 1; + } + } .card-pic-cell { + position: relative; border: 1px solid #bcbcbc; border-radius: 4px; background-size: cover; @@ -31,9 +51,47 @@ margin-bottom: 12px; line-height: 1.5; cursor: pointer; + transition: all 0.3s; } - .card-pic-cell:hover, .card-pic-cell.active { + .card-pic-cell.active { border-color: #1890ff; box-shadow: 0px 0px 4px #1890ff; } + + .card-cell:not(.bg-control).active::after { + content: ' '; + position: absolute; + display: table; + border: 2px solid #ffffff; + border-top: 0; + border-left: 0; + bottom: 0; + right: 12px; + width: 6px; + height: 12px; + transform: rotate(45deg) scale(1) translate(-50%, -50%); + } +} +.check-card-form-box:not(.readonly) { + .card-cell:not(.bg-control):hover { + border-color: #1890ff; + background: #1890ff; + span { + color: #ffffff!important; + } + } + .card-cell.bg-control:not(.active):hover { + .bg-mask { + opacity: 0.7; + } + } + .card-pic-cell:hover { + border-color: #1890ff; + box-shadow: 0px 0px 4px #1890ff; + } +} +.check-card-form-box.readonly { + .card-cell, .card-pic-cell { + cursor: not-allowed; + } } \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.jsx b/src/tabviews/zshare/mutilform/customSwitch/index.jsx deleted file mode 100644 index 4a3c83a..0000000 --- a/src/tabviews/zshare/mutilform/customSwitch/index.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' -import { Switch } from 'antd' - -import './index.scss' - -class CheckCard extends Component { - static propTpyes = { - Item: PropTypes.bool, // 琛ㄥ崟 - onChange: PropTypes.func // 鏁版嵁鍒囨崲 - } - - state = { - defaultChecked: this.props.Item.initval === true - } - - UNSAFE_componentWillMount () { - const { Item, onChange } = this.props - if (Item.initval === true) { - onChange && onChange(Item.openVal) - } else { - onChange && onChange(Item.closeVal) - } - } - - onChange = (val) => { - const { Item, onChange } = this.props - if (val) { - onChange && onChange(Item.openVal) - } else { - onChange && onChange(Item.closeVal) - } - } - - render() { - const { Item } = this.props - const { defaultChecked } = this.state - - return ( - <Switch checkedChildren={Item.openText || ''} unCheckedChildren={Item.closeText || ''} defaultChecked={defaultChecked} onChange={this.onChange}/> - ) - } -} - -export default CheckCard \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customTextArea/index.jsx b/src/tabviews/zshare/mutilform/customTextArea/index.jsx deleted file mode 100644 index 457e5f2..0000000 --- a/src/tabviews/zshare/mutilform/customTextArea/index.jsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' -import { Input } from 'antd' - -import './index.scss' - -const { TextArea } = Input - -class CustomTextArea extends Component { - static propTpyes = { - Item: PropTypes.bool, // 琛ㄥ崟 - onChange: PropTypes.func // 鏁版嵁鍒囨崲 - } - - state = { - value: '', - encryption: false - } - - UNSAFE_componentWillMount () { - let value = '' - let encryption = false - - if (this.props['data-__meta']) { - value = this.props['data-__meta'].initialValue || '' - } - - if (this.props.Item && this.props.Item.encryption === 'true') { - encryption = true - if (value) { - try { - value = window.decodeURIComponent(window.atob(value)) - } catch { - value = this.props['data-__meta'].initialValue || '' - } - } - } - - this.setState({ - value, - encryption - }) - } - - UNSAFE_componentWillReceiveProps(nextProps) { - const { value, encryption } = this.state - - if (!encryption && value !== nextProps.value) { - this.setState({ value: nextProps.value || '' }) - } else if (encryption && window.btoa(window.encodeURIComponent(value)) !== nextProps.value) { - let _value = nextProps.value || '' - try { - _value = window.decodeURIComponent(window.atob(_value)) - } catch { - _value = nextProps.value || '' - } - this.setState({ value: _value }) - } - } - - onChange = (e) => { - const { encryption } = this.state - let val = e.target.value - - this.setState({ value: val }) - - let _val = val - if (encryption) { - try { - _val = window.btoa(window.encodeURIComponent(_val)) - } catch { - _val = val - } - } - this.props.onChange(_val) - } - - render() { - const { Item } = this.props - const { value } = this.state - - return ( - <TextArea value={value} autoSize={{ minRows: 2, maxRows: Item.maxRows || 6 }} onChange={this.onChange} disabled={Item.readonly === 'true'} /> - ) - } -} - -export default CustomTextArea \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx index 1efef2a..28affdd 100644 --- a/src/tabviews/zshare/mutilform/index.jsx +++ b/src/tabviews/zshare/mutilform/index.jsx @@ -1,7 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { fromJS } from 'immutable' -import { Form, Row, Col, Input, InputNumber, Select, DatePicker, notification, Checkbox, Radio, Tooltip, Icon } from 'antd' +import { Form, Row, Col, notification, Tooltip, Icon } from 'antd' import moment from 'moment' import Api from '@/api' @@ -9,17 +9,21 @@ import { formRule } from '@/utils/option.js' import Utils from '@/utils/utils.js' import asyncComponent from '@/utils/asyncComponent' -import asyncSpinComponent from '@/utils/asyncSpinComponent' +import MKEmitter from '@/utils/events.js' +import MKInput from './mkInput' +import MKNumberInput from './mkNumberInput' +import MKSelect from './mkSelect' import './index.scss' -const { MonthPicker } = DatePicker - -const CheckCard = asyncComponent(() => import('./checkCard')) -const CustomSwitch = asyncComponent(() => import('./customSwitch')) -const CustomTextArea = asyncComponent(() => import('./customTextArea')) -const FileUpload = asyncComponent(() => import('../fileupload')) -const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) -const Editor = asyncSpinComponent(() => import('@/components/editor')) +const MKCheckCard = asyncComponent(() => import('./mkCheckCard')) +const MKSwitch = asyncComponent(() => import('./mkSwitch')) +const MKCheckbox = asyncComponent(() => import('./mkCheckbox')) +const MKRadio = asyncComponent(() => import('./mkRadio')) +const MKDatePicker = asyncComponent(() => import('./mkDatePicker')) +const MKTextArea = asyncComponent(() => import('./mkTextArea')) +const MKFileUpload = asyncComponent(() => import('../fileupload')) +const MKColor = asyncComponent(() => import('./mkColor')) +const MKEditor = asyncComponent(() => import('@/components/editor')) class MainSearch extends Component { static propTpyes = { @@ -33,154 +37,24 @@ } state = { - datatype: null, // 鏁版嵁绫诲瀷 - readtype: null, // 鏄惁鍙 - readin: null, // 琛屾暟鎹槸鍚﹀啓鍏� - writein: null, // 鎵ц鏃舵槸鍚﹀~鍏ラ粯璁ql - fieldlen: null, // 瀛楁闀垮害 formlist: [], // 琛ㄥ崟椤� - intercepts: [], // 鎴彇瀛楁 - record: {} // 璁板綍涓嬫媺琛ㄥ崟鍏宠仈瀛楁锛岀敤浜庢暟鎹啓鍏� } + + record = {} componentDidMount () { const { data, BData, action } = this.props - let datatype = {} - let readtype = {} - let readin = {} - let writein = {} - let fieldlen = {} - let intercepts = [] - let _inputfields = [] let linkFields = {} // 鍏宠仈鑿滃崟 - let supItemVal = {} // 涓婄骇鑿滃崟鍒濆鍊� + let controlFields = {} // 鎺у埗琛ㄥ崟 let deForms = [] // 闇�瑕佸姩鎬佽幏鍙栦笅鎷夎彍鍗曠殑琛ㄥ崟 + let record = {} let formlist = fromJS(action.fields).toJS() + let fieldMap = new Map() - formlist.forEach(item => { - if (item.type === 'text' || item.type === 'number') { // 鐢ㄤ簬杩囨护涓嬫媺鑿滃崟鍏宠仈琛ㄥ崟 - _inputfields.push(item.field) - } else if (item.type === 'textarea') { - _inputfields.push(item.field) - } else if (item.type === 'link') { - linkFields[item.linkField] = linkFields[item.linkField] || [] - linkFields[item.linkField].push(item.field) - } - if (item.interception === 'true') { // 瀛楃鎴彇瀛楁 - intercepts.push(item.field) - } - }) - - formlist = formlist.map(item => { - if (item.labelwidth) { - item.labelCol = {style: {width: item.labelwidth + '%'}} - item.wrapperCol = {style: {width: (100 - item.labelwidth) + '%'}} - } - if (item.type === 'split' || item.type === 'hint') return item - - // 鏁版嵁鑷姩濉厖 - let _readin = item.readin !== 'false' - if (item.type === 'linkMain' || item.type === 'funcvar') { - _readin = false - } - - let _fieldlen = item.fieldlength || 50 - if (item.type === 'textarea' || item.type === 'fileupload' || item.type === 'multiselect' || item.type === 'brafteditor') { - _fieldlen = item.fieldlength || 512 - } else if (item.type === 'number') { - _fieldlen = item.decimal ? item.decimal : 0 - item.initval = item.initval || 0 - } - - datatype[item.field] = item.type - readtype[item.field] = item.readonly === 'true' - readin[item.field] = _readin - writein[item.field] = item.writein !== 'false' - fieldlen[item.field] = _fieldlen - - if (item.setAll === 'true' && (item.type === 'select' || item.type === 'link' || item.type === 'radio')) { // 娣诲姞绌哄�� - item.options.unshift({ - key: Utils.getuuid(), - Value: '', - Text: item.emptyText || '绌�', - ParentID: '' - }) - } - - item.oriOptions = item.options ? fromJS(item.options).toJS() : null // 淇濆瓨鍒濆鍒楄〃锛岀敤浜庤仈鍔ㄨ彍鍗曟帶鍒� - - // 涓嬬骇琛ㄥ崟鎺у埗-瀛楁鍐欏叆 - if ((item.type === 'select' || item.type === 'radio') && item.linkSubField && item.linkSubField.length > 0) { - item.linkSubField = item.linkSubField.filter(_item => _inputfields.includes(_item)) - } - if (item.linkSubField && item.linkSubField.length === 0) { - item.linkSubField = null - } - - let newval = '' - - if (item.type === 'linkMain') { - newval = BData && BData[item.field] ? BData[item.field] : '' - } else if (_readin && !/^date/.test(item.type) && data && data.hasOwnProperty(item.field)) { - newval = data[item.field] - } else if (item.type === 'date') { // 鏃堕棿鎼滅储 - if (_readin && data && data.hasOwnProperty(item.field)) { - newval = data[item.field] - } - if (newval) { - newval = moment(newval, 'YYYY-MM-DD') - newval = newval.format('YYYY-MM-DD') === 'Invalid date' ? '' : newval - } - if (!newval && item.initval) { - newval = moment().subtract(item.initval, 'days') - } else if (!newval) { - newval = null - } - } else if (item.type === 'datemonth') { - if (_readin && data && data.hasOwnProperty(item.field)) { - newval = data[item.field] - } - if (newval) { - newval = moment(newval, 'YYYY-MM') - newval = newval.format('YYYY-MM') === 'Invalid date' ? '' : newval - } - if (!newval && item.initval) { - newval = moment().subtract(item.initval, 'month') - } else if (!newval) { - newval = null - } - } else if (item.type === 'datetime') { - if (_readin && data && data.hasOwnProperty(item.field)) { - newval = data[item.field] - } - if (newval) { - newval = moment(newval, 'YYYY-MM-DD HH:mm:ss') - newval = newval.format('YYYY-MM-DD HH:mm:ss') === 'Invalid date' ? '' : newval - } - if (!newval && item.initval) { - newval = moment(moment().subtract(item.initval, 'days').format('YYYY-MM-DD') + ' 00:00:00', 'YYYY-MM-DD HH:mm:ss') - } else if (!newval) { - newval = null - } - } - - if (item.type === 'switch' && newval !== '') { // 寮�鍏冲彧鎺ユ敹鍥哄畾鍊� - if (newval !== item.closeVal && newval !== item.openVal) { - newval = '' - } else if (newval === item.openVal) { - newval = true - } else { - newval = false - } - } - - // 璇诲彇琛ㄦ牸鏁版嵁鎴栬鏈夋椂闂寸殑鍒濆鍊� - item.initval = newval !== '' ? newval : item.initval - - // 涓嬫媺琛ㄥ崟锛屽瓨鍦ㄤ笂绾ц彍鍗曟椂锛岀敓鎴愭樉绀哄�煎垪琛紝浼樺厛浠ユ暟瀛楀垽鏂� - if (item.supvalue) { + formlist = formlist.filter(item => { + if (item.supField && item.supvalue) { // 澶氬眰琛ㄥ崟鎺у埗 let supvals = [] item.supvalue.split(',').forEach(val => { supvals.push(val) @@ -188,88 +62,306 @@ supvals.push(+val) } }) - item.supvalue = supvals + controlFields[item.supField] = controlFields[item.supField] || [] + controlFields[item.supField].push({field: item.field, values: supvals}) + } + if (item.type === 'link') { + linkFields[item.linkField] = linkFields[item.linkField] || [] + linkFields[item.linkField].push({field: item.field, uuid: item.uuid}) + } + + if (item.type === 'split' || item.type === 'hint') return true + + if (!item.field || !['text', 'number', 'switch', 'select', 'link', 'linkMain', 'funcvar', 'date', 'datemonth', 'datetime', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color'].includes(item.type)) return false + + // 鏁版嵁鑷姩濉厖 + item.readin = item.readin !== 'false' + item.readonly = item.readonly === 'true' + item.writein = item.writein !== 'false' + item.hidden = item.hidden === 'true' + item.fieldlength = item.fieldlength || 50 + + if (item.type === 'funcvar') { + item.readin = false + item.hidden = true + } else if (item.type === 'number') { + item.decimal = item.decimal || 0 + item.fieldlength = item.decimal + item.initval = item.initval || 0 + } + + if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type)) { + item.options = item.options || [] + item.options = item.options.map(cell => { + cell.value = cell.Value + cell.label = cell.Text + return cell + }) + if (item.setAll === 'true' && ['select', 'link', 'radio'].includes(item.type)) { // 娣诲姞绌哄�� + item.options.unshift({ + key: Utils.getuuid(), + value: '', + label: item.emptyText || '绌�', + ParentID: '' + }) + } + item.oriOptions = fromJS(item.options).toJS() + } + + let newval = '$empty' + + if (item.readin && data && data.hasOwnProperty(item.field)) { + newval = data[item.field] + } + if (item.type === 'linkMain') { + newval = BData && BData[item.field] ? BData[item.field] : '$empty' + } else if (item.type === 'date') { // 鏃堕棿鎼滅储 + if (newval !== '$empty') { + newval = moment(newval, 'YYYY-MM-DD').format('YYYY-MM-DD') + newval = newval === 'Invalid date' ? '$empty' : newval + } + if (newval === '$empty' && item.initval) { + newval = moment().subtract(item.initval, 'days').format('YYYY-MM-DD') + } + } else if (item.type === 'datemonth') { + if (newval !== '$empty') { + newval = moment(newval, 'YYYY-MM').format('YYYY-MM') + newval = newval === 'Invalid date' ? '$empty' : newval + } + if (newval === '$empty' && item.initval) { + newval = moment().subtract(item.initval, 'month').format('YYYY-MM') + } + } else if (item.type === 'datetime') { + if (newval !== '$empty') { + newval = moment(newval, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss') + newval = newval === 'Invalid date' ? '$empty' : newval + } + if (newval === '$empty' && item.initval) { + newval = moment().subtract(item.initval, 'days').format('YYYY-MM-DD') + ' 00:00:00' + } + } else if (item.type === 'switch') { // 寮�鍏冲彧鎺ユ敹鍥哄畾鍊� + if (newval !== '$empty' && (newval === item.closeVal || newval === item.openVal)) { + + } else if (item.initval === true) { + newval = item.openVal + } else { + newval = item.closeVal + } + } + + if (newval !== '$empty') { + item.initval = newval + } else if (item.initval === undefined) { + item.initval = '' + } + + if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type) && item.resourceType === '1') { + deForms.push(item) + } + + if (item.type === 'text') { + let _rules = [{ + pattern: /^[^']*$/ig, + message: formRule.input.quotemsg + }, { + required: item.required === 'true', + message: item.label + '涓嶅彲涓虹┖!' + }, { + max: item.fieldlength, + message: formRule.input.formMessage.replace('@max', item.fieldlength) + }] + + if (item.regular) { + if (item.regular === 'number') { + _rules.push({ + pattern: /^[0-9.-]*$/ig, + message: formRule.input.numbermsg + }) + } else if (item.regular === 'letter') { + _rules.push({ + pattern: /^[a-zA-Z]*$/ig, + message: formRule.input.lettermsg + }) + } else if (item.regular === 'letter&number') { + _rules.push({ + pattern: /^[a-zA-Z0-9]*$/ig, + message: formRule.input.letternummsg + }) + } else if (item.regular === 'funcname') { + _rules.push({ + pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig, + message: formRule.input.funcname + }) + } + } + + item.rules = _rules + } else if (item.type === 'number') { + item.rules = [{ + required: true, + message: item.label + '涓嶅彲涓虹┖!' + }, { + validator: (rule, value, callback) => this.handleConfirmPassword(rule, value, callback, item) + }] + } else if (item.type === 'textarea') { + let _rules = [ + { + required: item.required === 'true', + message: item.label + '涓嶅彲涓虹┖!' + }, + { + max: item.fieldlength, + message: formRule.input.formMessage.replace('@max', item.fieldlength) + } + ] + if (item.encryption !== 'true') { + _rules.push({ + pattern: /^[^']*$/ig, + message: formRule.input.quotemsg + }) + } + item.rules = _rules + } else if (item.type === 'brafteditor') { + item.rules = [ + { + required: item.required === 'true', + message: item.label + '涓嶅彲涓虹┖!' + }, + { + max: item.fieldlength, + message: formRule.input.formMessage.replace('@max', item.fieldlength) + } + ] + } else if (item.type === 'linkMain') { + item.rules = [ + { + required: item.required === 'true', + message: item.label + '涓嶅彲涓虹┖!' + } + ] + } else { + item.rules = [ + { + required: item.required === 'true', + message: '璇烽�夋嫨' + item.label + '!' + } + ] + } + + fieldMap.set(item.field, item) + + return true + }) + + Object.keys(controlFields).forEach(key => { + if (!fieldMap.has(key)) return + + let supItem = fieldMap.get(key) + let fields = [] + + controlFields[key].forEach(item => { + if (!fieldMap.has(item.field)) return + + let cell = fieldMap.get(item.field) + + if (cell.hidden) return + + if (supItem.hidden || !item.values.includes(supItem.initval)) { + cell.hidden = true + fieldMap.set(item.field, cell) + } + + fields.push(item) + }) + + supItem.controlFields = fields + + fieldMap.set(key, supItem) + }) + + formlist = formlist.map(cell => { + if (cell.labelwidth) { + cell.labelCol = {style: {width: cell.labelwidth + '%'}} + cell.wrapperCol = {style: {width: (100 - cell.labelwidth) + '%'}} + } + if (!cell.field || !fieldMap.has(cell.field)) return cell + let item = fieldMap.get(cell.field) + + if (item.type === 'link') { + item.supInitVal = '' + + if (fieldMap.has(item.linkField)) { + item.supInitVal = fieldMap.get(item.linkField).initval || '' + } else if (data && data.hasOwnProperty(item.linkField)) { + item.supInitVal = data[item.linkField] + } + + item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.value === '') + } + + if (['select', 'link', 'radio'].includes(item.type) && item.resourceType !== '1') { // 閫変腑绗竴椤� + if (typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { + item.initval = item.options[0] ? item.options[0].value : '' + } + } + + if (typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { + record[item.field] = '' + } else { + record[item.field] = item.initval } if (linkFields[item.field]) { item.linkFields = linkFields[item.field] } - supItemVal[item.field] = item.initval - if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type) && item.resourceType === '1') { - deForms.push(item) - } else if (['select', 'link', 'radio'].includes(item.type) && item.resourceType !== '1') { // 閫変腑绗竴椤� - if (typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { - item.initval = item.options[0] ? item.options[0].Value : '' + // 涓嬬骇琛ㄥ崟鎺у埗-瀛楁鍐欏叆 + if ((['select', 'radio'].includes(item.type) || (item.type === 'checkcard' && item.multiple !== 'true')) && item.linkSubField) { + item.subFields = [] + item.linkSubField.forEach(m => { + let n = fieldMap.get(m) + if (n && ['text', 'number', 'textarea'].includes(n.type)) { + item.subFields.push({ + uuid: n.uuid, + field: m + }) + } + }) + + if (item.subFields.length === 0) { + item.subFields = null } + item.linkSubField = null } + if (item.enter === 'tab' || item.enter === 'sub') { + if (fieldMap.has(item.tabField)) { + item.tabUuid = fieldMap.get(item.tabField).uuid + } else { + item.tabUuid = item.uuid + } + } + return item }) - formlist = formlist.map(item => { - if (item.type === 'link') { - item.supInitVal = '' + this.record = record - if (supItemVal[item.linkField]) { - item.supInitVal = supItemVal[item.linkField] - } else if (data && data.hasOwnProperty(item.linkField)) { - item.supInitVal = data[item.linkField] - } - - item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '') - } - return item - }) - - this.setState({ - readin, - writein, - readtype, - datatype, - fieldlen, - intercepts, - formlist - }, () => { - if (action.setting && action.setting.focus) { + this.setState({ formlist }, () => { + if (action.setting && action.setting.focus && fieldMap.has(action.setting.focus)) { setTimeout(() => { - this.selectInput(action.setting.focus) + MKEmitter.emit('mkFC', 'focus', fieldMap.get(action.setting.focus).uuid) }, 500) } - // 鐢ㄦ潵鏇存柊state锛岄槻姝㈠彈鎺ц〃鍗曞垵濮嬫椂涓嶆樉绀� - this.setState({ - loaded: true - }) - this.improveActionForm(deForms) - }) - } - selectInput = (selectId) => { - try { - let _form = document.getElementById('main-form-box') - let _inputs = _form.getElementsByTagName('input') - _inputs = [..._inputs] - _inputs.forEach(input => { - if (!input || input.id !== selectId) return - - if (input.className === 'ant-select-search__field') { - let div = input.parentNode - while (div && div.parentNode) { - div = div.parentNode - if (div.id === selectId) { - div && div.click && div.click() - div = null - } - } - } else if (input.select) { - input.select() - } else if (input.focus) { - input.focus() + if (deForms.length > 0) { + if (this.props.menuType !== 'HS' && options.sysType === 'local' && window.GLOB.systemType !== 'production') { + this.improveSimpleActionForm(deForms) + } else { + this.improveActionForm(deForms) } - }) - } catch { - console.warn('focus error锛�') - } + } + }) } /** @@ -277,14 +369,6 @@ */ improveActionForm = (deForms) => { const { BID, menuType } = this.props - const { formlist } = this.state - - if (deForms.length === 0) { - return - } else if (menuType !== 'HS' && options.sysType === 'local' && !window.GLOB.systemType) { - this.improveSimpleActionForm(deForms) - return - } let deffers = [] let mainItems = [] // 浜戠鎴栧崟鐐规暟鎹� @@ -298,7 +382,7 @@ } }) - if (menuType !== 'HS' && window.GLOB.systemType !== 'production') { + if (menuType !== 'HS' && options.sysType !== 'local') { localItems = [...localItems, ...mainItems] mainItems = [] } @@ -309,11 +393,8 @@ LText: localItems.join(' union all '), obj_name: '', arr_field: '', - table_type: 'Y' - } - - if (BID) { - param.BID = BID + table_type: 'Y', + BID: BID || '' } if (param.LText) { @@ -347,11 +428,8 @@ LText: mainItems.join(' union all '), obj_name: '', arr_field: '', - table_type: 'Y' - } - - if (BID) { - mainparam.BID = BID + table_type: 'Y', + BID: BID || '' } if (mainparam.LText) { @@ -394,62 +472,7 @@ delete result.message delete result.status - let _formlist = formlist.map(item => { - if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type) && result[item.field] && result[item.field].length > 0) { - let options = [] - result[item.field].forEach(cell => { - let _cell = { key: Utils.getuuid() } - - if (item.type !== 'checkcard') { - _cell.Value = cell[item.valueField] - _cell.Text = cell[item.valueText] - if ((!_cell.Value && _cell.Value !== 0) || (!_cell.Text && _cell.Text !== 0)) return - } else { - _cell.$value = cell[item.valueField] - _cell = {..._cell, ...cell} - if (!_cell.$value && _cell.$value !== 0) return - } - - if (item.type === 'link') { - _cell.ParentID = cell[item.linkField] === undefined ? '' : cell[item.linkField] - } else if (item.linkSubField) { - item.linkSubField.forEach(_field => { - _cell[_field] = (cell[_field] || cell[_field] === 0) ? cell[_field] : '' - }) - } - - options.push(_cell) - }) - - item.oriOptions = [...item.oriOptions, ...options] - } - return item - }) - let values = [] - - this.setState({ - formlist: _formlist.map(item => { - if (item.type === 'link') { - item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '') - } else if (['select', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type)) { - item.options = item.oriOptions - } - if (['select', 'link', 'radio'].includes(item.type) && typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { // 閫変腑绗竴椤� - item.initval = item.options[0] ? item.options[0].Value : '' - values.push({field: item.field, value: item.initval}) - } - return item - }) - }, () => { - if (values.length === 0) return - let fieldsvalue = {} - values.forEach(item => { - if (this.props.form.getFieldValue(item.field) !== undefined) { - fieldsvalue[item.field] = item.value - } - }) - this.props.form.setFieldsValue(fieldsvalue) - }) + this.resetFormList(result) }) } @@ -457,18 +480,13 @@ * @description 娴嬭瘯绯荤粺鑾峰彇涓嬫媺琛ㄥ崟閫夐」淇℃伅 */ improveSimpleActionForm = (deForms) => { - const { formlist } = this.state - let deffers = deForms.map(form => { let param = { func: 'sPC_Get_SelectedList', LText: form.data_sql, obj_name: form.field, - arr_field: form.arr_field - } - - if (this.props.BID) { - param.BID = this.props.BID + arr_field: form.arr_field, + BID: this.props.BID || '' } param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') @@ -501,152 +519,56 @@ delete result.message delete result.status - let _formlist = formlist.map(item => { - if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type) && result[item.field] && result[item.field].length > 0) { - let options = [] - result[item.field].forEach(cell => { - let _cell = { key: Utils.getuuid() } - - if (item.type !== 'checkcard') { - _cell.Value = cell[item.valueField] - _cell.Text = cell[item.valueText] - if ((!_cell.Value && _cell.Value !== 0) || (!_cell.Text && _cell.Text !== 0)) return - } else { - _cell.$value = cell[item.valueField] - _cell = {..._cell, ...cell} - if (!_cell.$value && _cell.$value !== 0) return - } - - if (item.type === 'link') { - _cell.ParentID = cell[item.linkField] === undefined ? '' : cell[item.linkField] - } else if (item.linkSubField) { - item.linkSubField.forEach(_field => { - _cell[_field] = (cell[_field] || cell[_field] === 0) ? cell[_field] : '' - }) - } - - options.push(_cell) - }) - - item.oriOptions = [...item.oriOptions, ...options] - } - return item - }) - let values = [] - - this.setState({ - formlist: _formlist.map(item => { - if (item.type === 'link') { - item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '') - } else if (['select', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type)) { - item.options = item.oriOptions - } - if (['select', 'link', 'radio'].includes(item.type) && typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { // 閫変腑绗竴椤� - item.initval = item.options[0] ? item.options[0].Value : '' - values.push({field: item.field, value: item.initval}) - } - return item - }) - }, () => { - if (values.length === 0) return - let fieldsvalue = {} - values.forEach(item => { - if (this.props.form.getFieldValue(item.field) !== undefined) { - fieldsvalue[item.field] = item.value - } - }) - this.props.form.setFieldsValue(fieldsvalue) - }) + this.resetFormList(result) }) } - resetform = (formlist, supfields, index, fieldsvalue) => { - index++ - let subfields = [] + resetFormList = (result) => { + let _formlist = this.state.formlist.map(item => { + if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type) && result[item.field] && result[item.field].length > 0) { + let options = [] + result[item.field].forEach(cell => { + let _cell = { key: Utils.getuuid() } - supfields.forEach(supfield => { - formlist = formlist.map(item => { - if (item.type === 'link' && item.linkField === supfield.field) { - - item.options = item.oriOptions.filter(option => option.ParentID === supfield.initval || option.Value === '') - item.initval = item.options[0] ? item.options[0].Value : '' - - if (this.props.form.getFieldValue(item.field) !== undefined) { - fieldsvalue[item.field] = item.initval + if (item.type !== 'checkcard') { + _cell.value = cell[item.valueField] + _cell.label = cell[item.valueText] + if (!_cell.label && _cell.label !== 0) return + } else { + _cell.$value = cell[item.cardValField] + _cell = {..._cell, ...cell} } - subfields.push(item) + if (item.type === 'link') { + _cell.ParentID = cell[item.linkField] === undefined ? '' : cell[item.linkField] + } else if (item.subFields) { + item.subFields.forEach(m => { + _cell[m.field] = (cell[m.field] || cell[m.field] === 0) ? cell[m.field] : '' + }) + } + + options.push(_cell) + }) + + item.oriOptions = [...item.oriOptions, ...options] + + if (item.type === 'link') { + item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.value === '') + } else if (['select', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type)) { + item.options = item.oriOptions } - return item - }) - }) - - if (subfields.length === 0 || index > 6) { - return {formlist: formlist, fieldsvalue: fieldsvalue} - } else { - return this.resetform(formlist, subfields, index, fieldsvalue) - } - } - - selectChange = (_field, value) => { - const { record } = this.state - let formlist = fromJS(this.state.formlist).toJS() - let subfields = [] - let fieldsvalue = {} - let _record = {} - - formlist = formlist.map(item => { - if (item.type === 'link' && item.linkField === _field.field) { - item.options = item.oriOptions.filter(option => option.ParentID === value || option.Value === '') - item.initval = item.options[0] ? item.options[0].Value : '' - - if (this.props.form.getFieldValue(item.field) !== undefined) { - fieldsvalue[item.field] = item.initval - } - - subfields.push(item) } + + if (['select', 'link', 'radio'].includes(item.type) && typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { // 閫変腑绗竴椤� + item.initval = item.options[0] ? item.options[0].value : '' + this.record[item.field] = item.initval + } + return item }) - - // 琛ㄥ崟鍒囨崲鏃讹紝鏇存柊鍏宠仈瀛楁 - if (_field.linkSubField) { - let _data = _field.options.filter(op => op.Value === value)[0] - - if (_data) { - _field.linkSubField.forEach(subfield => { - if (this.props.form.getFieldValue(subfield) !== undefined) { - fieldsvalue[subfield] = (_data[subfield] || _data[subfield] === 0) ? _data[subfield] : '' - } else { - _record[subfield] = (_data[subfield] || _data[subfield] === 0) ? _data[subfield] : '' - } - }) - } - } - if (subfields.length === 0) { - this.props.form.setFieldsValue(fieldsvalue) - this.setState({ - record: {...record, ..._record} - }) - } else { - let result = this.resetform(formlist, subfields, 0, fieldsvalue) - - this.props.form.setFieldsValue(fieldsvalue) - this.setState({ - formlist: result.formlist, - record: {...record, ..._record} - }) - } - - this.setState({}, () => { - if (!_field.enter || _field.enter === 'false') return - - if (_field.enter === 'tab') { - this.selectInput(_field.tabField) - } else if (_field.enter === 'sub') { - this.handleSubmit() - } + this.setState({ + formlist: _formlist }) } @@ -663,26 +585,45 @@ callback() } - handleChange = (e, item) => { - let val = e.target.value + recordChange = (values, item) => { + this.record = {...this.record, ...values} - if (item.enter === 'false') return - if (!val || !/\n/ig.test(val)) return - if (item.enter === 'tab') { - this.selectInput(item.tabField) - } else { - this.handleSubmit(e) - this.selectInput(item.tabField || item.field) - } - } + if (item && item.controlFields) { + let map = new Map() + this.state.formlist.forEach(cell => { + if (!cell.field) return + map.set(cell.field, cell) + }) - handleInputSubmit = (e, item) => { - if (item.enter === 'false') return - if (item.enter === 'tab') { - this.selectInput(item.tabField) - } else { - this.handleSubmit(e) - this.selectInput(item.tabField || item.field) + let reset = (current) => { + let val = this.record[current.field] + + current.controlFields.forEach(cell => { + let m = map.get(cell.field) + m.hidden = current.hidden || !cell.values.includes(val) + + if (m.hidden) { + m.initval = this.record[m.field] + } + + map.set(cell.field, m) + + if (m.controlFields) { + reset(m) + } + }) + } + + reset(item) + + this.setState({ + formlist: this.state.formlist.map(cell => { + if (cell.field) { + return map.get(cell.field) + } + return cell + }) + }) } } @@ -691,24 +632,9 @@ const { formlist } = this.state const fields = [] - let filtration = {} formlist.forEach((item, index) => { - if ((!item.field && item.type !== 'split' && item.type !== 'hint') || item.hidden === 'true' || item.type === 'funcvar') return - if (item.supField) { // 澶氬眰琛ㄥ崟鎺у埗 - let _supVal = this.props.form.getFieldValue(item.supField) - - if (_supVal === undefined && filtration[item.supField]) { - _supVal = filtration[item.supField] - } - - if (item.supvalue.includes(_supVal)) { - let _subVal = this.props.form.getFieldValue(item.field) - filtration[item.field] = _subVal === undefined ? item.initval : _subVal - } else { - return - } - } + if (item.hidden) return if (item.type === 'split') { fields.push( @@ -719,559 +645,59 @@ } else if (item.type === 'hint') { fields.push( <Col span={item.span || 24} key={index}> - <Form.Item - colon={!!item.label} - label={item.label} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - className="hint" - > + <Form.Item className="hint" colon={!!item.label} label={item.label} labelCol={item.labelCol} wrapperCol={item.wrapperCol}> <div className="message">{item.message}</div> </Form.Item> </Col> ) - } else if (item.type === 'text') { - let _max = item.fieldlength || 50 - let _rules = [{ - pattern: /^[^']*$/ig, - message: formRule.input.quotemsg - }] - - if (item.regular) { - if (item.regular === 'number') { - _rules = [{ - pattern: /^[0-9.-]*$/ig, - message: formRule.input.numbermsg - }] - } else if (item.regular === 'letter') { - _rules = [{ - pattern: /^[a-zA-Z]*$/ig, - message: formRule.input.lettermsg - }] - } else if (item.regular === 'letter&number') { - _rules = [{ - pattern: /^[a-zA-Z0-9]*$/ig, - message: formRule.input.letternummsg - }] - } else if (item.regular === 'funcname') { - _rules = [{ - pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig, - message: formRule.input.funcname - }] - } + } else { + let content = null + let className = '' + let label = item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}><Icon type="question-circle" />{item.label}</Tooltip> : item.label + + if (item.type === 'text' || item.type === 'linkMain') { + content = (<MKInput config={item} onChange={(val) => this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />) + } else if (item.type === 'number') { + content = (<MKNumberInput config={item} onChange={(val) => this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />) + } else if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') { + content = (<MKSelect config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} onSubmit={this.props.inputSubmit} />) + } else if (item.type === 'color') { + content = (<MKColor config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>) + } else if (item.type === 'checkcard') { + className = "checkcard" + content = (<MKCheckCard config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>) + } else if (item.type === 'switch') { + content = (<MKSwitch config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>) + } else if (item.type === 'checkbox') { + content = (<MKCheckbox config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>) + } else if (item.type === 'radio') { + content = (<MKRadio config={item} onChange={(val) => this.recordChange({[item.field]: val}, item)}/>) + } else if (item.type === 'date' || item.type === 'datemonth' || item.type === 'datetime') { + content = (<MKDatePicker config={item} onChange={(val) => this.recordChange({[item.field]: val})} />) + } else if (item.type === 'fileupload') { + content = (<MKFileUpload config={item} onChange={(val) => this.recordChange({[item.field]: val})} />) + } else if (item.type === 'textarea') { + content = (<MKTextArea config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>) + } else if (item.type === 'brafteditor') { + content = (<MKEditor config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>) + label = item.hidelabel !== 'true' ? label : '' } - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval + '', - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.input'] + item.label + '!' - }, - { - max: _max, - message: formRule.input.formMessage.replace('@max', _max) - }, - ..._rules - ] - })(<Input placeholder="" autoComplete="off" disabled={item.readonly === 'true'} onChange={(e) => this.handleChange(e, item)} onPressEnter={(e) => this.handleInputSubmit(e, item)} />)} - </Form.Item> - </Col> - ) - } else if (item.type === 'number') { // 鏁板瓧 - let precision = (item.decimal || item.decimal === 0) ? item.decimal : null + if (!content) return fields.push( <Col span={item.span || 24} key={index}> <Form.Item + label={label} + className={className} extra={item.extra || null} labelCol={item.labelCol} wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } > {getFieldDecorator(item.field, { initialValue: item.initval, - rules: [ - { - required: true, - message: this.props.dict['form.required.input'] + item.label + '!' - }, - { - validator: (rule, value, callback) => this.handleConfirmPassword(rule, value, callback, item) - } - ] - })( - precision === null ? - <InputNumber disabled={item.readonly === 'true'} onPressEnter={(e) => this.handleInputSubmit(e, item)} /> : - <InputNumber precision={precision} disabled={item.readonly === 'true'} onPressEnter={(e) => this.handleInputSubmit(e, item)} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'color') { // 棰滆壊閫夋嫨 - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval || 'transparent', - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <ColorSketch /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'checkcard') { // 澶氶�夋 - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - className="checkcard" - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })(<CheckCard card={item} />)} - </Form.Item> - </Col> - ) - } else if (item.type === 'switch') { // 澶氶�夋 - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })(<CustomSwitch Item={item} />)} - </Form.Item> - </Col> - ) - } else if (item.type === 'checkbox') { // 澶氶�夋 - let _initval = item.initval ? item.initval.split(',').filter(Boolean) : [] - - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: _initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <Checkbox.Group disabled={item.readonly === 'true'}> - {item.options.map(option => <Checkbox key={option.key} title={option.Text} value={option.Value}>{option.Text}</Checkbox>)} - </Checkbox.Group> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'radio') { // 鍗曢�夋 - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <Radio.Group disabled={item.readonly === 'true'} onChange={(e) => {this.selectChange(item, e.target.value)}}> - {item.options.map(option => <Radio key={option.key} value={option.Value}>{option.Text}</Radio>)} - </Radio.Group> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'select' || item.type === 'link') { // 涓嬫媺鎼滅储 - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <Select - showSearch - allowClear={true} - filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} - onSelect={(value) => {this.selectChange(item, value)}} - disabled={item.readonly === 'true'} - > - {item.options.map(option => - <Select.Option id={option.key} title={option.Text} key={option.key} value={option.Value}>{option.Text}</Select.Option> - )} - </Select> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'multiselect') { // 澶氶�� - let _initval = item.initval ? item.initval.split(',').filter(Boolean) : [] - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: _initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <Select - showSearch - mode="multiple" - filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} - disabled={item.readonly === 'true'} - > - {item.options.map(option => - <Select.Option id={option.key} title={option.Text} key={option.key} value={option.Value}>{option.Text}</Select.Option> - )} - </Select> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'date') { // 鏃堕棿鎼滅储 - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <DatePicker disabled={item.readonly === 'true'} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'datemonth') { - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <MonthPicker disabled={item.readonly === 'true'} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'datetime') { - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <DatePicker showTime disabled={item.readonly === 'true'} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'fileupload') { - let filelist = this.props.data ? this.props.data[item.field] : item.initval - if (filelist && this.state.readin[item.field]) { - try { - filelist = filelist.split(',').map((url, index) => { - return { - uid: `${index}`, - name: url.slice(url.lastIndexOf('/') + 1), - status: 'done', - url: url, - origin: true - } - }) - } catch { - filelist = [] - } - } else { - filelist = [] - } - - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: filelist, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.select'] + item.label + '!' - } - ] - })( - <FileUpload accept={item.suffix} maxFile={item.maxfile} fileType={item.fileType || 'text'} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'linkMain') { - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.input'] + item.label + '!' - } - ] - })(<Input placeholder="" autoComplete="off" disabled={item.readonly === 'true'} />)} - </Form.Item> - </Col> - ) - } else if (item.type === 'funcvar') { - // 鍑芥暟鍙橀噺瀛楁锛岄粯璁や笉鏄剧ず - } else if (item.type === 'textarea') { - let _max = item.fieldlength || 512 - let _rules = [] - if (item.encryption !== 'true') { - _rules = [{ - pattern: /^[^']*$/ig, - message: formRule.input.quotemsg - }] - } - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : item.label - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.input'] + item.label + '!' - }, - { - max: _max, - message: formRule.input.formMessage.replace('@max', _max) - }, - ..._rules - ] - })(<CustomTextArea Item={item} />)} - </Form.Item> - </Col> - ) - } else if (item.type === 'brafteditor') { - let _max = item.fieldlength || 512 - - fields.push( - <Col span={item.span || 24} key={index}> - <Form.Item - extra={item.extra || null} - labelCol={item.labelCol} - wrapperCol={item.wrapperCol} - label={item.hidelabel !== 'true' && item.tooltip ? - <Tooltip placement="topLeft" title={item.tooltip}> - <Icon type="question-circle" /> - {item.label} - </Tooltip> : (item.hidelabel !== 'true' ? item.label : '') - } - > - {getFieldDecorator(item.field, { - initialValue: item.initval || '', - rules: [ - { - required: item.required === 'true', - message: this.props.dict['form.required.input'] + item.label + '!' - }, - { - max: _max, - message: formRule.input.formMessage.replace('@max', _max) - } - ] - })(<Editor Item={item}/>)} + rules: item.rules + })(content)} </Form.Item> </Col> ) @@ -1282,164 +708,57 @@ } handleConfirm = () => { - const { record, intercepts, writein } = this.state - let _format = { - date: 'YYYY-MM-DD', - datemonth: 'YYYY-MM', - datetime: 'YYYY-MM-DD HH:mm:ss' - } + const { formlist } = this.state // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� return new Promise((resolve, reject) => { this.props.form.validateFieldsAndScroll((err, values) => { - if (!err) { - let search = [] - // 闅愯棌琛ㄥ崟 - this.state.formlist.forEach(item => { - if (!item.field) return + if (err) { + reject(err) + return + } + let search = [] + let record = {...this.record, ...values} - let _item = null - if (item.type === 'funcvar') { - _item = { - type: 'funcvar', - readonly: 'true', - readin: false, - writein: writein[item.field], - fieldlen: this.state.fieldlen[item.field], - key: item.field, - value: '' - } - } else if (item.hidden === 'true') { - let _val = item.initval - if (record.hasOwnProperty(item.field)) { - _val = record[item.field] - } - - _item = { - type: this.state.datatype[item.field], - readonly: this.state.readtype[item.field], - readin: this.state.readin[item.field], - writein: writein[item.field], - fieldlen: this.state.fieldlen[item.field], - key: item.field, - value: _val - } - } else if (item.supField && !item.supvalue.includes(this.props.form.getFieldValue(item.supField))) { - _item = { - type: this.state.datatype[item.field], - readonly: this.state.readtype[item.field], - readin: this.state.readin[item.field], - writein: writein[item.field], - fieldlen: this.state.fieldlen[item.field], - key: item.field, - value: item.initval - } + formlist.forEach(item => { + if (!item.field) return + + let _item = { + type: item.type, + readonly: item.readonly, + readin: item.readin, + writein: item.writein, + fieldlen: item.fieldlength, + key: item.field + } + + _item.value = record[item.field] !== undefined ? record[item.field] : '' + + if (item.type === 'funcvar') { + _item.value = '' + } else if (_item.value && (item.type === 'text' || item.type === 'textarea' || item.type === 'linkMain')) { + _item.value = _item.value.replace(/\t*|\v*/g, '') // 鍘婚櫎鍒惰〃绗� + + if (item.interception === 'true') { // 鍘婚櫎棣栧熬绌烘牸 + _item.value = _item.value.replace(/(^\s*|\s*$)/g, '') } - - if (!_item) return - - if (_item.value === undefined) { - _item.value = '' - } else if (item.type === 'date' || item.type === 'datemonth' || item.type === 'datetime') { - if (!_item.value) { - _item.value = '' - } else if (_item.value.format) { - _item.value = _item.value.format(_format[item.type]) - } - } else if (item.type === 'text' && _item.value && typeof(_item.value) === 'string') { // 鐗规畩瀛楁鏇挎崲 + if (item.type === 'text' && typeof(_item.value) === 'string') { // 鐗规畩瀛楁鏇挎崲 _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey) _item.value = _item.value.replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')) _item.value = _item.value.replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || '')) } - - search.push(_item) - }) - - Object.keys(values).forEach(key => { - if (values[key] === undefined) { // 琛ㄥ崟寮傚父锛燂紵锛� - if (search.filter(s => s.key === key).length === 0) { - search.push({ - type: this.state.datatype[key], - readonly: this.state.readtype[key], - readin: this.state.readin[key], - writein: writein[key], - fieldlen: this.state.fieldlen[key], - key: key, - value: '' - }) - } - return + } else if (item.type.indexOf('date') > -1) { + if (item.declareType === 'nvarchar(50)') { + _item.type = 'text' } + } + + search.push(_item) + }) - let _value = '' - let _type = this.state.datatype[key] - if (_type === 'datetime') { - _value = values[key] ? moment(values[key]).format('YYYY-MM-DD HH:mm:ss') : '' - } else if (_type === 'datemonth') { - _value = values[key] ? moment(values[key]).format('YYYY-MM') : '' - } else if (_type === 'date') { - _value = values[key] ? moment(values[key]).format('YYYY-MM-DD') : '' - } else if (_type === 'number') { - _value = values[key] - - } else if (_type === 'multiselect' || _type === 'checkbox') { - _value = values[key] ? values[key].join(',') : '' - - } else if (_type === 'fileupload') { - let vals = [] - - if (values[key] && values[key].length > 0) { - values[key].forEach(_val => { - if (_val.origin && _val.url) { - vals.push(_val.url) - } else if (!_val.origin && _val.status === 'done' && _val.response) { - vals.push(Utils.getrealurl(_val.response)) - } - }) - } - - _value = vals.join(',') - } else if (_type === 'text' || _type === 'textarea') { - _value = values[key].replace(/\t*|\v*/g, '') // 鍘婚櫎鍒惰〃绗� - - if (intercepts.includes(key)) { // 鍘婚櫎棣栧熬绌烘牸 - _value = _value.replace(/(^\s*|\s*$)/g, '') - } - if (_type === 'text' && _value) { // 鐗规畩瀛楁鏇挎崲 - _value = _value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey) - _value = _value.replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')) - _value = _value.replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || '')) - } - } else { - _value = values[key] - } - - if (_value === undefined) { - _value = '' - } - - search.push({ - type: this.state.datatype[key], - readonly: this.state.readtype[key], - readin: this.state.readin[key], - writein: writein[key], - fieldlen: this.state.fieldlen[key], - key: key, - value: _value - }) - }) - - resolve(search) - } else { - reject(err) - } + resolve(search) }) }) - } - - handleSubmit = (e) => { - e && e.preventDefault() - this.props.inputSubmit() } render() { diff --git a/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx b/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx new file mode 100644 index 0000000..316fb81 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx @@ -0,0 +1,140 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Col, Row } from 'antd' + +import MKEmitter from '@/utils/events.js' +import './index.scss' + +class MKCheckCard extends Component { + static propTpyes = { + config: PropTypes.object, + onChange: PropTypes.func + } + + state = { + selectKeys: null + } + + UNSAFE_componentWillMount() { + const { config } = this.props + + if (config.multiple === 'true') { + this.setState({ + selectKeys: config.initval ? config.initval.split(',') : [] + }) + } else { + this.setState({ + selectKeys: config.initval + }) + } + } + + changeCard = (item) => { + const { config } = this.props + const { selectKeys } = this.state + + if (config.readonly) return + + if (config.multiple === 'true') { + let keys = [] + if (selectKeys.includes(item.$value)) { + keys = selectKeys.filter(key => key !== item.$value) + } else { + keys = [...selectKeys, item.$value] + } + + this.setState({ + selectKeys: keys + }, () => { + this.props.onChange(keys.join(',')) + }) + } else if (selectKeys !== item.$value) { + let other = {} + config.subFields && config.subFields.forEach((n, i) => { + other[n.field] = item[n.field] + setTimeout(() => { + MKEmitter.emit('mkFC', 'input', n.uuid, item[n.field]) + }, i * 5) + }) + config.linkFields && config.linkFields.forEach((m, i) => { + setTimeout(() => { + MKEmitter.emit('mkFP', m.uuid, item.$value, 0) + }, (i + 1) * 100) + }) + + this.setState({ + selectKeys: item.$value + }, () => { + this.props.onChange(item.$value, other) + }) + } + } + + getCards = () => { + const { display, width, options, fields, ratio, multiple, backgroundColor, borderColor } = this.props.config + const { selectKeys } = this.state + + let paddingTop = '100%' + if (ratio === '4:3') { + paddingTop = '75%' + } else if (ratio === '3:2') { + paddingTop = '66.7%' + } else if (ratio === '16:9') { + paddingTop = '56.25%' + } + + let style = borderColor ? {borderColor} : {} + let _style = backgroundColor ? {backgroundColor} : null + + if (!options || options.length === 0) { + return null + } else if (display !== 'picture') { + if (!fields || fields.length === 0) { + return null + } + return options.map(item => { + let _active = false + if (multiple === 'true' && selectKeys.includes(item.$value)) { + _active = true + } else if (multiple !== 'true' && selectKeys === item.$value) { + _active = true + } + + return <Col span={width} key={item.key}> + <div className={'card-cell' + (_active ? ' active' : '') + (_style ? ' bg-control' : '')} style={style} onClick={() => this.changeCard(item)}> + <div className="bg-mask" style={_style}></div> + {fields.map(col => { + return <span key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span> + })} + </div> + </Col> + }) + } else { + return options.map(item => { + let _active = false + if (multiple === 'true' && selectKeys.includes(item.$value)) { + _active = true + } else if (multiple !== 'true' && selectKeys === item.$value) { + _active = true + } + + return <Col span={width} key={item.key}> + <div className={'card-pic-cell ' + (_active ? 'active' : '')} onClick={() => this.changeCard(item)} style={{...style, paddingTop, backgroundImage: `url(${item.$url})`}}> + </div> + </Col> + }) + } + } + + render() { + const { config } = this.props + + return ( + <div className={'check-card-form-box' + (config.readonly ? ' readonly' : '')}> + <Row gutter={12}>{this.getCards()}</Row> + </div> + ) + } +} + +export default MKCheckCard \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkCheckCard/index.scss b/src/tabviews/zshare/mutilform/mkCheckCard/index.scss new file mode 100644 index 0000000..922b70f --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkCheckCard/index.scss @@ -0,0 +1,98 @@ +.check-card-form-box { + margin-top: 10px; + margin-bottom: -10px; + .card-cell { + position: relative; + border: 1px solid #bcbcbc; + border-radius: 4px; + padding: 6px; + margin-bottom: 12px; + line-height: 1.5; + transition: all 0.3s; + cursor: pointer; + span { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + position: relative; + z-index: 1; + } + .bg-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0.5; + border-radius: 4px; + background-color: transparent; + transition: opacity 0.3s; + } + } + .card-cell:not(.bg-control).active { + border-color: #1890ff; + background: #1890ff; + span { + color: #ffffff!important; + } + } + .card-cell.bg-control.active { + .bg-mask { + opacity: 1; + } + } + .card-pic-cell { + position: relative; + border: 1px solid #bcbcbc; + border-radius: 4px; + background-size: cover; + background-position: center; + margin-bottom: 12px; + line-height: 1.5; + cursor: pointer; + transition: all 0.3s; + } + .card-pic-cell.active { + border-color: #1890ff; + box-shadow: 0px 0px 4px #1890ff; + } + + .card-cell:not(.bg-control).active::after { + content: ' '; + position: absolute; + display: table; + border: 2px solid #ffffff; + border-top: 0; + border-left: 0; + bottom: 0; + right: 10px; + width: 6px; + height: 12px; + transform: rotate(45deg) scale(1) translate(-50%, -50%); + } +} + +.check-card-form-box:not(.readonly) { + .card-cell:not(.bg-control):hover { + border-color: #1890ff; + background: #1890ff; + span { + color: #ffffff!important; + } + } + .card-cell.bg-control:not(.active):hover { + .bg-mask { + opacity: 0.7; + } + } + .card-pic-cell:hover { + border-color: #1890ff; + box-shadow: 0px 0px 4px #1890ff; + } +} +.check-card-form-box.readonly { + .card-cell, .card-pic-cell { + cursor: not-allowed; + } +} \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkCheckbox/index.jsx b/src/tabviews/zshare/mutilform/mkCheckbox/index.jsx new file mode 100644 index 0000000..494719d --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkCheckbox/index.jsx @@ -0,0 +1,39 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Checkbox } from 'antd' + +import './index.scss' + +class MKCheckbox extends Component { + static propTpyes = { + config: PropTypes.object, + onChange: PropTypes.func + } + + state = { + defaultValue: this.props.config.initval ? this.props.config.initval.split(',').filter(Boolean) : [] + } + + onChange = (values) => { + this.props.onChange(values.join(',')) + } + + componentWillUnmount () { + this.setState = () => { + return + } + } + + render() { + const { config } = this.props + const { defaultValue } = this.state + + return ( + <Checkbox.Group defaultValue={defaultValue} disabled={config.readonly} onChange={this.onChange}> + {config.options.map(option => <Checkbox key={option.key} title={option.label} value={option.value}>{option.label}</Checkbox>)} + </Checkbox.Group> + ) + } +} + +export default MKCheckbox \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/tabviews/zshare/mutilform/mkCheckbox/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkCheckbox/index.scss diff --git a/src/tabviews/zshare/mutilform/mkColor/index.jsx b/src/tabviews/zshare/mutilform/mkColor/index.jsx new file mode 100644 index 0000000..d783e56 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkColor/index.jsx @@ -0,0 +1,60 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { SketchPicker } from 'react-color' +import { Popover } from 'antd' + +import './index.scss' + +const presetColors = [ + '#f5222d', '#fa541c', '#fa8c16', '#faad14', '#fadb14', '#a0d911', '#52c41a', '#13c2c2', '#1890ff', '#2f54eb', '#722ed1', + '#eb2f96', '#595959', '#ffa39e', '#ffbb96', '#ffd591', '#ffe58f', '#fffb8f', '#eaff8f', '#b7eb8f', '#87e8de', '#91d5ff', + '#adc6ff', '#d3adf7', '#ffadd2', '#d9d9d9', '#434343', '#000000', '#ffffff', 'transparent' +] + +class MkColor extends Component { + static propTpyes = { + config: PropTypes.object, + onChange: PropTypes.func + } + state = { + color: '', + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({color: config.initval}) + } + + handleChange = (color) => { + let _color = `rgba(${ color.rgb.r }, ${ color.rgb.g }, ${ color.rgb.b }, ${ color.rgb.a })` + + this.setState({ color: _color }, () => { + this.props.onChange(_color) + }) + } + + componentWillUnmount () { + this.setState = () => { + return + } + } + + render() { + const { color } = this.state + return ( + <div className="color-sketch-block"> + <Popover content={ + <SketchPicker color={ color } presetColors={presetColors} onChange={ this.handleChange } /> + } overlayClassName="color-sketch-popover" placement="bottomRight" title="" trigger="click"> + <div className="color-sketch-block-box"> + <div className="color-sketch-block-inner" style={ {background: color} }></div> + </div> + </Popover> + <div className="color-sketch-value">{color}</div> + </div> + ) + } +} + +export default MkColor \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkColor/index.scss b/src/tabviews/zshare/mutilform/mkColor/index.scss new file mode 100644 index 0000000..b6aec44 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkColor/index.scss @@ -0,0 +1,41 @@ +.color-sketch-block { + height: 25px; + width: 100%; + + .color-sketch-block-box { + display: inline-block; + width: calc(100% - 160px); + height: 100%; + border-radius: 4px; + background: #ffffff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==') left center; + } + .color-sketch-block-inner { + display: inline-block; + cursor: pointer; + border-radius: 4px; + box-shadow: 0 0 0 1px rgba(0, 0, 0, .1); + width: 100%; + height: 100%; + } + .color-sketch-value { + display: inline-block; + font-size: 13px; + width: 160px; + padding-left: 10px; + height: 25px; + line-height: 25px; + vertical-align: top; + white-space: nowrap; + overflow: visible; + } +} + +.color-sketch-popover { + z-index: 1090!important; + .ant-popover-inner-content { + padding: 0; + .sketch-picker { + width: 250px!important; + } + } +} \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx b/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx new file mode 100644 index 0000000..ad7558d --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx @@ -0,0 +1,71 @@ +import React, { Component } from 'react' +import { is, fromJS } from 'immutable' +import { DatePicker } from 'antd' +import moment from 'moment' + +import './index.scss' + +const { MonthPicker } = DatePicker + +/** + * @description 鑷畾涔夋椂闂撮�夋嫨鍣� + */ +class MkDatePicker extends Component { + constructor(props) { + super(props) + + const config = props.config + + let mode = 'date' + let format = 'YYYY-MM-DD' + + if (config.type === 'datemonth') { + mode = 'month' + format = 'YYYY-MM' + } else if (config.type === 'datetime') { + mode = 'datetime' + format = 'YYYY-MM-DD HH:mm:ss' + } + let value = config.initval || null + if (value) { + value = moment(value, format) + } + + this.state = { + value, + mode, + format + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentWillUnmount () { + this.setState = () => { + return + } + } + + onChange = (val) => { + const { format } = this.state + + this.props.onChange(val ? moment(val).format(format) : '') + } + + render() { + const { config } = this.props + const { value, mode } = this.state + + if (mode === 'date') { + return <DatePicker defaultValue={value} disabled={config.readonly} onChange={this.onChange}/> + } else if (mode === 'month') { + return <MonthPicker defaultValue={value} disabled={config.readonly} onChange={this.onChange}/> + } else if (mode === 'datetime') { + return <DatePicker defaultValue={value} showTime disabled={config.readonly} onChange={this.onChange}/> + } + } +} + +export default MkDatePicker \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/tabviews/zshare/mutilform/mkDatePicker/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkDatePicker/index.scss diff --git a/src/tabviews/zshare/mutilform/mkInput/index.jsx b/src/tabviews/zshare/mutilform/mkInput/index.jsx new file mode 100644 index 0000000..9b090dd --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkInput/index.jsx @@ -0,0 +1,84 @@ +import React, { Component } from 'react' +import { is, fromJS } from 'immutable' +import { Input } from 'antd' + +import MKEmitter from '@/utils/events.js' + +import './index.scss' + +/** + * @description 鑷畾涔夋枃鏈緭鍏� + */ +class MKInput extends Component { + constructor(props) { + super(props) + + const config = props.config + + this.state = { + value: config.initval + } + } + + inputRef = React.createRef() + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('mkFC', this.mkFormHandle) + } + + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('mkFC', this.mkFormHandle) + } + + mkFormHandle = (type, uuid, value) => { + if (uuid !== this.props.config.uuid) return + if (type === 'focus') { + this.inputRef.current.select() + } else if (type === 'input') { + this.setState({value}) + } + } + + handleChange = (e) => { + let val = e.target.value + + if (!/\n/ig.test(val)) { + this.props.onChange(val) + this.setState({value: val}) + } else { + val = val.replace(/\n/ig, '') + + this.props.onChange(val) + this.setState({value: val}, () => { + this.handleInputSubmit() + }) + } + } + + handleInputSubmit = () => { + const { config } = this.props + + if (config.enter === 'false') return + if (config.enter === 'tab') { + MKEmitter.emit('mkFC', 'focus', config.tabUuid) + } else { + this.props.onSubmit() + } + } + + render() { + const { config } = this.props + const { value } = this.state + + return <Input ref={this.inputRef} placeholder="" value={value} autoComplete="off" disabled={config.readonly} onChange={this.handleChange} onPressEnter={this.handleInputSubmit} /> + } +} + +export default MKInput \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkInput/index.scss b/src/tabviews/zshare/mutilform/mkInput/index.scss new file mode 100644 index 0000000..93dcc24 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkInput/index.scss @@ -0,0 +1,27 @@ +.am-list-item.am-input-item { + .am-input-control { + height: 100%; + input { + height: 100%; + } + } + .am-input-label { + width: 28%; + max-width: 120px; + text-overflow: ellipsis; + } + .am-input-extra { + max-height: 40px; + .anticon-scan { + font-size: 22px; + padding: 8px 5px; + } + } +} +.am-input-item.right { + .am-input-control { + input { + text-align: right; + } + } +} \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx b/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx new file mode 100644 index 0000000..7dde469 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx @@ -0,0 +1,67 @@ +import React, { Component } from 'react' +import { is, fromJS } from 'immutable' +import { InputNumber } from 'antd' + +import MKEmitter from '@/utils/events.js' + +import './index.scss' + +class MKNumberInput extends Component { + constructor(props) { + super(props) + + const config = props.config + + let precision = (config.decimal || config.decimal === 0) ? config.decimal : null + + this.state = { + precision, + value: config.initval + } + } + + inputNumberRef = React.createRef() + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentDidMount () { + MKEmitter.addListener('mkFC', this.mkFormHandle) + } + + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('mkFC', this.mkFormHandle) + } + + mkFormHandle = (type, uuid, value) => { + if (uuid !== this.props.config.uuid) return + if (type === 'focus') { + this.inputNumberRef.current.focus() + } else if (type === 'input') { + this.setState({value}) + } + } + + handleChange = (val) => { + + this.props.onChange(val) + this.setState({value: val}) + } + + render() { + const { config, onSubmit } = this.props + const { value, precision } = this.state + + if (precision === null) { + return (<InputNumber ref={this.inputNumberRef} value={value} disabled={config.readonly} onChange={this.handleChange} onPressEnter={onSubmit}/>) + } else { + return (<InputNumber ref={this.inputNumberRef} value={value} precision={precision} disabled={config.readonly} onChange={this.handleChange} onPressEnter={onSubmit} />) + } + } +} + +export default MKNumberInput \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkNumberInput/index.scss b/src/tabviews/zshare/mutilform/mkNumberInput/index.scss new file mode 100644 index 0000000..93dcc24 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkNumberInput/index.scss @@ -0,0 +1,27 @@ +.am-list-item.am-input-item { + .am-input-control { + height: 100%; + input { + height: 100%; + } + } + .am-input-label { + width: 28%; + max-width: 120px; + text-overflow: ellipsis; + } + .am-input-extra { + max-height: 40px; + .anticon-scan { + font-size: 22px; + padding: 8px 5px; + } + } +} +.am-input-item.right { + .am-input-control { + input { + text-align: right; + } + } +} \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/mkRadio/index.jsx b/src/tabviews/zshare/mutilform/mkRadio/index.jsx new file mode 100644 index 0000000..18022bf --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkRadio/index.jsx @@ -0,0 +1,40 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Radio } from 'antd' + +import './index.scss' + +class MKRadio extends Component { + static propTpyes = { + config: PropTypes.object, + onChange: PropTypes.func + } + + state = { + defaultValue: this.props.config.initval + } + + onChange = (e) => { + let value = e.target.value + this.props.onChange(value) + } + + componentWillUnmount () { + this.setState = () => { + return + } + } + + render() { + const { config } = this.props + const { defaultValue } = this.state + + return ( + <Radio.Group defaultValue={defaultValue} disabled={config.readonly} onChange={this.onChange}> + {config.options.map(option => <Radio key={option.key} value={option.value}>{option.label}</Radio>)} + </Radio.Group> + ) + } +} + +export default MKRadio \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/tabviews/zshare/mutilform/mkRadio/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkRadio/index.scss diff --git a/src/tabviews/zshare/mutilform/mkSelect/index.jsx b/src/tabviews/zshare/mutilform/mkSelect/index.jsx new file mode 100644 index 0000000..24da440 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkSelect/index.jsx @@ -0,0 +1,179 @@ +import React, {Component} from 'react' +import { is, fromJS } from 'immutable' +import { Select } from 'antd' + +import MKEmitter from '@/utils/events.js' +import './index.scss' + +class MKSelect extends Component { + constructor(props) { + super(props) + + const config = props.config + let value = config.initval + + if (config.type === 'multiselect') { + if (value) { + value = value.split(',') + } else { + value = [] + } + } + + this.state = { + config: fromJS(config).toJS(), + options: fromJS(config.options).toJS(), + value, + } + } + + componentDidMount () { + const { config } = this.state + + if (config.type !== 'multiselect') { + MKEmitter.addListener('mkFP', this.mkFormHandle) + } + MKEmitter.addListener('mkFC', this.mkFormFocus) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { config } = this.state + + if (!is(fromJS(config.oriOptions), fromJS(nextProps.config.oriOptions))) { + this.setState({ + config: fromJS(nextProps.config).toJS(), + options: fromJS(nextProps.config.options).toJS() + }) + + if (typeof(config.initval) === 'string' && config.initval.indexOf('$first') > -1) { + this.setState({ + value: nextProps.config.initval, + }) + } + } + } + + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('mkFP', this.mkFormHandle) + MKEmitter.removeListener('mkFC', this.mkFormFocus) + } + + mkFormFocus = (type, uuid) => { + if (uuid !== this.props.config.uuid) return + if (type !== 'focus') return + + let _div = document.getElementById(uuid) + _div && _div.click && _div.click() + } + + mkFormHandle = (uuid, parentId, level) => { + if (uuid !== this.state.config.uuid) return + + const { config } = this.state + + let options = config.oriOptions.filter(option => option.ParentID === parentId || option.value === '') + let val = options[0] ? options[0].value : '' + + this.setState({ + options, + value: val + }) + + this.props.onChange(val) + + if (level < 7 && config.linkFields) { + config.linkFields.forEach((m, i) => { + setTimeout(() => { + MKEmitter.emit('mkFP', m.uuid, val, level + 1) + }, (i + 1) * 70) + }) + } + } + + selectChange = (val) => { + const { config } = this.state + let other = {} + + if (config.subFields) { + let option = this.state.options.filter(m => m.value === val)[0] + option && config.subFields.forEach((n, i) => { + other[n.field] = option[n.field] + setTimeout(() => { + MKEmitter.emit('mkFC', 'input', n.uuid, option[n.field]) + }, i * 5) + }) + } + if (config.linkFields) { + config.linkFields.forEach((m, i) => { + setTimeout(() => { + MKEmitter.emit('mkFP', m.uuid, val, 0) + }, (i + 1) * 100) + }) + } + + this.props.onChange(val, other) + this.setState({value: val}, () => { + if (config.enter === 'tab') { + MKEmitter.emit('mkFC', 'focus', config.tabUuid) + } else if (config.enter === 'sub') { + if (config.linkFields || config.subFields || config.controlFields) { + setTimeout(() => { + this.props.onSubmit() + }, 1000) + } else { + this.props.onSubmit() + } + } + }) + } + + mutilselectChange = (val) => { + this.props.onChange(val.join(',')) + } + + render() { + const { value, config, options } = this.state + + if (config.type !== 'multiselect') { + return ( + <Select + showSearch + allowClear + id={config.uuid} + value={value} + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + onSelect={this.selectChange} + onClear={() => this.selectChange('')} + disabled={config.readonly} + > + {options.map(option => + <Select.Option id={option.key} title={option.label} key={option.key} value={option.value}>{option.label}</Select.Option> + )} + </Select> + ) + } else { + return (<Select + showSearch + id={config.uuid} + mode="multiple" + defaultValue={value} + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={this.mutilselectChange} + disabled={config.readonly} + > + {options.map(option => + <Select.Option id={option.key} title={option.label} key={option.key} value={option.value}>{option.label}</Select.Option> + )} + </Select>) + } + } +} + +export default MKSelect \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/tabviews/zshare/mutilform/mkSelect/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkSelect/index.scss diff --git a/src/tabviews/zshare/mutilform/mkSwitch/index.jsx b/src/tabviews/zshare/mutilform/mkSwitch/index.jsx new file mode 100644 index 0000000..b3eff86 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkSwitch/index.jsx @@ -0,0 +1,43 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Switch } from 'antd' + +import './index.scss' + +class MKSwitch extends Component { + static propTpyes = { + config: PropTypes.object, + onChange: PropTypes.func + } + + state = { + defaultChecked: this.props.config.initval === this.props.config.openVal + } + + onChange = (val) => { + const { config } = this.props + + if (val) { + this.props.onChange(config.openVal) + } else { + this.props.onChange(config.closeVal) + } + } + + componentWillUnmount () { + this.setState = () => { + return + } + } + + render() { + const { config } = this.props + const { defaultChecked } = this.state + + return ( + <Switch checkedChildren={config.openText || ''} unCheckedChildren={config.closeText || ''} defaultChecked={defaultChecked} onChange={this.onChange}/> + ) + } +} + +export default MKSwitch \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/tabviews/zshare/mutilform/mkSwitch/index.scss similarity index 100% rename from src/tabviews/zshare/mutilform/customSwitch/index.scss rename to src/tabviews/zshare/mutilform/mkSwitch/index.scss diff --git a/src/tabviews/zshare/mutilform/mkTextArea/index.jsx b/src/tabviews/zshare/mutilform/mkTextArea/index.jsx new file mode 100644 index 0000000..531aa49 --- /dev/null +++ b/src/tabviews/zshare/mutilform/mkTextArea/index.jsx @@ -0,0 +1,92 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Input } from 'antd' + +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const { TextArea } = Input + +class MkTextArea extends Component { + static propTpyes = { + config: PropTypes.bool, + onChange: PropTypes.func + } + + inputRef = React.createRef() + + state = { + value: '', + encryption: 'false' + } + + UNSAFE_componentWillMount () { + const { config } = this.props + let _value = config.initval + let encryption = 'false' + + if (config.encryption === 'true') { + encryption = 'true' + if (_value) { + try { + _value = window.decodeURIComponent(window.atob(_value)) + } catch { + _value = config.initval + } + } + } + + this.setState({ + value: _value, + encryption + }) + } + + componentDidMount () { + MKEmitter.addListener('mkFC', this.mkFormHandle) + } + + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('mkFC', this.mkFormHandle) + } + + mkFormHandle = (type, uuid, value) => { + if (uuid !== this.props.config.uuid) return + if (type === 'focus') { + this.inputRef.current.focus() + } else if (type === 'input') { + this.setState({value}) + } + } + + onChange = (e) => { + const { encryption } = this.state + let val = e.target.value + + this.setState({ value: val }) + + let _val = val + if (encryption === 'true') { + try { + _val = window.btoa(window.encodeURIComponent(_val)) + } catch { + _val = val + } + } + this.props.onChange(_val) + } + + render() { + const { config } = this.props + const { value } = this.state + + return ( + <TextArea ref={this.inputRef} value={value} autoSize={{ minRows: 2, maxRows: config.maxRows || 6 }} onChange={this.onChange} disabled={config.readonly} /> + ) + } +} + +export default MkTextArea \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customTextArea/index.scss b/src/tabviews/zshare/mutilform/mkTextArea/index.scss similarity index 100% rename from src/tabviews/zshare/mutilform/customTextArea/index.scss rename to src/tabviews/zshare/mutilform/mkTextArea/index.scss diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx index 3746355..aa989fb 100644 --- a/src/tabviews/zshare/normalTable/index.jsx +++ b/src/tabviews/zshare/normalTable/index.jsx @@ -17,6 +17,7 @@ const PopupButton = asyncComponent(() => import('@/tabviews/zshare/actionList/popupbutton')) const TabButton = asyncComponent(() => import('@/tabviews/zshare/actionList/tabbutton')) const NewPageButton = asyncComponent(() => import('@/tabviews/zshare/actionList/newpagebutton')) +const ImgScale = asyncComponent(() => import('@/tabviews/zshare/imgScale')) class NormalTable extends Component { static propTpyes = { @@ -45,7 +46,7 @@ pageSize: 10, // 姣忛〉鏁版嵁鏉℃暟 columns: null, // 鏄剧ず鍒� imgShow: false, // 鍥剧墖鏀惧ぇ妯℃�佹 - imgSrc: '', // 鍥剧墖璺緞 + imgData: {}, // 鍥剧墖闆� lineMarks: null, // 琛屾爣璁� activeIndex: null, // 鏍囪褰撳墠閫変腑琛� rowspans: null // 琛屽悎骞跺瓧娈典俊鎭� @@ -139,7 +140,10 @@ if (item.rowspan === 'true') { rowspans.push(item.field) } - if (_format && !Math.floor(Math.random() * radio)) { + if (item.type === 'index') { + item.field = '$Index' + item.type = 'text' + } else if (_format && !Math.floor(Math.random() * radio)) { item.blur = true } @@ -165,14 +169,6 @@ render: (text, record) => { return this.getContent(item, record) } - } - } - - if (item.fixed === true || item.fixed === 'true') { - if (index < columns.length / 2) { - cell.fixed = 'left' - } else { - cell.fixed = 'right' } } @@ -552,7 +548,7 @@ let photos = '' if (item.field && record.hasOwnProperty(item.field)) { photos = record[item.field] + '' - photos = photos.split(',') + photos = photos.split(',').filter(Boolean) } else { photos = '' } @@ -562,7 +558,7 @@ <div className="picture-col"> {photos && photos.map((url, i) => { if (item.scale === 'true') { - return <img style={{maxHeight: maxHeight}} className="image-scale" onClick={this.imgScale} key={`${i}`} src={url} alt=""/> + return <img style={{maxHeight: maxHeight}} className="image-scale" onClick={() => this.imgScale(photos, i)} key={`${i}`} src={url} alt=""/> } else { return <img style={{maxHeight: maxHeight}} key={`${i}`} src={url} alt=""/> } @@ -738,7 +734,7 @@ let photos = [] try { photos = record[col.field] + '' - photos = photos.split(',') + photos = photos.split(',').filter(Boolean) } catch { photos = [] } @@ -874,9 +870,8 @@ <div className="content-fence"> <div className="content-fence-top" style={images[0] ? {textAlign: images[0].align} : null}> {images.map((_img, index) => { - if (!_img.url) return '' if (_img.scale) { - return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={this.imgScale} key={`${index}`} src={_img.url} alt=""/> + return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={() => this.imgScale(images, index)} key={`${index}`} src={_img.url} alt=""/> } else { return (<img style={{maxHeight: _img.maxHeight}} key={`${index}`} src={_img.url} alt=""/>) } @@ -894,9 +889,8 @@ <div className="content-fence"> <div className="content-fence-left" style={images[0] ? {textAlign: images[0].align} : null}> {images.map((_img, index) => { - if (!_img.url) return '' if (_img.scale) { - return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={this.imgScale} key={`${index}`} src={_img.url} alt=""/> + return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={() => this.imgScale(images, index)} key={`${index}`} src={_img.url} alt=""/> } else { return (<img style={{maxHeight: _img.maxHeight}} key={`${index}`} src={_img.url} alt=""/>) } @@ -915,18 +909,19 @@ /** * @description 鍥剧墖缂╂斁 */ - imgScaleClose = () => { + imgScale = (images, index) => { this.setState({ - imgShow: false + imgShow: true, + imgData: { + list: images.map(item => { + if (typeof(item) === 'string') { + return item + } + return item.url + }), + index + } }) - } - imgScale = (e) => { - if (e.target.nodeName === 'IMG') { - this.setState({ - imgShow: true, - imgSrc: e.target.src - }) - } } /** @@ -1242,12 +1237,12 @@ visible={this.state.imgShow} width="70vw" maskClosable={true} - onCancel={this.imgScaleClose} + onCancel={() => {this.setState({ imgShow: false })}} title={this.props.dict['main.form.picture.check']} - footer={[<span key="close" onClick={this.imgScaleClose}>{this.props.dict['main.close']}</span>]} + footer={[<span key="close" onClick={() => {this.setState({ imgShow: false })}}>{this.props.dict['main.close']}</span>]} destroyOnClose > - <img style={{maxWidth:'100%'}} src={this.state.imgSrc} alt="" /> + <ImgScale data={this.state.imgData}/> </Modal> </div> ) diff --git a/src/tabviews/zshare/topSearch/advanceform/index.jsx b/src/tabviews/zshare/topSearch/advanceform/index.jsx new file mode 100644 index 0000000..dd07f57 --- /dev/null +++ b/src/tabviews/zshare/topSearch/advanceform/index.jsx @@ -0,0 +1,112 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Form, Row, Col, Input, Button } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const { Search } = Input +const MKCheckCard = asyncComponent(() => import('@/tabviews/zshare/mutilform/checkCard')) +const MKSelect = asyncComponent(() => import('../mkSelect')) +const MKDatePicker = asyncComponent(() => import('../mkDatePicker')) + +class AdvanceSearch extends Component { + static propTpyes = { + record: PropTypes.object, // 鎼滅储鏉′欢鍊� + searchlist: PropTypes.array, // 鎼滅储鏉′欢鍒楄〃 + advanceSubmit: PropTypes.func, // 鎼滅储鏉′欢鎻愪氦 + handleClose: PropTypes.func // 鍏抽棴 + } + + state = { + searchlist: fromJS(this.props.searchlist).toJS() + } + + getFields() { + const { getFieldDecorator } = this.props.form + const { record } = this.props + const fields = [] + + this.state.searchlist.forEach((item, index) => { + if (!item.advanced || item.hidden) return + + const _rules = [ + { + required: item.required, + message: item.label + '涓嶅彲涓虹┖!' + } + ] + + let content = null + item.initval = record[item.field] || '' + + if (item.type === 'text') { + if (item.inputType === 'search') { + content = <Search placeholder={item.labelShow === 'false' ? item.label : ''} autoComplete="off" onSearch={this.handleSubmit} enterButton/> + } else { + content = <Input placeholder={item.labelShow === 'false' ? item.label : ''} autoComplete="off" onPressEnter={this.handleSubmit} /> + } + } else if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') { + content = (<MKSelect config={item}/>) + } else if (item.type === 'date' || item.type === 'datemonth' || item.type === 'dateweek' || item.type === 'daterange') { + content = (<MKDatePicker config={item}/>) + } else if (item.type === 'checkcard') { + content = <MKCheckCard card={item}/> + } + + if (content) { + fields.push( + <Col span={item.ratio || 6} key={index}> + <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> + {getFieldDecorator(item.field, { + initialValue: item.initval, + rules: _rules + })(content)} + </Form.Item> + </Col> + ) + } + }) + + return fields + } + + handleSubmit = () => { + // 鍥炶溅鎴栫偣鍑绘悳绱� + this.props.form.validateFields((err, values) => { + if (err) return + + this.props.advanceSubmit(values) + }) + } + + render() { + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout} className="advance-search"> + <Row gutter={24}>{this.getFields()}</Row> + <div className="advance-button"> + <Button style={{ marginRight: 8 }} onClick={this.props.handleClose}> + 鍏抽棴 + </Button> + <Button type="primary" onClick={this.handleSubmit}> + 纭畾 + </Button> + </div> + </Form> + ) + } +} + +export default Form.create()(AdvanceSearch) \ No newline at end of file diff --git a/src/tabviews/zshare/topSearch/advanceform/index.scss b/src/tabviews/zshare/topSearch/advanceform/index.scss new file mode 100644 index 0000000..74b0bca --- /dev/null +++ b/src/tabviews/zshare/topSearch/advanceform/index.scss @@ -0,0 +1,41 @@ +.advance-search { + background: #ffffff; + margin-bottom: 35px; + .ant-form-item { + display: flex; + margin-bottom: 0px; + min-height: 60px; + .ant-form-explain { + white-space: nowrap; + } + } + .ant-form-item-control-wrapper { + flex: 1; + width: calc(100% - 100px); + } + .ant-form-item-label { + text-overflow: ellipsis; + } + .daterange .ant-calendar-picker-input { + padding: 4px 20px 4px 5px; + font-size: 13px; + } + .ant-select-dropdown { + z-index: 10 !important; + } + .ant-calendar-picker-container { + z-index: 10 !important; + } + .check-card-form-box { + margin-top: 5px; + } + .advance-button { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + text-align: right; + padding: 10px; + border-top: 1px solid #f0f0f0; + } +} \ No newline at end of file diff --git a/src/tabviews/zshare/topSearch/dategroup/index.jsx b/src/tabviews/zshare/topSearch/dategroup/index.jsx new file mode 100644 index 0000000..ab2b3a2 --- /dev/null +++ b/src/tabviews/zshare/topSearch/dategroup/index.jsx @@ -0,0 +1,138 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { DatePicker, Tooltip, Icon } from 'antd' +import moment from 'moment' + +import Utils from '@/utils/utils.js' +import QuarterPicker from './quarterpicker' +import YearPicker from './yearpicker' +import './index.scss' + +const { MonthPicker, WeekPicker, RangePicker } = DatePicker + +class DateGroup extends Component { + static propTpyes = { + config: PropTypes.object, + position: PropTypes.number, // 绱㈠紩锛岀敤浜庢帶鍒跺搴﹀拰骞寸殑灞曞紑鏂瑰悜 + onChange: PropTypes.func + } + + state = { + active: '', + quarterId: Utils.getuuid(), + yearId: Utils.getuuid(), + dateRange: '', + placement: this.props.position % 4 !== 3 ? 'bottomLeft' : 'bottomRight' + } + + UNSAFE_componentWillMount() { + const { config } = this.props + + this.setState({ + active: config.initType, + dateRange: config.initval + }) + } + + onChange = (date, type) => { + let values = [] + if (type === 'day') { + values = [moment(date).format('YYYY-MM-DD'), moment(date).format('YYYY-MM-DD')] + } else if (type === 'week') { + values = [moment(date).startOf('week').format('YYYY-MM-DD'), moment(date).endOf('week').format('YYYY-MM-DD')] + } else if (type === 'month') { + values = [moment(date).startOf('month').format('YYYY-MM-DD'), moment(date).endOf('month').format('YYYY-MM-DD')] + } else if (type === 'quarter') { + values = date + document.getElementById(this.state.quarterId).click() + } else if (type === 'year') { + values = date + document.getElementById(this.state.yearId).click() + } else if (type === 'customized') { + values = [moment(date[0]).format('YYYY-MM-DD'), moment(date[1]).format('YYYY-MM-DD')] + } + + values = values.join(',') + + this.setState({ + active: type, + dateRange: values + }, () => { + this.props.onChange(values, type) + }) + } + + clearTime = () => { + this.setState({ + active: '', + dateRange: '' + }, () => { + this.props.onChange('', '') + }) + } + + render() { + const { config } = this.props + const { active, quarterId, yearId, dateRange, placement } = this.state + let tabs = {day: '鏃�', week: '鍛�', month: '鏈�', quarter: '瀛�', year: '骞�', customized: '鑷畾涔�'} + + return ( + <div className="table-search-date-group"> + {config.items.map(tab => { + if (tab === 'day') { + return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > + {tabs[tab]} + <DatePicker allowClear={false} onChange={(date) => this.onChange(date, tab)} /> + </span>) + } else if (tab === 'week') { + return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > + {tabs[tab]} + <WeekPicker dropdownClassName="group-week-picker" allowClear={false} onChange={(date) => this.onChange(date, tab)} /> + </span>) + } else if (tab === 'month') { + return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > + {tabs[tab]} + <MonthPicker allowClear={false} onChange={(date) => this.onChange(date, tab)} /> + </span>) + } else if (tab === 'quarter') { + return ( + <Tooltip key={tab} placement={placement} overlayClassName={'quarter-picker-tooltip ' + placement} trigger="click" title={ + <div> + <QuarterPicker card={config} onChange={(date) => this.onChange(date, tab)}/> + </div> + }> + <span id={quarterId} className={'ant-tag ant-tag-quarter ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > + {tabs[tab]} + </span> + </Tooltip> + ) + } else if (tab === 'year') { + return ( + <Tooltip key={tab} placement={placement} overlayClassName={'year-picker-tooltip ' + placement} trigger="click" title={ + <div> + <YearPicker card={config} onChange={(date) => this.onChange(date, tab)}/> + </div> + }> + <span id={yearId} className={'ant-tag ant-tag-quarter ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > + {tabs[tab]} + </span> + </Tooltip> + ) + } else { + return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} > + {tabs[tab]} + <RangePicker allowClear={false} onChange={(date) => this.onChange(date, tab)} /> + </span>) + } + })} + + {dateRange ? <div className="table-search-date-group-value"> + {dateRange.replace(',', ' ~ ')} + <Icon type="close-circle" onClick={this.clearTime} className="ant-calendar-picker-clear" /> + </div> : null} + </div> + ) + } +} + +export default DateGroup \ No newline at end of file diff --git a/src/tabviews/zshare/dategroup/index.scss b/src/tabviews/zshare/topSearch/dategroup/index.scss similarity index 100% rename from src/tabviews/zshare/dategroup/index.scss rename to src/tabviews/zshare/topSearch/dategroup/index.scss diff --git a/src/tabviews/zshare/dategroup/quarterpicker/index.jsx b/src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.jsx similarity index 100% rename from src/tabviews/zshare/dategroup/quarterpicker/index.jsx rename to src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.jsx diff --git a/src/tabviews/zshare/dategroup/quarterpicker/index.scss b/src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.scss similarity index 100% rename from src/tabviews/zshare/dategroup/quarterpicker/index.scss rename to src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.scss diff --git a/src/tabviews/zshare/dategroup/yearpicker/index.jsx b/src/tabviews/zshare/topSearch/dategroup/yearpicker/index.jsx similarity index 100% rename from src/tabviews/zshare/dategroup/yearpicker/index.jsx rename to src/tabviews/zshare/topSearch/dategroup/yearpicker/index.jsx diff --git a/src/tabviews/zshare/dategroup/yearpicker/index.scss b/src/tabviews/zshare/topSearch/dategroup/yearpicker/index.scss similarity index 100% rename from src/tabviews/zshare/dategroup/yearpicker/index.scss rename to src/tabviews/zshare/topSearch/dategroup/yearpicker/index.scss diff --git a/src/tabviews/zshare/topSearch/index.jsx b/src/tabviews/zshare/topSearch/index.jsx index 79a77e4..c16a881 100644 --- a/src/tabviews/zshare/topSearch/index.jsx +++ b/src/tabviews/zshare/topSearch/index.jsx @@ -1,18 +1,25 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { fromJS } from 'immutable' -import { Form, Row, Col, Input, Button, Select, DatePicker, notification } from 'antd' +import { Form, Row, Col, Input, Button, notification, Modal, Icon } from 'antd' import moment from 'moment' import Api from '@/api' import options from '@/store/options.js' -import DateGroup from '@/tabviews/zshare/dategroup' +import asyncComponent from '@/utils/asyncComponent' +import asyncSpinComponent from '@/utils/asyncSpinComponent' import Utils from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/main.js' import enUS from '@/locales/en-US/main.js' import './index.scss' -const { MonthPicker, WeekPicker, RangePicker } = DatePicker +const { Search } = Input + +const MutilForm = asyncSpinComponent(() => import('./advanceform')) +const MKCheckCard = asyncComponent(() => import('@/tabviews/zshare/mutilform/checkCard')) +const MKSelect = asyncComponent(() => import('./mkSelect')) +const DateGroup = asyncComponent(() => import('./dategroup')) +const MKDatePicker = asyncComponent(() => import('./mkDatePicker')) class MainSearch extends Component { static propTpyes = { @@ -20,33 +27,30 @@ menuType: PropTypes.any, // 鑿滃崟鏉冮檺锛屾槸鍚︿负HS searchlist: PropTypes.array, // 鎼滅储鏉′欢鍒楄〃 config: PropTypes.object, // 缁勪欢閰嶇疆淇℃伅(鑷畾涔夐〉闈�) + setting: PropTypes.object, // 缁勪欢閰嶇疆淇℃伅(鑷畾涔夐〉闈�) refreshdata: PropTypes.func // 鍒锋柊鏁版嵁 } state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, - oriId: Utils.getuuid(), // 鎼滅储琛ㄥ崟Id - formId: '', // 鎼滅储琛ㄥ崟Id - match: null, // 鎼滅储鏉′欢鍖归厤瑙勫垯 - style: null, // 鎼滅储鏉′欢绫诲瀷 - label: null, // 鎻愮ず鏂囧瓧 - required: null, // 鏄惁蹇呭~ searchlist: null, // 鎼滅储椤� - groups: null, // 缁勫悎鎼滅储椤� + reset: true, // 鎺у埗缁勫悎鎼滅储椤归噸缃� float: '', // 娴姩 showButton: true, // 鏄惁鏄剧ず鎼滅储鎸夐挳 - searchStyle: null // 鎼滅储鏉′欢鏍峰紡 + showAdvanced: false, // 鏄惁鏄剧ず楂樼骇鎼滅储 + searchStyle: null, // 鎼滅储鏉′欢鏍峰紡 + advanceValues: [], // 楂樼骇鎼滅储鏉′欢淇濆瓨鍊� + visible: false, + adModelWidth: '1000px', + hasReqFields: false } + record = {} + UNSAFE_componentWillMount () { - const { config, menuType, searchlist } = this.props + const { config, menuType, searchlist, setting } = this.props let _searchlist = [] - let match = {} - let label = {} - let style = {} - let required = {} - let _list = [] let fieldMap = new Map() let mainItems = [] // 浜戠鎴栧崟鐐规暟鎹� let localItems = [] // 鏈湴鏁版嵁 @@ -54,7 +58,24 @@ let float = '' let showButton = true let searchStyle = null - let formId = Utils.getuuid() + let advanceValues = [] + let showAdvanced = false + let adModelWidth = 1000 + let linkFields = {} + let record = {} + let hasReqFields = false + + if (setting && setting.advanceWidth) { + adModelWidth = setting.advanceWidth + } else if (config && config.wrap && config.wrap.advanceWidth) { + adModelWidth = config.wrap.advanceWidth + } + + if (adModelWidth < 100) { + adModelWidth = adModelWidth + 'vw' + } else { + adModelWidth = adModelWidth + 'px' + } if (searchlist) { _searchlist = fromJS(searchlist).toJS() @@ -62,28 +83,48 @@ _searchlist = fromJS(config.search).toJS() if (config.type === 'search' && config.subtype === 'mainsearch') { float = config.wrap.float - showButton = config.wrap.float === 'left' && config.wrap.show === 'true' + showButton = config.wrap.show !== 'false' searchStyle = config.style } else { - formId = '' showButton = false float = 'right' } } _searchlist.forEach(item => { + if (item.type === 'link') { + linkFields[item.linkField] = linkFields[item.linkField] || [] + linkFields[item.linkField].push({field: item.field, uuid: item.uuid}) + } + if (fieldMap.has(item.field)) { item.field = item.field + '@tail@' } - fieldMap.set(item.field, item) - match[item.field] = item.match - label[item.field] = item.label - style[item.field] = item.type - required[item.field] = item.required === 'true' + if (item.required) { + hasReqFields = true + } - if (['select', 'link', 'multiselect'].includes(item.type)) { - if (item.setAll === 'true' && item.type !== 'multiselect') { + if (showButton && item.advanced) { + showAdvanced = true + } else { + item.advanced = false + } + + if (item.advanced && item.initval) { + advanceValues.push({field: item.field, type: item.type, label: item.label, value: item.initval}) + } + + if (item.type === 'group') { + record[item.field] = item.initType + record[item.datefield] = item.initval + } else { + record[item.field] = item.initval + } + + if (['select', 'link', 'multiselect', 'checkcard'].includes(item.type)) { + item.options = item.options || [] + if (item.setAll === 'true' && ['select', 'link'].includes(item.type)) { item.options.unshift({ key: Utils.getuuid(), Value: '', @@ -103,10 +144,6 @@ data_sql: Utils.formatOptions(_option.sql) }) } else { // 鍚堝苟璇锋眰锛屽尯鍒嗘湰鍦板強绯荤粺 - // 澶栬仈鏁版嵁搴撴浛鎹� - if (window.GLOB.externalDatabase !== null) { - _option.sql = _option.sql.replace(/@db@/ig, window.GLOB.externalDatabase) - } if (item.database === 'sso') { mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql))}' as LText`) } else { @@ -117,11 +154,18 @@ item.oriOptions = fromJS(item.options).toJS() } - _list.push(item) + fieldMap.set(item.field, item) }) - let _groups = [] - _list = _list.map(item => { + this.record = record + + let _list = _searchlist.map(item => { + if (item.hidden) return item + + if (linkFields[item.field]) { + item.linkFields = linkFields[item.field] + } + if (item.type === 'link') { let supItem = fieldMap.get(item.linkField) @@ -131,29 +175,25 @@ message: '鏈煡璇㈠埌鎼滅储鏉′欢銆�' + item.label + '銆嬪叧鑱斿瓧娈碉紒', duration: 5 }) - item.supInitVal = '' + item.type = 'select' } else { item.supInitVal = supItem.initval item.options = item.oriOptions.filter(option => option.ParentID === supItem.initval || option.Value === '') } - } else if (item.type === 'group' && item.Hide !== 'true') { - _groups.push(fromJS(item).toJS()) } return item }) this.setState({ - match, - label, - style, float, - formId, - required, showButton, searchStyle, - searchlist: _list, - groups: _groups + hasReqFields, + showAdvanced, + adModelWidth, + advanceValues, + searchlist: _list }, () => { if (menuType !== 'HS' && options.sysType === 'local' && !window.GLOB.systemType) { this.improveSimpleSearch(deForms) @@ -264,42 +304,7 @@ delete result.message delete result.status - let _searchlist = this.state.searchlist.map(item => { - if (['select', 'link', 'multiselect'].includes(item.type) && result[item.field] && result[item.field].length > 0) { - let options = result[item.field].map(cell => { - let _item = { - key: Utils.getuuid(), - Value: cell[item.valueField], - Text: cell[item.valueText] - } - - if (item.type === 'link') { - _item.ParentID = cell[item.linkField] - } - - return _item - }) - - item.oriOptions = [...item.oriOptions, ...options] - } - return item - }) - - this.setState({ - searchlist: _searchlist.map(item => { - if (item.type === 'link') { - if (item.supInitVal) { - item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '') - } else { - item.options = item.oriOptions - } - } else if (item.type === 'select' || item.type === 'multiselect') { - item.options = item.oriOptions - } - - return item - }) - }) + this.resetSearch(result) }) } @@ -350,283 +355,119 @@ delete result.message delete result.status - let _searchlist = this.state.searchlist.map(item => { - if (['select', 'link', 'multiselect'].includes(item.type) && result[item.field] && result[item.field].length > 0) { - let options = result[item.field].map(cell => { - let _item = { - key: Utils.getuuid(), - Value: cell[item.valueField], - Text: cell[item.valueText] - } + this.resetSearch(result) + }) + } - if (item.type === 'link') { - _item.ParentID = cell[item.linkField] - } + resetSearch = (result) => { + let _searchlist = this.state.searchlist.map(item => { + if (['select', 'link', 'multiselect', 'checkcard'].includes(item.type) && result[item.field] && result[item.field].length > 0) { + let options = result[item.field].map(cell => { + let _item = { + key: Utils.getuuid() + } - return _item - }) + if (item.type !== 'checkcard') { + _item.Value = cell[item.valueField] + _item.Text = cell[item.valueText] + } else { + _item.$value = cell[item.cardValField] + _item = {..._item, ...cell} + } - item.oriOptions = [...item.oriOptions, ...options] - } - return item - }) - - this.setState({ - searchlist: _searchlist.map(item => { if (item.type === 'link') { - if (item.supInitVal) { - item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '') - } else { - item.options = item.oriOptions - } - } else if (item.type === 'select' || item.type === 'multiselect') { - item.options = item.oriOptions + _item.ParentID = cell[item.linkField] } - return item + return _item }) - }) - }) - } - resetform = (formlist, supfields, index, fieldsvalue) => { - index++ - let subfields = [] - - supfields.forEach(supfield => { - formlist = formlist.map(item => { - if (item.type === 'link' && item.linkField === supfield.field) { - item.options = item.oriOptions.filter(option => option.ParentID === supfield.initval || option.Value === '') - item.initval = item.options[0] ? item.options[0].Value : '' - - if (this.props.form.getFieldValue(item.field) !== undefined) { - fieldsvalue[item.field] = item.initval - } - - subfields.push(item) - } - return item - }) - }) - - if (subfields.length === 0 || index > 6) { - return formlist - } else { - return this.resetform(formlist, subfields, index, fieldsvalue) - } - } - - selectChange = (_field, value) => { - let formlist = fromJS(this.state.searchlist).toJS() - - let subfields = [] - let fieldsvalue = {} - formlist = formlist.map(item => { - if (item.type === 'link' && item.linkField === _field.field) { - item.options = item.oriOptions.filter(option => option.ParentID === value || option.Value === '') - item.initval = item.options[0] ? item.options[0].Value : '' - - if (this.props.form.getFieldValue(item.field) !== undefined) { - fieldsvalue[item.field] = item.initval - } - - subfields.push(item) + item.oriOptions = [...item.oriOptions, ...options] } return item }) - if (subfields.length === 0) { - this.searchChange() - return - } - - formlist = this.resetform(formlist, subfields, 0, fieldsvalue) - - if (Object.keys(fieldsvalue).length > 0) { - this.props.form.setFieldsValue(fieldsvalue) - } - this.setState({ - searchlist: formlist - }, () => { - this.searchChange() + searchlist: _searchlist.map(item => { + if (item.type === 'link') { + if (item.supInitVal) { + item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '') + } else { + item.options = item.oriOptions + } + } else if (item.type === 'select' || item.type === 'multiselect' || item.type === 'checkcard') { + item.options = item.oriOptions + } + + return item + }) }) + } + + recordChange = (val, defer, item) => { + this.record[item.field] = val + + if (defer) return + + if (item.linkFields) { + setTimeout(() => { + this.handleSubmit() + }, 1000) + } else { + this.handleSubmit() + } + } + + dateGroupChange = (val, type, item) => { + this.record[item.datefield] = val + this.record[item.field] = type + + this.handleSubmit() } getFields() { const { getFieldDecorator } = this.props.form - const { dict, showButton, formId } = this.state + const { dict, showButton, showAdvanced, float } = this.state const fields = [] this.state.searchlist.forEach((item, index) => { - if (item.Hide === 'true') return - - if (item.type === 'text') { // 鏂囨湰鎼滅储 - fields.push( - <Col span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: dict['form.required.input'] + item.label + '!' - } - ] - })(<Input placeholder={item.labelShow === 'false' ? item.label : ''} autoComplete="off" onPressEnter={this.handleSearch} />)} - </Form.Item> - </Col> - ) - } else if (item.type === 'select') { // 涓嬫媺鎼滅储 - fields.push( - <Col span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> - {getFieldDecorator(item.field, { - initialValue: item.initval, - rules: [ - { - required: item.required === 'true', - message: dict['form.required.select'] + item.label + '!' - } - ] - })( - <Select - showSearch - onChange={(value) => {this.selectChange(item, value)}} - filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} - getPopupContainer={() => formId ? document.getElementById(formId) : document.body} - > - {item.options.map((option, i) => - <Select.Option id={`${i}`} title={option.Text} key={`${i}`} value={option.Value}>{option.Text}</Select.Option> - )} - </Select> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'multiselect') { // 涓嬫媺澶氶�� - let _initval = item.initval ? item.initval.split(',').filter(Boolean) : [] - fields.push( - <Col span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> - {getFieldDecorator(item.field, { - initialValue: _initval, - rules: [ - { - required: item.required === 'true', - message: dict['form.required.select'] + item.label + '!' - } - ] - })( - <Select - showSearch - mode="multiple" - onChange={this.searchChange} - filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} - getPopupContainer={() => formId ? document.getElementById(formId) : document.body} - > - {item.options.map((option, i) => - <Select.Option id={`${i}`} title={option.Text} key={`${i}`} value={option.Value}>{option.Text}</Select.Option> - )} - </Select> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'date') { // 鏃堕棿鎼滅储 - fields.push( - <Col span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> - {getFieldDecorator(item.field, { - initialValue: item.initval ? moment().subtract(item.initval, 'days') : null, - rules: [ - { - required: item.required === 'true', - message: dict['form.required.select'] + item.label + '!' - } - ] - })( - <DatePicker onChange={this.searchChange} getCalendarContainer={() => formId ? document.getElementById(formId) : document.body} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'datemonth') { - fields.push( - <Col span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> - {getFieldDecorator(item.field, { - initialValue: item.initval ? moment().subtract(item.initval, 'month') : null, - rules: [ - { - required: item.required === 'true', - message: dict['form.required.select'] + item.label + '!' - } - ] - })( - <MonthPicker onChange={this.searchChange} getCalendarContainer={() => formId ? document.getElementById(formId) : document.body} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'dateweek') { - fields.push( - <Col span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> - {getFieldDecorator(item.field, { - initialValue: item.initval ? moment().subtract(item.initval * 7, 'days') : null, - rules: [ - { - required: item.required === 'true', - message: dict['form.required.select'] + item.label + '!' - } - ] - })( - <WeekPicker onChange={this.searchChange} getCalendarContainer={() => formId ? document.getElementById(formId) : document.body} /> - )} - </Form.Item> - </Col> - ) - } else if (item.type === 'daterange') { - let _defaultValue = [null, null] + if (item.hidden || item.advanced) return - if (item.initval) { - try { - let _initval = JSON.parse(item.initval) - _defaultValue = [moment().subtract(_initval[0], 'days'), moment().subtract(_initval[1], 'days')] - } catch { - _defaultValue = [null, null] - } + const _rules = [ + { + required: item.required, + message: item.label + '涓嶅彲涓虹┖!' } + ] - fields.push( - <Col className="daterange" span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> - {getFieldDecorator(item.field, - { - initialValue: _defaultValue, - rules: [ - { - required: item.required === 'true', - message: dict['form.required.select'] + item.label + '!' - } - ] - })( - <RangePicker - placeholder={['寮�濮嬫棩鏈�', '缁撴潫鏃ユ湡']} - renderExtraFooter={() => 'extra footer'} - onChange={this.searchChange} - getCalendarContainer={() => formId ? document.getElementById(formId) : document.body} - /> - )} - </Form.Item> - </Col> - ) + let content = null + let field = item.field + + if (item.type === 'text') { + if (item.inputType === 'search') { + content = <Search placeholder={item.labelShow === 'false' ? item.label : ''} autoComplete="off" onSearch={this.handleSubmit} enterButton/> + } else { + content = <Input placeholder={item.labelShow === 'false' ? item.label : ''} autoComplete="off" onPressEnter={this.handleSubmit} /> + } + } else if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') { + content = (<MKSelect config={item} onChange={(val, defer) => this.recordChange(val, defer, item)} />) + } else if (item.type === 'date' || item.type === 'datemonth' || item.type === 'dateweek' || item.type === 'daterange') { + content = (<MKDatePicker config={item} onChange={(val) => this.recordChange(val, false, item)} />) } else if (item.type === 'group') { + field = item.datefield + content = <DateGroup position={index} config={item} onChange={(val, type) => this.dateGroupChange(val, type, item)} /> + } else if (item.type === 'checkcard') { + content = <MKCheckCard card={item} onChange={this.handleSubmit} /> + } + + if (content) { fields.push( <Col span={item.ratio || 6} key={index}> - <Form.Item label={item.labelShow !== 'false' ? item.label : ''} className={item.required === 'true' ? 'group-required' : ''}> - <DateGroup ref={item.uuid} position={index} card={item} onGroupChange={this.searchChange} /> + <Form.Item label={item.labelShow !== 'false' ? item.label : ''}> + {getFieldDecorator(field, { + initialValue: item.initval, + rules: _rules + })(content)} </Form.Item> </Col> ) @@ -634,78 +475,58 @@ }) if (showButton) { - fields.push( + let action = ( <Col span={6} style={{ whiteSpace: 'nowrap' }} className="search-button" key="actions"> <Form.Item label={' '} colon={false} style={{ minHeight: '40px' }}> - <Button type="primary" onClick={this.handleSearch}> + <Button type="primary" onClick={this.handleSubmit}> {dict['main.search']} </Button> <Button style={{ marginLeft: 8 }} onClick={this.handleReset}> {dict['main.reset']} </Button> + {showAdvanced ? <Button type="link" onClick={this.handleAdvance}> + 楂樼骇 + </Button> : null} </Form.Item> </Col> ) + if (float === 'right') { + fields.unshift(action) + } else { + fields.push(action) + } } return fields } - addHideFieldValue = (values) => { - const { searchlist } = this.state - let hideValue = {} - searchlist.forEach(item => { - if (item.Hide === 'true') { - let value = '' - - if (item.type === 'multiselect') { // 涓嬫媺澶氶�� - value = item.initval ? item.initval.split(',').filter(Boolean) : [] - } else if (item.type === 'date') { // 鏃堕棿鎼滅储 - value = item.initval ? moment().subtract(item.initval, 'days') : '' - } else if (item.type === 'datemonth') { - value = item.initval ? moment().subtract(item.initval, 'month') : '' - } else if (item.type === 'dateweek') { - value = item.initval ? moment().subtract(item.initval * 7, 'days') : '' - } else if (item.type === 'daterange') { - if (item.initval) { - try { - let _initval = JSON.parse(item.initval) - value = [moment().subtract(_initval[0], 'days'), moment().subtract(_initval[1], 'days')] - } catch { - value = '' - } - } - } else if (item.type !== 'group') { - value = item.initval - } - - hideValue[item.field] = value - } - }) - - return {...hideValue, ...values} + handleAdvance = () => { + this.setState({visible: true}) } - handleSearch = (e) => { - // 鍥炶溅鎴栫偣鍑绘悳绱� - e.preventDefault() - this.props.form.validateFields((err, values) => { - if (!err) { - values = this.addHideFieldValue(values) - let searches = this.getFieldsValues(values) - this.props.refreshdata(searches) - } - }) - } - - searchChange = () => { + handleSubmit = () => { this.setState({}, () => { this.props.form.validateFields((err, values) => { - if (!err) { - values = this.addHideFieldValue(values) - let searches = this.getFieldsValues(values) - this.props.refreshdata(searches) + if (err) return + + let searches = this.getFieldsValues(values) + + if (this.state.hasReqFields) { + let requireFields = searches.filter(item => item.required && item.value === '') + if (requireFields.length > 0) { + let labels = requireFields.map(item => item.label) + labels = Array.from(new Set(labels)) + + notification.warning({ + top: 92, + message: this.state.dict['form.required.input'] + labels.join('銆�') + ' !', + duration: 3 + }) + return + } } + + this.props.refreshdata(searches) }) }) } @@ -714,87 +535,109 @@ * @description 鎼滅储鏉′欢閲嶇疆 */ handleReset = () => { - const { groups } = this.state - - if (groups.length > 0) { - groups.forEach(item => { - this.refs[item.uuid].reset() - }) - } - + let record = {} + let advanceValues = [] let searchlist = this.state.searchlist.map(item => { item.initval = item.oriInitval + + if (item.type === 'group') { + record[item.datefield] = item.initval + record[item.field] = item.initType + } else { + record[item.field] = item.initval + } + if (item.advanced && item.initval) { + advanceValues.push({field: item.field, type: item.type, label: item.label, value: item.initval}) + } + return item }) - this.setState({searchlist}, () => { - this.props.form.resetFields() - this.props.form.validateFields((err, values) => { - if (!err) { - // 寮傛鑾峰彇鏇存柊鍚庣殑鏃堕棿缁� - this.setState({}, () => { - values = this.addHideFieldValue(values) - let searches = this.getFieldsValues(values) - this.props.refreshdata(searches) - }) - } + this.record = record + + this.setState({searchlist: [], advanceValues}, () => { + this.setState({searchlist}, () => { + this.handleSubmit() }) }) } - getFieldsValues = (values) => { - const { groups } = this.state + getFieldsValues = (vals) => { + const { searchlist } = this.state + let values = {...this.record, ...vals} + this.record = values + // 鑾峰彇鎼滅储鏉′欢鍊� let search = [] - Object.keys(values).forEach(key => { - let _value = '' - if (this.state.style[key] === 'daterange') { - if (values[key].length > 0 && values[key][0] && values[key][1]) { - _value = [moment(values[key][0]).format('YYYY-MM-DD'), moment(values[key][1]).format('YYYY-MM-DD')] - } - } else if (this.state.style[key] === 'dateweek') { - if (values[key]) { - _value = [moment(values[key]).startOf('week').format('YYYY-MM-DD'), moment(values[key]).endOf('week').format('YYYY-MM-DD')] - } - } else if (this.state.style[key] === 'date') { - if (values[key]) { - _value = moment(values[key]).format('YYYY-MM-DD') - } - } else if (this.state.style[key] === 'datemonth') { - if (values[key]) { - _value = moment(values[key]).format('YYYY-MM') - } - } else if (this.state.style[key] === 'multiselect') { - _value = values[key] || [] - + searchlist.forEach(item => { + if (item.type === 'group') { + search.push({ + type: 'daterange', + key: item.datefield, + value: values[item.datefield] || '', + label: item.label, + match: 'between', + required: item.required + }, { + type: 'group', + key: item.field, + value: values[item.field] || '', + label: item.label, + match: '=', + forbid: true, + required: item.required + }) } else { - _value = (values[key] || values[key] === 0) ? values[key] : '' + let type = item.type + if (type === 'multiselect' || (type === 'checkcard' && item.multiple === 'true')) { + type = 'multi' + } + let val = values[item.field] !== undefined ? values[item.field] : '' - _value = _value.replace(/(^\s*|\s*$)/ig, '') + if (typeof(val) === 'string') { + val = val.replace(/(^\s*|\s*$)/ig, '') + } + + search.push({ + type: type, + key: item.field.replace(/@tail@$/, ''), + value: val, + label: item.label, + match: item.match, + required: item.required + }) } - - search.push({ - type: this.state.style[key], - key: key.replace(/@tail@$/, ''), - value: _value, - label: this.state.label[key], - match: this.state.match[key], - required: this.state.required[key] - }) }) - - if (groups.length > 0) { - groups.forEach(item => { - let items = this.refs[item.uuid].getSearchItems() - search.push(...items) - }) - } return search } + handleOk = (values) => { + this.record = {...this.record, ...values} + + let advanceValues = [] + this.state.searchlist.forEach(item => { + if (!item.advanced) return + + let val = this.record[item.field] + if (val || val === 0) { + advanceValues.push({field: item.field, type: item.type, label: item.label, value: val}) + } + }) + + this.setState({advanceValues, visible: false}) + this.handleSubmit() + } + + closeAdvanceForm = (cell) => { + this.record[cell.field] = '' + + this.setState({advanceValues: this.state.advanceValues.filter(item => item.field !== cell.field)}) + this.handleSubmit() + } + render() { - const { float, searchStyle } = this.state + const { float, searchStyle, visible, searchlist, showAdvanced, advanceValues, adModelWidth } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -807,9 +650,39 @@ } return ( - <Form {...formItemLayout} className={`top-search ${float}`} style={searchStyle} id={this.state.formId || this.state.oriId}> - <Row gutter={24}>{this.getFields()}</Row> - </Form> + <> + <Form {...formItemLayout} className={`top-search ${float}`} style={searchStyle}> + <Row gutter={24}>{this.getFields()}</Row> + <Row gutter={24}> + {showAdvanced ? <div className="advanced-list"> + {advanceValues.map((item, index) => { + return ( + <div key={index}> + <span>{item.label}: </span> + <span className="advance-value">{item.value}</span> + <Icon type="close" onClick={() => this.closeAdvanceForm(item)} /> + </div>) + })} + </div> : null} + </Row> + </Form> + <Modal + title="楂樼骇鎼滅储" + maskClosable={false} + visible={visible} + width={adModelWidth} + closable={false} + footer={null} + destroyOnClose + > + <MutilForm + searchlist={searchlist} + record={this.record} + advanceSubmit={this.handleOk} + handleClose={() => this.setState({visible: false})} + /> + </Modal> + </> ) } } diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss index 9388a99..f5378b0 100644 --- a/src/tabviews/zshare/topSearch/index.scss +++ b/src/tabviews/zshare/topSearch/index.scss @@ -36,6 +36,37 @@ content: '*'; } } + .search-button { + .ant-btn-link, .ant-btn-link:hover, .ant-btn-link:active{ + border-color: transparent; + span { + position: relative; + top: 5px; + } + } + } + .advanced-list { + font-size: 13px; + padding: 0 12px; + > div { + display: inline-block; + margin-right: 10px; + border: 1px solid #dddddd; + padding: 0 4px 0 4px; + background: rgba(0, 0, 0, 0.02); + + .anticon-close { + margin-left: 5px; + cursor: pointer; + color: #bcbcbc; + font-size: 12px; + padding: 2px; + } + } + } + .check-card-form-box { + margin-top: 5px; + } } .top-search.right { >.ant-row { @@ -43,4 +74,4 @@ float: right; } } -} \ No newline at end of file +} diff --git a/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx b/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx new file mode 100644 index 0000000..036049b --- /dev/null +++ b/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx @@ -0,0 +1,93 @@ +import React, { Component } from 'react' +import { is, fromJS } from 'immutable' +import { DatePicker } from 'antd' +import moment from 'moment' + +import './index.scss' + +const { MonthPicker, WeekPicker, RangePicker } = DatePicker + +/** + * @description 鑷畾涔夋椂闂撮�夋嫨鍣� + */ +class MkDatePicker extends Component { + constructor(props) { + super(props) + + const config = props.config + + let mode = 'date' + let format = 'YYYY-MM-DD' + + if (config.type === 'datemonth') { + mode = 'month' + format = 'YYYY-MM' + } else if (config.type === 'week') { + mode = 'week' + format = 'YYYY-MM-DD' + } else if (config.type === 'daterange') { + mode = 'daterange' + format = 'YYYY-MM-DD' + } + let value = config.initval || null + + if (mode === 'daterange') { + if (value) { + let val = value.split(',') + value = [moment(val[0], format), moment(val[1], format)] + } else { + value = [null, null] + } + } else if (value) { + value = moment(value, format) + } + + this.state = { + value, + mode, + format + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + componentWillUnmount () { + this.setState = () => { + return + } + } + + onChange = (val) => { + const { format, mode } = this.state + + this.setState({value: val}) + + if (mode === 'daterange') { + let _val = val + if (_val && !_val[0]) { + _val = '' + } + this.props.onChange(_val ? `${moment(_val[0]).format(format)},${moment(_val[1]).format(format)}` : '') + } else { + this.props.onChange(val ? moment(val).format(format) : '') + } + } + + render() { + const { value, mode } = this.state + + if (mode === 'date') { + return <DatePicker value={value} onChange={this.onChange}/> + } else if (mode === 'month') { + return <MonthPicker value={value} onChange={this.onChange}/> + } else if (mode === 'week') { + return <WeekPicker value={value} onChange={this.onChange}/> + } else if (mode === 'daterange') { + return <RangePicker placeholder={['寮�濮嬫棩鏈�', '缁撴潫鏃ユ湡']} value={value} onChange={this.onChange}/> + } + } +} + +export default MkDatePicker \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/tabviews/zshare/topSearch/mkDatePicker/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/topSearch/mkDatePicker/index.scss diff --git a/src/tabviews/zshare/topSearch/mkSelect/index.jsx b/src/tabviews/zshare/topSearch/mkSelect/index.jsx new file mode 100644 index 0000000..725c805 --- /dev/null +++ b/src/tabviews/zshare/topSearch/mkSelect/index.jsx @@ -0,0 +1,121 @@ +import React, {Component} from 'react' +import { is, fromJS } from 'immutable' +import { Select } from 'antd' + +import MKEmitter from '@/utils/events.js' +import './index.scss' + +class MKSearchSelect extends Component { + constructor(props) { + super(props) + + const config = props.config + let value = config.initval + + if (config.type === 'multiselect') { + if (value) { + value = value.split(',') + } else { + value = [] + } + } + + this.state = { + config: fromJS(config).toJS(), + options: fromJS(config.options).toJS(), + value, + } + } + + componentDidMount () { + const { config } = this.state + + if (config.type !== 'multiselect') { + MKEmitter.addListener('mkSP', this.mkFormHandle) + } + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + UNSAFE_componentWillReceiveProps (nextProps) { + const { config } = this.state + + if (!is(fromJS(config.oriOptions), fromJS(nextProps.config.oriOptions))) { + this.setState({ + config: fromJS(nextProps.config).toJS(), + options: fromJS(nextProps.config.options).toJS() + }) + } + } + + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('mkSP', this.mkFormHandle) + } + + mkFormHandle = (uuid, parentId, level) => { + const { config } = this.state + + if (uuid !== config.uuid) return + + let options = config.oriOptions.filter(option => option.ParentID === parentId || option.Value === '') + let val = options[0] ? options[0].Value : '' + + this.setState({ + options, + value: val + }) + + this.props.onChange(val, true) + + if (level < 7 && config.linkFields) { + config.linkFields.forEach((m, i) => { + setTimeout(() => { + MKEmitter.emit('mkSP', m.uuid, val, level + 1) + }, (i + 1) * 10) + }) + } + } + + selectChange = (val) => { + const { config } = this.state + + if (config.type === 'multiselect') { + this.props.onChange(val.join(',')) + } else { + config.linkFields && config.linkFields.forEach((m, i) => { + setTimeout(() => { + MKEmitter.emit('mkSP', m.uuid, val, 0) + }, (i + 1) * 10) + }) + + this.props.onChange(val) + } + + this.setState({value: val}) + } + + render() { + const { value, config, options } = this.state + + return ( + <Select + showSearch + mode={config.type === 'multiselect' ? 'multiple' : ''} + value={value} + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={this.selectChange} + > + {options.map(option => + <Select.Option id={option.key} key={option.key} value={option.Value}>{option.Text}</Select.Option> + )} + </Select> + ) + } +} + +export default MKSearchSelect \ No newline at end of file diff --git a/src/tabviews/zshare/mutilform/customSwitch/index.scss b/src/tabviews/zshare/topSearch/mkSelect/index.scss similarity index 100% copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/topSearch/mkSelect/index.scss diff --git a/src/templates/calendarconfig/source.jsx b/src/templates/calendarconfig/source.jsx index 061fc0c..9ed369e 100644 --- a/src/templates/calendarconfig/source.jsx +++ b/src/templates/calendarconfig/source.jsx @@ -106,6 +106,12 @@ }, { type: 'search', + label: '閫夐」鍗�', + subType: 'checkcard', + url: '' + }, + { + type: 'search', label: CommonDict['model.form.dateday'], subType: 'date', url: '' diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx index 2b88631..c7b4f43 100644 --- a/src/templates/comtableconfig/index.jsx +++ b/src/templates/comtableconfig/index.jsx @@ -26,6 +26,7 @@ const { Panel } = Collapse const { confirm } = Modal const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent')) +const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent')) const SettingComponent = asyncComponent(() => import('@/templates/sharecomponent/settingcomponent')) const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) @@ -1205,6 +1206,7 @@ </div> } bordered={false} extra={ <div> + <ReplaceField type="table" config={config} updateConfig={this.updateconfig}/> <EditComponent dict={this.state.dict} options={['search', 'action', 'columns']} config={this.state.config} MenuID={this.props.menu.MenuID} thawButtons={this.state.thawButtons} refresh={this.editConfig}/> <Switch className="big" checkedChildren={this.state.dict['model.enable']} unCheckedChildren={this.state.dict['model.disable']} checked={this.state.config.enabled} onChange={this.onEnabledChange} /> <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['model.save']}</Button> diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx index 6a33c64..d5297f9 100644 --- a/src/templates/comtableconfig/source.jsx +++ b/src/templates/comtableconfig/source.jsx @@ -228,6 +228,12 @@ }, { type: 'search', + label: '閫夐」鍗�', + subType: 'checkcard', + url: '' + }, + { + type: 'search', label: CommonDict['model.form.dateday'], subType: 'date', url: '' @@ -351,6 +357,12 @@ label: CommonDict['model.form.colspan'], subType: 'colspan', url: '' + }, + { + type: 'columns', + label: '搴忓彿', + subType: 'index', + url: '' } ] diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx index 47db6ac..c5bca12 100644 --- a/src/templates/formtabconfig/index.jsx +++ b/src/templates/formtabconfig/index.jsx @@ -16,23 +16,25 @@ import TabsComponent from '@/templates/sharecomponent/tabscomponent' -import ModalForm from '@/templates/zshare/modalform' import PasteForm from '@/templates/zshare/pasteform' import ActionForm from './actionform' import SettingForm from './settingform' import DragElement from './dragelement' import GroupForm from './groupform' import EditCard from '@/templates/zshare/editcard' -import VerifyCard from '@/templates/zshare/verifycard' + import MenuForm from '@/templates/zshare/menuform' import SourceElement from '@/templates/zshare/dragsource' -import CreateFunc from '@/templates/zshare/createfunc' +import asyncComponent from '@/utils/asyncComponent' import Source from './source' import './index.scss' const { Panel } = Collapse const { Option } = Select const { confirm } = Modal +const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) +const CreateFunc = asyncComponent(() => import('@/templates/zshare/createfunc')) +const VerifyCard = asyncComponent(() => import('@/templates/zshare/verifycard')) class ComTableConfig extends Component { static propTpyes = { diff --git a/src/templates/formtabconfig/settingform/index.jsx b/src/templates/formtabconfig/settingform/index.jsx index 9a407ea..54c7b3a 100644 --- a/src/templates/formtabconfig/settingform/index.jsx +++ b/src/templates/formtabconfig/settingform/index.jsx @@ -197,8 +197,8 @@ message: dict['form.required.input'] + '琛ㄥ悕!' }, { - max: formRule.input.max, - message: formRule.input.message + max: 50, + message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!' } ] })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} diff --git a/src/templates/menuconfig/editfirstmenu/index.jsx b/src/templates/menuconfig/editfirstmenu/index.jsx index 3df062c..200a619 100644 --- a/src/templates/menuconfig/editfirstmenu/index.jsx +++ b/src/templates/menuconfig/editfirstmenu/index.jsx @@ -39,6 +39,7 @@ thawMvisible: false, // 瑙i櫎鍐荤粨妯℃�佹 confirmLoading: false, // 鎻愪氦涓�傘�傘�� dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + targetKeys: [] // 瑙e喕鑿滃崟鍒楄〃 } handlePreviewList = (List) => { @@ -165,7 +166,9 @@ } thawMemuSubmit = () => { - if (this.refs.trawmenu.state.targetKeys.length === 0) { + const { targetKeys } = this.state + + if (targetKeys.length === 0) { notification.warning({ top: 92, message: this.state.dict['form.required.select'] + this.state.dict['model.menu'], @@ -175,7 +178,7 @@ this.setState({ confirmLoading: true }) - let defers = this.refs.trawmenu.state.targetKeys.map(item => { + let defers = targetKeys.map(item => { return new Promise((resolve) => { Api.getSystemConfig({ func: 'sPC_MainMenu_ReDel', @@ -201,6 +204,7 @@ this.setState({ confirmLoading: false, thawMvisible: false, + targetKeys: [], thawmenulist: null }) this.props.reload() @@ -212,6 +216,7 @@ thawMemuCancel = () => { this.setState({ thawMvisible: false, + targetKeys: [], thawmenulist: null }) } @@ -276,7 +281,8 @@ }) } else if (type === 'thawmenu') { this.setState({ - thawMvisible: true + thawMvisible: true, + targetKeys: [] }) Api.getSystemConfig({ func: 'sPC_Get_FrozenMenu', @@ -378,7 +384,7 @@ destroyOnClose > {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />} - {this.state.thawmenulist && <TransferForm ref="trawmenu" menulist={this.state.thawmenulist}/>} + {this.state.thawmenulist && <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/>} </Modal> {/* 缂栬緫鑿滃崟妯℃�佹 */} <Modal diff --git a/src/templates/menuconfig/editsecmenu/index.jsx b/src/templates/menuconfig/editsecmenu/index.jsx index 6d9733e..a30f148 100644 --- a/src/templates/menuconfig/editsecmenu/index.jsx +++ b/src/templates/menuconfig/editsecmenu/index.jsx @@ -33,15 +33,16 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, - menulist: null, // 鑿滃崟鍒楄〃 - type: '', // 缂栬緫绫诲瀷锛宎dd or edit - title: '', // 妯℃�佹鏍囬 - visible: null, // 妯℃�佹鏄惁鍙 - formlist: null, // 琛ㄥ崟淇℃伅 - editMenu: null, // 缂栬緫鑿滃崟 - thawmenulist: null, // 宸插喕缁撶殑浜岀骇鑿滃崟 - thawMvisible: false, // 瑙i櫎鍐荤粨妯℃�佹 - confirmLoading: false // 鎻愪氦涓�傘�傘�� + menulist: null, // 鑿滃崟鍒楄〃 + type: '', // 缂栬緫绫诲瀷锛宎dd or edit + title: '', // 妯℃�佹鏍囬 + visible: null, // 妯℃�佹鏄惁鍙 + formlist: null, // 琛ㄥ崟淇℃伅 + editMenu: null, // 缂栬緫鑿滃崟 + thawmenulist: null, // 宸插喕缁撶殑浜岀骇鑿滃崟 + thawMvisible: false, // 瑙i櫎鍐荤粨妯℃�佹 + confirmLoading: false, // 鎻愪氦涓�傘�傘�� + targetKeys: [] // 瑙e喕鑿滃崟鍒楄〃 } handlePreviewList = (List) => { @@ -170,7 +171,8 @@ }) } else if (type === 'thaw') { // 瑙e喕宸叉湁鑿滃崟 this.setState({ - thawMvisible: true + thawMvisible: true, + targetKeys: [] }) Api.getSystemConfig({ func: 'sPC_Get_FrozenMenu', @@ -329,7 +331,9 @@ } thawMemuSubmit = () => { // 瑙e喕鑿滃崟锛屾彁浜わ紝瀛樺湪澶氫釜鏃讹紝寰幆鎻愪氦 - if (this.refs.trawmenu.state.targetKeys.length === 0) { + const { targetKeys } = this.state + + if (targetKeys.length === 0) { notification.warning({ top: 92, message: this.state.dict['form.required.select'] + this.state.dict['model.menu'], @@ -339,7 +343,7 @@ this.setState({ confirmLoading: true }) - let defers = this.refs.trawmenu.state.targetKeys.map(item => { + let defers = targetKeys.map(item => { return new Promise((resolve) => { Api.getSystemConfig({ func: 'sPC_MainMenu_ReDel', @@ -365,6 +369,7 @@ this.setState({ confirmLoading: false, thawMvisible: false, + targetKeys: [], thawmenulist: null }) this.props.reload() @@ -376,6 +381,7 @@ thawMemuCancel = () => { // 瑙e喕鑿滃崟鍙栨秷 this.setState({ thawMvisible: false, + targetKeys: [], thawmenulist: null }) } @@ -458,7 +464,7 @@ onCancel={this.thawMemuCancel} > {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />} - {this.state.thawmenulist && <TransferForm ref="trawmenu" menulist={this.state.thawmenulist}/>} + {this.state.thawmenulist && <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/>} </Modal> </div> ) diff --git a/src/templates/menuconfig/editthdmenu/index.jsx b/src/templates/menuconfig/editthdmenu/index.jsx index 72cc5e2..76cc412 100644 --- a/src/templates/menuconfig/editthdmenu/index.jsx +++ b/src/templates/menuconfig/editthdmenu/index.jsx @@ -79,6 +79,7 @@ btnTabConfig: null, // 鎵撳紑鏂版爣绛炬寜閽厤缃� handleMVisible: false, // 娣诲姞鎴栦慨鏀硅彍鍗曟ā鎬佹锛堣鑹叉潈闄愬垎閰嶇瓑锛� sysMenu: false, // 娣诲姞鎴栫紪杈戣彍鍗曪紙瑙掕壊鏉冮檺鍒嗛厤绛夛級 + targetKeys: [] // 瑙e喕鑿滃崟鍒楄〃 } /** @@ -268,7 +269,8 @@ return } this.setState({ - thawMvisible: true + thawMvisible: true, + targetKeys: [] }) Api.getSystemConfig({ func: 'sPC_Get_FrozenMenu', @@ -347,8 +349,9 @@ } thawMemuSubmit = () => { + const { targetKeys } = this.state // 涓夌骇鑿滃崟瑙i櫎鍐荤粨 - if (this.refs.trawmenu.state.targetKeys.length === 0) { + if (targetKeys.length === 0) { notification.warning({ top: 92, message: this.state.dict['form.required.select'] + this.state.dict['model.menu'], @@ -358,7 +361,7 @@ this.setState({ confirmLoading: true }) - let defers = this.refs.trawmenu.state.targetKeys.map(item => { + let defers = targetKeys.map(item => { return new Promise((resolve) => { Api.getSystemConfig({ func: 'sPC_MainMenu_ReDel', @@ -384,6 +387,7 @@ this.setState({ confirmLoading: false, thawMvisible: false, + targetKeys: [], thawmenulist: null }) this.props.reload() @@ -396,7 +400,8 @@ // 瑙i櫎鍐荤粨-鍙栨秷 this.setState({ thawMvisible: false, - thawmenulist: null + thawmenulist: null, + targetKeys: [] }) } @@ -560,7 +565,7 @@ } else if (temp.Template === 'CustomPage' && memberLevel < 20) { return } - + _templates.push({ uuid: temp.MenuID, title: temp.MenuName, @@ -612,7 +617,7 @@ let sysTemplates = fromJS(this.state.sysTemplates).toJS() // 瑙掕壊鏉冮檺鍒嗛厤妯℃澘锛屽彧鍙互娣诲姞涓�娆� - if (sysMenu.isSystem && sysMenu.Template === 'RolePermission') { + if (sysMenu.isSystem && (sysMenu.Template === 'RolePermission')) { sysTemplates = sysTemplates.map(temp => { if (temp.type === sysMenu.type) { temp.hidden = true @@ -673,6 +678,7 @@ }) this.props.reload() + document.getElementById('root').style.overflowY = 'unset' } else { this.setState({ confirmLoading: false @@ -725,6 +731,7 @@ }) this.props.reload() + document.getElementById('root').style.overflowY = 'unset' } else { this.setState({ confirmLoading: false @@ -932,7 +939,7 @@ destroyOnClose > {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />} - {this.state.thawmenulist && <TransferForm ref="trawmenu" menulist={this.state.thawmenulist}/>} + {this.state.thawmenulist && <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/>} </Modal> {/* 娣诲姞绯荤粺鑿滃崟 */} <Modal diff --git a/src/templates/modalconfig/checkCard/index.jsx b/src/templates/modalconfig/checkCard/index.jsx index 63c3164..3575d22 100644 --- a/src/templates/modalconfig/checkCard/index.jsx +++ b/src/templates/modalconfig/checkCard/index.jsx @@ -6,33 +6,38 @@ class CheckCard extends Component { static propTpyes = { - multiple: PropTypes.bool, // 鏄惁鍙閫� - ratio: PropTypes.string, // 鍥剧墖姣斾緥 - width: PropTypes.number, // 瀹藉害 - display: PropTypes.string, // 鏄剧ず涓猴細text锛堟枃鏈級銆乸icture锛堝浘鐗囷級 - fields: PropTypes.array, // 瀛楁闆� - options: PropTypes.array, // 鏁版嵁鍒楄〃 + config: PropTypes.object, // 琛ㄥ崟閰嶇疆淇℃伅 onChange: PropTypes.func, // 鏁版嵁鍒囨崲 } state = {} getCards = () => { - const { display, width, options, fields, ratio } = this.props + const { display, width, options, fields, ratio, picratio, backgroundColor, borderColor } = this.props.config + let _ratio = picratio || ratio let paddingTop = '100%' - if (ratio === '4:3') { + if (_ratio === '4:3') { paddingTop = '75%' - } else if (ratio === '3:2') { + } else if (_ratio === '3:2') { paddingTop = '66.7%' - } else if (ratio === '16:9') { + } else if (_ratio === '16:9') { paddingTop = '56.25%' } + let style = {} + + if (borderColor) { + style.borderColor = borderColor + } + if (display !== 'picture') { + let _style = backgroundColor ? {backgroundColor} : null + if (!options || options.length === 0) { return <Col span={width}> - <div className="card-cell"> + <div className="card-cell" style={style}> + <div className="bg-mask" style={_style}></div> {fields ? fields.map(col => { return <span key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{col.field}</span> }) : null} @@ -42,7 +47,8 @@ } return options.map(item => { return <Col span={width} key={item.key}> - <div className="card-cell"> + <div className="card-cell" style={style}> + <div className="bg-mask" style={_style}></div> {fields.map(col => { return <span key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span> })} @@ -52,13 +58,13 @@ } else { if (!options || options.length === 0) { return <Col span={width}> - <div className="card-pic-cell" style={{paddingTop, background: '#91d5ff'}}> + <div className="card-pic-cell" style={{...style, paddingTop, background: '#91d5ff'}}> </div> </Col> } return options.map(item => { return <Col span={width} key={item.key}> - <div className="card-pic-cell" style={{paddingTop, backgroundImage: `url(${item.$url})`}}> + <div className="card-pic-cell" style={{...style, paddingTop, backgroundImage: `url(${item.$url})`}}> </div> </Col> }) diff --git a/src/templates/modalconfig/checkCard/index.scss b/src/templates/modalconfig/checkCard/index.scss index 985c786..8a6d3aa 100644 --- a/src/templates/modalconfig/checkCard/index.scss +++ b/src/templates/modalconfig/checkCard/index.scss @@ -1,5 +1,7 @@ .check-card-edit-box { + line-height: 1.5; .card-cell { + position: relative; border: 1px solid #bcbcbc; border-radius: 4px; padding: 6px; @@ -9,6 +11,18 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + position: relative; + z-index: 1; + } + .bg-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 1; + border-radius: 4px; + background-color: transparent; } } .card-pic-cell { diff --git a/src/templates/modalconfig/dragelement/card.jsx b/src/templates/modalconfig/dragelement/card.jsx index bfb0c5b..f5ad414 100644 --- a/src/templates/modalconfig/dragelement/card.jsx +++ b/src/templates/modalconfig/dragelement/card.jsx @@ -114,7 +114,7 @@ } else if (card.type === 'split') { formItem = <div className="split-line">{card.label}</div> } else if (card.type === 'checkcard') { - formItem = <CheckCard width={card.width} ratio={card.ratio} display={card.display} fields={card.fields} options={card.options} /> + formItem = <CheckCard config={card} /> } let _label = card.label @@ -145,7 +145,7 @@ wrapperCol={card.labelwidth ? {style: {width: (100 - card.labelwidth) + '%'}} : null} > {formItem} - {showField ? <div className="field-name">{card.field}</div> : ''} + {showField ? <div className="field-name">{card.field}{card.hidden === 'true' ? '(闅愯棌)' : ''}</div> : ''} </Form.Item>} </div> </div> diff --git a/src/templates/modalconfig/dragelement/index.jsx b/src/templates/modalconfig/dragelement/index.jsx index 42ded36..d09acc7 100644 --- a/src/templates/modalconfig/dragelement/index.jsx +++ b/src/templates/modalconfig/dragelement/index.jsx @@ -33,6 +33,7 @@ const editCard = id => { const { card } = findCard(id) + delete card.focus handleForm(card) } @@ -106,7 +107,7 @@ return ( <div ref={drop} className={'ant-row modal-fields-row ' + (setting.align || 'left_right')} > {cards.map(card => { - return <Col key={card.uuid} span={card.span || 24}> + return <Col key={card.uuid} span={card.type === 'split' ? 24 : (card.span || 24)}> <Card id={card.uuid} card={card} diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx index 8934dad..3ab3c92 100644 --- a/src/templates/modalconfig/index.jsx +++ b/src/templates/modalconfig/index.jsx @@ -13,7 +13,6 @@ import enUS from '@/locales/en-US/model.js' import { getModalForm } from '@/templates/zshare/formconfig' -import ModalForm from '@/templates/zshare/modalform' import SourceElement from './dragelement/source' import SettingForm from './settingform' import MenuForm from './menuform' @@ -25,6 +24,9 @@ const { Panel } = Collapse const { confirm } = Modal const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS + +const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) +const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent')) const DragElement = asyncComponent(() => import('./dragelement')) const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) @@ -218,7 +220,7 @@ if (card.uuid === item.uuid) { index = i } - if (item.type !== 'select' && item.type !== 'link' && item.type !== 'radio') return + if (!['select', 'link', 'radio', ''].includes(item.type)) return if (item.field && !uniq.has(item.field)) { uniq.set(item.field, true) @@ -338,7 +340,7 @@ _config.fields = _config.fields.filter(item => !item.origin) - if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { + if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { this.setState({ sqlVerifing: true }) @@ -645,6 +647,7 @@ <div className="setting"> <Card title={dict['header.menu.form.configurable']} bordered={false} extra={ <div> + <ReplaceField type="form" config={config} updateConfig={this.updateconfig}/> <EditComponent dict={dict} options={['form']} config={this.state.config} refresh={this.updateEditConfig}/> <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{dict['model.save']}</Button> <Button onClick={this.cancelConfig}>{dict['model.back']}</Button> @@ -710,7 +713,7 @@ <Modal title={dict['model.edit']} visible={this.state.settingVisible} - width={700} + width={850} maskClosable={false} onOk={this.settingSave} onCancel={() => { this.setState({ settingVisible: false }) }} diff --git a/src/templates/modalconfig/settingform/index.jsx b/src/templates/modalconfig/settingform/index.jsx index 14517aa..a4ff109 100644 --- a/src/templates/modalconfig/settingform/index.jsx +++ b/src/templates/modalconfig/settingform/index.jsx @@ -1,7 +1,8 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Input, Radio, InputNumber, Select } from 'antd' +import { Form, Row, Col, Input, Radio, InputNumber, Select, Tooltip, Icon } from 'antd' import { formRule } from '@/utils/option.js' +import StyleInput from '@/menu/stylecontroller/styleInput' import './index.scss' class SettingForm extends Component { @@ -14,11 +15,13 @@ state = { fields: null, + display: this.props.config.setting.display, appType: sessionStorage.getItem('appType') } UNSAFE_componentWillMount () { const { config } = this.props + const { appType, display } = this.state let fields = [] config.fields.forEach(f => { @@ -27,8 +30,14 @@ } }) + let _display = display + if (appType === 'mob' && display !== 'prompt' && display !== 'drawer') { + _display = 'drawer' + } + this.setState({ - fields: fields + fields: fields, + display: _display }) } @@ -56,7 +65,7 @@ render() { const { config, dict } = this.props - const { fields, appType } = this.state + const { fields, appType, display } = this.state const { getFieldDecorator } = this.props.form const formItemLayout = { @@ -86,13 +95,25 @@ })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} </Form.Item> </Col> - <Col span={12}> - <Form.Item label="瀹藉害"> + {appType !== 'mob' ? <Col span={12}> + <Form.Item label="瀹藉害锛�%锛�"> {getFieldDecorator('width', { initialValue: config.setting.width - })(<InputNumber min={10} max={90} precision={0} />)} + })(<InputNumber min={10} max={90} precision={0} onPressEnter={this.handleSubmit}/>)} </Form.Item> - </Col> + </Col> : null} + {appType === 'mob' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="瀹藉害灏忎簬100鏃朵负鐧惧垎鐜囷紝澶т簬100鏃朵负缁濆鍊笺��"> + <Icon type="question-circle" /> + 瀹藉害 + </Tooltip> + }> + {getFieldDecorator('width', { + initialValue: config.setting.width + })(<InputNumber min={10} max={2000} precision={0} onPressEnter={this.handleSubmit}/>)} + </Form.Item> + </Col> : null} <Col span={12}> <Form.Item label="鐒︾偣"> {getFieldDecorator('focus', { @@ -114,7 +135,7 @@ )} </Form.Item> </Col> - <Col span={12}> + {appType !== 'mob' ? <Col span={12}> <Form.Item label="琛ㄥ崟鎺掑垪"> {getFieldDecorator('align', { initialValue: config.setting.align || 'left_right' @@ -125,7 +146,7 @@ </Radio.Group> )} </Form.Item> - </Col> + </Col> : null} <Col span={12}> <Form.Item label="瀹屾垚鍚�"> {getFieldDecorator('finish', { @@ -150,7 +171,20 @@ )} </Form.Item> </Col> - {!this.props.isSubTab && appType !== 'pc' ? <Col span={12}> + <Col span={12}> + <Form.Item label="鏄剧ず鏂瑰紡"> + {getFieldDecorator('display', { + initialValue: display || 'modal' + })( + <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({display: e.target.value})}> + {appType !== 'mob' ? <Radio value="modal">妯℃�佹</Radio> : null} + <Radio value="prompt">鏄惁妗�</Radio> + <Radio value="drawer">鎶藉眽</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {!this.props.isSubTab && !appType && display === 'modal' ? <Col span={12}> <Form.Item label="鎸傝浇瀵硅薄"> {getFieldDecorator('container', { initialValue: config.setting.container || 'tab' @@ -162,18 +196,38 @@ )} </Form.Item> </Col> : null} - <Col span={12}> - <Form.Item label="鏄剧ず鏂瑰紡"> - {getFieldDecorator('display', { - initialValue: config.setting.display || 'modal' + {display === 'drawer' ? <Col span={12}> + <Form.Item label="鎶藉眽鏂瑰悜"> + {getFieldDecorator('placement', { + initialValue: config.setting.placement || 'right' })( - <Radio.Group> - <Radio value="modal">妯℃�佹</Radio> - <Radio value="prompt">鏄惁妗�</Radio> + <Radio.Group style={{whiteSpace: 'nowrap'}}> + <Radio value="right">鍙充晶</Radio> + <Radio value="left">宸︿晶</Radio> + <Radio value="top">涓婁晶</Radio> + <Radio value="bottom">涓嬩晶</Radio> </Radio.Group> )} </Form.Item> - </Col> + </Col> : null} + {appType === 'mob' ? <Col span={12}> + <Form.Item label="宸﹁竟璺�"> + {getFieldDecorator('paddingLeft', { + initialValue: config.setting.paddingLeft || '10px' + })( + <StyleInput options={['px', '%']} /> + )} + </Form.Item> + </Col> : null} + {appType === 'mob' ? <Col span={12}> + <Form.Item label="鍙宠竟璺�"> + {getFieldDecorator('paddingRight', { + initialValue: config.setting.paddingRight || '10px' + })( + <StyleInput options={['px', '%']} /> + )} + </Form.Item> + </Col> : null} </Row> </Form> ) diff --git a/src/templates/modalconfig/settingform/index.scss b/src/templates/modalconfig/settingform/index.scss index 091801f..9a74987 100644 --- a/src/templates/modalconfig/settingform/index.scss +++ b/src/templates/modalconfig/settingform/index.scss @@ -10,4 +10,9 @@ .ant-input-number { width: 100%; } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } } \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx index 1addfe3..53a733a 100644 --- a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx +++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx @@ -38,6 +38,7 @@ position: null, // 鎸夐挳浣嶇疆 procMode: null, // 澶栭儴鎺ュ彛鍙傛暟澶勭悊鏂瑰紡 pageTemplate: null, + Ot: null, requireOptions: [{ value: 'notRequired', text: this.props.dict['header.form.notRequired'] @@ -97,6 +98,7 @@ let _funcType = card.funcType || '' // 鍔熻兘鎸夐挳榛樿绫诲瀷 let _tabTemplate = card.tabTemplate // 鎸夐挳涓烘爣绛鹃〉鏃讹紝鏍囩绫诲瀷锛氫笁绾ц彍鍗曟垨琛ㄥ崟鏍囩椤� let _pageTemplate = card.pageTemplate // 鏂伴〉闈㈢被鍨� + let _Ot = card.Ot || 'requiredSgl' if (_opentype === 'outerpage') { card.pageTemplate = 'custom' @@ -104,9 +106,10 @@ } let _tabs = this.props.tabs.filter(tab => tab.type === 'SubTable') - let _options = this.getOptions(_opentype, _intertype, _funcType, _pageTemplate, _tabTemplate, _procMode) + let _options = this.getOptions(_opentype, _intertype, _funcType, _pageTemplate, _tabTemplate, _procMode, _Ot) this.setState({ + Ot: _Ot, openType: _opentype, pageTemplate: _pageTemplate, interType: _intertype, @@ -172,7 +175,7 @@ } } - getOptions = (_opentype, _intertype, _funcType, _pageTemplate, _tabTemplate, _procMode) => { + getOptions = (_opentype, _intertype, _funcType, _pageTemplate, _tabTemplate, _procMode, _Ot) => { let _options = fromJS(actionTypeOptions[_opentype]).toJS() // 閫夐」鍒楄〃 if (_opentype === 'innerpage') { // 鏂伴〉闈紝鍙�夋ā鏉�(鑷畾涔夋椂锛屽彲濉叆澶栭儴閾炬帴) @@ -227,6 +230,10 @@ _options.push('resetPageIndex') } + if (_Ot !== 'notRequired' && _opentype !== 'excelOut') { + _options.push('controlField', 'controlVal') + } + return _options } @@ -234,11 +241,11 @@ * @description 鍒囨崲 */ optionChange = (key, value) => { - const { openType, funcType, procMode } = this.state + const { openType, funcType, procMode, Ot } = this.state const { card } = this.props if (key === 'OpenType') { - let _options = this.getOptions(value, 'system', '', this.state.pageTemplate, card.tabTemplate, 'system') + let _options = this.getOptions(value, 'system', '', this.state.pageTemplate, card.tabTemplate, 'system', Ot) let _fieldval = {} let _formlist = this.state.formlist.map(item => { item.hidden = !_options.includes(item.key) @@ -343,7 +350,7 @@ // this.props.form.setFieldsValue(_fieldval) // }) } else if (key === 'funcType') { - let _options = this.getOptions('funcbutton', this.state.interType, value, card.pageTemplate, card.tabTemplate, procMode) + let _options = this.getOptions('funcbutton', this.state.interType, value, card.pageTemplate, card.tabTemplate, procMode, Ot) let _fieldval = {} this.setState({ @@ -397,7 +404,7 @@ this.props.form.setFieldsValue(_fieldval) }) } else if (key === 'pageTemplate') { - let _options = this.getOptions('innerpage', this.state.interType, this.state.funcType, value, card.tabTemplate, procMode) + let _options = this.getOptions('innerpage', this.state.interType, this.state.funcType, value, card.tabTemplate, procMode, Ot) let _fieldval = {} this.setState({ @@ -438,7 +445,7 @@ }) }) } else if (key === 'intertype') { - let _options = this.getOptions(openType, value, funcType, '', '', procMode) + let _options = this.getOptions(openType, value, funcType, '', '', procMode, Ot) this.setState({ interType: value, @@ -458,7 +465,7 @@ }) }) } else if (key === 'procMode') { - let _options = this.getOptions(openType, this.state.interType, funcType, '', '', value) + let _options = this.getOptions(openType, this.state.interType, funcType, '', '', value, Ot) this.setState({ procMode: value, @@ -468,6 +475,16 @@ if (item.key === 'innerFunc') { item.required = true } + return item + }) + }) + } else if (key === 'Ot') { + let _options = this.getOptions(openType, this.state.interType, funcType, this.state.pageTemplate, card.tabTemplate, procMode, value) + + this.setState({ + Ot: value, + formlist: this.state.formlist.map(item => { + item.hidden = !_options.includes(item.key) return item }) }) @@ -599,8 +616,8 @@ 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 id={`${index}`} title={option.text} key={`${index}`} value={option.value || option.field}> + {item.key === 'icon' && option.value ? <Icon type={option.value} /> : null} {option.text || option.label} </Select.Option> )} </Select> diff --git a/src/templates/sharecomponent/actioncomponent/index.scss b/src/templates/sharecomponent/actioncomponent/index.scss index d5643e2..93cc1b7 100644 --- a/src/templates/sharecomponent/actioncomponent/index.scss +++ b/src/templates/sharecomponent/actioncomponent/index.scss @@ -16,7 +16,7 @@ .page-card { display: inline-block; margin: 0px 0px 0px 0px; - padding: 0px 10px 0 0; + padding: 0px 10px 10px 0; position: relative; div { cursor: move; diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx index 26c87fe..dd5f292 100644 --- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx @@ -229,8 +229,10 @@ fields = fields + ',' } - let database = btn.sheet.match(/(.*)\.(.*)\./ig) || '' - let sheet = btn.sheet.replace(/(.*)\.(.*)\./ig, '') + let database = btn.sheet.match(/(.*)\.(.*)\.|@db@/ig) || '' + let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '') + + database = database ? (database[0] || '') : '' _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From @${sheet}` } else { diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx index 01ec3e6..d050d57 100644 --- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Button, Input, InputNumber } from 'antd' +import { Form, Row, Col, Button, Input, InputNumber, Radio } from 'antd' import './index.scss' class ExcelOutColumn extends Component { @@ -40,7 +40,7 @@ return ( <Form {...formItemLayout} className="verify-form"> <Row gutter={24}> - <Col span={7}> + <Col span={5}> <Form.Item label={dict['model.form.field']}> {getFieldDecorator('Column', { initialValue: '', @@ -53,7 +53,7 @@ })(<Input placeholder="" autoComplete="off" />)} </Form.Item> </Col> - <Col span={7}> + <Col span={5}> <Form.Item label={dict['model.name']}> {getFieldDecorator('Text', { initialValue: '', @@ -66,7 +66,7 @@ })(<Input placeholder="" autoComplete="off" />)} </Form.Item> </Col> - <Col span={7}> + <Col span={5}> <Form.Item label={dict['model.form.columnWidth']}> {getFieldDecorator('Width', { initialValue: 20, @@ -79,7 +79,19 @@ })(<InputNumber min={5} max={200} precision={0} />)} </Form.Item> </Col> - <Col span={3} className="add"> + <Col span={5}> + <Form.Item label="绫诲瀷"> + {getFieldDecorator('type', { + initialValue: 'text' + })( + <Radio.Group> + <Radio value="text">鏂囨湰</Radio> + <Radio value="image">鍥剧墖</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={4} className="add"> <Button onClick={this.handleConfirm} type="primary" className="mk-green"> 娣诲姞 </Button> diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx index 8fb4902..f937f81 100644 --- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx @@ -33,14 +33,14 @@ inputType: 'input', editable: true, unique: true, - width: '25%' + width: '20%' }, { title: this.props.dict['model.name'], dataIndex: 'Text', inputType: 'input', editable: true, - width: '25%' + width: '20%' }, { title: this.props.dict['model.form.columnWidth'], @@ -49,7 +49,26 @@ min: 5, max: 200, editable: true, - width: '25%' + width: '20%' + }, + { + title: '绫诲瀷', + dataIndex: 'type', + inputType: 'select', + editable: true, + required: false, + width: '20%', + render: (text) => { + if (text === 'image') { + return '鍥剧墖' + } else { + return '鏂囨湰' + } + }, + options: [ + {value: 'text', text: '鏂囨湰'}, + {value: 'image', text: '鍥剧墖'} + ] }, { title: '鍙栫粷瀵瑰��', @@ -57,7 +76,7 @@ inputType: 'select', editable: true, required: false, - width: '25%', + width: '20%', render: (text) => { if (text === 'true') { return '鏄�' @@ -87,11 +106,18 @@ if (card.intertype !== 'system') { _verify.enable = 'false' } + if (_verify.columns[0] && !_verify.columns[0].type) { + _verify.columns = _verify.columns.map(col => { + col.type = col.type || 'text' + return col + }) + } let defaultscript = '' if (!_verify.script && card.intertype === 'system') { let search = this.formatSearch(config.search) search = Utils.joinMainSearchkey(search) + search = search.replace(/@\$@/ig, '') search = search ? 'where ' + search : '' defaultscript = `update ${config.setting.tableName || ''} set idefine5= idefine5+1 ,modifydate=getdate(),cdefine5='宸插鍑�',modifyuserid=@userid@ ${search}` @@ -113,36 +139,37 @@ let newsearches = [] searches.forEach(search => { + if (!search.field) return + let item = { key: search.field, match: search.match, type: search.type, label: search.label, - value: `@${search.field}@`, + value: search.initval, required: search.required === 'true' } if (item.type === 'group') { - let copy = fromJS(item).toJS() - copy.key = search.datefield + item.key = search.datefield + item.type = 'daterange' + item.match = 'between' + item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') - item.value = `@${search.field}@` - item.match = '=' - - copy.type = 'daterange' - copy.match = 'between' - copy.value = [`@${search.datefield}@`, `@${search.datefield}1@`] - - if (search.transfer === 'true') { - newsearches.push(item) - } - newsearches.push(copy) + newsearches.push(item) return + } else if (item.type === 'date') { + item.value = moment().format('YYYY-MM-DD') + } else if (item.type === 'datemonth') { + item.value = moment().format('YYYY-MM') } else if (item.type === 'dateweek') { - item.value = [`@${search.field}@`, `@${search.field}1@`] + item.value = moment().format('YYYY-MM-DD') } else if (item.type === 'daterange') { - item.value = [`@${search.field}@`, `@${search.field}1@`] - } else if (item.type === 'multiselect') { - item.value = [`@${search.field}@`] + item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') + } else if (item.type === 'multiselect' || (item.type === 'checkcard' && search.multiple === 'true')) { + item.type = 'multi' + item.value = '@$@' + } else { + item.value = '@$@' } newsearches.push(item) }) @@ -370,6 +397,7 @@ Text: item.label, Width: 20, abs: 'false', + type: 'text', uuid: Utils.getuuid() }) }) @@ -428,6 +456,7 @@ <Button className="excel-col-add mk-red" title="娓呯┖Excel鍒�" onClick={this.clearField}> 娓呯┖Excel鍒� </Button> + <div style={{color: '#959595', fontSize: '13px', paddingLeft: '10px'}}>濡傞渶瀵煎嚭搴忓彿锛岃浣跨敤瀛楁 $Index銆�</div> <EditTable actions={['edit', 'move', 'copy', 'del']} type="exceloutcolumn" data={verify.columns} columns={excelColumns} onChange={(columns) => this.setState({verify: {...verify, columns}})}/> </TabPane> {card.intertype === 'system' ? <TabPane tab={ diff --git a/src/templates/sharecomponent/columncomponent/columnform/index.jsx b/src/templates/sharecomponent/columncomponent/columnform/index.jsx index 8bfffcb..5932983 100644 --- a/src/templates/sharecomponent/columncomponent/columnform/index.jsx +++ b/src/templates/sharecomponent/columncomponent/columnform/index.jsx @@ -11,7 +11,8 @@ number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'], link: ['label', 'field', 'type', 'nameField', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist'], textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'fieldlength', 'blacklist'], - picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'maxHeight'] + picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'maxHeight'], + index: ['label', 'type', 'Align', 'Width'] } class MainSearch extends Component { diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx index 8447dd0..8f2a184 100644 --- a/src/templates/sharecomponent/fieldscomponent/index.jsx +++ b/src/templates/sharecomponent/fieldscomponent/index.jsx @@ -19,6 +19,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), fields: [], // 瀛楁闆� tableVisible: false, // 妯℃�佹鎺у埗 } @@ -54,7 +55,7 @@ } else if (type === 'columns') { // 娣诲姞鏄剧ず鍒楋紝瀛楁闆嗕腑瀛樺湪鏄剧ず鍒楀瓧娈碉紝浣跨敤鏄剧ず鍒楀璞℃浛鎹㈠瓧娈甸泦锛岃缃暟鎹被鍨� config.columns.forEach(item => { - if (columns.has(item.field.toLowerCase())) { + if (item.field && columns.has(item.field.toLowerCase())) { let _datatype = columns.get(item.field.toLowerCase()).datatype columns.set(item.field.toLowerCase(), {...item, selected: true, datatype: _datatype}) } @@ -162,7 +163,7 @@ config.search = items } else if (type === 'columns') { config.columns.forEach(item => { - if (columnsMap.has(item.field.toLowerCase())) { + if (item.field && columnsMap.has(item.field.toLowerCase())) { let cell = columnsMap.get(item.field.toLowerCase()) if (cell.selected) { @@ -216,12 +217,13 @@ let _columns = [...columnsMap.values()] _columns.forEach(item => { + let _t = item.$datatype || (item.type === 'number' ? 'Decimal(18,0)' : 'Nvarchar(50)') if (item.selected) { let newcard = { uuid: Utils.getuuid(), label: item.label, field: item.field, - datatype: item.type === 'number' ? 'Decimal(18,0)' : 'Nvarchar(50)' + datatype: _t } items.push(newcard) @@ -247,7 +249,10 @@ let _columns = [...columnsMap.values()] let lastItem = config.fields[config.fields.length - 1] - let span = lastItem ? lastItem.span || 12 : 12 + let span = this.state.appType === 'mob' ? 24 : 12 + if (lastItem && lastItem.span) { + span = lastItem.span + } _columns.forEach(item => { // 寰幆娣诲姞鏂板瀛楁 if (item.selected) { diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx index 812ed31..1981f06 100644 --- a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx +++ b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx @@ -4,11 +4,13 @@ import moment from 'moment' import DateGroup from '../dategroup' +import asyncComponent from '@/utils/asyncComponent' import './index.scss' const { MonthPicker, WeekPicker, RangePicker } = DatePicker +const CheckCard = asyncComponent(() => import('@/templates/modalconfig/checkCard')) -const Card = ({ id, card, moveCard, copyCard, findCard, editCard, delCard }) => { +const Card = ({ id, card, showField, moveCard, copyCard, findCard, editCard, delCard }) => { const originalIndex = findCard(id).index const [{ isDragging }, drag] = useDrag({ item: { type: 'search', id, originalIndex }, @@ -57,6 +59,30 @@ } } + let formItem = null + if (card.type === 'text') { + formItem = (<Input style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} />) + } else if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link') { + formItem = (<Select value={_defaultValue}></Select>) + } else if (card.type === 'date') { + formItem = (<DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} />) + } else if (card.type === 'dateweek') { + formItem = (<WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} />) + } else if (card.type === 'datemonth') { + formItem = (<MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} />) + } else if (card.type === 'daterange') { + formItem = (<RangePicker + className="data-range" + placeholder={['BeginTime', 'EndTime']} + renderExtraFooter={() => 'extra footer'} + value={_defaultValue} + />) + } else if (card.type === 'group') { + formItem = (<DateGroup card={card} />) + } else if (card.type === 'checkcard') { + formItem = <CheckCard config={card} /> + } + return ( <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> @@ -72,31 +98,9 @@ wrapperCol = {{xs: { span: 24 }, sm: { span: 16 }}} label={card.labelShow !== 'false' ? card.label : ''} required={card.required === 'true'} + help={showField ? card.field + (card.datefield ? ', ' + card.datefield : '') : ''} > - {card.type === 'text' ? - <Input style={{marginTop: '4px'}} value={card.initval} /> : null - } - {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ? - <Select value={_defaultValue}></Select> : null - } - {card.type === 'date' ? - <DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null - } - {card.type === 'dateweek' ? - <WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null - } - {card.type === 'datemonth' ? - <MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null - } - {card.type === 'daterange' ? - <RangePicker - className="data-range" - placeholder={['BeginTime', 'EndTime']} - renderExtraFooter={() => 'extra footer'} - value={_defaultValue} - /> : null - } - {card.type === 'group' ? <DateGroup card={card} /> : null } + {formItem} </Form.Item> </div> </div> diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx index 4af02e9..d65fdec 100644 --- a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx +++ b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx @@ -7,7 +7,7 @@ import Card from './card' import './index.scss' -const Container = ({list, placeholder, handleList, handleMenu, deleteMenu }) => { +const Container = ({list, placeholder, showField, handleList, handleMenu, deleteMenu }) => { const [cards, setCards] = useState(list) const moveCard = (id, atIndex) => { const { card, index } = findCard(id) @@ -94,7 +94,7 @@ newcard.display = 'dropdown' let _match = 'like' - if (item.subType === 'select' || item.subType === 'link') { + if (item.subType === 'select' || item.subType === 'link' || item.subType === 'checkcard') { _match = '=' } else if (item.subType === 'date' || item.subType === 'datemonth') { _match = '>=' @@ -130,6 +130,7 @@ <Card id={`${card.uuid}`} card={card} + showField={showField} moveCard={moveCard} copyCard={copyCard} editCard={editCard} @@ -139,7 +140,7 @@ </Col> ))} {cards.length > 0 ? <Col key="action" className="action" span={6}> - <div className="ant-row ant-form-item" style={{lineHeight: '40px', height: '55px', marginBottom: 0}}> + <div className="ant-row ant-form-item" style={{whiteSpace: 'nowrap', lineHeight: '40px', height: '55px', marginBottom: 0}}> <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8"> </div> <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16"> diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx index c17f639..44d9716 100644 --- a/src/templates/sharecomponent/searchcomponent/index.jsx +++ b/src/templates/sharecomponent/searchcomponent/index.jsx @@ -1,7 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Icon, Tooltip, Modal, notification } from 'antd' +import { Icon, Tooltip, Modal, notification, Switch } from 'antd' import moment from 'moment' import Api from '@/api' @@ -27,6 +27,7 @@ searchlist: null, // 鎼滅储鏉′欢闆� sqlVerifing: false, // sql楠岃瘉涓� visible: false, // 妯℃�佹鎺у埗 + showField: false, card: null // 缂栬緫涓厓绱� } @@ -79,12 +80,14 @@ let linkableFields = [] searchlist.forEach(item => { - if (item.uuid !== card.uuid && (item.type === 'select' || item.type === 'link')) { - linkableFields.push({ - value: item.field, - text: item.label - }) - } + if (item.uuid === card.uuid) return + if (!['select', 'link', 'checkcard'].includes(item.type)) return + if (item.type === 'checkcard' && item.multiple === 'true') return + + linkableFields.push({ + value: item.field, + text: item.label + }) }) this.setState({ @@ -187,7 +190,7 @@ return } - if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { + if (['checkcard', 'select', 'multiselect', 'link'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { this.setState({ sqlVerifing: true }) @@ -261,6 +264,15 @@ }) } + onFieldChange = () => { + const { showField } = this.state + + this.setState({ + showField: !showField + }) + } + + /** * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 */ @@ -275,15 +287,17 @@ } render() { - const { dict, searchlist, visible, sqlVerifing, card } = this.state + const { dict, searchlist, visible, sqlVerifing, card, showField } = this.state return ( <div className={'model-table-search-list length' + searchlist.length}> <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.search.guide']}> <Icon type="question-circle" /> </Tooltip> + <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={showField} onChange={this.onFieldChange} /> <DragElement list={searchlist} + showField={showField} handleList={this.handleList} handleMenu={this.handleSearch} deleteMenu={this.deleteElement} diff --git a/src/templates/sharecomponent/searchcomponent/index.scss b/src/templates/sharecomponent/searchcomponent/index.scss index cf4253b..2b8857c 100644 --- a/src/templates/sharecomponent/searchcomponent/index.scss +++ b/src/templates/sharecomponent/searchcomponent/index.scss @@ -1,6 +1,7 @@ .model-table-search-list { padding: 1px 24px 20px; min-height: 87px; + position: relative; border-bottom: 1px solid #d9d9d9; .anticon-question-circle { @@ -8,6 +9,12 @@ position: relative; left: -15px; top: 5px; + } + >.ant-switch { + position: absolute; + z-index: 1; + right: 20px; + bottom: 10px; } > .ant-row { min-height: 65px; @@ -68,4 +75,7 @@ min-width: 100px!important; width: 100%; } + .check-card-edit-box { + margin-top: 5px!important; + } } \ No newline at end of file diff --git a/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx b/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx index 7465a79..eb43982 100644 --- a/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx +++ b/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx @@ -113,14 +113,14 @@ 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> + <span className="operation-btn" title={props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <Popconfirm overlayClassName="popover-confirm" title={props.dict['model.query.delete']} onConfirm={() => this.handleDelete(record.key) }> - <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + <span style={{color: '#ff4d4f', cursor: 'pointer'}}><Icon type="delete" /></span> </Popconfirm> </div> ) : null, @@ -171,8 +171,9 @@ } handleDelete = key => { - const dataSource = [...this.state.dataSource] - this.setState({ dataSource: dataSource.filter(item => item.key !== key) }) + const dataSource = this.state.dataSource.filter(item => item.key !== key) + this.setState({ dataSource }) + this.props.onChange && this.props.onChange(dataSource) } handleAdd = () => { @@ -185,10 +186,12 @@ if (type === 'link') { newData.ParentID = `${count}` } + let data = [...dataSource, newData] this.setState({ - dataSource: [...dataSource, newData], + dataSource: data, count: count + 1 }) + this.props.onChange && this.props.onChange(data) } handleSave = row => { @@ -200,6 +203,7 @@ ...row }) this.setState({ dataSource: newData }) + this.props.onChange && this.props.onChange(newData) } resetColumn = (type) => { diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx index 843331c..96c3459 100644 --- a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx +++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx @@ -1,11 +1,17 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' +import { fromJS } from 'immutable' import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber, Checkbox, Cascader } from 'antd' import { dateOptions, matchReg, formRule } from '@/utils/option.js' import EditTable from '../searcheditable' import Utils from '@/utils/utils.js' import CodeMirror from '@/templates/zshare/codemirror' +import asyncComponent from '@/utils/asyncComponent' import './index.scss' + +const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) +const FieldsTable = asyncComponent(() => import('@/templates/zshare/modalform/fieldtable')) +const DataTable = asyncComponent(() => import('@/templates/zshare/modalform/datatable')) const groupOptions = [ { @@ -80,6 +86,20 @@ }, ] +const searchTypeOptions = { + text: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'inputType', 'advanced'], + select: ['label', 'field', 'resourceType', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'setAll'], + multiselect: ['label', 'field', 'resourceType', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced'], + link: ['label', 'field', 'resourceType', 'initval', 'type', 'linkField', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'setAll'], + date: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced'], + checkcard: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'resourceType', 'display', 'width', 'multiple', 'borderColor', 'required', 'Hide', 'labelShow', 'advanced'], + dateweek: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced'], + datemonth: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced'], + daterange: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced'], + group: ['label', 'type', 'field', 'datefield', 'initval', 'blacklist', 'ratio', 'items', 'required', 'labelShow'], + range: ['label', 'type', 'field', 'initval', 'match', 'blacklist', 'Hide', 'required', 'maxValue', 'minValue', 'step', 'labelShow'] +} + class MainSearch extends Component { static propTpyes = { dict: PropTypes.object, // 瀛楀吀椤� @@ -92,6 +112,8 @@ openType: null, // 鎼滅储鏉′欢鏄剧ず绫诲瀷 resourceType: null, // 涓嬫媺鎼滅储鏃讹紝閫夐」鏉ユ簮绫诲瀷 formlist: null, // 琛ㄥ崟 + display: null, + cFields: [], textTooltip: '瀛楁鍚嶅彲浠ヤ娇鐢ㄩ�楀彿鍒嗛殧锛岃繘琛岀患鍚堟悳绱�', } @@ -103,31 +125,37 @@ UNSAFE_componentWillMount () { const { formlist, dict } = this.props - let type = formlist.filter(cell => cell.key === 'type')[0].initVal - let _items = formlist.filter(cell => cell.key === 'items')[0].initVal - let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal - let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow'] // 榛樿鏄剧ず椤� + let type = '' + let _items = [] + let resourceType = '' + let display = '' + let cFields = [] + let multiple = 'false' - if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '0') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮 - _options = [..._options, 'resourceType', 'options', 'display'] - } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙� - _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database'] - } else if (type === 'group') { - _options = ['label', 'type', 'field', 'datefield', 'initval', 'blacklist', 'ratio', 'items', 'required', 'transfer', 'labelShow'] - } + formlist.forEach(cell => { + if (cell.key === 'type') { + type = cell.initVal + } else if (cell.key === 'items') { + _items = cell.initVal + } else if (cell.key === 'display') { + display = cell.initVal + } else if (cell.key === 'resourceType') { + resourceType = cell.initVal + } else if (cell.key === 'fields') { + cFields = cell.initVal + } else if (cell.key === 'multiple') { + multiple = cell.initVal + } + }) - if (type === 'select' || type === 'link') { - _options.push('setAll') - } - - if (type === 'link') { // 鍏宠仈绫诲瀷銆佸鍔犲叧鑱斾笂绾х殑瀛楁鍚� - _options = [..._options, 'linkField'] - } + let _options = this.getOptions(type, resourceType, display) this.setState({ + display, + cFields, openType: type, items: _items, - resourceType: resourceType, + resourceType, formlist: formlist.map(form => { // 琛ㄥ崟涓哄垵濮嬪�煎瓧娈碉紝涓旀暟鎹被鍨嬪睘浜庢椂闂寸被鍨嬫椂锛岃缃垵濮嬪�间负涓嬫媺閫夋嫨锛屽苟閲嶇疆閫夋嫨椤� if (form.key === 'initval' && dateOptions.hasOwnProperty(type)) { @@ -139,20 +167,21 @@ } else if (form.key === 'match') { // 琛ㄥ崟涓哄尮閰嶅瓧娈垫椂锛屾牴鎹笉鍚岀殑绫诲瀷锛屾樉绀哄搴旂殑鍖归厤瑙勫垯 if (type === 'text') { form.options = matchReg.text - } else if (type === 'multiselect') { + } else if (type === 'multiselect' || (type === 'checkcard' && multiple === 'true')) { form.options = matchReg.multiselect - } else if (type === 'select' || type === 'link') { + } else if (type === 'select' || type === 'link' || type === 'checkcard') { 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') { + } else if (type === 'dateweek' || type === 'daterange' || type === 'range') { form.options = matchReg.daterange } - } else if (form.key === 'field' && type === 'text') { + } else if (form.key === 'field' && (type === 'text' || type === 'select')) { form.tooltip = this.state.textTooltip } else if (form.key === 'field' && type === 'group') { + form.tooltip = '鏌ヨ鏁版嵁鏃讹紙鑷畾涔夎剼鏈垨缁熻鏁版嵁婧愶級锛岀被鍨嬪瓧娈靛皢鐢ㄤ綔鏇挎崲鑴氭湰涓殑 @瀛楁@ 锛岀被鍨嬪瓧娈靛搴斿�间负 {"鏃�": "day", "鍛�": "week", "鏈�": "month", "瀛�": "quarter", "骞�": "year", "鑷畾涔�": "customized"}銆�' form.label = dict['model.form.type'] + dict['model.form.field'] } form.hidden = !_options.includes(form.key) @@ -174,32 +203,41 @@ } } + getOptions = (type, resourceType, display) => { + let _options = fromJS(searchTypeOptions[type]).toJS() // 閫夐」鍒楄〃 + + if (['multiselect', 'select', 'link'].includes(type) && resourceType === '0') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮 + _options.push('options') + } else if (['multiselect', 'select', 'link'].includes(type) && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙� + _options.push('dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database') + } else if (type === 'checkcard') { + if (display === 'picture') { + if (resourceType === '0') { // 鑷畾涔夎祫婧� + _options.push('options', 'picratio') + } else if (resourceType === '1') { // 鏁版嵁婧� + _options.push('dataSource', 'cardValField', 'urlField', 'orderBy', 'orderType', 'database', 'picratio') + } + } else { + if (resourceType === '0') { // 鑷畾涔夎祫婧� + _options.push('options', 'fields', 'backgroundColor') + } else if (resourceType === '1') { // 鏁版嵁婧� + _options.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'database', 'backgroundColor') + } + } + } + + return _options + } + /** * @description 鎼滅储鏉′欢绫诲瀷鍒囨崲 */ openTypeChange = (key, value) => { const { dict } = this.props - const { resourceType, items } = this.state + const { resourceType, items, display } = this.state if (key === 'type') { - let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow'] - - if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '0') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮 - _options = [..._options, 'resourceType', 'options', 'display'] - } else if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙� - _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database'] - } else if (value === 'group') { - _options = ['label', 'type', 'field', 'datefield', 'initval', 'items', 'ratio', 'blacklist', 'required', 'transfer', 'labelShow'] - } - - if (value === 'select' || value === 'link') { - _options.push('setAll') - } - - if (value === 'link') { - _options = [..._options, 'linkField'] - } - + let _options = this.getOptions(value, resourceType, display) let matchs = [] this.setState({ @@ -222,22 +260,23 @@ form.options = matchReg.text } else if (value === 'multiselect') { form.options = matchReg.multiselect - } else if (value === 'select' || value === 'link') { + } else if (value === 'select' || value === 'link' || value === 'checkcard') { 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') { + } else if (value === 'dateweek' || value === 'daterange' || value === 'range') { form.options = matchReg.daterange } matchs = form.options } else if (form.key === 'field') { form.tooltip = '' form.label = dict['model.form.field'] - if (value === 'text') { + if (value === 'text' || value === 'select') { form.tooltip = this.state.textTooltip } else if (value === 'group') { + form.tooltip = '鏌ヨ鏁版嵁鏃讹紙鑷畾涔夎剼鏈垨缁熻鏁版嵁婧愶級锛岀被鍨嬪瓧娈靛皢鐢ㄤ綔鏇挎崲鑴氭湰涓殑 @瀛楁@ 锛岀被鍨嬪瓧娈靛搴斿�间负 {"鏃�": "day", "鍛�": "week", "鏈�": "month", "瀛�": "quarter", "骞�": "year", "鑷畾涔�": "customized"}銆�' form.label = dict['model.form.type'] + dict['model.form.field'] } } @@ -251,6 +290,9 @@ if (this.props.form.getFieldValue('match') !== undefined) { this.props.form.setFieldsValue({match: matchs[0].value}) } + if (this.props.form.getFieldValue('multiple') !== undefined) { + this.props.form.setFieldsValue({multiple: 'false'}) + } }) } } @@ -259,26 +301,12 @@ * @description 鏁版嵁婧愮被鍨嬪垏鎹� */ onChange = (e, key) => { - const { openType } = this.state + const { openType, display, resourceType } = this.state let value = e.target.value if (key === 'resourceType') { - let _options = ['label', 'field', 'initval', 'type', 'match', 'resourceType', 'display', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow'] + let _options = this.getOptions(openType, value, display) - if (value === '0') { - _options = [..._options, 'options'] - } 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 => { @@ -286,7 +314,49 @@ return form }) }) + } else if (key === 'display') { + let _options = this.getOptions(openType, resourceType, value) + + this.setState({ + display: value, + formlist: this.state.formlist.map(form => { + form.hidden = !_options.includes(form.key) + return form + }) + }) + } else if (key === 'multiple') { + let matchs = [] + this.setState({ + formlist: this.state.formlist.map(form => { + if (form.key === 'match') { + if (value === 'true') { + form.options = matchReg.multiselect + } else { + form.options = matchReg.select + } + matchs = form.options + } + + return form + }) + }, () => { + if (this.props.form.getFieldValue('match') !== undefined) { + this.props.form.setFieldsValue({match: matchs[0].value}) + } + }) } + } + + changeField = (data) => { + this.setState({ + cFields: data, + formlist: this.state.formlist.map(form => { + if (form.key === 'fields') { + form.initVal = data + } + return form + }) + }) } checkChange = (values, key) => { @@ -324,7 +394,7 @@ const { getFieldDecorator } = this.props.form const fields = [] this.state.formlist.forEach((item, index) => { - if (item.hidden) return + if (item.hidden || item.forbid) return if (item.type === 'text') { // 鏂囨湰鎼滅储 let rules = [] @@ -374,14 +444,17 @@ </Tooltip> : item.label }> {getFieldDecorator(item.key, { - initialValue: item.initVal || 6, + initialValue: item.initVal, rules: [ { required: item.required, message: this.props.dict['form.required.input'] + item.label + '!' } ] - })(<InputNumber min={item.min} max={item.max} precision={0} onPressEnter={this.handleSubmit}/>)} + })(item.max ? + <InputNumber min={item.min} max={item.max} precision={0} onPressEnter={this.handleSubmit}/> : + <InputNumber onPressEnter={this.handleSubmit}/> + )} </Form.Item> </Col> ) @@ -447,8 +520,8 @@ ) } else if (item.type === 'textarea') { fields.push( - <Col span={20} offset={4} key={index}> - <Form.Item className="text-area"> + <Col span={24} key={index}> + <Form.Item className="text-area" label={item.label}> {getFieldDecorator(item.key, { initialValue: item.initVal, rules: [ @@ -462,9 +535,35 @@ </Col> ) } else if (item.type === 'options') { + if (openType !== 'checkcard') { + fields.push( + <Col span={24} key={index}> + <Form.Item label={item.label} className="text-area"> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })(<EditTable dict={this.props.dict} type={this.state.openType} data={item.initVal}/>)} + </Form.Item> + </Col> + ) + } else { + fields.push( + <Col span={24} key={index}> + <Form.Item label={item.label} className="text-area"> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })(<DataTable dict={this.props.dict} type={this.state.display} fields={this.state.cFields}/>)} + </Form.Item> + </Col> + ) + } + } else if (item.type === 'fields') { fields.push( - <Col span={20} offset={4} key={index}> - <EditTable data={item.initVal} type={this.state.openType} dict={this.props.dict} ref="editTable"/> + <Col span={24} key={index}> + <Form.Item label={item.label} className="text-area"> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })(<FieldsTable dict={this.props.dict} onChange={this.changeField}/>)} + </Form.Item> </Col> ) } else if (item.type === 'checkbox') { @@ -517,6 +616,16 @@ </Form.Item> </Col> ) + } else if (item.type === 'color') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label} className="color-form-item"> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })(<ColorSketch allowClear={true}/>)} + </Form.Item> + </Col> + ) } }) @@ -531,22 +640,63 @@ 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 + if (['multiselect', 'select', 'link', 'checkcard'].includes(values.type) && values.resourceType === '0') { + values.options = values.options || [] values.dataSource = '' let emptys = [] - if (values.type === 'multiselect' || values.type === 'select') { + if (['multiselect', 'select'].includes(values.type)) { emptys = values.options.filter(op => !(op.Value && op.Text)) - } else { + } else if (values.type === 'link') { 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') { + } else if (['multiselect', 'select', 'link', 'checkcard'].includes(values.type) && values.resourceType === '1') { values.options = [] } + if (values.type === 'range') { + let error = '' + if (values.maxValue <= values.minValue) { + error = '鏈�澶у�煎繀椤诲ぇ浜庢渶灏忓��' + } else if (values.step <= 0) { + error = '姝ラ暱蹇呴』澶т簬0' + } else { + let s = (values.maxValue - values.minValue) / values.step + if (s !== parseInt(s)) { + error = '姝ラ暱蹇呴』琚� (max - min) 鏁撮櫎' + } + } + + if (!error && values.initval) { + let vals = values.initval.split(',') + if (vals.length !== 2) { + error = '鍒濆鍊艰缃敊璇紒' + } else if (isNaN(parseFloat(vals[0])) || isNaN(parseFloat(vals[1]))) { + error = '鍒濆鍊艰缃敊璇紒' + } else { + let start = parseFloat(vals[0]) + let end = parseFloat(vals[1]) + let s = (values.maxValue - start) / values.step + let e = (values.maxValue - end) / values.step + if (start > end || start < values.minValue || end > values.maxValue) { + error = '鍒濆鍊艰缃敊璇紒' + } else if (s !== parseInt(s) || e !== parseInt(e)) { + error = '鍒濆鍊艰缃敊璇紒' + } + } + } + if (error) { + notification.warning({ + top: 92, + message: error, + duration: 5 + }) + return + } + } + if (isvalid) { ['linkField', 'valueField', 'valueText', 'orderBy'].forEach(item => { if (values[item]) { diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.scss b/src/templates/sharecomponent/searchcomponent/searchform/index.scss index cc9c99c..56d3f89 100644 --- a/src/templates/sharecomponent/searchcomponent/searchform/index.scss +++ b/src/templates/sharecomponent/searchcomponent/searchform/index.scss @@ -5,9 +5,12 @@ padding-bottom: 20px; } .ant-form-item.text-area { - margin-bottom: 0px; + // margin-bottom: 0px; .ant-form-item-control-wrapper { - width: 100%; + width: 84%; + } + .ant-form-item-label { + width: 16%; } .CodeMirror { height: 150px; @@ -29,4 +32,12 @@ } } } + .color-form-item { + .ant-form-item-control { + height: 40px; + .color-sketch-block { + margin-top: 7px; + } + } + } } \ No newline at end of file diff --git a/src/templates/sharecomponent/settingcalcomponent/index.jsx b/src/templates/sharecomponent/settingcalcomponent/index.jsx index 416e27d..9aa21fa 100644 --- a/src/templates/sharecomponent/settingcalcomponent/index.jsx +++ b/src/templates/sharecomponent/settingcalcomponent/index.jsx @@ -44,6 +44,17 @@ this.setState({loading: true}) this.verifyRef.submitDataSource().then(res => { + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig') + res.scripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + if (res.setting.dataresource) { + res.setting.dataresource = res.setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + } + }) + } this.setState({loading: false, visible: false}) this.props.updateConfig({...config, ...res}) diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx index 065406a..8e00256 100644 --- a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx +++ b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx @@ -71,10 +71,25 @@ UNSAFE_componentWillMount() { const { config } = this.props + let _setting = fromJS(config.setting).toJS() + let _scripts = fromJS(config.scripts).toJS() + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig') + _scripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + if (_setting.dataresource) { + _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`) + } + }) + } + this.setState({ - setting: fromJS(config.setting).toJS(), + setting: _setting, columns: fromJS(config.columns).toJS(), - scripts: fromJS(config.scripts).toJS() + scripts: _scripts }) } @@ -327,6 +342,7 @@ } render() { + const { config } = this.props const { columns, setting, scripts, colColumns, activeKey, loading } = this.state return ( @@ -350,7 +366,7 @@ wrappedComponentRef={(inst) => this.contrastForm = inst} /> <FieldsComponent - config={{...this.props.config, columns}} + config={{...config, columns}} type="fields" updatefield={this.updatefields} /> @@ -373,6 +389,7 @@ dict={this.props.dict} setting={setting} scripts={scripts} + urlFields={config.urlFields} defaultSql={this.state.defaultsql} searches={this.props.searches} scriptsChange={this.scriptsChange} diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx index da7e7b1..d2ace67 100644 --- a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx +++ b/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Input, Radio, Tooltip, Icon, notification } from 'antd' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, notification, InputNumber } from 'antd' import moment from 'moment' import Api from '@/api' @@ -184,6 +184,10 @@ { required: true, message: this.props.dict['form.required.input'] + '琛ㄥ悕!' + }, + { + max: 50, + message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!' } ] })(<Input placeholder={''} autoComplete="off" />)} @@ -308,6 +312,18 @@ </Radio.Group>)} </Form.Item> </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��"> + <Icon type="question-circle" /> + 楂樼骇鎼滅储 + </Tooltip> + }> + {getFieldDecorator('advanceWidth', { + initialValue: setting.advanceWidth || 1000 + })(<InputNumber min={10} max={3000} precision={0}/>)} + </Form.Item> + </Col> </Row> </Form> </div> diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx index da2b30d..fa3d829 100644 --- a/src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx +++ b/src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx @@ -30,6 +30,14 @@ if (setting.execute !== 'false') { _dataresource = setting.dataresource || '' } + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } _dataresource = _dataresource.replace(/@\$|\$@/ig, '') _customScript = _customScript.replace(/@\$|\$@/ig, '') diff --git a/src/templates/sharecomponent/settingcomponent/index.jsx b/src/templates/sharecomponent/settingcomponent/index.jsx index bad5664..dfd1ac0 100644 --- a/src/templates/sharecomponent/settingcomponent/index.jsx +++ b/src/templates/sharecomponent/settingcomponent/index.jsx @@ -59,7 +59,8 @@ this.setState({ loading: true }) - this.settingRef.handleConfirm().then(res => { + this.settingRef.handleConfirm().then(setting => { + let res = this.resetSetting(setting) this.setState({ visible: false, loading: false @@ -83,7 +84,8 @@ const { menu } = this.state this.settingRef.handleConfirm('func').then(setting => { - let _config = {...config, setting: setting} + let res = this.resetSetting(setting) + let _config = {...config, setting: res} let newLText = Utils.formatOptions(FuncUtils.getTableFunc(setting, menu, _config)) // 鍒涘缓瀛樺偍杩囩▼sql let DelText = Utils.formatOptions(FuncUtils.dropfunc(setting.innerFunc)) // 鍒犻櫎瀛樺偍杩囩▼sql @@ -103,7 +105,8 @@ const { menu } = this.state this.settingRef.handleConfirm('interface').then(setting => { - let _config = {...config, setting: setting} + let res = this.resetSetting(setting) + let _config = {...config, setting: res} let _menu = { type: config.Template === 'CommonTable' ? 'main' : 'subtable', MenuID: menu.MenuID, @@ -115,6 +118,30 @@ }) } + resetSetting = (s) => { + let setting = fromJS(s).toJS() + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig') + setting.scripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + setting.preScripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + setting.cbScripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + if (setting.dataresource) { + setting.dataresource = setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + } + }) + } + + return setting + } + shouldComponentUpdate (nextProps, nextState) { return !is(fromJS(this.state), fromJS(nextState)) } diff --git a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx index 27b3f4d..4c4b17a 100644 --- a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx +++ b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Input, Radio, Tooltip, Icon, notification, Select } from 'antd' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, notification, Select, InputNumber } from 'antd' import moment from 'moment' import Api from '@/api' @@ -216,6 +216,10 @@ required: true, message: dict['form.required.input'] + '琛ㄥ悕!' }, + { + max: 50, + message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!' + } ] })(<Input placeholder={''} autoComplete="off" />)} </Form.Item> @@ -409,7 +413,7 @@ </Col> : null} {interType === 'system' || (interType === 'custom' && requestMode === 'system') ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}> <Form.Item help={'鏁版嵁ID锛�' + menu.MenuID} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } label={ - <Tooltip placement="topLeft" title={'浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\''}> + <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''锛涙煡璇㈡浛鎹㈢ $select@ -> /* 鎴� ''銆� @select$ -> */ 鎴� ''锛涚粺璁℃浛鎹㈢ $sum@ -> /* 鎴� ''銆� @sum$ -> */ 鎴� ''銆俙}> <Icon type="question-circle" /> 鏁版嵁婧� </Tooltip> @@ -612,6 +616,18 @@ </Col> <Col span={12}> <Form.Item label={ + <Tooltip placement="topLeft" title="楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��"> + <Icon type="question-circle" /> + 楂樼骇鎼滅储 + </Tooltip> + }> + {getFieldDecorator('advanceWidth', { + initialValue: setting.advanceWidth || 1000 + })(<InputNumber min={10} max={3000} precision={0}/>)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ <Tooltip placement="topLeft" title="鍙屽嚮琛ㄦ牸涓锛岃Е鍙戠殑鎸夐挳銆�"> <Icon type="question-circle" /> 鍙屽嚮浜嬩欢 diff --git a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.scss b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.scss index a6d2df7..f404309 100644 --- a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.scss +++ b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.scss @@ -17,6 +17,9 @@ color: #c49f47; margin-right: 3px; } + .ant-input-number { + width: 100%; + } } } \ No newline at end of file diff --git a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx index a66ce20..f68c91e 100644 --- a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx +++ b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx @@ -97,6 +97,24 @@ }) } + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig') + _scripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + _preScripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + _cbScripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + if (_setting.dataresource) { + _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`) + } + }) + } + this.setState({ setting: _setting, search: _search, @@ -129,32 +147,26 @@ value: search.initval, required: search.required === 'true' } + if (item.type === 'group') { - let copy = fromJS(item).toJS() - copy.key = search.datefield + item.key = search.datefield + item.type = 'daterange' + item.match = 'between' + item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') - item.value = search.initval && search.initval[0] ? search.initval[0] : '@$@' - item.match = '=' - - copy.type = 'daterange' - copy.match = 'between' - copy.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')] - - if (search.transfer === 'true') { - newsearches.push(item) - } - newsearches.push(copy) + newsearches.push(item) return } else if (item.type === 'date') { item.value = moment().format('YYYY-MM-DD') } else if (item.type === 'datemonth') { item.value = moment().format('YYYY-MM') } else if (item.type === 'dateweek') { - item.value = [moment().startOf('week').format('YYYY-MM-DD'), moment().endOf('week').format('YYYY-MM-DD')] + item.value = moment().format('YYYY-MM-DD') } else if (item.type === 'daterange') { - item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')] - } else if (item.type === 'multiselect') { - item.value = ['@$@'] + item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') + } else if (item.type === 'multiselect' || (item.type === 'checkcard' && search.multiple === 'true')) { + item.type = 'multi' + item.value = '@$@' } else { item.value = '@$@' } @@ -463,6 +475,7 @@ setting={setting} scripts={scripts} defaultSql={defaultSql} + urlFields={config.urlFields} searches={this.props.search} scriptsChange={this.scriptsChange} scriptsUpdate={this.scriptsUpdate} @@ -480,6 +493,7 @@ setting={setting} scripts={preScripts} regoptions={regoptions} + urlFields={config.urlFields} searches={this.props.search} scriptsUpdate={this.preScriptsUpdate} wrappedComponentRef={(inst) => this.preScriptsForm = inst} diff --git a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx index 1096b9c..f27e974 100644 --- a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx +++ b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx @@ -20,6 +20,7 @@ setting: PropTypes.object, // 璁剧疆 scripts: PropTypes.array, // 鑷畾涔夎剼鏈垪琛� searches: PropTypes.array, // 鎼滅储鏉′欢 + urlFields: PropTypes.any, // url鍙橀噺 regoptions: PropTypes.any, // 姝e垯鏇挎崲 scriptsChange: PropTypes.func, // 鑷畾涔夎剼鏈垏鎹㈡椂楠岃瘉 scriptsUpdate: PropTypes.func // 琛ㄥ崟 @@ -100,7 +101,7 @@ } UNSAFE_componentWillMount() { - const { searches, scripts } = this.props + const { searches, scripts, urlFields } = this.props let _usefulFields = [] let scriptsColumns = fromJS(this.state.scriptsColumns).toJS() @@ -109,9 +110,7 @@ searches.forEach(item => { if (!item.field) return if (item.type === 'group') { - if (item.transfer === 'true') { - _usefulFields.push(item.field) - } + _usefulFields.push(item.field) _usefulFields.push(item.datefield) _usefulFields.push(item.datefield + '1') } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { @@ -123,6 +122,11 @@ _usefulFields.push(item.field) } }) + + if (urlFields) { + _usefulFields.push(...urlFields) + } + _usefulFields = _usefulFields.join(', ') scriptsColumns = scriptsColumns.filter(item => { if (item.dataIndex === 'sql') { diff --git a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx index 2801901..003b030 100644 --- a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx +++ b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx @@ -26,13 +26,22 @@ if (setting.default === 'false') { _dataresource = '' } + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } - if (_dataresource) { - _dataresource = _dataresource.replace(/@\$|\$@/ig, '') - } - if (_customScript) { - _customScript = _customScript.replace(/@\$|\$@/ig, '') - } + _dataresource = _dataresource.replace(/@\$|\$@/ig, '') + _customScript = _customScript.replace(/@\$|\$@/ig, '') + _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '') + _customScript = _customScript.replace(/@select\$|\$select@/ig, '') + _dataresource = _dataresource.replace(/@sum\$|\$sum@/ig, '') + _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '') + // 澶栬仈鏁版嵁搴撴浛鎹� if (window.GLOB.externalDatabase !== null) { _dataresource = _dataresource.replace(/@db@/ig, window.GLOB.externalDatabase) @@ -138,6 +147,13 @@ ` } + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } + _customScript = _customScript.replace(/@\$|\$@/ig, '') _customScript = _customScript.replace(/@userName@|@fullName@|@login_city@/ig, `''`) // 澶栬仈鏁版嵁搴撴浛鎹� diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx index e52ef08..0ff4bcf 100644 --- a/src/templates/sharecomponent/tablecomponent/index.jsx +++ b/src/templates/sharecomponent/tablecomponent/index.jsx @@ -137,6 +137,7 @@ datatype: _type, decimal: _decimal, length: _length, + $datatype: item.FieldType.toLowerCase() } }) } diff --git a/src/templates/sharecomponent/treesettingcomponent/index.jsx b/src/templates/sharecomponent/treesettingcomponent/index.jsx index 359d52f..db18c0b 100644 --- a/src/templates/sharecomponent/treesettingcomponent/index.jsx +++ b/src/templates/sharecomponent/treesettingcomponent/index.jsx @@ -45,6 +45,17 @@ loading: true }) this.settingRef.handleConfirm().then(res => { + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig') + res.scripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + if (res.dataresource) { + res.dataresource = res.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + } + }) + } this.setState({ visible: false, loading: false diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx index 4d1c6f3..caadc2b 100644 --- a/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx +++ b/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx @@ -201,8 +201,8 @@ message: dict['form.required.input'] + '琛ㄥ悕!' }, { - max: formRule.input.max, - message: formRule.input.message + max: 50, + message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!' } ] })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit}/>)} diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx index 056813e..3f3d3a4 100644 --- a/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx +++ b/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx @@ -35,6 +35,18 @@ let _setting = fromJS(config.setting).toJS() let _scripts = _setting.scripts || [] + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig') + _scripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + if (_setting.dataresource) { + _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`) + } + }) + } + this.setState({ setting: _setting, scripts: _scripts diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx index 721c7c9..332934c 100644 --- a/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx +++ b/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx @@ -26,6 +26,14 @@ if (setting.default === 'false') { _dataresource = '' } + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } _dataresource = _dataresource.replace(/@\$|\$@/ig, '') _customScript = _customScript.replace(/@\$|\$@/ig, '') diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx index d3bda26..34bf35d 100644 --- a/src/templates/subtableconfig/index.jsx +++ b/src/templates/subtableconfig/index.jsx @@ -26,6 +26,7 @@ const { Panel } = Collapse const { confirm } = Modal +const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent')) const SettingComponent = asyncComponent(() => import('@/templates/sharecomponent/settingcomponent')) const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) @@ -1008,6 +1009,7 @@ </div> } bordered={false} extra={ <div> + <ReplaceField type="table" config={config} updateConfig={this.updateconfig}/> <EditComponent dict={this.state.dict} options={['search', 'action', 'columns']} config={config} MenuID={config.uuid} thawButtons={this.state.thawButtons} refresh={this.updateConfig}/> <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['model.save']}</Button> diff --git a/src/templates/subtableconfig/source.jsx b/src/templates/subtableconfig/source.jsx index 4c69050..4ccd3bf 100644 --- a/src/templates/subtableconfig/source.jsx +++ b/src/templates/subtableconfig/source.jsx @@ -206,6 +206,12 @@ }, { type: 'search', + label: '閫夐」鍗�', + subType: 'checkcard', + url: '' + }, + { + type: 'search', label: CommonDict['model.form.dateday'], subType: 'date', url: '' @@ -329,6 +335,12 @@ label: CommonDict['model.form.colspan'], subType: 'colspan', url: '' + }, + { + type: 'columns', + label: '搴忓彿', + subType: 'index', + url: '' } ] } diff --git a/src/templates/treepageconfig/index.jsx b/src/templates/treepageconfig/index.jsx index 8a4b4dd..d1aa9bd 100644 --- a/src/templates/treepageconfig/index.jsx +++ b/src/templates/treepageconfig/index.jsx @@ -501,6 +501,7 @@ } let submenu = menu.fstMenuList.filter(item => item.MenuID === config.fstMenuId)[0] + let _Menu = { ...menu, LongParam: config, @@ -509,7 +510,7 @@ MenuNo: config.MenuNo, ParentId: config.ParentId, fstMenuId: config.fstMenuId, - supMenuList: submenu ? submenu.options : [] + supMenuList: submenu ? submenu.children : [] } _Menu.activeKey = activeKey // 淇濆瓨褰撳墠鎵撳紑椤电 diff --git a/src/templates/zshare/basetransferform/index.jsx b/src/templates/zshare/basetransferform/index.jsx index 8dd7462..c3e3233 100644 --- a/src/templates/zshare/basetransferform/index.jsx +++ b/src/templates/zshare/basetransferform/index.jsx @@ -6,7 +6,8 @@ class TransferForm extends Component { static propTypes = { - menulist: PropTypes.array + menulist: PropTypes.array, + onChange: PropTypes.func } state = { @@ -16,6 +17,7 @@ handleChange = (nextTargetKeys, direction, moveKeys) => { this.setState({ targetKeys: nextTargetKeys }) + this.props.onChange(nextTargetKeys) } handleSelectChange = (sourceSelectedKeys, targetSelectedKeys) => { diff --git a/src/templates/zshare/customscript/index.jsx b/src/templates/zshare/customscript/index.jsx index a69270f..e2db585 100644 --- a/src/templates/zshare/customscript/index.jsx +++ b/src/templates/zshare/customscript/index.jsx @@ -19,6 +19,7 @@ setting: PropTypes.object, // 璁剧疆 scripts: PropTypes.array, // 鑷畾涔夎剼鏈垪琛� searches: PropTypes.array, // 鎼滅储鏉′欢 + urlFields: PropTypes.any, // url鍙橀噺 defaultSql: PropTypes.string, // 榛樿sql scriptsChange: PropTypes.func, // 鑷畾涔夎剼鏈垏鎹㈡椂楠岃瘉 scriptsUpdate: PropTypes.func // 琛ㄥ崟 @@ -87,15 +88,13 @@ } UNSAFE_componentWillMount() { - const { searches, scripts } = this.props + const { searches, scripts, urlFields } = this.props let _usefulFields = [] searches.forEach(item => { if (!item.field) return if (item.type === 'group') { - if (item.transfer === 'true') { - _usefulFields.push(item.field) - } + _usefulFields.push(item.field) _usefulFields.push(item.datefield) _usefulFields.push(item.datefield + '1') } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { @@ -108,6 +107,10 @@ } }) + if (urlFields) { + _usefulFields.push(...urlFields) + } + this.setState({ usefulFields: _usefulFields.join(', '), scripts: fromJS(scripts).toJS() diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx index 9f96d5f..5e1d00b 100644 --- a/src/templates/zshare/editTable/index.jsx +++ b/src/templates/zshare/editTable/index.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' import { DndProvider, DragSource, DropTarget } from 'react-dnd' -import { Table, Input, InputNumber, Popconfirm, Form, Icon, Select, Radio, Cascader, notification, message, Modal } from 'antd' +import { Table, Input, InputNumber, Popconfirm, Form, Icon, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd' import Utils from '@/utils/utils.js' import ColorSketch from '@/mob/colorsketch' @@ -15,6 +15,7 @@ let eTDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS const EditableContext = React.createContext() let dragingIndex = -1 +const { Paragraph } = Typography class BodyRow extends React.Component { render() { @@ -170,6 +171,7 @@ UNSAFE_componentWillMount () { const { data, actions } = this.props let columns = fromJS(this.props.columns).toJS() + let operation = null if (actions && (actions.includes('edit') || actions.includes('copy') || actions.includes('del'))) { let _operation = null @@ -180,7 +182,7 @@ return item.dataIndex !== 'operation' }) - let operation = { + operation = { title: (<div> {eTDict['model.operation']} {actions.includes('copy') ? ( @@ -232,7 +234,7 @@ this.setState({ data: data || [], - oricolumns: fromJS(this.props.columns).toJS(), + operation, columns }) } @@ -240,19 +242,26 @@ UNSAFE_componentWillReceiveProps (nextProps) { if (!is(fromJS(this.state.data), fromJS(nextProps.data))) { this.setState({data: nextProps.data, editingKey: ''}) - } else if (!is(fromJS(this.state.oricolumns), fromJS(nextProps.columns))) { - let cols = {} - nextProps.columns.forEach(col => {cols[col.dataIndex] = col}) - - this.setState({ - oricolumns: fromJS(nextProps.columns).toJS(), - columns: this.state.columns.map(col => { - if (cols[col.dataIndex]) { - return cols[col.dataIndex] - } - return col + } else if (!is(fromJS(this.props.columns), fromJS(nextProps.columns))) { + if (nextProps.columns.length === this.props.columns.length) { + let cols = {} + nextProps.columns.forEach(col => {cols[col.dataIndex] = col}) + + this.setState({ + columns: this.state.columns.map(col => { + if (cols[col.dataIndex]) { + return cols[col.dataIndex] + } + return col + }) }) - }) + } else { + let columns = fromJS(nextProps.columns).toJS() + if (this.state.operation) { + columns.push(this.state.operation) + } + this.setState({columns}) + } } } @@ -353,7 +362,7 @@ if (!unique) return - data.unshift(cell) + data.push(cell) }) this.setState({ data, editingKey: '', visible: false }, () => { @@ -493,7 +502,10 @@ moveprops.moveRow = this.moveRow } - const columns = this.state.columns.map(col => { + let columns = this.state.columns.map(col => { + if (col.copy) { + col.render = (text) => (<Paragraph copyable>{text}</Paragraph>) + } if (!col.editable) return col return { ...col, @@ -513,6 +525,19 @@ } }) + columns.unshift({ + title: '搴忓彿', + dataIndex: '$index', + className: 'mk-index', + width: '60px', + }) + + const data = this.state.data.map((item, index) => { + item.$index = index + 1 + + return item + }) + return ( <EditableContext.Provider value={this.props.form}> <div className="modal-edit-table"> @@ -521,7 +546,7 @@ bordered rowKey="uuid" components={components} - dataSource={this.state.data} + dataSource={data} columns={columns} rowClassName="editable-row" pagination={false} diff --git a/src/templates/zshare/editTable/index.scss b/src/templates/zshare/editTable/index.scss index 5943f34..8713c7f 100644 --- a/src/templates/zshare/editTable/index.scss +++ b/src/templates/zshare/editTable/index.scss @@ -20,6 +20,10 @@ padding: 0px; } } + .mk-index { + text-align: center; + white-space: nowrap; + } thead tr th:last-child { text-align: center; diff --git a/src/templates/zshare/editcomponent/index.jsx b/src/templates/zshare/editcomponent/index.jsx index 80f2599..6fd72b8 100644 --- a/src/templates/zshare/editcomponent/index.jsx +++ b/src/templates/zshare/editcomponent/index.jsx @@ -1,7 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { fromJS } from 'immutable' -import { Menu, Dropdown, Icon, Modal, Spin, notification } from 'antd' +import { Modal, Spin, notification, Button } from 'antd' import Api from '@/api' import Utils from '@/utils/utils.js' @@ -25,14 +25,7 @@ thawVisible: false, thawbtnlist: null, pasteVisible: false, - } - - handleMenuClick = e => { - if (e.key === 'thaw') { - this.handleThaw() - } else if (e.key === 'paste') { - this.setState({pasteVisible: true}) - } + targetKeys: [] } /** @@ -42,7 +35,8 @@ const { MenuID } = this.props this.setState({ - thawVisible: true + thawVisible: true, + targetKeys: [] }) Api.getSystemConfig({ @@ -92,32 +86,31 @@ */ thawBtnSubmit = () => { const { thawButtons } = this.props - const { thawbtnlist, dict } = this.state + const { thawbtnlist, dict, targetKeys } = this.state let config = fromJS(this.props.config).toJS() - // 涓夌骇鑿滃崟瑙i櫎鍐荤粨 - if (this.refs.trawmenu.state.targetKeys.length === 0) { + if (targetKeys.length === 0) { notification.warning({ top: 92, message: dict['form.required.select'] + dict['header.form.thawbutton'], duration: 5 }) } else { - thawbtnlist.forEach(item => { - if (this.refs.trawmenu.state.targetKeys.includes(item.key)) { + if (targetKeys.includes(item.key)) { config.action.push(item.btnParam) } }) this.props.refresh({ type: 'thaw', - thawButtons: [...thawButtons, ...this.refs.trawmenu.state.targetKeys], + thawButtons: [...thawButtons, ...targetKeys], config: config }) this.setState({ - thawVisible: false + thawVisible: false, + targetKeys: [] }) } } @@ -141,26 +134,10 @@ config: _config }) }) - } else if (options.includes('search') && (res.copyType === 'search' || res.copyType === 'form')) { + } else if (options.includes('search') && res.copyType === 'search') { res.uuid = Utils.getuuid() _config.search = _config.search.filter(item => !item.origin) let keys = _config.search.map(item => item.field.toLowerCase()) - - // search锛� text select multiselect link date dateweek datemonth daterange group - // form锛� text number select multiselect link switch checkbox radio checkcard - // fileupload date datemonth datetime textarea hint color funcvar - if (res.copyType === 'form') { - if (['number', 'switch', 'textarea', 'checkcard', 'fileupload', 'hint', 'color', 'funcvar'].includes(res.type)) { - res.type = 'text' - } else if (res.type === 'radio') { - res.type = 'select' - } else if (res.type === 'checkbox') { - res.type = 'multiselect' - } else if (res.type === 'datetime') { - res.type = 'date' - } - } - res.copyType = 'search' _config.search.push(res) @@ -206,20 +183,10 @@ config: _config }) }) - } else if (options.includes('form') && (res.copyType === 'form' || res.copyType === 'search')) { + } else if (options.includes('form') && res.copyType === 'form') { let fields = [] let labels = [] res.uuid = Utils.getuuid() - - // search锛� text select multiselect link date dateweek datemonth daterange group - // form锛� text number select multiselect link switch checkbox radio checkcard - // fileupload date datemonth datetime textarea hint color funcvar - if (res.copyType === 'search') { - if (res.type === 'dateweek' || res.type === 'daterange' || res.type === 'group') { - res.type = 'date' - } - } - res.copyType = 'form' _config.fields.forEach(item => { item.field && fields.push(item.field.toLowerCase()) @@ -262,33 +229,32 @@ }) } + handleMenuClick = e => { + if (e.key === 'thaw') { + this.handleThaw() + } else if (e.key === 'paste') { + this.setState({pasteVisible: true}) + } + } + render() { const { MenuID } = this.props const { dict } = this.state - const menu = ( - <Menu onClick={this.handleMenuClick}> - {MenuID ? <Menu.Item key="thaw"><Icon type="unlock" />{dict['header.form.thawbutton']}</Menu.Item> : null} - <Menu.Item key="paste"><Icon type="snippets" />{dict['header.form.paste']}</Menu.Item> - </Menu> - ) return ( <div style={{display: 'inline-block'}}> - <Dropdown overlay={menu} overlayClassName="edit-component-box"> - <span style={{color: '#1890ff', display: 'inline-block', height: 25}}> - {dict['model.edit']} <Icon type="down" /> - </span> - </Dropdown> + {MenuID ? <Button className="mk-border-green" onClick={this.handleThaw} icon="unlock">{dict['header.form.thawbutton']}</Button> : null} + <Button style={{borderColor: '#40a9ff', color: '#40a9ff'}} onClick={() => this.setState({pasteVisible: true})} icon="snippets">{dict['header.form.paste']}</Button> {/* 瑙e喕鎸夐挳妯℃�佹 */} <Modal title={dict['header.form.thawbutton']} visible={this.state.thawVisible} onOk={this.thawBtnSubmit} - onCancel={() => {this.setState({thawVisible: false, thawbtnlist: null})}} + onCancel={() => {this.setState({thawVisible: false, thawbtnlist: null, targetKeys: []})}} destroyOnClose > {!this.state.thawbtnlist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />} - {this.state.thawbtnlist && <TransferForm ref="trawmenu" menulist={this.state.thawbtnlist}/>} + {this.state.thawbtnlist && <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawbtnlist}/>} </Modal> {/* 鎸夐挳閰嶇疆淇℃伅绮樿创澶嶅埗 */} <Modal diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx index 759648c..2b1c010 100644 --- a/src/templates/zshare/formconfig.jsx +++ b/src/templates/zshare/formconfig.jsx @@ -288,6 +288,7 @@ */ export function getSearchForm (card, linkableFields) { let roleList = sessionStorage.getItem('sysRoles') + let appType = sessionStorage.getItem('appType') if (roleList) { try { roleList = JSON.parse(roleList) @@ -296,6 +297,71 @@ } } else { roleList = [] + } + + let typeOptions = [] + + if (appType === 'mob') { + typeOptions = [{ + value: 'range', + text: '鏁板�硷紙鍖洪棿锛�' + }, { + value: 'checkcard', + text: '閫夐」鍗�' + }, { + value: 'date', + text: Formdict['model.form.dateday'] + }, { + value: 'datemonth', + text: Formdict['model.form.datemonth'] + }, { + value: 'daterange', + text: Formdict['model.form.daterange'] + }] + } else { + typeOptions = [{ + value: 'text', + text: Formdict['model.form.text'] + }, { + value: 'select', + text: Formdict['model.form.select'] + }, { + value: 'multiselect', + text: Formdict['model.form.multiselect'] + }, { + value: 'link', + text: Formdict['model.form.link'] + }, { + value: 'checkcard', + text: '閫夐」鍗�' + }, { + value: 'date', + text: Formdict['model.form.dateday'] + }, { + value: 'dateweek', + text: Formdict['model.form.dateweek'] + }, { + value: 'datemonth', + text: Formdict['model.form.datemonth'] + }, { + value: 'daterange', + text: Formdict['model.form.daterange'] + }, { + value: 'group', + text: Formdict['model.form.dategroup'] + }] + } + + if (card.focus) { + if (['text', 'multiselect'].includes(card.type)) { + card.match = 'like' + } else if (['select', 'link', 'checkcard'].includes(card.type)) { + card.match = '=' + } else if (card.type === 'date') { + card.match = '>=' + } else if (['datemonth', 'dateweek', 'daterange', 'range'].includes(card.type)) { + card.match = 'between' + } } return [ @@ -322,34 +388,7 @@ label: Formdict['model.form.type'], initVal: card.type, required: true, - options: [{ - value: 'text', - text: Formdict['model.form.text'] - }, { - value: 'select', - text: Formdict['model.form.select'] - }, { - value: 'multiselect', - text: Formdict['model.form.multiselect'] - }, { - value: 'link', - text: Formdict['model.form.link'] - }, { - value: 'date', - text: Formdict['model.form.dateday'] - }, { - value: 'dateweek', - text: Formdict['model.form.dateweek'] - }, { - value: 'datemonth', - text: Formdict['model.form.datemonth'] - }, { - value: 'daterange', - text: Formdict['model.form.daterange'] - }, { - value: 'group', - text: Formdict['model.form.dategroup'] - }] + options: typeOptions }, { type: 'text', @@ -363,7 +402,7 @@ type: 'text', key: 'initval', label: Formdict['header.form.initval'], - tooltip: '绫诲瀷涓轰笅鎷夎彍鍗曟椂锛屽垵濮嬪�煎簲涓烘暟鎹殑Value鍊硷紙浣跨敤鏁版嵁婧愭椂锛屽簲涓恒�婂�悸峰瓧娈点�嬬殑鍊硷級', + tooltip: '绫诲瀷涓轰笅鎷夎彍鍗曟椂锛屽垵濮嬪�煎簲涓烘暟鎹殑Value鍊硷紙浣跨敤鏁版嵁婧愭椂锛屽簲涓恒�婂�悸峰瓧娈点�嬬殑鍊硷級;绫诲瀷涓烘暟鍊硷紙鍖洪棿锛夋椂锛屽垵濮嬪�间娇鐢ㄩ�楀彿鎷兼帴锛屼緥濡� 3,10', initVal: card.initval, required: false }, @@ -395,6 +434,75 @@ }] }, { + type: 'radio', + key: 'display', + label: '鏄剧ず', + initVal: card.display || 'text', + required: true, + options: [{ + value: 'text', + text: '鏂囨湰' + }, { + value: 'picture', + text: '鍥剧墖' + }] + }, + { + type: 'number', + key: 'width', + min: 1, + max: 24, + precision: 0, + label: '鍏冪礌瀹藉害', + initVal: card.width || 4, + tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��', + required: true + }, + { + type: 'text', + key: 'cardValField', + label: Formdict['header.form.valueField'], + initVal: card.cardValField || 'Value', + required: true, + readonly: false + }, + { + type: 'text', + key: 'urlField', + label: '鍦板潃瀛楁', + initVal: card.urlField || '', + required: true, + readonly: false + }, + { + type: 'radio', + key: 'picratio', + label: '鍥剧墖姣斾緥', + initVal: card.picratio || '1:1', + required: true, + options: [{ + value: '1:1', + text: '1:1' + }, { + value: '3:2', + text: '3:2' + }, { + value: '4:3', + text: '4:3' + }, { + value: '16:9', + text: '16:9' + }] + }, + { + type: 'fields', + key: 'fields', + label: '瀛楁闆�', + initVal: card.fields || [], + required: true, + readonly: false + }, + { type: 'textarea', key: 'dataSource', label: Formdict['header.form.datasource'], @@ -405,7 +513,7 @@ { type: 'options', key: 'options', - label: '', + label: '閫夐」', initVal: card.options || [], required: true, readonly: false @@ -506,20 +614,6 @@ text: '>=' }] }, - // { - // type: 'select', - // key: 'display', - // label: Formdict['header.form.display'], - // initVal: card.display || 'dropdown', - // required: true, - // options: [{ - // value: 'dropdown', - // text: Formdict['header.form.dropdown'] - // // }, { - // // value: 'button', - // // text: Formdict['header.form.button'] - // }] - // }, { type: 'radio', key: 'database', @@ -540,8 +634,23 @@ max: 24, label: Formdict['header.form.ratio'], tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��', - initVal: card.ratio, + initVal: card.ratio || 6, + forbid: appType === 'mob', required: false + }, + { + type: 'radio', + key: 'multiple', + label: '鍙閫�', + initVal: card.multiple || 'false', + required: true, + options: [{ + value: 'true', + text: '鏄�' + }, { + value: 'false', + text: '鍚�' + }] }, { type: 'radio', @@ -569,19 +678,44 @@ text: Formdict['model.false'] }] }, + // { + // type: 'radio', + // key: 'transfer', + // label: '浼犻��', + // initVal: card.transfer || 'false', + // tooltip: '鏁版嵁鏌ヨ鏃讹紝绫诲瀷瀛楁鏄惁浣滀负鍙傛暟浼犻�掞紝绫诲瀷瀛楁瀵瑰簲鍊间负 {"鏃�": "day", "鍛�": "week", "鏈�": "month", "瀛�": "quarter", "骞�": "year", "鑷畾涔�": "customized"}銆�', + // options: [{ + // value: 'true', + // text: Formdict['model.true'] + // }, { + // value: 'false', + // text: Formdict['model.false'] + // }] + // }, { - type: 'radio', - key: 'transfer', - label: '浼犻��', - initVal: card.transfer || 'false', - tooltip: '鏁版嵁鏌ヨ鏃讹紝绫诲瀷瀛楁鏄惁浣滀负鍙傛暟浼犻�掞紝绫诲瀷瀛楁瀵瑰簲鍊间负 {"鏃�": "day", "鍛�": "week", "鏈�": "month", "瀛�": "quarter", "骞�": "year", "鑷畾涔�": "customized"}銆�', - options: [{ - value: 'true', - text: Formdict['model.true'] - }, { - value: 'false', - text: Formdict['model.false'] - }] + type: 'number', + key: 'maxValue', + label: '鏈�澶у��', + initVal: card.maxValue, + forbid: appType !== 'mob', + required: true + }, + { + type: 'number', + key: 'minValue', + label: '鏈�灏忓��', + initVal: card.minValue, + forbid: appType !== 'mob', + required: true + }, + { + type: 'number', + key: 'step', + label: '姝ラ暱', + initVal: card.step, + tooltip: '姝ラ暱鍙栧�煎繀椤诲ぇ浜� 0锛屽苟涓斿彲琚� (max - min) 鏁撮櫎', + forbid: appType !== 'mob', + required: true }, { type: 'radio', @@ -595,6 +729,50 @@ value: 'false', text: Formdict['model.false'] }] + }, + { + type: 'radio', + key: 'advanced', + label: '楂樼骇鎼滅储', + initVal: card.advanced || 'false', + forbid: appType === 'mob', + options: [{ + value: 'true', + text: Formdict['model.true'] + }, { + value: 'false', + text: Formdict['model.false'] + }] + }, + { + type: 'radio', + key: 'inputType', + label: '杈撳叆鏍峰紡', + initVal: card.inputType || 'input', + required: false, + forbid: appType === null, + options: [{ + value: 'input', + text: '杈撳叆妗�' + }, { + value: 'search', + text: '鎼滅储妗�' + }] + }, + { + type: 'color', + key: 'backgroundColor', + label: '鑳屾櫙鑹�', + initVal: card.backgroundColor || '', + tooltip: '璁剧疆鑳屾櫙鑹插悗锛岄�変腑鏁堟灉鐢辫儗鏅鑹叉帶鍒躲��', + required: false + }, + { + type: 'color', + key: 'borderColor', + label: '杈规棰滆壊', + initVal: card.borderColor || '', + required: false }, { type: 'multiselect', @@ -616,6 +794,8 @@ * @param {*} type 鎸夐挳绫诲瀷锛岀敤浜庡尯鍒嗗彲閫夌殑鎵撳紑鏂瑰紡 */ export function getActionForm (card, functip, config, usefulFields, type, menulist = [], printTemps = []) { + let columns = (config.columns || []).filter(col => col.field) + let opentypes = [ { value: 'pop', @@ -1126,6 +1306,23 @@ value: 'false', text: '闈炲繀濉�' }] + }, + { + type: 'select', + key: 'controlField', + label: '鎺у埗瀛楁', + tooltip: '绂佺敤鎺у埗瀛楁锛屽彲鏍规嵁鏁版嵁鎺у埗鎸夐挳鏄惁绂佺敤銆�', + initVal: card.controlField || '', + required: false, + options: [{label: '鏃�', field: ''}, ...columns] + }, + { + type: 'text', + key: 'controlVal', + label: '鎺у埗鍊�', + tooltip: '褰撻�夋嫨鎺у埗瀛楁锛屼笖瀛楁鍊间笌鎺у埗鍊肩浉绛夋椂锛屾寜閽細绂佺敤锛屽涓�肩敤閫楀彿鍒嗛殧銆�', + initVal: card.controlVal || '', + required: false } ] } @@ -1188,6 +1385,9 @@ }, { value: 'textarea', text: Formdict['model.form.textarea'] + }, { + value: 'index', + text: '搴忓彿' }] }, { @@ -1906,6 +2106,7 @@ * @param {*} subtable // 鏄惁涓哄瓙琛ㄨ〃鍗� */ export function getModalForm (card, inputfields = [], tabfields = [], linkableFields, linksupFields, subtable = false) { + let appType = sessionStorage.getItem('appType') let roleList = sessionStorage.getItem('sysRoles') if (roleList) { try { @@ -1924,10 +2125,118 @@ roleList = [] } - let _openType = [] + let _openType = [{ + value: 'text', + text: Formdict['model.form.text'] + }, { + value: 'number', + text: Formdict['model.form.number'] + }, { + value: 'select', + text: Formdict['model.form.select'] + }, { + value: 'multiselect', + text: Formdict['model.form.multiselect'] + }, { + value: 'link', + text: Formdict['model.form.link'] + }, { + value: 'switch', + text: '寮�鍏�' + }, { + value: 'checkbox', + text: '澶氶�夋' + }, { + value: 'radio', + text: '鍗曢�夋' + }, { + value: 'checkcard', + text: '閫夐」鍗�' + }, { + value: 'fileupload', + text: Formdict['header.form.fileupload'] + }, { + value: 'date', + text: Formdict['model.form.dateday'] + }, { + value: 'datemonth', + text: Formdict['model.form.datemonth'] + }, { + value: 'datetime', + text: Formdict['model.form.datetime'] + }, { + value: 'textarea', + text: Formdict['model.form.textarea'] + }, { + value: 'color', + text: Formdict['model.form.color'] + }, { + value: 'brafteditor', + text: '瀵屾枃鏈�' + }, { + value: 'funcvar', + text: Formdict['header.form.funcvar'] + }, { + value: 'hint', + text: '鎻愮ず' + }, { + value: 'split', + text: '鍒嗛殧绾�' + }] + let _fieldlength = 50 - if (subtable) { + if (appType === 'mob') { + _openType = [{ + value: 'text', + text: Formdict['model.form.text'] + }, { + value: 'number', + text: Formdict['model.form.number'] + }, { + value: 'select', + text: '閫夋嫨鍣�' + }, { + value: 'link', + text: Formdict['model.form.link'] + }, { + value: 'switch', + text: '寮�鍏�' + }, { + value: 'checkbox', + text: '澶氶�夋' + }, { + value: 'radio', + text: '鍗曢�夋' + }, { + value: 'checkcard', + text: '閫夐」鍗�' + }, { + value: 'fileupload', + text: Formdict['header.form.fileupload'] + }, { + value: 'date', + text: Formdict['model.form.dateday'] + }, { + value: 'datemonth', + text: Formdict['model.form.datemonth'] + }, { + value: 'datetime', + text: Formdict['model.form.datetime'] + }, { + value: 'textarea', + text: Formdict['model.form.textarea'] + }, { + value: 'funcvar', + text: Formdict['header.form.funcvar'] + }, { + value: 'hint', + text: '鎻愮ず' + }, { + value: 'split', + text: '鍒嗛殧绾�' + }] + } else if (subtable) { _openType.push({ value: 'linkMain', text: Formdict['header.form.linkMain'] @@ -1963,65 +2272,7 @@ label: Formdict['model.form.type'], initVal: card.type, required: true, - options: [{ - value: 'text', - text: Formdict['model.form.text'] - }, { - value: 'number', - text: Formdict['model.form.number'] - }, { - value: 'select', - text: Formdict['model.form.select'] - }, { - value: 'multiselect', - text: Formdict['model.form.multiselect'] - }, { - value: 'link', - text: Formdict['model.form.link'] - }, { - value: 'switch', - text: '寮�鍏�' - }, { - value: 'checkbox', - text: '澶氶�夋' - }, { - value: 'radio', - text: '鍗曢�夋' - }, { - value: 'checkcard', - text: '閫夐」鍗�' - }, { - value: 'fileupload', - text: Formdict['header.form.fileupload'] - }, { - value: 'date', - text: Formdict['model.form.dateday'] - }, { - value: 'datemonth', - text: Formdict['model.form.datemonth'] - }, { - value: 'datetime', - text: Formdict['model.form.datetime'] - }, { - value: 'textarea', - text: Formdict['model.form.textarea'] - }, { - value: 'color', - text: Formdict['model.form.color'] - }, { - value: 'brafteditor', - text: '瀵屾枃鏈�' - }, { - value: 'funcvar', - text: Formdict['header.form.funcvar'] - }, { - value: 'hint', - text: '鎻愮ず' - }, { - value: 'split', - text: '鍒嗛殧绾�' - }, - ..._openType] + options: _openType }, { type: 'text', @@ -2058,14 +2309,16 @@ key: 'openText', label: '寮�鍚彁绀�', initVal: card.openText || '', - required: false + required: false, + forbid: appType === 'mob' }, { type: 'text', key: 'closeText', label: '鍏抽棴鎻愮ず', initVal: card.closeText || '', - required: false + required: false, + forbid: appType === 'mob' }, { type: 'radio', @@ -2101,7 +2354,7 @@ min: 1, max: 24, precision: 0, - label: '鍗$墖瀹藉害', + label: '鍏冪礌瀹藉害', initVal: card.width || 4, tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��', required: true @@ -2277,11 +2530,12 @@ { type: 'number', key: 'maxRows', - min: 2, + min: 1, max: 100, precision: 0, - label: Formdict['header.form.maxRows'], - initVal: card.maxRows || 6, + label: appType === 'mob' ? '琛屾暟' : Formdict['header.form.maxRows'], + tooltip: appType === 'mob' ? '琛屾暟涓虹┖鏃讹紝楂樺害鑷�傚簲' : '', + initVal: card.maxRows || (appType === 'mob' ? '' : 6), required: false }, { @@ -2307,40 +2561,28 @@ type: 'select', key: 'fileType', label: '鏄剧ず鏂瑰紡', - initVal: card.fileType || 'text', + initVal: card.fileType || (appType === 'mob' ? 'picture-card' : 'text'), options: [{ + value: 'text', + text: '鏂囦欢' + }, { value: 'picture', text: '鍥炬枃淇℃伅' }, { value: 'picture-card', text: '鍥剧墖鍗�' - }, { - value: 'text', - text: '鏂囦欢' }] }, { type: 'number', key: 'maxfile', - min: 1, - max: 1000000, + min: 0, + max: 1000, precision: 0, label: '鏈�澶ф枃浠舵暟', initVal: card.maxfile || '', + tooltip: '绛変簬0鏃朵笉鍋氶檺鍒躲��', required: false - }, - { - type: 'radio', - key: 'hidelabel', - label: '闅愯棌鍚嶇О', - initVal: card.hidelabel || 'false', - options: [{ - value: 'true', - text: Formdict['model.true'] - }, { - value: 'false', - text: Formdict['model.false'] - }] }, { type: 'radio', @@ -2396,6 +2638,37 @@ }, { type: 'radio', + key: 'cursor', + label: '鍏夋爣', + initVal: card.cursor || 'left', + options: [{ + value: 'right', + text: '鍙冲榻�' + }, { + value: 'left', + text: '宸﹀榻�' + }], + forbid: appType !== 'mob' + }, + { + type: 'radio', + key: 'scan', + label: '鎵爜', + initVal: card.scan || 'false', + options: [{ + value: 'false', + text: '绂佺敤' + }, { + value: 'simple', + text: '鍗曟' + }, { + value: 'multi', + text: '杩炵画' + }], + forbid: appType !== 'mob' + }, + { + type: 'radio', key: 'readin', label: Formdict['header.form.readin'], tooltip: Formdict['header.form.readin.tooltip'], @@ -2423,6 +2696,76 @@ }] }, { + type: 'radio', + key: 'hidelabel', + label: '闅愯棌鍚嶇О', + initVal: card.hidelabel || 'false', + options: [{ + value: 'true', + text: Formdict['model.true'] + }, { + value: 'false', + text: Formdict['model.false'] + }] + }, + { + type: 'radio', + key: 'arrange', + label: '鍏冪礌鎺掑垪', + initVal: card.arrange || 'adaptive', + forbid: appType !== 'mob', + options: [{ + value: 'line', + text: '鏁磋' + }, { + value: 'adaptive', + text: '鑷�傚簲' + }] + }, + { + type: 'color', + key: 'backgroundColor', + label: '鑳屾櫙鑹�', + initVal: card.backgroundColor || '', + tooltip: '璁剧疆鑳屾櫙鑹插悗锛岄�変腑鏁堟灉鐢辫儗鏅鑹叉帶鍒躲��', + required: false + }, + { + type: 'color', + key: 'borderColor', + label: '杈规棰滆壊', + initVal: card.borderColor || '', + required: false + }, + { + type: 'radio', + key: 'declareType', + label: '鏁版嵁绫诲瀷', + tooltip: '澹版槑鍙橀噺鏃剁殑绫诲瀷锛屾椂闂存牸寮廳atetime鎴栨枃鏈牸寮弉varchar(50)銆�', + initVal: card.declareType || 'datetime', + options: [{ + value: 'datetime', + text: 'datetime' + }, { + value: 'nvarchar(50)', + text: 'nvarchar(50)' + }] + }, + { + type: 'radio', + key: 'mode', + label: '妯″紡', + initVal: card.mode || 'picker', + options: [{ + value: 'picker', + text: '閫夋嫨鍣�' + }, { + value: 'calendar', + text: '鏃ュ巻' + }], + forbid: appType !== 'mob' + }, + { type: 'number', key: 'span', min: 1, @@ -2431,7 +2774,8 @@ label: '琛ㄥ崟瀹藉害', initVal: card.span || (['textarea', 'hint', 'checkcard', 'brafteditor'].includes(card.type) ? 24 : 12), tooltip: '鏍呮牸甯冨眬鏁磋24绛夊垎銆�', - required: true + required: true, + forbid: appType === 'mob' }, { type: 'number', @@ -2442,7 +2786,53 @@ label: '鍚嶇О瀹藉害', initVal: card.labelwidth || 33.3, tooltip: '鍚嶇О鍗犳嵁琛ㄥ崟瀹藉害鐨勭櫨鍒嗘瘮銆傛敞锛氬瓨鍦ㄥ鍒楄〃鍗曟椂锛屽綋鍓嶈〃鍗曞鏋滄兂瑕佸崰鎹暣琛屽彲鍙傜収浠ヤ笅姣斾緥锛屼袱鍒楋紙16.2锛夈�佷笁鍒楋紙10.5锛夈�佸洓鍒楋紙7.7锛�', + required: true, + forbid: appType === 'mob' + }, + { + type: 'radio', + key: 'compress', + label: '鍘嬬缉', + initVal: card.compress || 'false', + tooltip: '鏂囦欢鍘嬬缉蹇呴』涓哄浘鐗囷紝鍥剧墖鏍煎紡涓簀pg銆乸ng銆乬if 鎴� jpeg', + options: [{ + value: 'true', + text: Formdict['model.true'] + }, { + value: 'false', + text: Formdict['model.false'] + }] + }, + { + type: 'number', + key: 'limit', + min: 0.01, + max: 1000, + precision: 2, + label: '璧风偣锛圡锛�', + initVal: card.limit || 2, + tooltip: '鍘嬬缉璧风偣锛屽皬浜庤捣鐐瑰�肩殑鏂囦欢涓嶈繘琛屽帇缂┿��', required: true + }, + { + type: 'textarea', + key: 'rduri', + label: '杞瓨鎺ュ彛', + rows: 1, + initVal: card.rduri || '', + tooltip: '鍥剧墖杞瓨鍦ㄥ悓涓�鍗曠偣鏈嶅姟鍣ㄤ笅鐨勫叾浠栦笟鍔$郴缁熴��', + required: false, + readonly: false + }, + { + type: 'textarea', + key: 'proRduri', + label: '姝e紡鎺ュ彛', + rows: 1, + initVal: card.proRduri || '', + tooltip: '姝e紡绯荤粺杞瓨鎺ュ彛锛屽浘鐗囪浆瀛樺湪鍚屼竴鍗曠偣鏈嶅姟鍣ㄤ笅鐨勫叾浠栦笟鍔$郴缁熴��', + required: false, + readonly: false }, { type: 'text', @@ -2481,6 +2871,35 @@ }] }, { + type: 'radio', + key: 'splitline', + label: '鍒嗗壊绾�', + initVal: card.splitline || 'true', + forbid: appType !== 'mob', + options: [{ + value: 'true', + text: '鏄剧ず' + }, { + value: 'false', + text: '闅愯棌' + }] + }, + { + type: 'radio', + key: 'count', + label: '璁℃暟鍔熻兘', + initVal: card.count || 'false', + tooltip: '鏄剧ず杈撳叆鐨勫瓧绗︽暟锛岃缃鏁版椂鐢熸晥锛屾敞锛氬姞瀵嗕紶杈撴椂鏈�澶у�间笌瀛楁闀垮害涓嶇瓑銆�', + options: [{ + value: 'true', + text: '寮�鍚�' + }, { + value: 'false', + text: '鍏抽棴' + }], + forbid: appType !== 'mob' + }, + { type: 'select', key: 'supField', label: '涓婄骇琛ㄥ崟', @@ -2494,7 +2913,7 @@ type: 'text', key: 'supvalue', label: '鏄剧ず鍊�', - tooltip: '璇峰~鍐欐樉绀哄�硷紝鍙湁涓婄骇琛ㄥ崟鍊间笌鏄剧ず鍊肩浉鍚屾椂锛岃琛ㄥ崟鎵嶄細鏄剧ず锛屾敞锛氬涓�肩敤閫楀彿鍒嗛殧銆�', + tooltip: '璇峰~鍐欐樉绀哄�硷紝鍙湁涓婄骇琛ㄥ崟鍊间笌鏄剧ず鍊肩浉鍚屾椂锛岃琛ㄥ崟鎵嶄細鏄剧ず锛屾敞锛�1銆佸涓�肩敤閫楀彿鍒嗛殧锛�2銆佷笂绾ц〃鍗曞垵濮嬪�间负$first鏃舵殏鏈鐞嗐��', initVal: card.supvalue || '', required: true, readonly: false @@ -2505,7 +2924,8 @@ label: '鎮诞鎻愮ず', tooltip: '榧犳爣鎮诞浜庢彁绀烘枃瀛椾笂鏂规椂锛屾樉绀烘彁绀轰俊鎭��', initVal: card.tooltip || '', - required: false + required: false, + forbid: appType === 'mob' }, { type: 'text', @@ -2513,7 +2933,8 @@ label: '搴曢儴鎻愮ず', tooltip: '鏄剧ず浜庤〃鍗曞簳閮ㄣ��', initVal: card.extra || '', - required: false + required: false, + forbid: appType === 'mob' }, { type: 'text', @@ -2552,7 +2973,7 @@ type: 'multiselect', key: 'linkSubField', label: Formdict['model.form.linkform'], - tooltip: '鍦ㄥ垏鎹㈤�夐」鏃朵細鎶婁俊鎭嚜鍔ㄥ~鍏ュ叧鑱旂殑琛ㄥ崟锛堟枃鏈垨鏁板瓧琛ㄥ崟锛変腑銆�', + tooltip: '鍦ㄥ垏鎹㈤�夐」鏃朵細鎶婁俊鎭嚜鍔ㄥ~鍏ュ叧鑱旂殑琛ㄥ崟锛堟枃鏈垨鏁板瓧琛ㄥ崟锛変腑銆傛敞锛氫娇鐢ㄩ�夐」鍗′笖璁句负鍙閫夋椂鏃犳晥銆�', initVal: card.linkSubField || [], options: inputfields }, diff --git a/src/templates/zshare/modalform/datatable/index.jsx b/src/templates/zshare/modalform/datatable/index.jsx index 50e0cc6..21ae904 100644 --- a/src/templates/zshare/modalform/datatable/index.jsx +++ b/src/templates/zshare/modalform/datatable/index.jsx @@ -70,9 +70,14 @@ class EditableCell extends Component { getInput = (form) => { - const { inputType } = this.props + const { inputType, record } = this.props if (inputType === 'file') { - return <FileUpload maxFile={1} fileType="picture-card"/> + return <FileUpload config={{ + initval: record ? (record.$url || '') : '', + suffix: '', + maxfile: 1, + fileType: 'picture-card' + }}/> } else { return <Input onPressEnter={() => this.getValue(form)} /> } @@ -85,15 +90,6 @@ return } - if (row.$url && Array.isArray(row.$url)) { - if (!row.$url[0]) { - row.$url = '' - } else if (row.$url[0].origin) { - row.$url = row.$url[0].url || '' - } else if (!row.$url[0].origin && row.$url[0].status === 'done' && row.$url[0].response) { - row.$url = row.$url[0].response - } - } this.props.onSave({...record, ...row}) }) } @@ -116,18 +112,6 @@ if (record && dataIndex) { _val = record[dataIndex] - } - - if (dataIndex === '$url' && _val) { - _val = [{ - uid: `10086`, - name: _val.slice(_val.lastIndexOf('/') + 1), - status: 'done', - url: _val, - origin: true - }] - } else if (dataIndex === '$url') { - _val = [] } return ( @@ -291,16 +275,6 @@ return; } - if (row.$url && Array.isArray(row.$url)) { - if (!row.$url[0]) { - row.$url = '' - } else if (row.$url[0].origin) { - row.$url = row.$url[0].url || '' - } else if (!row.$url[0].origin && row.$url[0].status === 'done' && row.$url[0].response) { - row.$url = row.$url[0].response - } - } - const newData = [...this.state.data] const index = newData.findIndex(item => key === item.key) if (index > -1) { @@ -323,10 +297,10 @@ handleAdd = () => { const { fields, type } = this.props - if (this.state.data.length >= 20) { + if (this.state.data.length >= 100) { notification.warning({ top: 92, - message: '鏈�澶氬彲娣诲姞20椤癸紒', + message: '鏈�澶氬彲娣诲姞100椤癸紒', duration: 5 }) return diff --git a/src/templates/zshare/modalform/datatable/index.scss b/src/templates/zshare/modalform/datatable/index.scss index e80b7bf..6d5ee71 100644 --- a/src/templates/zshare/modalform/datatable/index.scss +++ b/src/templates/zshare/modalform/datatable/index.scss @@ -21,17 +21,11 @@ padding: 16px 10px; } .fileupload-form-container .ant-upload-list-picture-card .ant-upload-list-item { - width: 70px; - height: 70px; margin: 0; padding: 2px; .ant-upload-list-item-info > span { height: 100%; } - } - .fileupload-form-container .ant-upload.ant-upload-select-picture-card { - width: 70px; - height: 70px; } } .operation-btn { diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx index dd53a73..a8bb337 100644 --- a/src/templates/zshare/modalform/index.jsx +++ b/src/templates/zshare/modalform/index.jsx @@ -6,33 +6,35 @@ import { dateOptions } from '@/utils/option.js' import Utils from '@/utils/utils.js' import EditTable from './modaleditable' -import DataTable from './datatable' -import FieldsTable from './fieldtable' +import asyncComponent from '@/utils/asyncComponent' import CodeMirror from '@/templates/zshare/codemirror' import './index.scss' const { TextArea } = Input +const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) +const FieldsTable = asyncComponent(() => import('./fieldtable')) +const DataTable = asyncComponent(() => import('./datatable')) const modalTypeOptions = { - text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'tooltip', 'extra', 'enter'], - number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter'], - select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter'], - checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'tooltip', 'extra'], - radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'setAll', 'emptyText'], - checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'fieldlength', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'width', 'multiple'], + text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline'], + number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline'], + select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline'], + checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'arrange'], + radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'setAll', 'emptyText', 'splitline', 'arrange'], + checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'fieldlength', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'width', 'multiple', 'borderColor', 'splitline'], multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra'], - link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter'], - fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'tooltip', 'extra', 'suffix'], - switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra'], - date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra'], - datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra'], - datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra'], - textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'span', 'labelwidth', 'maxRows', 'encryption', 'interception', 'tooltip', 'extra'], + link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline'], + fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'tooltip', 'extra', 'compress', 'splitline'], + switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline'], + date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline'], + datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'splitline'], + datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline'], + textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'span', 'labelwidth', 'maxRows', 'encryption', 'interception', 'tooltip', 'extra', 'count'], color: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra'], - hint: ['label', 'type', 'blacklist', 'message', 'span', 'labelwidth'], + hint: ['label', 'type', 'blacklist', 'message', 'span', 'labelwidth', 'splitline'], split: ['label', 'type'], brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption'], - funcvar: ['span', 'labelwidth'], + funcvar: ['span', 'labelwidth', 'splitline'], linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra'] } @@ -49,6 +51,7 @@ openType: null, resourceType: null, supField: '', + compress: 'false', display: 'text', enter: '', cFields: [], @@ -62,6 +65,7 @@ let resourceType = '' let supField = '' let display = '' + let compress = 'false' let enter = '' let cFields = [] let linkSubFields = [] @@ -69,6 +73,8 @@ formlist.forEach(cell => { if (cell.key === 'type') { type = cell.initVal + } else if (cell.key === 'compress') { + compress = cell.initVal } else if (cell.key === 'display') { display = cell.initVal } else if (cell.key === 'enter') { @@ -92,10 +98,11 @@ } }) - let _options = this.getOptions(type, resourceType, supField, display, enter) + let _options = this.getOptions(type, resourceType, supField, display, enter, compress) this.setState({ enter: enter, + compress: compress, openType: type, supField: supField, display: display, @@ -143,7 +150,7 @@ } } - getOptions = (type, resourceType, supField, display, enter) => { + getOptions = (type, resourceType, supField, display, enter, compress) => { let _options = ['label', 'field', 'type', 'blacklist', 'writein', ...fromJS(modalTypeOptions[type]).toJS()] if (type === 'hint') { @@ -165,10 +172,20 @@ } } else { if (resourceType === '0') { // 鑷畾涔夎祫婧� - _options.push('options', 'fields') + _options.push('options', 'fields', 'backgroundColor') } else if (resourceType === '1') { // 鏁版嵁婧� - _options.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'database') + _options.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'database', 'backgroundColor') } + } + + if (sessionStorage.getItem('appType') === 'mob') { + _options.push('hidelabel') + } + } else if (type === 'fileupload') { + if (compress === 'true') { + _options.push('limit', 'rduri', 'proRduri') + } else { + _options.push('suffix') } } @@ -201,8 +218,7 @@ fieldValue.enter = 'false' } - let _options = this.getOptions(value, this.state.resourceType, this.state.supField, this.state.display, enter) - + let _options = this.getOptions(value, this.state.resourceType, this.state.supField, this.state.display, enter, this.state.compress) this.setState({ openType: value, @@ -265,6 +281,10 @@ if (value === 'brafteditor') { fieldValue.encryption = 'true' } + } else if (form.key === 'hidden') { + if (value === 'linkMain') { + fieldValue.hidden = 'true' + } } return form @@ -311,10 +331,10 @@ } onChange = (e, key) => { - const { openType } = this.state + const { openType, compress } = this.state let value = e.target.value if (key === 'resourceType') { - let _options = this.getOptions(openType, value, this.state.supField, this.state.display, this.state.enter) + let _options = this.getOptions(openType, value, this.state.supField, this.state.display, this.state.enter, compress) this.setState({ resourceType: value, @@ -324,7 +344,7 @@ }) }) } else if (key === 'display') { - let _options = this.getOptions(openType, this.state.resourceType, this.state.supField, value, this.state.enter) + let _options = this.getOptions(openType, this.state.resourceType, this.state.supField, value, this.state.enter, compress) this.setState({ display: value, @@ -333,8 +353,18 @@ return form }) }) + } else if (key === 'compress') { + let _options = this.getOptions(openType, this.state.resourceType, this.state.supField, this.state.display, this.state.enter, value) + + this.setState({ + compress: value, + formlist: this.state.formlist.map(form => { + form.show = _options.includes(form.key) + return form + }) + }) } else if (key === 'enter') { - let _options = this.getOptions(openType, this.state.resourceType, this.state.supField, this.state.display, value) + let _options = this.getOptions(openType, this.state.resourceType, this.state.supField, this.state.display, value, compress) this.setState({ enter: value, @@ -422,7 +452,7 @@ const fields = [] this.state.formlist.forEach((item, index) => { - if (!item.show) return + if (!item.show || item.forbid) return null if (item.type === 'text') { // 鏂囨湰鎼滅储 let rules = [] @@ -617,7 +647,12 @@ } else if (item.type === 'textarea') { fields.push( <Col span={24} key={index}> - <Form.Item className="text-msg" label={item.label}> + <Form.Item className="text-msg" 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: [ @@ -626,7 +661,7 @@ message: this.props.dict['form.required.input'] + item.label + '!' } ] - })(<TextArea rows={4} />)} + })(<TextArea rows={item.rows || 4} />)} </Form.Item> </Col> ) @@ -662,6 +697,16 @@ </Form.Item> </Col> ) + } else if (item.type === 'color') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label} className="color-form-item"> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })(<ColorSketch allowClear={true}/>)} + </Form.Item> + </Col> + ) } }) diff --git a/src/templates/zshare/modalform/index.scss b/src/templates/zshare/modalform/index.scss index 75706c5..672e7e4 100644 --- a/src/templates/zshare/modalform/index.scss +++ b/src/templates/zshare/modalform/index.scss @@ -33,4 +33,12 @@ .ant-input-number { width: 100%; } + .color-form-item { + .ant-form-item-control { + height: 40px; + .color-sketch-block { + margin-top: 7px; + } + } + } } \ No newline at end of file diff --git a/src/templates/zshare/modalform/modaleditable/index.jsx b/src/templates/zshare/modalform/modaleditable/index.jsx index 314fe78..5b5a0a2 100644 --- a/src/templates/zshare/modalform/modaleditable/index.jsx +++ b/src/templates/zshare/modalform/modaleditable/index.jsx @@ -300,7 +300,8 @@ }) } - handleAdd = () => { + handleAdd = (e) => { + e.stopPropagation() const { type, count, dataSource } = this.state const newData = { key: Utils.getuuid(), @@ -388,7 +389,7 @@ title={this.props.dict['model.query.delete']} onConfirm={() => this.handleDelete(record.key) }> - <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + <span style={{color: '#ff4d4f', cursor: 'pointer'}}><Icon type="delete" /></span> </Popconfirm> </div> ) : null, diff --git a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx index 5d9f5e7..bed203c 100644 --- a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx +++ b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx @@ -127,6 +127,13 @@ LText: this.props.initsql + _prevCustomScript + _backCustomScript + tail } + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + param.LText = param.LText.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } + // 鏁版嵁鏉冮檺 param.LText = param.LText.replace(/@\$|\$@/ig, '') diff --git a/src/templates/zshare/verifycard/customform/index.jsx b/src/templates/zshare/verifycard/customform/index.jsx index c9be94d..d203f25 100644 --- a/src/templates/zshare/verifycard/customform/index.jsx +++ b/src/templates/zshare/verifycard/customform/index.jsx @@ -101,6 +101,13 @@ LText: this.props.initsql + values.sql } + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + param.LText = param.LText.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } + // 鏁版嵁鏉冮檺 param.LText = param.LText.replace(/@\$|\$@/ig, '') diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx index f7f1d2e..a5a1162 100644 --- a/src/templates/zshare/verifycard/customscript/index.jsx +++ b/src/templates/zshare/verifycard/customscript/index.jsx @@ -139,6 +139,13 @@ LText: this.props.initsql + _initCustomScript + _prevCustomScript + _backCustomScript + tail } + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(item => { + let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') + param.LText = param.LText.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) + }) + } + // 鏁版嵁鏉冮檺 param.LText = param.LText.replace(/@\$|\$@/ig, '') // check diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx index a3a388e..5e448f2 100644 --- a/src/templates/zshare/verifycard/index.jsx +++ b/src/templates/zshare/verifycard/index.jsx @@ -556,6 +556,21 @@ _verify.scripts = _verify.scripts || [] _verify.cbScripts = _verify.cbScripts || [] + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig') + _verify.customverifys.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + _verify.scripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + _verify.cbScripts.forEach(item => { + item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) + }) + }) + } + this.setState({ verify: _verify }) @@ -860,7 +875,7 @@ _columns = fromJS(columns).toJS() let hasbid = false _columns = _columns.filter(col => { - if (col.field.toLowerCase() === 'bid') { + if (col.field && col.field.toLowerCase() === 'bid') { hasbid = true } @@ -926,8 +941,8 @@ }, { obj_name: 'noteCodes', - arr_field: 'templatecode,describe', - LText: window.btoa(window.encodeURIComponent(`select templatecode,'['+SignName+']'+describe as describe from (select * from bd_msn_sms_temp where deleted=0 and TypeDesc='QX' and status=20 ) t inner join (select openid from susers where uid=@userid@) u on t.openid =t.openid`)) + arr_field: 'templatecode,describe,id', + LText: window.btoa(window.encodeURIComponent(`select t.id,templatecode,'['+SignName+']'+describe as describe from (select * from bd_msn_sms_temp where deleted=0 and TypeDesc='QX' and status=20 ) t inner join (select openid from susers where uid=@userid@) u on t.openid =t.openid`)) }, { obj_name: 'scripts', @@ -967,7 +982,8 @@ notes: res.noteCodes.map(item => { return { name: item.describe, - value: item.templatecode + value: item.templatecode, + id: item.id } }), systemScripts: res.scripts.map(item => { @@ -1092,11 +1108,11 @@ this.setState({ verify }) } - onNoteCodeChange = (val) => { + onNoteCodeChange = (val, option) => { const { verify } = this.state this.setState({ - verify: {...verify, noteCode: val} + verify: {...verify, noteCode: val, noteId: option.props.id} }) } @@ -1301,7 +1317,7 @@ // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� return new Promise((resolve, reject) => { - if (card.sqlType !== 'custom' && verify.default === 'false' && verify.scripts.length === 0) { + if ((card.sqlType === 'custom' || verify.default === 'false') && verify.scripts.length === 0) { notification.warning({ top: 92, message: '涓嶆墽琛岄粯璁ql鏃讹紝蹇呴』璁剧疆鑷畾涔夎剼鏈紒', @@ -1334,6 +1350,21 @@ verify.noteEnable = 'false' } else if (verify.noteEnable !== 'true' && verify.noteCode) { verify.noteCode = '' + } + + if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { + window.GLOB.funcs.forEach(m => { + let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig') + verify.customverifys.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + verify.scripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + verify.cbScripts.forEach(item => { + item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) + }) + }) } if (msg) { @@ -1452,7 +1483,7 @@ <Form.Item label="鐭俊妯℃澘"> <Select value={verify.noteCode} onSelect={this.onNoteCodeChange}> {notes.map(option => - <Select.Option key={option.value} value={option.value}> + <Select.Option key={option.value} id={option.id} value={option.value}> {option.name} </Select.Option> )} diff --git a/src/utils/option.js b/src/utils/option.js index 75fca24..4306074 100644 --- a/src/utils/option.js +++ b/src/utils/option.js @@ -87,18 +87,18 @@ isSystem: true }, { - title: '瑙掕壊鏉冮檺鍒嗛厤', - type: 'RolePermission', - url: rolemanage, - isSystem: true, - hidden: true - }, - { title: '澶栭儴椤甸潰', type: 'NewPage', url: customImg, baseconfig: '', isSystem: true + }, + { + title: '瑙掕壊鏉冮檺鍒嗛厤', + type: 'RolePermission', + url: rolemanage, + isSystem: true, + hidden: true } ] @@ -210,9 +210,6 @@ // 鎸夐挳鍥炬爣闆� export const btnIcons = [{ - value: '', - text: '鏃�' -}, { value: 'plus', text: 'plus' }, { @@ -284,6 +281,9 @@ }, { value: 'double-left', text: 'double-left' +}, { + value: 'search', + text: 'search' }] // 鎸夐挳棰滆壊闆� @@ -681,19 +681,8 @@ 'step-forward', 'fast-backward', 'fast-forward', - 'shrink', - 'arrows-alt', - 'up-circle', - 'down-circle', - 'left-circle', - 'right-circle', 'double-right', 'double-left', - 'vertical-left', - 'vertical-right', - 'vertical-align-top', - 'vertical-align-middle', - 'vertical-align-bottom', 'forward', 'backward', 'rollback', @@ -703,56 +692,31 @@ 'swap-left', 'swap-right', 'play-circle', - 'up-square', - 'down-square', - 'left-square', - 'right-square', 'login', 'logout', - 'menu-fold', - 'menu-unfold', - 'border-bottom', - 'border-horizontal', - 'border-inner', - 'border-outer', - 'border-left', - 'border-right', - 'border-top', - 'border-verticle', - 'pic-center', - 'pic-left', - 'pic-right', - 'radius-bottomleft', - 'radius-bottomright', - 'radius-upleft', - 'radius-upright', + 'search', 'fullscreen', - 'fullscreen-exit' + 'fullscreen-exit', + 'download', + 'upload' ], hint: [ 'question', 'question-circle', 'plus', 'plus-circle', - 'pause', 'pause-circle', 'minus', 'minus-circle', - 'plus-square', - 'minus-square', - 'info', 'info-circle', - 'exclamation', 'exclamation-circle', 'close', 'close-circle', - 'close-square', 'check', 'check-circle', 'check-square', 'clock-circle', 'warning', - 'issues-close', 'stop' ], edit: [ @@ -762,33 +726,14 @@ 'scissor', 'delete', 'snippets', - 'diff', 'highlight', - 'align-center', - 'align-left', - 'align-right', - 'bg-colors', - 'bold', - 'italic', - 'underline', - 'strikethrough', 'redo', 'undo', 'zoom-in', 'zoom-out', - 'font-colors', - 'font-size', - 'line-height', 'dash', - 'small-dash', 'sort-ascending', - 'sort-descending', - 'drag', - 'ordered-list', - 'unordered-list', - 'radius-setting', - 'column-width', - 'column-height' + 'sort-descending' ], data: [ 'area-chart', @@ -797,66 +742,26 @@ 'dot-chart', 'line-chart', 'radar-chart', - 'heat-map', 'fall', 'rise', 'stock', - 'box-plot', - 'fund', - 'sliders' ], trademark: [ 'android', 'apple', - 'windows', - 'ie', 'chrome', - 'github', 'aliwangwang', 'dingding', - 'weibo-square', - 'weibo-circle', - 'taobao-circle', - 'html5', 'weibo', 'twitter', 'wechat', - 'youtube', 'alipay-circle', 'taobao', - 'skype', 'qq', - 'medium-workmark', - 'gitlab', - 'medium', - 'linkedin', - 'google-plus', - 'dropbox', - 'facebook', - 'codepen', - 'code-sandbox', - 'amazon', - 'google', - 'codepen-circle', 'alipay', - 'ant-design', - 'ant-cloud', - 'aliyun', - 'zhihu', - 'slack', - 'slack-square', - 'behance', - 'behance-square', - 'dribbble', - 'dribbble-square', - 'instagram', - 'yuque', - 'alibaba', - 'yahoo', - 'reddit', - 'sketch' ], normal: [ + 'user', 'account-book', 'alert', 'api', @@ -864,42 +769,19 @@ 'audio', 'bank', 'bell', - 'book', 'bug', - 'bulb', - 'calculator', - 'build', 'calendar', 'camera', - 'car', - 'carry-out', 'cloud', - 'code', 'compass', - 'contacts', - 'container', - 'control', 'credit-card', - 'crown', 'customer-service', 'dashboard', 'database', 'dislike', 'environment', - 'experiment', 'eye-invisible', 'eye', - 'file-add', - 'file-excel', - 'file-exclamation', - 'file-image', - 'file-markdown', - 'file-pdf', - 'file-ppt', - 'file-text', - 'file-unknown', - 'file-word', - 'file-zip', 'file', 'filter', 'fire', @@ -907,22 +789,13 @@ 'folder-add', 'folder', 'folder-open', - 'frown', - 'funnel-plot', - 'gift', - 'hdd', 'heart', 'home', 'hourglass', 'idcard', - 'insurance', - 'interaction', - 'layout', 'like', 'lock', 'mail', - 'medicine-box', - 'meh', 'message', 'mobile', 'phone', @@ -931,16 +804,15 @@ 'smile', 'star', 'thunderbolt', - 'trophy', 'unlock', 'barcode', 'key', 'man', 'woman', + 'team', 'poweroff', - 'search', 'shopping-cart', - 'link' + 'link', ] } diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js index e991da4..058d369 100644 --- a/src/utils/utils-custom.js +++ b/src/utils/utils-custom.js @@ -166,11 +166,89 @@ } /** + * @description 鑾峰彇鍙叧鑱旀ā鍧� + */ + static getLinkModules (components) { + let modules = components.map(item => { + if ((item.type === 'card' && item.subtype === 'datacard') || (item.type === 'table' && item.subtype === 'normaltable')) { + return { + value: item.uuid, + label: item.name + } + } else if (item.type === 'tabs') { + let _item = { + value: item.uuid, + label: item.name, + children: item.subtabs.map(f_tab => { + let subItem = { + value: f_tab.uuid, + label: f_tab.label, + children: this.getLinkModules(f_tab.components) + } + + if (!subItem.children || subItem.children.length === 0) { + return {children: null} + } + return subItem + }) + } + + _item.children = _item.children.filter(t => t.children !== null) + + if (_item.children.length === 0) { + return {children: null} + } + + return _item + } else if (item.type === 'group') { + let _item = { + value: item.uuid, + label: item.name, + children: item.components.map(f_tab => { + if ((f_tab.type === 'card' && f_tab.subtype === 'datacard') || (f_tab.type === 'table' && f_tab.subtype === 'normaltable')) { + return { + value: f_tab.uuid, + label: f_tab.name + } + } + return { + children: null + } + }) + } + + _item.children = _item.children.filter(t => t.children !== null) + + if (_item.children.length === 0) { + return {children: null} + } + + return _item + } else { + return { + children: null + } + } + }) + + modules = modules.filter(mod => mod.children !== null) + + if (modules.length === 0) { + return null + } + return modules + } + + /** * @description 鑾峰彇鍒犻櫎鎸夐挳Id * @return {String} name */ static getDelButtonIds (card) { + let appType = sessionStorage.getItem('appType') let uuids = [] + + if (appType === 'mob') return uuids + const getUuids = (item) => { if (item.type === 'tabs') { item.subtabs.forEach(tab => { @@ -183,48 +261,41 @@ getUuids(c) }) } else { - if (item.action && item.action.length > 0) { - item.action.forEach(act => { - if (!act.origin) { - uuids.push(act.uuid) - } - }) - } - if (item.type === 'card') { - item.subcards.forEach(_card => { + item.action && item.action.forEach(act => { + if (act.origin || (appType === 'pc' && act.OpenType !== 'popview')) return + + uuids.push(act.uuid) + }) + + if (card.type === 'card' || item.type === 'carousel' || (card.type === 'table' && card.subtype === 'tablecard')) { + card.subcards.forEach(_card => { _card.elements && _card.elements.forEach(cell => { - if (cell.eleType === 'button') { - uuids.push(cell.uuid) - } - }) - _card.backElements && _card.backElements.forEach(cell => { - if (cell.eleType === 'button') { - uuids.push(cell.uuid) - } - }) - }) - } else if (item.type === 'carousel') { - item.subcards.forEach(_card => { - _card.elements && _card.elements.forEach(cell => { - if (cell.eleType === 'button') { - uuids.push(cell.uuid) - } - }) - }) - } else if (item.type === 'table' && item.subtype === 'tablecard') { - item.subcards.forEach(_card => { - _card.elements && _card.elements.forEach(cell => { - if (cell.eleType === 'button') { - uuids.push(cell.uuid) - } - }) - }) - } else if (item.type === 'table' && item.subtype === 'normaltable') { - item.cols && item.cols.forEach(col => { - if (col.type !== 'action') return - col.elements && col.elements.forEach(cell => { + if (cell.eleType !== 'button') return + if (appType === 'pc' && cell.OpenType !== 'popview') return + uuids.push(cell.uuid) }) + _card.backElements && _card.backElements.forEach(cell => { + if (cell.eleType !== 'button') return + if (appType === 'pc' && cell.OpenType !== 'popview') return + + uuids.push(cell.uuid) + }) + }) + } else if (card.type === 'table' && card.subtype === 'normaltable') { + card.cols && card.cols.forEach(col => { + if (col.type !== 'action') return + col.elements && col.elements.forEach(cell => { + if (appType === 'pc' && cell.OpenType !== 'popview') return + + uuids.push(cell.uuid) + }) + }) + } else if (card.type === 'balcony') { + card.elements && card.elements.forEach(cell => { + if (appType === 'pc' && cell.OpenType !== 'popview') return + + uuids.push(cell.uuid) }) } } @@ -280,6 +351,11 @@ return cell }) item.components = this.resetConfig(item.components) + } else if (item.type === 'menubar') { + item.subMenus = item.subMenus.map(cell => { + cell.uuid = this.getuuid() + return cell + }) } else if (item.type === 'card' || item.type === 'carousel' || (item.type === 'table' && item.subtype === 'tablecard')) { item.subcards.forEach(card => { card.uuid = this.getuuid() @@ -366,4 +442,27 @@ return item }) } +} + +/** + * @description 閲嶇疆绉诲姩绔痵tyle + * @return {Object} style + */ +export function resetStyle (style) { + if (!style) return {} + if (sessionStorage.getItem('appType') === 'mob') { + let _style = JSON.stringify(style) + + // scaleview + _style = _style.replace(/\d+vw/ig, (word) => { + return parseFloat(word) * (window.GLOB.winWidth || 420) / 100 + 'px' + // return parseFloat(word) * 350 / 100 + 'px' + }).replace(/\d+vh/ig, (word) => { + return parseFloat(word) * (window.GLOB.winHeight || 738) / 100 + 'px' + // return parseFloat(word) * 615 / 100 + 'px' + }) + + return JSON.parse(_style) + } + return JSON.parse(JSON.stringify(style)) } \ No newline at end of file diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js index f684846..2584cd9 100644 --- a/src/utils/utils-datamanage.js +++ b/src/utils/utils-datamanage.js @@ -1,3 +1,4 @@ +import md5 from 'md5' import moment from 'moment' import options from '@/store/options.js' import Utils from './utils.js' @@ -65,7 +66,7 @@ if (setting.sysInterface === 'true' && window.GLOB.mainSystemApi) { param.rduri = window.GLOB.mainSystemApi } else if (setting.sysInterface !== 'true') { - param.rduri = setting.interface + param.rduri = window.GLOB.systemType === 'production' ? (setting.proInterface || setting.interface) : setting.interface } } @@ -108,6 +109,13 @@ ` } + _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '') + _customScript = _customScript.replace(/@select\$|\$select@/ig, '') + _dataresource = _dataresource.replace(/\$sum@/ig, '/*') + _dataresource = _dataresource.replace(/@sum\$/ig, '*/') + _customScript = _customScript.replace(/\$sum@/ig, '/*') + _customScript = _customScript.replace(/@sum\$/ig, '*/') + let regoptions = null if (setting.queryType === 'statistics' || _customScript) { let allSearch = Utils.getAllSearchOptions(search) @@ -118,15 +126,6 @@ } }) regoptions.push({ - reg: new RegExp('@login_city@', 'ig'), - value: `'${city}'` - }, { - reg: new RegExp('@userName@', 'ig'), - value: `'${userName}'` - }, { - reg: new RegExp('@fullName@', 'ig'), - value: `'${fullName}'` - }, { reg: new RegExp('@orderBy@', 'ig'), value: orderBy }, { @@ -190,8 +189,8 @@ // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞 if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) { - _customScript && console.info(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) - LText && console.info(LText) + _customScript && console.info(`${setting.$name ? `/*缁勪欢-${setting.$name} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) + LText && console.info(`${setting.$name ? `/*缁勪欢-${setting.$name} 鏁版嵁婧�*/\n` : ''}` + LText) } param.custom_script = Utils.formatOptions(_customScript) @@ -240,6 +239,13 @@ ` } + _dataresource = _dataresource.replace(/@sum\$|\$sum@/ig, '') + _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '') + _dataresource = _dataresource.replace(/\$select@/ig, '/*') + _dataresource = _dataresource.replace(/@select\$/ig, '*/') + _customScript = _customScript.replace(/\$select@/ig, '/*') + _customScript = _customScript.replace(/@select\$/ig, '*/') + let regoptions = null if (setting.queryType === 'statistics' || _customScript) { let allSearch = Utils.getAllSearchOptions(search) @@ -251,15 +257,6 @@ } }) regoptions.push({ - reg: new RegExp('@login_city@', 'ig'), - value: `'${city}'` - }, { - reg: new RegExp('@userName@', 'ig'), - value: `'${userName}'` - }, { - reg: new RegExp('@fullName@', 'ig'), - value: `'${fullName}'` - }, { reg: new RegExp('@orderBy@', 'ig'), value: orderBy }, { @@ -280,6 +277,7 @@ regoptions.forEach(item => { _dataresource = _dataresource.replace(item.reg, item.value) }) + _search = '' } if (_customScript) { @@ -300,8 +298,8 @@ // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞 if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) { - _customScript && console.info(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) - LText && console.info(LText) + _customScript && console.info(`${setting.$name ? `/*缁勪欢-${setting.$name} 鑷畾涔夎剼鏈� 缁熻鏌ヨ*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) + LText && console.info(`${setting.$name ? `/*缁勪欢-${setting.$name} 鏁版嵁婧� 缁熻鏌ヨ*/\n` : ''}` + LText) } param.custom_script = Utils.formatOptions(_customScript) @@ -357,7 +355,7 @@ } /** - * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鐨勫弬鏁� + * @description 鑾峰彇绯荤粺鍓嶇疆鑴氭湰 */ static getDefaultPrevQueryParam (setting, search, menuType) { let param = { @@ -441,7 +439,7 @@ } /** - * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鐨勫弬鏁� + * @description 鑾峰彇绯荤粺鍥炶皟鑴氭湰 */ static getCallBackQueryParams (setting, sql, errSql) { let param = { @@ -540,6 +538,9 @@ subObjs.push(val) } } else { + if (typeof(val) === 'string') { + val = val.replace(/'/ig, '"') + } keys.push(key) vals.push(`'${val}'`) } @@ -575,4 +576,132 @@ return [...lineMap.values()] } +} + +/** + * @description 鐢熸垚鍗曚釜缁勪欢sPC_Get_structured_data璇锋眰鍙傛暟 + */ +export function getStructDefaultParam (component, searchlist) { + const { columns, setting, dataName, format } = component + + let arr_field = columns.map(col => col.field) + let _dataresource = setting.dataresource + let _customScript = setting.customScript + + if (setting.queryType === 'statistics' || _customScript) { + let allSearch = Utils.getAllSearchOptions(searchlist) + let regoptions = allSearch.map(item => { + return { + reg: new RegExp('@' + item.key + '@', 'ig'), + value: `'${item.value}'` + } + }) + + regoptions.forEach(item => { + if (_dataresource && setting.queryType === 'statistics') { + _dataresource = _dataresource.replace(item.reg, item.value) + } + _customScript = _customScript.replace(item.reg, item.value) + }) + } + + _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '') + _customScript = _customScript.replace(/@select\$|\$select@/ig, '') + _dataresource = _dataresource.replace(/\$sum@/ig, '/*') + _dataresource = _dataresource.replace(/@sum\$/ig, '*/') + _customScript = _customScript.replace(/\$sum@/ig, '/*') + _customScript = _customScript.replace(/@sum\$/ig, '*/') + + let _search = '' + if (setting.queryType !== 'statistics' && _dataresource) { + _search = Utils.joinMainSearchkey(searchlist) + _search = _search ? 'where ' + _search : '' + } + + if (setting.order && _dataresource) { + _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows ` + } else if (_dataresource) { + _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} ` + } + + // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞 + if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) { + _customScript && console.info(`${setting.$name ? `/*缁勪欢-${setting.$name} 鑷畾涔夎剼鏈�*/\n` : ''}${_dataresource ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`) + _dataresource && console.info(`${setting.$name ? `/*缁勪欢-${setting.$name} 鏁版嵁婧�*/\n` : ''}` + _dataresource) + } + + return { + name: dataName, + columns: columns, + par_tablename: '', + type: format === 'array' ? format : '', + primaryKey: setting.primaryKey || '', + foreign_key: '', + sql: _dataresource, + script: _customScript + } +} + +/** + * @description 鐢熸垚sPC_Get_structured_data璇锋眰鍙傛暟 + * 1銆佹妸澶ф帴鍙PC_Get_structured_data鐨刲text鎷嗘垚涓変唤锛岀涓�娈碉細@LText1锛岀浜屾@LText锛岀涓夋@LText2 + */ +export function getStructuredParams (params, config, BID = '') { + let LText_field = [] + let diffUser = false + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + let _LText = params.map((item, index) => { + let _script = item.script + + if (index === 0) { + _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50) + select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}' + ${_script} + ` + } + if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) { + diffUser = true + } + + item.columns.forEach(cell => { + LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`) + }) + return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort` + }) + + let param = { + func: 'sPC_Get_structured_data', + LText: _LText.join(' union all '), + LText_field: LText_field.join(' union all '), + BID: BID + } + + let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText) + + param.LText1 = LText1 + param.LText = LText + param.LText2 = LText2 + param.LText_field = Utils.formatOptions(param.LText_field) + + if (config.cacheUseful === 'true') { + param.time_type = config.timeUnit + param.time_limit = config.cacheTime + if (diffUser) { + param.userid = sessionStorage.getItem('UserID') + } + param.data_md5 = md5(JSON.stringify(param)) + } + + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + + return param } \ No newline at end of file diff --git a/src/utils/utils.js b/src/utils/utils.js index d0a9b07..93d0120 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -236,54 +236,55 @@ } /** - * @description 鍒濆鍖栨悳绱㈡潯浠� + * @description 鍒濆鍖栨悳绱㈡潯浠跺垵濮嬪�� * @param {Array} searches 鎼滅储鏉′欢 - * @return {String} searches 鏍煎紡鍖栧悗缁撴灉 */ - static initMainSearch (searches) { - if (!searches || searches.length === 0) return [] + static initSearchVal (searches) { + if (!searches) 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' - } + let roleId = sessionStorage.getItem('role_id') || '' - if (item.type === 'group') { - let copy = JSON.parse(JSON.stringify(item)) - copy.key = search.datefield + return searches.map(item => { + item.hidden = item.Hide === 'true' + item.required = !item.hidden && item.required === 'true' + item.advanced = item.advanced === 'true' - item.value = search.initval && search.initval[0] ? search.initval[0] : '' - item.match = '=' - item.forbid = true - - copy.type = 'daterange' - copy.match = 'between' - copy.value = '' - - if (search.initval && search.initval.length > 0) { - let _type = search.initval[0] - let _val = search.initval[1] - + if (item.type === 'date') { // 鏃堕棿鎼滅储 + item.initval = item.initval ? moment().subtract(item.initval, 'days').format('YYYY-MM-DD') : '' + } else if (item.type === 'datemonth') { + item.initval = item.initval ? moment().subtract(item.initval, 'month').format('YYYY-MM') : '' + } else if (item.type === 'dateweek') { + item.initval = item.initval ? moment().subtract(item.initval * 7, 'days').format('YYYY-MM-DD') : '' + } else if (item.type === 'daterange') { + if (item.initval) { + try { + let _initval = JSON.parse(item.initval) + let _vals = [moment().subtract(_initval[0], 'days').format('YYYY-MM-DD'), moment().subtract(_initval[1], 'days').format('YYYY-MM-DD')] + item.initval = _vals.join(',') + } catch { + item.initval = '' + } + } + } else if (item.type === 'group') { + if (item.initval && item.initval[0]) { + let _type = item.initval[0] + let _val = item.initval[1] + let _dateRange = '' + if (_type === 'day') { - copy.value = [moment().subtract(_val, 'days').format('YYYY-MM-DD'), + _dateRange = [moment().subtract(_val, 'days').format('YYYY-MM-DD'), moment().subtract(_val, 'days').format('YYYY-MM-DD')] } else if (_type === 'week') { - copy.value = [moment().subtract(_val * 7, 'days').startOf('week').format('YYYY-MM-DD'), + _dateRange = [moment().subtract(_val * 7, 'days').startOf('week').format('YYYY-MM-DD'), moment().subtract(_val * 7, 'days').endOf('week').format('YYYY-MM-DD')] } else if (_type === 'month') { - copy.value = [moment().subtract(_val, 'month').startOf('month').format('YYYY-MM-DD'), + _dateRange = [moment().subtract(_val, 'month').startOf('month').format('YYYY-MM-DD'), moment().subtract(_val, 'month').endOf('month').format('YYYY-MM-DD')] } else if (_type === 'quarter') { let _differ = parseInt(moment().format('MM')) % 3 let _pdiffer = 0 let _ndiffer = 0 - + // 宸�艰绠� switch(_differ) { case 0: @@ -300,82 +301,108 @@ break default: } - - copy.value = [moment().subtract(_pdiffer + _val * 3, 'month').startOf('month').format('YYYY-MM-DD'), + _dateRange = [moment().subtract(_pdiffer + _val * 3, 'month').startOf('month').format('YYYY-MM-DD'), moment().subtract(_ndiffer + _val * 3, 'month').endOf('month').format('YYYY-MM-DD')] } else if (_type === 'year') { let _year = parseInt(moment().format('YYYY')) - _val - copy.value = [_year + '-01-01', _year + '-12-31'] + _dateRange = [_year + '-01-01', _year + '-12-31'] } else if (_type === 'customized') { try { _val = JSON.parse(_val) } catch { _val = [0, 0] } - copy.value = [moment().subtract(_val[0], 'days').format('YYYY-MM-DD'), + _dateRange = [moment().subtract(_val[0], 'days').format('YYYY-MM-DD'), moment().subtract(_val[1], 'days').format('YYYY-MM-DD')] } - } - if (search.transfer === 'true') { - newsearches.push(item) + item.initval = _dateRange.join(',') + item.initType = _type + } else { + item.initval = '' + item.initType = '' } - newsearches.push(copy) - return - } else 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) + + item.oriInitval = item.initval + + if (item.blacklist && item.blacklist.length > 0 && !item.hidden) { + if (item.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) { + item.hidden = true + item.required = false + } + } + + return item }) - - return newsearches } /** * @description 鍒濆鍖栨悳绱㈡潯浠� * @param {Array} searches 鎼滅储鏉′欢 - * @return {String} searches 鏍煎紡鍖栧悗缁撴灉 + */ + static initMainSearch (searches) { + if (!searches) return [] + + let values = [] + searches.forEach(cell => { + let item = { + key: cell.field, + match: cell.match, + type: cell.type, + label: cell.label, + value: cell.initval, + required: cell.required + } + + if (cell.type === 'multiselect' || (cell.type === 'checkcard' && cell.multiple === 'true')) { + item.type = 'multi' + } else if (item.type === 'group') { + item.key = cell.datefield + item.type = 'daterange' + item.match = 'between' + + values.push({ + type: 'group', + key: cell.field, + value: cell.initType, + label: cell.label, + match: '=', + forbid: true, + required: cell.required + }) + } + + values.push(item) + }) + + return values + } + + /** + * @description 鍒濆鍖栬嚜瀹氫箟鍑芥暟鎼滅储鏉′欢 + * @param {Array} searches 鎼滅储鏉′欢 */ static formatCustomMainSearch (searches) { - if (!searches || searches.length === 0) return {} + if (!searches) return {} let newsearches = {} searches.forEach(item => { if (item.type === 'date') { - let timetail = '' - let _val = item.value + 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') + if (_val) { + if (item.match === '<' || item.match === '<=') { + _val = moment(_val, 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' + } else if (item.match === '>' || item.match === '>=') { + _val = _val + ' 00:00:00.000' } - } else if (item.match === '>' || item.match === '>=') { - timetail = ' 00:00:00.000' } if (newsearches[item.key]) { - newsearches[item.key + '1'] = _val ? _val + timetail : '' + newsearches[item.key + '1'] = _val } else { - newsearches[item.key] = _val ? _val + timetail : '' + newsearches[item.key] = _val } } else if (item.type === 'datemonth') { // 鏈�-杩囨护鏉′欢锛屼粠鏈堝紑濮嬭嚦缁撴潫 @@ -390,35 +417,32 @@ newsearches[item.key] = _startval newsearches[item.key + '1'] = _endval } else if (item.type === 'dateweek') { + let _startval = '' let _endval = '' if (item.value) { - _endval = moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + _startval = moment(item.value, 'YYYY-MM-DD' ).startOf('week').format('YYYY-MM-DD') + ' 00:00:00.000' + _endval = moment(item.value, 'YYYY-MM-DD').endOf('week').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' } - newsearches[item.key] = item.value ? item.value[0] + ' 00:00:00.000' : '' - newsearches[item.key + '1'] = item.value ? _endval + ' 00:00:00.000' : '' + newsearches[item.key] = _startval + newsearches[item.key + '1'] = _endval } else if (item.type === 'daterange') { + let _startval = '' let _endval = '' if (item.value) { - _endval = moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + let val = item.value.split(',') + _startval = val[0] + ' 00:00:00.000' + _endval = moment(val[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' } - newsearches[item.key] = item.value ? item.value[0] + ' 00:00:00.000' : '' - newsearches[item.key + '1'] = item.value ? _endval + ' 00:00:00.000' : '' + newsearches[item.key] = _startval + newsearches[item.key + '1'] = _endval } else if (item.type === 'text' || item.type === 'select') { 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] } }) @@ -435,7 +459,7 @@ let searchText = '' searches.forEach(item => { - if (item.forbid || !item.value || (item.type === 'multiselect' && item.value.length === 0)) return + if (item.forbid || !item.value) return searchText += (searchText !== '' ? ' AND ' : '') if (item.type === 'text' || item.type === 'select') { // 缁煎悎鎼滅储锛屾枃鏈垨涓嬫媺锛屾墍鏈夊瓧娈垫嫾鎺� @@ -445,9 +469,8 @@ }) searchText += '(' + fields.join(' OR ') + ')' - } else if (item.type === 'multiselect') { - - searchText += `'${item.value}' ` + item.match + ' \'%\'+' + item.key + '+\'%\'' + } else if (item.type === 'multi') { + searchText += `'${item.value}' ${item.match} '%'+${item.key}+'%'` } else if (item.type === 'date') { let _val = item.value let timetail = ' 00:00:00.000' @@ -467,15 +490,20 @@ 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' + let _startval = moment(item.value, 'YYYY-MM-DD' ).startOf('week').format('YYYY-MM-DD') + ' 00:00:00.000' + let _endval = moment(item.value, 'YYYY-MM-DD').endOf('week').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' + let val = item.value.split(',') + let _startval = val[0] + ' 00:00:00.000' + let _endval = moment(val[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 === 'range') { + let val = item.value.split(',') + + searchText += '(' + item.key + ' >= \'' + val[0] + '\' AND ' + item.key + ' < \'' + val[1] + '\')' } else { searchText += '(' + item.key + ' ' + item.match + ' \'' + item.value + '\')' } @@ -529,8 +557,8 @@ options.push(item) options.push(copy) } else if (item.type === 'dateweek') { - let _startval = item.value && item.value[0] ? moment(item.value[0], 'YYYY-MM-DD').format('YYYY-MM-DD') + ' 00:00:00.000' : '1970-01-01 00:00:00.000' - let _endval = item.value && item.value[1] ? moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' : '2050-01-01 00:00:00.000' + let _startval = item.value ? moment(item.value, 'YYYY-MM-DD').startOf('week').format('YYYY-MM-DD') + ' 00:00:00.000' : '1970-01-01 00:00:00.000' + let _endval = item.value ? moment(item.value, 'YYYY-MM-DD').endOf('week').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' : '2050-01-01 00:00:00.000' let copy = JSON.parse(JSON.stringify(item)) copy.key = copy.key + '1' @@ -541,8 +569,14 @@ options.push(item) options.push(copy) } else if (item.type === 'daterange') { - let _startval = item.value && item.value[0] ? item.value[0] + ' 00:00:00.000' : '1970-01-01 00:00:00.000' - let _endval = item.value && item.value[1] ? moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' : '2050-01-01 00:00:00.000' + let _startval = '1970-01-01 00:00:00.000' + let _endval = '2050-01-01 00:00:00.000' + + if (item.value) { + let val = item.value.split(',') + _startval = val[0] + ' 00:00:00.000' + _endval = moment(val[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' + } let copy = JSON.parse(JSON.stringify(item)) copy.key = copy.key + '1' @@ -552,10 +586,6 @@ options.push(item) options.push(copy) - } else if (item.type === 'multiselect') { - item.value = item.value ? item.value.join(',') : item.value - - options.push(item) } else if (item.type === 'text' || item.type === 'select') { item.key.split(',').forEach(field => { // 缁煎悎鎼滅储锛屾墍瀛楁鎷兼帴 let cell = JSON.parse(JSON.stringify(item)) @@ -595,6 +625,10 @@ if (search.type === 'group') { options.push({ + key: search.field, + value: '0' + }) + options.push({ key: search.datefield, value: '0' }) @@ -602,9 +636,7 @@ key: search.datefield + '1', value: '0' }) - if (search.transfer === 'true') { - options.push(item) - } + options.push(item) } else if (['datemonth', 'dateweek', 'daterange'].includes(search.type)) { options.push(item) options.push({ @@ -624,33 +656,6 @@ }) return options - } - - /** - * @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 } /** @@ -702,7 +707,10 @@ arrfield.push(...item.linkSubField) } else if (item.type === 'checkcard') { arrfield = item.fields.map(f => f.field) - arrfield.push(item.valueField) + arrfield.push(item.cardValField) + if (item.urlField) { + arrfield.push(item.urlField) + } } arrfield = Array.from(new Set(arrfield)) @@ -758,14 +766,21 @@ let userName = sessionStorage.getItem('User_Name') || '' let fullName = sessionStorage.getItem('Full_Name') || '' let city = sessionStorage.getItem('city') || '' + let _sheet = item.sheet if (sessionStorage.getItem('isEditState') === 'true') { userName = sessionStorage.getItem('CloudUserName') || '' fullName = sessionStorage.getItem('CloudFullName') || '' } - let database = item.sheet.match(/(.*)\.(.*)\./ig) || '' - let sheet = item.sheet.replace(/(.*)\.(.*)\./ig, '') + if (window.GLOB.externalDatabase !== null) { + _sheet = _sheet.replace(/@db@/ig, window.GLOB.externalDatabase) + } + + let database = _sheet.match(/(.*)\.(.*)\./ig) + let sheet = _sheet.replace(/(.*)\.(.*)\./ig, '') + + database = database ? (database[0] || '') : '' let getuuid = () => { let uuid = [] @@ -811,6 +826,11 @@ // 鎺у埗鍙版墦鍗版暟鎹� let conLtext = [] + let cols = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] + for (let i = 0; i < 26; i++) { + cols.push('A' + cols[i]) + } + let _Ltext = data.map((item, lindex) => { let vals = [] let convals = [] @@ -818,14 +838,15 @@ if (col.import === 'false') return let val = item[col.Column] !== undefined ? item[col.Column] : '' - let _position = (_topline + lindex + 1) + dict['main.excel.line'] + ' ' + (cindex + 1) + dict['main.excel.column'] + ' ' + let _colindex = cols[cindex] || (cindex + 1) + let _position = (_topline + lindex + 1) + dict['main.excel.line'] + ' ' + _colindex + dict['main.excel.column'] + ' ' if (/^Nvarchar/ig.test(col.type)) { if (typeof(val) === 'number') { val = val.toString() } - val = val.replace(/(^\s*$)|\t*|\v*/ig, '') + val = val.replace(/(^\s*$)|\t*|\v*|'*/ig, '') if (!val && col.required === 'true') { // 蹇呭~鏍¢獙 errors.push(_position + dict['main.excel.content.emptyerror']) @@ -1057,13 +1078,14 @@ * @return {Object} tab 鏍囩淇℃伅 * @return {Boolean} retmsg 鏄惁闇�瑕佹暟鎹繑鍥� */ -export function getSysDefaultSql (btn, setting, formdata, param, data, columns, tab, retmsg = false) { +export function getSysDefaultSql (btn, setting, formdata, param, data, columns, tab, retmsg = false, moduleParams, getOptions) { let primaryId = param.ID let BID = param.BID let verify = btn.verify || {} let datavars = {} // 澹版槑鐨勫彉閲忥紝琛ㄥ崟鍙婃樉绀哄垪 let _actionType = null let _callbacksql = '' + let foreignKey = tab && tab.foreignKey ? tab.foreignKey.toLowerCase() : '' if (verify.default !== 'false') { // 鍒ゆ柇鏄惁浣跨敤榛樿sql _actionType = btn.sqlType @@ -1156,7 +1178,7 @@ } // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃) - if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce') { + if (data && !btn.$forbid && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce') { datavars = {...data, ...datavars} const setField = (col) => { @@ -1290,14 +1312,53 @@ // 澶辨晥楠岃瘉锛屾坊鍔犳暟鎹椂涓嶇敤 if (btn.sqlType !== 'insert' && btn.Ot !== 'notRequired' && verify.invalid === 'true' && setting.dataresource) { let datasource = setting.dataresource + let customScript = setting.customScript || '' + let search = moduleParams ? moduleParams.search : null + let orderBy = moduleParams ? moduleParams.orderBy : setting.order + if (/\s/.test(datasource) && !/tb$/.test(datasource)) { // 鎷兼帴鍒悕 datasource = '(' + datasource + ') tb' } - if (setting.customScript) { + if (getOptions && (setting.queryType === 'statistics' || customScript)) { + let allSearch = getOptions(search) + + let regoptions = allSearch.map(item => { + return { + reg: new RegExp('@' + item.key + '@', 'ig'), + value: `'${item.value}'` + } + }) + regoptions.push({ + reg: new RegExp('@login_city@', 'ig'), + value: `'${city}'` + }, { + reg: new RegExp('@userName@', 'ig'), + value: `'${userName}'` + }, { + reg: new RegExp('@fullName@', 'ig'), + value: `'${fullName}'` + }, { + reg: new RegExp('@orderBy@', 'ig'), + value: orderBy + }, { + reg: new RegExp('@pageSize@', 'ig'), + value: 999999 + }, { + reg: new RegExp('@pageIndex@', 'ig'), + value: 1 + }) + + regoptions.forEach(item => { + datasource = datasource.replace(item.reg, item.value) + customScript = customScript.replace(item.reg, item.value) + }) + } + + if (customScript) { _sql += ` /* 鏁版嵁婧愯嚜瀹氫箟鑴氭湰锛岃娉ㄦ剰鍙橀噺瀹氫箟鏄惁閲嶅 */ - ${setting.customScript} + ${customScript} ` } @@ -1435,9 +1496,9 @@ if (_key === 'bid' && !datavars.bid) { // 琛ㄥ崟涓病鏈塨id鍒欎娇鐢ㄧ郴缁焍id鍙橀噺 _fval = '@BID@' } - if (_key === 'bid' && tab && tab.foreignKey) { - arr.push(tab.foreignKey.toLowerCase()) - _fieldValue.push(`${tab.foreignKey}=${_fval}`) + if (_key === 'bid' && foreignKey) { + arr.push(foreignKey) + _fieldValue.push(`${foreignKey}=${_fval}`) } else { arr.push(_key) _fieldValue.push(`${_key}=${_fval}`) @@ -1558,14 +1619,14 @@ values.push('@fullname') } if (!keys.includes('bid')) { - if (tab && tab.foreignKey && !keys.includes(tab.foreignKey.toLowerCase())) { - keys.push(tab.foreignKey.toLowerCase()) + if (foreignKey && !keys.includes(foreignKey)) { + keys.push(foreignKey) } else { keys.push('bid') } values.push('@BID@') - } else if (tab && tab.foreignKey && !keys.includes(tab.foreignKey.toLowerCase())) { - keys.push(tab.foreignKey.toLowerCase()) + } else if (foreignKey && !keys.includes(foreignKey)) { + keys.push(foreignKey) values.push('@BID@') } @@ -1714,6 +1775,45 @@ } /** + * @description 鐢熸垚鏇挎崲鍑芥暟鍒楄〃 + */ +export function setGLOBFuncs () { + window.GLOB.funcs = [] + if (!window.GLOB.WebSql && !window.GLOB.IndexDB) { + return + } + + if (window.GLOB.WebSql) { + window.GLOB.WebSql.transaction(tx => { + tx.executeSql("SELECT * FROM FUNCS", [], (tx, results) => { + let rows = results.rows + if (!rows || rows.length === 0) return + for (let i = 0; i < rows.length; i++) { + window.GLOB.funcs.push({ + func_code: rows[i].func_code, + key_sql: window.decodeURIComponent(window.atob(rows[i].key_sql)) + }) + } + }) + }) + } else { + let objectStore = window.GLOB.IndexDB.transaction('funcs').objectStore('funcs') + + objectStore.openCursor().onsuccess = (event) => { + let cursor = event.target.result + + if (cursor) { + window.GLOB.funcs.push({ + func_code: cursor.value.func_code, + key_sql: window.decodeURIComponent(window.atob(cursor.value.key_sql)) + }) + cursor.continue() + } + } + } +} + +/** * @description 鍒涘缓瀛樺偍杩囩▼绫� */ export class FuncUtils { diff --git a/src/views/appmanage/header/index.jsx b/src/views/appmanage/header/index.jsx new file mode 100644 index 0000000..96bba6d --- /dev/null +++ b/src/views/appmanage/header/index.jsx @@ -0,0 +1,31 @@ +import React, {Component} from 'react' + +import avatar from '@/assets/img/avatar.jpg' +import MainLogo from '@/assets/img/main-logo.png' +import './index.scss' + +class AppManageHeader extends Component { + state = { + avatar: sessionStorage.getItem('CloudAvatar') || avatar, + userName: sessionStorage.getItem('CloudUserName') + } + + render () { + return ( + <header className="app-manage-header-container"> + <div className="header-logo"><img src={MainLogo} alt=""/></div> + <div className="title"> + 搴旂敤绠$悊 + </div> + <div className="header-user"> + <img src={this.state.avatar} alt=""/> + <span> + <span className="username">{this.state.userName}</span> + </span> + </div> + </header> + ) + } +} + +export default AppManageHeader \ No newline at end of file diff --git a/src/views/appmanage/header/index.scss b/src/views/appmanage/header/index.scss new file mode 100644 index 0000000..fd7bb98 --- /dev/null +++ b/src/views/appmanage/header/index.scss @@ -0,0 +1,57 @@ +.app-manage-header-container { + width: 100%; + height: 48px; + color: rgba(255, 255, 255, 0.65); + position: fixed; + top: 0px; + z-index: 10; + padding-right: 0px; + left: 0; + + background: #001529; + border-bottom: 1px solid #000; + + .header-logo { + float: left; + width: 180px; + line-height: 48px; + text-align: center; + padding-left: 5px; + box-sizing: border-box; + opacity: 1; + img { + max-width: 100%; + max-height: 40px; + } + } + .header-user { + float: right; + line-height: 48px; + margin-right: 10px; + img { + width: 29px; + height: 29px; + border-radius: 30px; + margin-right: 7px; + } + span { + color: #ffffff; + font-size: 0.95rem; + .username { + display: inline-block; + height: 30px; + max-width: 95px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + } + .title { + position: absolute; + left: calc(50% - 36px); + top: 10px; + color: #ffffff; + font-size: 18px; + } +} \ No newline at end of file diff --git a/src/views/appmanage/index.jsx b/src/views/appmanage/index.jsx index 3efc3ba..c238f65 100644 --- a/src/views/appmanage/index.jsx +++ b/src/views/appmanage/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import { fromJS } from 'immutable' -import { Spin, notification, Button, Table, Modal, ConfigProvider } from 'antd' +import { Spin, notification, Input, Button, Table, Modal, ConfigProvider, Typography, Row, Col, Tooltip, Icon } from 'antd' import moment from 'moment' import md5 from 'md5' import enUS from 'antd/es/locale/en_US' @@ -12,114 +12,115 @@ import './index.scss' const { confirm } = Modal +const { Paragraph } = Typography +const { Search } = Input const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS -const Header = asyncComponent(() => import('@/mob/header')) +const Header = asyncComponent(() => import('./header')) const MutilForm = asyncComponent(() => import('./mutilform')) +const TransForm = asyncComponent(() => import('./transform')) +const ScriptForm = asyncComponent(() => import('./scriptform')) const SubMutilForm = asyncComponent(() => import('./submutilform')) + +let base_url = '' +if (process.env.NODE_ENV === 'production') { + base_url = document.location.origin + '/' + window.GLOB.service +} else { + base_url = window.GLOB.location + '/' + window.GLOB.service +} + +sessionStorage.setItem('isEditState', 'true') + +const skinStyle = { + bg_black_style_blue: {name: '钃濊壊', color: '#1890ff'}, + bg_black_style_red: {name: '绾㈣壊', color: '#f5222d'}, + bg_black_style_orange_red: {name: '姗欑孩鑹�', color: '#fa541c'}, + bg_black_style_orange: {name: '姗欒壊', color: '#fa8c16'}, + bg_black_style_orange_yellow: {name: '姗欓粍鑹�', color: '#faad14'}, + bg_black_style_yellow: {name: '榛勮壊', color: '#fadb14'}, + bg_black_style_yellow_green: {name: '榛勭豢鑹�', color: '#a0d911'}, + bg_black_style_green: {name: '缁胯壊', color: '#52c41a'}, + bg_black_style_cyan: {name: '闈掕壊', color: '#13c2c2'}, + bg_black_style_blue_purple: {name: '钃濈传鑹�', color: '#2f54eb'}, + bg_black_style_purple: {name: '绱壊', color: '#722ed1'}, + bg_black_style_magenta: {name: '娲嬬孩鑹�', color: '#eb2f96'}, + bg_black_style_grass_green: {name: '鑽夌豢鑹�', color: '#aeb303'}, + bg_black_style_deep_red: {name: '娣辩孩鑹�', color: '#c32539'} +} class AppManage extends Component { state = { loading: false, applist: [], columns: [ - { title: '搴旂敤鍚嶇О', dataIndex: 'remark', key: 'remark', align: 'center' }, - { title: '搴旂敤缂栫爜', dataIndex: 'kei_no', key: 'kei_no', align: 'center' }, + { title: '搴旂敤鍚嶇О', dataIndex: 'remark', key: 'remark', align: 'center', width: '30%' }, + { title: '搴旂敤缂栫爜', dataIndex: 'kei_no', key: 'kei_no', align: 'center', width: '30%' }, { title: '鎿嶄綔', key: 'action', align: 'center', - render: (text, record) => (<Button type="link" onClick={() => this.deleteApp(record)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button>), - }, - ], - subcolumns: [ - { - title: '搴旂敤绫诲瀷', dataIndex: 'typename', key: 'typename', align: 'center' - }, - { - title: '璇█', dataIndex: 'lang', key: 'lang', align: 'center', - render: (text, record) => text === 'en-US' ? '鑻辨枃' : '涓枃' - }, - { - title: '鐧诲綍', dataIndex: 'login_types', key: 'login_types', align: 'center', - render: (text, record) => text === 'false' ? '涓嶉渶瑕�' : '闇�瑕�' - }, - { - title: '鏉冮檺绠$悊', dataIndex: 'role_type', key: 'role_type', align: 'center', - render: (text, record) => text === 'false' ? '涓嶅惎鐢�' : '鍚敤' - }, - { - title: '鐭繛鎺�', dataIndex: 'link_type', key: 'link_type', align: 'center', - render: (text, record) => text === 'false' ? '涓嶅惎鐢�' : '鍚敤' - }, - { - title: '鐨偆', dataIndex: 'css', key: 'css', align: 'center', - render: (text, record) => { - const style = { - bg_black_style_blue: '钃濋粦鑹茬郴', - bg_white_style_blue: '钃濈櫧鑹茬郴', - bg_black_style_red: '绾㈤粦鑹茬郴', - bg_white_style_red: '绾㈢櫧鑹茬郴', - bg_black_style_orange_red: '姗欑孩榛戣壊绯�', - bg_white_style_orange_red: '姗欑孩鐧借壊绯�', - bg_black_style_orange: '姗欓粦鑹茬郴', - bg_white_style_orange: '姗欑櫧鑹茬郴', - bg_black_style_orange_yellow: '姗欓粍榛戣壊绯�', - bg_white_style_orange_yellow: '姗欓粍鐧借壊绯�', - bg_black_style_yellow: '榛勯粦鑹茬郴', - bg_white_style_yellow: '榛勭櫧鑹茬郴', - bg_black_style_yellow_green: '榛勭豢榛戣壊绯�', - bg_white_style_yellow_green: '榛勭豢鐧借壊绯�', - bg_black_style_green: '缁块粦鑹茬郴', - bg_white_style_green: '缁跨櫧鑹茬郴', - bg_black_style_cyan: '闈掗粦鑹茬郴', - bg_white_style_cyan: '闈掔櫧鑹茬郴', - bg_black_style_blue_purple: '钃濈传榛戣壊绯�', - bg_white_style_blue_purple: '钃濈传鐧借壊绯�', - bg_black_style_purple: '绱粦鑹茬郴', - bg_white_style_purple: '绱櫧鑹茬郴', - bg_black_style_magenta: '娲嬬孩榛戣壊绯�', - bg_white_style_magenta: '娲嬬孩鐧借壊绯�', - bg_black_style_grass_green: '鑽夌豢榛戣壊绯�', - bg_white_style_grass_green: '鑽夌豢鐧借壊绯�', - bg_black_style_deep_red: '娣辩孩榛戣壊绯�', - bg_white_style_deep_red: '娣辩孩鐧借壊绯�' - } - - return style[text] || '钃濋粦鑹茬郴' - } - }, - { - title: '鏍囬', dataIndex: 'title', key: 'title', align: 'center', width: '170px' - }, - { - title: '鍥炬爣', dataIndex: 'favicon', key: 'favicon', align: 'center', width: '120px', - render: (text, record) => (text ? <img style={{width: '32px', height: '32px'}} src={text} alt="" /> : null) - }, - { - title: '鎿嶄綔', - key: 'action', - align: 'center', - width: '190px', + width: '40%', render: (text, record) => ( <div> - <Button type="link" onClick={() => this.deleteSubApp(record)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button> - <Button type="link" onClick={() => this.jumpApp(record)}>缂栬緫搴旂敤</Button> + <Button type="link" onClick={() => this.setState({ selectApp: record, visible: 'edit' })} style={{color: '#8E44AD'}}>淇敼</Button> + <Button type="link" onClick={() => this.deleteApp(record)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button> + <Button type="link" onClick={() => this.setState({ selectSubApp: record, subVisible: 'plus' })} style={{color: '#26C281'}}>娣诲姞瀛愬簲鐢�</Button> </div> - ) + ), }, ], selectApp: null, selectSubApp: null, - selectedRowKeys: [], - selectedSubRowKeys: [], visible: false, - subVisible: false + subVisible: false, + transcolumns: [ + { title: '浼犺緭鍙�', dataIndex: 'VersionName', key: 'VersionName', align: 'left', render: (text, record) => ( + <Paragraph copyable={{text}}>{text}</Paragraph> + )}, + { title: '璇存槑', dataIndex: 'ProgramName', key: 'ProgramName', align: 'left' }, + { title: '鐘舵��', dataIndex: 'StatusName', key: 'StatusName', align: 'left' }, + { title: '鍒涘缓鏃堕棿', dataIndex: 'CreateDate', key: 'CreateDate', align: 'left' }, + { + title: '鎿嶄綔', + key: 'action', + align: 'center', + width: '230px', + render: (text, record) => ( + <div onClick={() => this.forbid = true}> + <Button type="link" onClick={() => this.setState({ editTran: record, transVisible: 'edit' })} style={{color: '#8E44AD'}}>淇敼</Button> + <Button type="link" onClick={() => this.deleteTran(record)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button> + <Button type="link" onClick={() => this.enableTran(record)} style={{color: '#26C281'}}>鍚敤</Button> + </div> + ), + }, + ], + transVisible: false, + translist: [], + tranSearchKey: '', + selectTran: null, + editTran: null, + transIndex: 1, + transTotal: 0, + scriptcolumns: [ + { title: '鍏抽敭瀛�', dataIndex: 'KeyWords', key: 'KeyWords', align: 'left' }, + { title: '鎻忚堪', dataIndex: 'Remark', key: 'Remark', align: 'left' }, + { title: '绫诲瀷', dataIndex: 'TypeName', key: 'TypeName', align: 'left' }, + { title: '鎺掑簭', dataIndex: 'Sort', key: 'Sort', align: 'left' }, + ], + scriptVisible: false, + scriptlist: [], + scriptSearchKey: '', + scriptIndex: 1, + scriptTotal: 0, } + + forbid = false UNSAFE_componentWillMount() { document.body.className = '' this.getAppList() + this.getSmStemp() + this.getTransList() } /** @@ -131,10 +132,322 @@ } } + getTransList = () => { + const { tranSearchKey, transIndex } = this.state + + let param = { + func: 's_get_sVersion', + dataM: 'Y', + PageSize: 10, + PageIndex: transIndex, + OrderCol: 'ID desc' + } + + if (tranSearchKey) { + param.VersionName = tranSearchKey + param.ProgramName = tranSearchKey + } + + this.setState({ + loading: true + }) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + this.setState({ + loading: false, + translist: result.data, + selectTran: null, + scriptlist: [], + transTotal: result.total + }) + } else { + this.setState({ + loading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }) + } + + getScriptList = () => { + const { scriptSearchKey, scriptIndex, selectTran } = this.state + + if (!selectTran || !selectTran.ID) { + notification.warning({ + top: 92, + message: '缂哄皯浼犺緭鍙稩D!', + duration: 3 + }) + return + } + + let param = { + func: 's_get_sVersionDetail', + dataM: 'Y', + PageSize: 10, + PageIndex: scriptIndex, + OrderCol: 'Sort desc', + BID: selectTran.ID, + } + + if (scriptSearchKey) { + param.TypeName = scriptSearchKey + param.KeyWords = scriptSearchKey + param.Remark = scriptSearchKey + } + + this.setState({ + loading: true + }) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + this.setState({ + loading: false, + scriptlist: result.data, + scriptTotal: result.total, + selectScriptKeys: [] + }) + } else { + this.setState({ + loading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }) + } + + scriptSearch = (value) => { + this.setState({scriptSearchKey: value, scriptIndex: 1}, () => { + this.getScriptList() + }) + } + + changeScriptTable = (pagination) => { + this.setState({ + scriptIndex: pagination.current + }, () => { + this.getScriptList() + }) + } + + changeTable = (pagination) => { + this.setState({ + transIndex: pagination.current + }, () => { + this.getTransList() + }) + } + + tranSearch = (value) => { + this.setState({tranSearchKey: value, transIndex: 1}, () => { + this.getTransList() + }) + } + + submitTrans = () => { + const { transVisible, editTran } = this.state + + this.transRef.handleConfirm().then(res => { + this.setState({ + confirmloading: true + }) + + let param = {} + + if (transVisible === 'plus') { + param.func = 's_sVersion_add' + param.VersionName = res.VersionName + param.ProgramName = res.ProgramName + } else { + param.func = 's_sVersion_upt' + param.ProgramName = res.ProgramName + param.ID = editTran.ID + } + + Api.getCloudConfig(param).then(result => { + if (result.status) { + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛锛�', + duration: 3 + }) + this.setState({ + confirmloading: false, + transVisible: false + }) + this.getTransList() + } else { + this.setState({ + confirmloading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }, () => { + this.setState({ + confirmloading: false + }) + }) + }) + } + + submitScript = () => { + const { selectTran } = this.state + + this.scriptRef.handleConfirm().then(res => { + this.setState({ + confirmloading: true + }) + + let kei_no = res.appId.split(',')[1] + let lang = res.subAppId.split(',')[1] + let kei_no_detail = res.subAppId.split(',')[2] + + let param = { + func: 's_sVersionDetail_CloudAdd', + kei_no: kei_no, + kei_no_detail: kei_no_detail, + lang: lang, + BID: selectTran.ID + } + + if (res.VType === 'subapp') { + param.VType = 'mob_menu' + param.TrdMenuID = '' + param.upid = md5(window.GLOB.appkey + kei_no + kei_no_detail + lang) + } else if (res.VType === 'view') { + param.VType = 'mob_menu' + param.TrdMenuID = res.viewId + } else if (res.VType === 'role') { + param.VType = 'mob_roletree' + param.upid = md5(window.GLOB.appkey + kei_no + kei_no_detail + lang) + } + + Api.getCloudConfig(param).then(result => { + if (result.status) { + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛锛�', + duration: 3 + }) + this.setState({ + scriptIndex: 1, + confirmloading: false, + scriptVisible: false + }, () => { + this.getScriptList() + }) + } else { + this.setState({ + confirmloading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }, () => { + this.setState({ + confirmloading: false + }) + }) + }) + } + + deleteTran = (record) => { + const _this = this + + let param = { + func: 's_sVersion_del', + ID: record.ID + } + + confirm({ + content: '纭畾鍒犻櫎璇ヤ紶杈撳彿鍚楋紵', + onOk() { + return new Promise(resolve => { + Api.getCloudConfig(param).then(result => { + if (result.status) { + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛锛�', + duration: 3 + }) + _this.getTransList() + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + resolve() + }, () => { + resolve() + }) + }) + }, + onCancel() {} + }) + } + + enableTran = (record) => { + const _this = this + + let param = { + func: 's_sVersion_sub', + ID: record.ID + } + + confirm({ + content: '纭畾鍚敤璇ヤ紶杈撳彿鍚楋紵', + onOk() { + return new Promise(resolve => { + Api.getCloudConfig(param).then(result => { + if (result.status) { + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛锛�', + duration: 3 + }) + _this.getTransList() + } else { + Modal.error({ + title: result.message, + }) + } + resolve() + }, () => { + resolve() + }) + }) + }, + onCancel() {} + }) + } + getAppList = () => { let param = { func: 's_get_kei' } + + this.setState({ + loading: true + }) Api.getCloudConfig(param).then(result => { if (result.status) { @@ -153,6 +466,10 @@ return item }) + if (!selectApp && applist[0]) { + selectApp = applist[0] + } + this.setState({ loading: false, applist: applist, @@ -169,6 +486,39 @@ duration: 5 }) } + }) + } + + getSmStemp = () => { + let _sql = `select ID,TemplateCode,SignName from (select * from bd_msn_sms_temp where deleted=0 and status=20 ) a + inner join (select openid from sapp where id='${window.GLOB.appkey}') b + on a.openid=b.openid` + + _sql = Utils.formatOptions(_sql) + + let param = { + func: 'sPC_Get_SelectedList', + LText: _sql, + obj_name: 'data', + arr_field: 'ID,TemplateCode,SignName' + } + + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉 + + Api.getSystemConfig(param).then(res => { + let msgs = [] + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } else if (res.data) { + msgs = res.data + } + sessionStorage.setItem('msgTemplate', JSON.stringify(msgs)) }) } @@ -194,8 +544,6 @@ }) _this.setState({ - selectedRowKeys: [], - selectedSubRowKeys: [], selectApp: null, selectSubApp: null, loading: true @@ -237,7 +585,8 @@ let sublist = fromJS(selectApp.sublist).toJS() sublist = sublist.filter(item => item.ID !== record.ID) - param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}'`) + // param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}'`) + param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || ''}','${item.sms_id || ''}'`) param.LText = param.LText.join(' union all ') param.LText = Utils.formatOptions(param.LText) @@ -254,7 +603,6 @@ }) _this.setState({ - selectedSubRowKeys: [], selectSubApp: null, loading: true }) @@ -287,74 +635,134 @@ window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'})))}`)) } - /** - * - */ + jumpMenu = (item) => { + const { selectApp } = this.state + + window.open(window.location.href.replace(/#.+/ig, `#/role/${window.btoa(window.encodeURIComponent(JSON.stringify({...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'})))}`)) + } + onSelectChange = selectedRowKeys => { const { applist } = this.state let selectApp = applist.filter(item => item.ID === selectedRowKeys[0])[0] - this.setState({ selectedRowKeys, selectApp }) + this.setState({ selectApp }) } - /** - * - */ - onSubChange = selectedSubRowKeys => { - this.setState({ selectedSubRowKeys }) + onScriptChange = selectedRowKeys => { + this.setState({ selectScriptKeys: selectedRowKeys }) + } + + onScriptSelect = (record) => { + const { selectScriptKeys } = this.state + + if (selectScriptKeys.includes(record.ID)) { + this.setState({ selectScriptKeys: selectScriptKeys.filter(key => key !== record.ID) }) + } else { + this.setState({ selectScriptKeys: [...selectScriptKeys, record.ID]}) + } + } + + deleteScripts = () => { + const { selectScriptKeys, selectTran } = this.state + + if (selectScriptKeys.length === 0) { + notification.warning({ + top: 92, + message: '璇烽�夋嫨瑕佸垹闄ょ殑鑴氭湰锛�', + duration: 3 + }) + return + } + + let params = selectScriptKeys.map(key => { + return { + func: 's_sVersionDetail_del', + BID: selectTran.ID, + ID: key + } + }) + + const _this = this + + confirm({ + content: '纭畾瑕佹墽琛屽悧锛�', + onOk() { + return new Promise(resolve => { + let deffers = params.map((param, i) => { + return new Promise(resolve => { + setTimeout(() => { + Api.getCloudConfig(param).then(res => { + resolve(res) + }, () => { + resolve({status: false, message: '鍒犻櫎澶辫触锛�'}) + }) + }, i * 150) + }) + }) + Promise.all(deffers).then(result => { + let errorMsg = '' + result.forEach(res => { + if (!res.status) { + errorMsg = res.message + } + }) + if (errorMsg) { + notification.warning({ + top: 92, + message: errorMsg, + duration: 3 + }) + } else { + notification.success({ + top: 92, + message: '鎵ц鎴愬姛銆�', + duration: 3 + }) + _this.setState({ + scriptIndex: 1 + }, () => { + _this.getScriptList() + }) + } + resolve() + }) + }) + }, + onCancel() {} + }) + } + + onTransChange = selectedRowKeys => { + const { translist, selectTran } = this.state + let _selectTran = translist.filter(item => item.ID === selectedRowKeys[0])[0] + + this.setState({ selectTran: _selectTran }) + + if (!selectTran || selectTran.ID !== _selectTran.ID) { + this.setState({ scriptIndex: 1 }, () => { + this.getScriptList() + }) + } + } + + onTransSelect = (record) => { + const { selectTran } = this.state + + this.setState({ selectTran: record }) + + if (!selectTran || selectTran.ID !== record.ID) { + this.setState({ scriptIndex: 1 }, () => { + this.getScriptList() + }) + } } /** * @description 鐐瑰嚮鏁磋锛岃Е鍙戝垏鎹紝 鍒ゆ柇鏄惁鍙�夛紝鍗曢�夋垨澶氶�夛紝杩涜瀵瑰簲鎿嶄綔 */ changeRow = (record) => { - this.setState({ selectedRowKeys: [record.ID], selectApp: record }) + this.setState({ selectApp: record }) } - - /** - * @description 鐐瑰嚮鏁磋锛岃Е鍙戝垏鎹紝 鍒ゆ柇鏄惁鍙�夛紝鍗曢�夋垨澶氶�夛紝杩涜瀵瑰簲鎿嶄綔 - */ - changeSubRow = (record) => { - this.setState({ selectedSubRowKeys: [record.ID], selectSubApp: record }) - } - - trigerApp = (type) => { - if (type === 'edit' && !this.state.selectApp) { - notification.warning({ - top: 92, - message: '璇烽�夋嫨闇�瑕佺紪杈戠殑搴旂敤锛�', - duration: 5 - }) - return - } - - this.setState({ - visible: type - }) - } - - trigerSubApp = (type) => { - if (type === 'edit' && !this.state.selectSubApp) { - notification.warning({ - top: 92, - message: '璇烽�夋嫨闇�瑕佺紪杈戠殑瀛愬簲鐢紒', - duration: 5 - }) - return - } else if (!this.state.selectApp) { - notification.warning({ - top: 92, - message: '璇烽�夋嫨搴旂敤锛�', - duration: 5 - }) - return - } - - this.setState({ - subVisible: type - }) - } - submitCard = () => { const { selectApp, visible } = this.state @@ -384,7 +792,8 @@ param.secretkey = Utils.encrypt('', param.timestamp) if (visible === 'edit') { - param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}'`) + // param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}'`) + param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || ''}','${item.sms_id || ''}'`) param.LText = param.LText.join(' union all ') param.LText = Utils.formatOptions(param.LText) } @@ -398,8 +807,6 @@ }) this.setState({ - selectedRowKeys: [], - selectedSubRowKeys: [], selectApp: null, selectSubApp: null, confirmloading: false, @@ -470,7 +877,8 @@ }) } - param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}'`) + // param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}'`) + param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || ''}','${item.sms_id || ''}'`) param.LText = param.LText.join(' union all ') param.LText = Utils.formatOptions(param.LText) @@ -483,7 +891,6 @@ }) this.setState({ - selectedSubRowKeys: [], selectSubApp: null, confirmloading: false, subVisible: false, @@ -509,7 +916,7 @@ } render () { - const { loading, visible, subVisible, columns, applist, selectedRowKeys, selectedSubRowKeys, subcolumns, selectApp, selectSubApp } = this.state + const { loading, visible, subVisible, columns, transcolumns, applist, translist, transVisible, selectApp, selectTran, selectSubApp, scriptVisible, scriptlist, scriptcolumns, selectScriptKeys } = this.state return ( <div className="mk-app-manage"> @@ -517,45 +924,161 @@ <Header view="manage" /> {loading ? <div className="loading-mask"> - <div className="ant-spin-blur"></div> - <Spin /> + <Spin size="large" /> </div> : null } - <div className="app-table"> - <div className="app-action"> - <Button className="mk-green" onClick={() => this.trigerApp('plus')}>娣诲姞</Button> - <Button className="mk-purple" onClick={() => this.trigerApp('edit')}>淇敼</Button> + <div className="view-wrap"> + <div className="left-view"> + <div className="app-table"> + <div className="app-action"> + <Button className="mk-green" onClick={() => this.setState({ visible: 'plus' })}>娣诲姞搴旂敤</Button> + </div> + <Table + rowKey="ID" + columns={columns} + dataSource={applist} + pagination={false} + rowSelection={{ type: 'radio', selectedRowKeys: selectApp ? [selectApp.ID] : [], onChange: this.onSelectChange }} + onRow={(record) => ({ onClick: () => this.setState({ selectApp: record })})} + /> + </div> + <div className={'trans-table' + (this.state.transTotal <= 10 ? ' no-footer' : '')}> + <div className="app-action"> + <Button className="mk-green" onClick={() => this.setState({ transVisible: 'plus' })}>娣诲姞浼犺緭鍙�</Button> + <Search placeholder="缁煎悎鎼滅储" onSearch={value => this.tranSearch(value)} enterButton /> + </div> + <Table + rowKey="ID" + columns={transcolumns} + dataSource={translist} + pagination={{ + current: this.state.transIndex, + pageSize: 10, + total: this.state.transTotal || 0, + showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉 + }} + rowSelection={{ type: 'radio', selectedRowKeys: selectTran ? [selectTran.ID] : [], onChange: this.onTransChange }} + onRow={(record) => ({ onClick: () => { + if (this.forbid) { + this.forbid = false + return + } + this.onTransSelect(record) + }})} + onChange={this.changeTable} + /> + </div> + {selectTran ? <div className="script-table"> + <div className="app-action"> + <Button className="mk-green" onClick={() => this.setState({ scriptVisible: true })}>娣诲姞鑴氭湰</Button> + <Button className="mk-danger" onClick={this.deleteScripts} style={{marginLeft: '15px'}}>鍒犻櫎</Button> + <Search placeholder="缁煎悎鎼滅储" defaultValue={this.state.scriptSearchKey} onSearch={value => this.scriptSearch(value)} enterButton /> + </div> + <Table + rowKey="ID" + columns={scriptcolumns} + dataSource={scriptlist} + pagination={{ + current: this.state.scriptIndex, + pageSize: 10, + total: this.state.scriptTotal || 0, + showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉 + }} + rowSelection={{ type: 'checkbox', selectedRowKeys: selectScriptKeys, onChange: this.onScriptChange }} + onRow={(record) => ({ onClick: () => this.onScriptSelect(record)})} + onChange={this.changeScriptTable} + /> + </div> : null} </div> - <Table - rowKey="ID" - columns={columns} - dataSource={applist} - pagination={false} - rowSelection={{ type: 'radio', selectedRowKeys, onChange: this.onSelectChange }} - onRow={(record) => ({ onClick: () => {this.changeRow(record)} })} - /> - </div> - <div className="app-table"> - <div className="sub-app-title"><span>瀛愬簲鐢�</span></div> - <div className="app-action"> - <Button className="mk-green" onClick={() => this.trigerSubApp('plus')}>娣诲姞</Button> - <Button className="mk-purple" onClick={() => this.trigerSubApp('edit')}>淇敼</Button> + <div className="right-view"> + {selectApp ? <div className="app-title">{selectApp.remark}</div> : null} + {selectApp && selectApp.sublist.map((item, index) => { + let css = skinStyle[item.css] ? skinStyle[item.css].name : '' + let color = skinStyle[item.css] ? skinStyle[item.css].color : '#e8e8e8' + let binding = '' + if (item.user_binding) { + if (item.user_binding.indexOf('uname_pwd') > -1) { + binding = '鐢ㄦ埛鍚�' + } + if (item.user_binding.indexOf('sms_vcode') > -1) { + binding = binding ? binding + '锛屾墜鏈哄彿' : '鎵嬫満鍙�' + } + } + return ( + <div className="sub-app" key={index} style={{borderColor: color}}> + <Row> + <Col span={12}> + <div className="app-item"> + <div className="label">搴旂敤绫诲瀷:</div> + <div className="content" style={{fontSize: '18px', fontWeight: 600}}>{item.typename}</div> + </div> + </Col> + <Col span={12}> + <div className="app-item"> + <div className="label">璇█:</div> + <div className="content" style={{textDecoration: 'underline'}}>{item.lang === 'en-US' ? '鑻辨枃' : '涓枃'}</div> + </div> + </Col> + <Col span={12}> + <div className="app-item"> + <div className="label">鏉冮檺绠$悊:</div> + <div className="content">{item.role_type === 'false' ? '涓嶅惎鐢�' : '鍚敤'}</div> + </div> + </Col> + <Col span={12}> + <div className="app-item"> + {/* <div className="label">鐧诲綍:</div> + <div className="content">{item.login_types === 'false' ? '涓嶉渶瑕�' : '闇�瑕�'}</div> */} + </div> + </Col> + <Col span={12}> + <div className="app-item"> + <div className="label">鐨偆:</div> + <div className="content" style={{color: color}}>{css}</div> + </div> + </Col> + <Col span={12}> + <div className="app-item"> + {binding ? <div className="label"> + <Tooltip placement="topLeft" title="寰俊鍏紬鍙风櫥褰曟椂锛岀郴缁熺敤鎴蜂笌寰俊鐢ㄦ埛鐨勭粦瀹氭柟寮忋��"> + <Icon type="question-circle" /> + 鐢ㄦ埛缁戝畾: + </Tooltip> + </div> : null} + <div className="content">{binding}</div> + </div> + </Col> + <Col span={12}> + <div className="app-item"> + <div className="label">鏍囬:</div> + <div className="content">{item.title || '鏃�'}</div> + </div> + </Col> + <Col span={12}> + <div className="app-item"> + <div className="label">缃戠珯鍥炬爣:</div> + <div className="content">{item.favicon ? <img style={{width: '30px', height: '30px'}} src={item.favicon} alt="" /> : '鏃�'}</div> + </div> + </Col> + </Row> + <div className="action"> + <Button type="link" onClick={() => this.jumpMenu(item)} style={{color: 'rgba(30, 228, 224, 1)'}}>鑿滃崟&鏉冮檺</Button> + <Button type="link" onClick={() => this.setState({ selectSubApp: item, subVisible: 'edit' })} style={{color: '#8E44AD'}}>淇敼</Button> + <Button type="link" onClick={() => this.deleteSubApp(item)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button> + <Button type="link" onClick={() => this.jumpApp(item)}>缂栬緫搴旂敤</Button> + <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${base_url}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}` }}></Paragraph> + </div> + </div> + ) + })} </div> - <Table - rowKey="ID" - columns={subcolumns} - dataSource={selectApp ? selectApp.sublist : []} - pagination={false} - rowSelection={{ type: 'radio', selectedRowKeys: selectedSubRowKeys, onChange: this.onSubChange }} - onRow={(record) => ({ onClick: () => {this.changeSubRow(record)} })} - /> </div> <Modal title={'缂栬緫搴旂敤'} width={'600px'} maskClosable={false} - visible={!!visible} - onCancel={() => this.setState({visible: false})} + visible={visible !== false} + onCancel={() => this.setState({visible: false, confirmloading: false})} confirmLoading={this.state.confirmloading} onOk={this.submitCard} cancelText="鍙栨秷" @@ -565,11 +1088,39 @@ <MutilForm type={visible} card={visible === 'edit' ? selectApp : ''} wrappedComponentRef={(inst) => this.mobcardRef = inst} inputSubmit={this.submitCard} /> </Modal> <Modal - title={'缂栬緫瀛愬簲鐢�'} - width={'750px'} + title={transVisible === 'plus' ? '娣诲姞浼犺緭鍙�' : '缂栬緫浼犺緭鍙�'} + width={'600px'} maskClosable={false} - visible={!!subVisible} - onCancel={() => this.setState({subVisible: false})} + visible={transVisible !== false} + onCancel={() => this.setState({transVisible: false, confirmloading: false})} + confirmLoading={this.state.confirmloading} + onOk={this.submitTrans} + cancelText="鍙栨秷" + okText="纭畾" + destroyOnClose + > + <TransForm type={transVisible} card={transVisible === 'edit' ? this.state.editTran : ''} wrappedComponentRef={(inst) => this.transRef = inst} inputSubmit={this.submitTrans} /> + </Modal> + <Modal + title={'娣诲姞鑴氭湰'} + width={750} + maskClosable={false} + visible={scriptVisible} + onCancel={() => this.setState({scriptVisible: false, confirmloading: false})} + confirmLoading={this.state.confirmloading} + onOk={this.submitScript} + cancelText="鍙栨秷" + okText="纭畾" + destroyOnClose + > + <ScriptForm applist={applist} wrappedComponentRef={(inst) => this.scriptRef = inst} inputSubmit={this.submitScript} /> + </Modal> + <Modal + title={'缂栬緫瀛愬簲鐢�'} + width={'850px'} + maskClosable={false} + visible={subVisible !== false} + onCancel={() => this.setState({subVisible: false, confirmloading: false})} confirmLoading={this.state.confirmloading} onOk={this.submitSubCard} cancelText="鍙栨秷" diff --git a/src/views/appmanage/index.scss b/src/views/appmanage/index.scss index b1aa6a4..5f9cb3b 100644 --- a/src/views/appmanage/index.scss +++ b/src/views/appmanage/index.scss @@ -1,41 +1,121 @@ .mk-app-manage { background: #fff; min-height: 100vh; - padding-bottom: 70px; + padding: 70px 30px; - .mob-header-container { - padding-right: 0px; - position: relative; - z-index: 10; + .loading-mask { + position: fixed; + top: 0px; + bottom: 0px; + left: 0px; + right: 0px; + z-index: 2; + background: rgba(255, 255, 255, 0.35); + + .ant-spin { + position: absolute; + left: 50%; + top: 50%; + } } - .app-table { - max-width: 1440px; - margin: 0 auto; - padding: 40px 30px 20px; - .sub-app-title { - margin-bottom: 15px; - border-bottom: 1px solid #e8e8e8; - span { - position: relative; - top: 1px; - display: inline-block; - color: #1890ff; - padding: 10px 15px 5px; - border-bottom: 2px solid #1890ff; + .view-wrap { + width: 100%; + position: relative; + display: flex; + + .left-view { + flex: 1; + width: 60%; + padding-right: 5px; + .trans-table, .script-table { + margin-top: 40px; + .ant-input-search { + width: 250px; + float: right; + } + .ant-typography, .ant-typography p { + margin-bottom: 0; + } + } + .trans-table.no-footer { + .ant-pagination { + display: none; + } + } + } + .right-view { + width: 40%; + padding-left: 20px; + + .app-title { + font-size: 16px; + font-weight: 500; + height: 30px; + line-height: 30px; + border-bottom: 1px solid #d8d8d8; + margin-bottom: 17px; + } + .sub-app { + margin: 10px 10px 25px; + border: 1px solid #e8e8e8; + height: 180px; + border-radius: 4px; + padding-top: 10px; + + .app-item { + height: 30px; + line-height: 30px; + div { + display: inline-block; + white-space: nowrap; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + line-height: 30px; + } + .label { + width: 40%; + text-align: right; + color: rgba(0, 0, 0, 0.65); + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + } + .content { + width: 60%; + padding-left: 10px; + color: rgba(0, 0, 0, 0.85); + } + } + .action { + text-align: right; + padding: 5px 20px; + margin-top: 5px; + border-top: 1px solid #e8e8e8; + + .ant-typography-copy { + color: #26C281; + } + } } } } .ant-table-wrapper { - border: 1px solid #e8e8e8; - border-bottom: 0; - border-radius: 4px; - .ant-table-tbody > tr.ant-table-row-selected td { - background: #bae7ff; + .ant-table-body { + border: 1px solid #e8e8e8; + border-bottom: 0; + border-radius: 4px; + } + .ant-table-tbody { + > tr.ant-table-row-selected td { + background: #bae7ff; + } } } .app-action { - button { - margin: 0px 15px 15px 0px; + >button { + margin-bottom: 10px; } } } diff --git a/src/views/appmanage/scriptform/index.jsx b/src/views/appmanage/scriptform/index.jsx new file mode 100644 index 0000000..999599d --- /dev/null +++ b/src/views/appmanage/scriptform/index.jsx @@ -0,0 +1,242 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, notification } from 'antd' +import moment from 'moment' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import './index.scss' + +const { TextArea } = Input + +class ScriptForm extends Component { + static propTpyes = { + applist: PropTypes.array, + inputSubmit: PropTypes.func + } + + state = { + type: 'subapp', + sublist: [], + views: [], + appId: '', + subAppId: '' + } + + viewList = {} + + UNSAFE_componentWillMount() { + const { applist } = this.props + + let sublist = [] + let appId = '' + let subAppId = '' + if (applist[0]) { + sublist = applist[0].sublist || [] + appId = applist[0].ID + ',' + applist[0].kei_no + + if (sublist[0]) { + subAppId = sublist[0].ID + ',' + sublist[0].lang + ',' + sublist[0].typename + } + } + + this.viewList = {} + + this.setState({sublist, appId, subAppId}) + } + + /** + * @description 鑾峰彇琛ㄥ崟鍊� + */ + handleConfirm = () => { + return new Promise(resolve => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } + }) + }) + } + + changeType = (val) => { + this.setState({type: val}, () => { + this.getViews() + }) + } + + changeApp = (val) => { + const { applist } = this.props + + let app = applist.filter(item => `${item.ID},${item.kei_no}` === val)[0] + + let appId = '' + let subAppId = '' + let sublist = [] + if (app) { + sublist = app.sublist || [] + appId = app.ID + ',' + app.kei_no + + if (sublist[0]) { + subAppId = sublist[0].ID + ',' + sublist[0].lang + ',' + sublist[0].typename + } + } + + this.setState({sublist, subAppId, appId}, () => { + this.getViews() + }) + this.props.form.setFieldsValue({subAppId}) + } + + changeSubApp = (val) => { + this.setState({subAppId: val}, () => { + this.getViews() + }) + } + + getViews = () => { + const { type, appId, subAppId } = this.state + + if (type !== 'view' || !appId || !subAppId) return + + this.setState({views: []}) + this.props.form.setFieldsValue({viewId: ''}) + + let kei = appId.split(',')[1] + let m = subAppId.split(',') + + let _param = { + func: 's_get_app_menus', + TypeCharOne: kei, + typename: m[2], + lang: m[1], + LText: `select '${window.GLOB.appkey}'`, + timestamp: moment().format('YYYY-MM-DD HH:mm:ss') + } + + _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp) + + Api.getCloudConfig(_param).then(res => { + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + return + } + + this.setState({views: res.menus}) + }) + } + + /** + * @description 鍥炶溅鎻愪氦 + */ + handleSubmit = (e) => { + e.preventDefault() + this.props.inputSubmit() + } + + render() { + const { applist } = this.props + const { getFieldDecorator } = this.props.form + const { sublist, appId, subAppId, type, views } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + return ( + <Form {...formItemLayout} className="app-script-form"> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="绫诲瀷"> + {getFieldDecorator('VType', { + initialValue: 'subapp', + rules: [{ + required: true, + message: '璇烽�夋嫨绫诲瀷!' + }] + })( + <Select onChange={this.changeType}> + <Select.Option value="subapp">瀛愬簲鐢�</Select.Option> + <Select.Option value="view">椤甸潰</Select.Option> + <Select.Option value="role">鏉冮檺鏍�</Select.Option> + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="搴旂敤"> + {getFieldDecorator('appId', { + initialValue: appId, + rules: [{ + required: true, + message: '璇烽�夋嫨搴旂敤!' + }] + })( + <Select onChange={this.changeApp}> + {applist.map(item => { + return <Select.Option key={item.ID} value={item.ID + ',' + item.kei_no}>{item.remark}</Select.Option> + })} + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label="瀛愬簲鐢�"> + {getFieldDecorator('subAppId', { + initialValue: subAppId, + rules: [{ + required: true, + message: '璇烽�夋嫨瀛愬簲鐢�!' + }] + })( + <Select onChange={this.changeSubApp}> + {sublist.map(item => { + return <Select.Option key={item.ID} value={item.ID + ',' + item.lang + ',' + item.typename}>{`${item.typename}锛�${item.lang !== 'zh-CN' ? '鑻辨枃' : '涓枃'}锛�${item.title || ''}`}</Select.Option> + })} + </Select> + )} + </Form.Item> + </Col> + {type === 'view' ? <Col span={12}> + <Form.Item label="椤甸潰"> + {getFieldDecorator('viewId', { + initialValue: '', + rules: [{ + required: true, + message: '璇烽�夋嫨椤甸潰!' + }] + })( + <Select> + {views.map(item => { + return <Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option> + })} + </Select> + )} + </Form.Item> + </Col> : null} + <Col span={24} className="remark"> + <Form.Item label="璇存槑"> + {getFieldDecorator('Remark', { + initialValue: '', + rules: [{ + max: 512, + message: '璇存槑涓嶅彲瓒呰繃512涓瓧绗�!' + }] + })(<TextArea autoSize={{ minRows: 2, maxRows: 6 }} />)} + </Form.Item> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(ScriptForm) \ No newline at end of file diff --git a/src/views/appmanage/scriptform/index.scss b/src/views/appmanage/scriptform/index.scss new file mode 100644 index 0000000..74e8f0b --- /dev/null +++ b/src/views/appmanage/scriptform/index.scss @@ -0,0 +1,12 @@ +.app-script-form { + padding: 0px 24px 20px; + + .remark { + .ant-form-item-label { + width: 16%; + } + .ant-form-item-control-wrapper { + width: 84%; + } + } +} \ No newline at end of file diff --git a/src/views/appmanage/submutilform/index.jsx b/src/views/appmanage/submutilform/index.jsx index 712464f..137c862 100644 --- a/src/views/appmanage/submutilform/index.jsx +++ b/src/views/appmanage/submutilform/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Select, Radio, Input } from 'antd' +import { Form, Row, Col, Select, Radio, Input, Tooltip, Icon, notification } from 'antd' import asyncComponent from '@/utils/asyncComponent' import './index.scss' @@ -14,7 +14,21 @@ inputSubmit: PropTypes.func // input鍥炶溅鎻愪氦 } - state = {} + state = {msgs: [], typename: 'mob', user_binding: []} + + UNSAFE_componentWillMount() { + const { card } = this.props + let msgs = sessionStorage.getItem('msgTemplate') + let user_binding = [] + let typename = 'mob' + + if (card) { + typename = card.typename || 'mob' + user_binding = card.user_binding ? card.user_binding.split(',') : [] + } + + this.setState({msgs: JSON.parse(msgs), typename, user_binding}) + } /** * @description 鑾峰彇琛ㄥ崟鍊� @@ -23,10 +37,14 @@ return new Promise(resolve => { this.props.form.validateFieldsAndScroll((err, values) => { if (!err) { - if (values.favicon && values.favicon.length > 0 && values.favicon[0].status === 'done') { - values.favicon = values.favicon[0].response || values.favicon[0].url || '' - } else { - values.favicon = '' + values.user_binding = values.user_binding ? values.user_binding.join(',') : '' + if (values.user_binding.indexOf('sms_vcode') > -1 && !values.sms_id) { + notification.warning({ + top: 92, + message: '鎵嬫満鍙风粦瀹氭椂锛岄渶瑕佺煭淇℃ā鏉匡紒', + duration: 5 + }) + return } resolve(values) } @@ -45,6 +63,7 @@ render() { const { card, type } = this.props const { getFieldDecorator } = this.props.form + const { msgs, typename, user_binding } = this.state const formItemLayout = { labelCol: { xs: { span: 24 }, @@ -56,28 +75,23 @@ } } - let filelist = [] + let file = '' if (type === 'edit' && card && card.favicon) { - filelist = [{ - uid: `favicon`, - name: card.favicon.slice(card.favicon.lastIndexOf('/') + 1), - status: 'done', - url: card.favicon, - origin: true - }] + file = card.favicon } return ( - <Form {...formItemLayout} className="mob-card-edit-form"> + <Form {...formItemLayout} className="sub-app-edit-form"> <Row gutter={24}> <Col span={12}> <Form.Item label="搴旂敤绫诲瀷"> {getFieldDecorator('typename', { - initialValue: card ? card.typename : 'mob' + initialValue: typename })( - <Select disabled={type === 'edit'}> + <Select disabled={type === 'edit'} onChange={(val) => this.setState({typename: val})}> <Select.Option value="mob">绉诲姩绔�(鍖呮嫭android銆乮os)</Select.Option> + <Select.Option value="pad">Pad绔�</Select.Option> <Select.Option value="pc">PC绔�</Select.Option> </Select> )} @@ -95,7 +109,7 @@ )} </Form.Item> </Col> - <Col span={12}> + {/* <Col span={12}> <Form.Item label="鐧诲綍"> {getFieldDecorator('login_types', { initialValue: card ? card.login_types || 'true' : 'true' @@ -106,7 +120,7 @@ </Radio.Group> )} </Form.Item> - </Col> + </Col> */} <Col span={12}> <Form.Item label="鏉冮檺绠$悊"> {getFieldDecorator('role_type', { @@ -119,52 +133,61 @@ )} </Form.Item> </Col> - <Col span={12}> - <Form.Item label="鐭繛鎺�"> - {getFieldDecorator('link_type', { - initialValue: card ? card.link_type || 'true' : 'true' + {typename !== 'pc' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="浣跨敤寰俊鎺堟潈鐧诲綍鏃讹紝鏄惁闇�瑕佺粦瀹氱敤鎴枫��"> + <Icon type="question-circle" /> + 鐢ㄦ埛缁戝畾 + </Tooltip> + }> + {getFieldDecorator('user_binding', { + initialValue: user_binding })( - <Radio.Group> - <Radio value="true">鍚敤</Radio> - <Radio value="false">涓嶅惎鐢�</Radio> - </Radio.Group> + <Select mode="multiple"> + <Select.Option value="uname_pwd">鐢ㄦ埛鍚�</Select.Option> + <Select.Option value="sms_vcode">鎵嬫満鍙�</Select.Option> + </Select> )} </Form.Item> - </Col> + </Col> : null} + {typename !== 'pc' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐭俊妯℃澘鍙湪绠$悊绯荤粺 HS-濂囦簯鐭俊妯℃澘 澶勬坊鍔犮��"> + <Icon type="question-circle" /> + 鐭俊妯℃澘 + </Tooltip> + }> + {getFieldDecorator('sms_id', { + initialValue: card ? card.sms_id || '' : '' + })( + <Select allowClear> + {msgs.map(option => + <Select.Option key={option.ID} value={option.ID}>{option.SignName + ' - ' + option.TemplateCode}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> : null} <Col span={12}> <Form.Item label="鐨偆"> {getFieldDecorator('css', { initialValue: card ? card.css : 'bg_black_style_blue' })( <Select> - <Select.Option value="bg_black_style_blue">钃濋粦鑹茬郴</Select.Option> - <Select.Option value="bg_white_style_blue">钃濈櫧鑹茬郴</Select.Option> - <Select.Option value="bg_black_style_red">绾㈤粦鑹茬郴</Select.Option> - <Select.Option value="bg_white_style_red">绾㈢櫧鑹茬郴</Select.Option> - <Select.Option value="bg_black_style_orange_red">姗欑孩榛戣壊绯�</Select.Option> - <Select.Option value="bg_white_style_orange_red">姗欑孩鐧借壊绯�</Select.Option> - <Select.Option value="bg_black_style_orange">姗欓粦鑹茬郴</Select.Option> - <Select.Option value="bg_white_style_orange">姗欑櫧鑹茬郴</Select.Option> - <Select.Option value="bg_black_style_orange_yellow">姗欓粍榛戣壊绯�</Select.Option> - <Select.Option value="bg_white_style_orange_yellow">姗欓粍鐧借壊绯�</Select.Option> - <Select.Option value="bg_black_style_yellow">榛勯粦鑹茬郴</Select.Option> - <Select.Option value="bg_white_style_yellow">榛勭櫧鑹茬郴</Select.Option> - <Select.Option value="bg_black_style_yellow_green">榛勭豢榛戣壊绯�</Select.Option> - <Select.Option value="bg_white_style_yellow_green">榛勭豢鐧借壊绯�</Select.Option> - <Select.Option value="bg_black_style_green">缁块粦鑹茬郴</Select.Option> - <Select.Option value="bg_white_style_green">缁跨櫧鑹茬郴</Select.Option> - <Select.Option value="bg_black_style_cyan">闈掗粦鑹茬郴</Select.Option> - <Select.Option value="bg_white_style_cyan">闈掔櫧鑹茬郴</Select.Option> - <Select.Option value="bg_black_style_blue_purple">钃濈传榛戣壊绯�</Select.Option> - <Select.Option value="bg_white_style_blue_purple">钃濈传鐧借壊绯�</Select.Option> - <Select.Option value="bg_black_style_purple">绱粦鑹茬郴</Select.Option> - <Select.Option value="bg_white_style_purple">绱櫧鑹茬郴</Select.Option> - <Select.Option value="bg_black_style_magenta">娲嬬孩榛戣壊绯�</Select.Option> - <Select.Option value="bg_white_style_magenta">娲嬬孩鐧借壊绯�</Select.Option> - <Select.Option value="bg_black_style_grass_green">鑽夌豢榛戣壊绯�</Select.Option> - <Select.Option value="bg_white_style_grass_green">鑽夌豢鐧借壊绯�</Select.Option> - <Select.Option value="bg_black_style_deep_red">娣辩孩榛戣壊绯�</Select.Option> - <Select.Option value="bg_white_style_deep_red">娣辩孩鐧借壊绯�</Select.Option> + <Select.Option value="bg_black_style_blue">钃濊壊</Select.Option> + <Select.Option value="bg_black_style_red">绾㈣壊</Select.Option> + <Select.Option value="bg_black_style_orange_red">姗欑孩鑹�</Select.Option> + <Select.Option value="bg_black_style_orange">姗欒壊</Select.Option> + <Select.Option value="bg_black_style_orange_yellow">姗欓粍鑹�</Select.Option> + <Select.Option value="bg_black_style_yellow">榛勮壊</Select.Option> + <Select.Option value="bg_black_style_yellow_green">榛勭豢鑹�</Select.Option> + <Select.Option value="bg_black_style_green">缁胯壊</Select.Option> + <Select.Option value="bg_black_style_cyan">闈掕壊</Select.Option> + <Select.Option value="bg_black_style_blue_purple">钃濈传鑹�</Select.Option> + <Select.Option value="bg_black_style_purple">绱壊</Select.Option> + <Select.Option value="bg_black_style_magenta">娲嬬孩鑹�</Select.Option> + <Select.Option value="bg_black_style_grass_green">鑽夌豢鑹�</Select.Option> + <Select.Option value="bg_black_style_deep_red">娣辩孩鑹�</Select.Option> </Select> )} </Form.Item> @@ -179,8 +202,13 @@ <Col span={12}> <Form.Item label="鍥炬爣"> {getFieldDecorator('favicon', { - initialValue: filelist - })(<FileUpload accept=".jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp,.ico" maxFile={1} fileType={'text'} />)} + initialValue: file + })(<FileUpload config={{ + initval: file, + suffix: '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp,.ico', + maxfile: 1, + fileType: 'text' + }}/>)} </Form.Item> </Col> </Row> diff --git a/src/views/appmanage/submutilform/index.scss b/src/views/appmanage/submutilform/index.scss index 28344fe..b2364d9 100644 --- a/src/views/appmanage/submutilform/index.scss +++ b/src/views/appmanage/submutilform/index.scss @@ -1,4 +1,8 @@ -.mob-card-edit-form { +.sub-app-edit-form { padding: 0px 24px 20px; + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } } \ No newline at end of file diff --git a/src/views/appmanage/transform/index.jsx b/src/views/appmanage/transform/index.jsx new file mode 100644 index 0000000..9ede6fb --- /dev/null +++ b/src/views/appmanage/transform/index.jsx @@ -0,0 +1,89 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input } from 'antd' +import './index.scss' + +class MainSearch extends Component { + static propTpyes = { + type: PropTypes.any, // 缂栬緫绫诲瀷 + card: PropTypes.any, // 缂栬緫搴旂敤 + inputSubmit: PropTypes.func // input鍥炶溅鎻愪氦 + } + + state = {} + + /** + * @description 鑾峰彇琛ㄥ崟鍊� + */ + handleConfirm = () => { + return new Promise(resolve => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } + }) + }) + } + + /** + * @description 鍥炶溅鎻愪氦 + */ + handleSubmit = (e) => { + e.preventDefault() + this.props.inputSubmit() + } + + render() { + const { card, type } = this.props + const { getFieldDecorator } = this.props.form + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 12 } + } + } + return ( + <Form {...formItemLayout} className="mob-card-edit-form"> + <Row gutter={24}> + {type !== 'edit' ? <Col span={24}> + <Form.Item label="浼犺緭鍙�"> + {getFieldDecorator('VersionName', { + initialValue: card ? card.VersionName : '', + rules: [{ + required: true, + message: '璇疯緭鍏ヤ紶杈撳彿!' + }, { + pattern: /^[a-zA-Z0-9]*$/gi, + message: '璇疯緭鍏ユ暟瀛楁垨瀛楁瘝!' + }, { + max: 20, + message: '浼犺緭鍙蜂笉鍙秴杩�20涓瓧绗�!' + }] + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> : null} + <Col span={24}> + <Form.Item label="鎻忚堪"> + {getFieldDecorator('ProgramName', { + initialValue: card ? card.ProgramName : '', + rules: [{ + required: true, + message: '璇疯緭鍏ユ弿杩�!' + }, { + max: 50, + message: '鎻忚堪涓嶅彲瓒呰繃50涓瓧绗�!' + }] + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(MainSearch) \ No newline at end of file diff --git a/src/views/appmanage/transform/index.scss b/src/views/appmanage/transform/index.scss new file mode 100644 index 0000000..28344fe --- /dev/null +++ b/src/views/appmanage/transform/index.scss @@ -0,0 +1,4 @@ +.mob-card-edit-form { + padding: 0px 24px 20px; + +} \ No newline at end of file diff --git a/src/views/billprint/index.jsx b/src/views/billprint/index.jsx index 66e09e1..38c9f1e 100644 --- a/src/views/billprint/index.jsx +++ b/src/views/billprint/index.jsx @@ -147,16 +147,44 @@ config.width = pageParam[config.pageSize][config.pageLayout] config.style.height = Math.floor(config.width * pageParam[config.pageSize][config.pageLayout + config.pagePadding]) + if (config.printCustom === 'true' && config.printWidth && config.printHeight) { + config.width = config.printWidth + config.style.height = config.printHeight + } + let params = [] let _pars = [] config.components = config.components.filter(item => !['tabs', 'search'].includes(item.type)) + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + let city = sessionStorage.getItem('city') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + let regs = [ + { reg: /@userName@/ig, value: `'${userName}'` }, + { reg: /@fullName@/ig, value: `'${fullName}'` }, + { reg: /@login_city@/ig, value: `'${city}'` } + ] + + if (window.GLOB.externalDatabase !== null) { + regs.push({ + reg: /@db@/ig, + value: window.GLOB.externalDatabase + }) + } + config.components = config.components.map(component => { if (component.action) component.action = [] if (component.search) component.search = [] component.data = [] // 鍒濆鍖栨暟鎹负绌� - if (['propcard', 'brafteditor', 'sandbox'].includes(component.subtype) && component.wrap.datatype === 'static') { + if (component.wrap.datatype === 'static') { component.format = '' } @@ -198,11 +226,10 @@ _customScript = _customScript.replace(/@\$|\$@/ig, '') } - // 澶栬仈鏁版嵁搴撴浛鎹� - if (window.GLOB.externalDatabase !== null) { - component.setting.dataresource = component.setting.dataresource.replace(/@db@/ig, window.GLOB.externalDatabase) - _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase) - } + regs.forEach(cell => { + component.setting.dataresource = component.setting.dataresource.replace(cell.reg, cell.value) + _customScript = _customScript.replace(cell.reg, cell.value) + }) component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰 @@ -502,6 +529,7 @@ let linkList = document.getElementsByTagName('link') // 鑾峰彇鐖剁獥鍙ink鏍囩瀵硅薄鍒楄〃 let styleList = document.getElementsByTagName('style') // 鑾峰彇鐖剁獥鍙tyle鏍囩瀵硅薄鍒楄〃 + iframe.style.marginTop = '600px' document.body.appendChild(iframe) let doc = iframe.contentWindow.document diff --git a/src/views/billprint/index.scss b/src/views/billprint/index.scss index 2c5512e..80dd4f8 100644 --- a/src/views/billprint/index.scss +++ b/src/views/billprint/index.scss @@ -32,17 +32,23 @@ } .print-page { + color: rgba(0,0,0,1); table { + color: rgba(0,0,0,1); border-radius: 0!important; .ant-table-column-sorter { display: none!important; } } .ant-table-thead > tr > th { + color: rgba(0,0,0,1); background: transparent!important; border-radius: 0!important; } } +.print-page:last-child { + height: auto!important; +} .normal-custom-table .main-pickup { display: none!important; diff --git a/src/views/design/header/index.jsx b/src/views/design/header/index.jsx index 5b8c73d..5b14744 100644 --- a/src/views/design/header/index.jsx +++ b/src/views/design/header/index.jsx @@ -2,7 +2,7 @@ import { withRouter } from 'react-router-dom' import {connect} from 'react-redux' import { is, fromJS } from 'immutable' -import { Dropdown, Menu, Icon, Modal, Form, notification, Switch, Button } from 'antd' +import { Dropdown, Menu, Icon, Modal, notification, Switch, Button } from 'antd' import asyncComponent from '@/utils/asyncComponent' import { @@ -327,6 +327,9 @@ {!editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' && this.props.memberLevel >= 20 ? <span onClick={() => {window.open('#/appmanage')}} className="mobile" type="edit"> 搴旂敤绠$悊 <Icon type="arrow-right" /></span> : null } + {!editLevel && options.sysType === 'local' && this.props.memberLevel >= 20 ? + <span onClick={() => {window.open('#/interface')}} className="interface" type="edit"> 鎺ュ彛璋冭瘯 <Icon type="arrow-right" /></span> : null + } {/* window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'home', MenuId: 'home_page_id', MenuName: '棣栭〉' }))) */} {!editLevel && window.GLOB.systemType !== 'production' && this.props.memberLevel >= 20 ? <span className="home-edit" onClick={() => {window.open('#/menudesign/JTdCJTIyTWVudVR5cGUlMjIlM0ElMjJob21lJTIyJTJDJTIyTWVudUlkJTIyJTNBJTIyaG9tZV9wYWdlX2lkJTIyJTJDJTIyTWVudU5hbWUlMjIlM0ElMjIlRTklQTYlOTYlRTklQTElQjUlMjIlN0Q=')}}> @@ -379,4 +382,4 @@ } } -export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Form.create()(Header))) \ No newline at end of file +export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header)) \ No newline at end of file diff --git a/src/views/design/header/index.scss b/src/views/design/header/index.scss index 705e4d5..4f796e4 100644 --- a/src/views/design/header/index.scss +++ b/src/views/design/header/index.scss @@ -130,6 +130,13 @@ color: #1890ff; cursor: pointer; } + .interface { + position: absolute; + top: 170px; + right: 50px; + color: #1890ff; + cursor: pointer; + } .home-edit { position: absolute; top: 100px; diff --git a/src/views/design/index.jsx b/src/views/design/index.jsx index 167b576..51fe335 100644 --- a/src/views/design/index.jsx +++ b/src/views/design/index.jsx @@ -5,6 +5,7 @@ import asyncComponent from '@/utils/asyncComponent' import Header from './header' +import { setGLOBFuncs } from '@/utils/utils.js' import Sidemenu from './sidemenu' import './index.scss' @@ -13,6 +14,10 @@ const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS class Design extends Component { + componentDidMount() { + setGLOBFuncs() + } + render () { return ( <div className="mk-main-view"> diff --git a/src/views/design/sidemenu/config.jsx b/src/views/design/sidemenu/config.jsx index 1ec2bae..9cca512 100644 --- a/src/views/design/sidemenu/config.jsx +++ b/src/views/design/sidemenu/config.jsx @@ -170,20 +170,20 @@ MenuID: '1589788042787ffdt9hle4s45k9r1nvs', MenuNo: 'bd_msn_email_tempM', MenuName: '閭欢妯℃澘', - }, { - src: '', - PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, - type: 'ManageTable', - MenuID: '15900310928174dro07ihfckghpb5h13', - MenuNo: 'bd_msn_sms_tempM', - MenuName: '澶т簬鐭俊妯℃澘', // }, { // src: '', // PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, // type: 'ManageTable', - // MenuID: '1599613340050c8nu6rbst9d4emnnbsq', - // MenuNo: 's_sms_qxM', - // MenuName: '濂囦簯鐭俊妯℃澘', + // MenuID: '15900310928174dro07ihfckghpb5h13', + // MenuNo: 'bd_msn_sms_tempM', + // MenuName: '澶т簬鐭俊妯℃澘', + }, { + src: '', + PageParam: {OpenType: 'newtab', Template: 'ManageTable'}, + type: 'ManageTable', + MenuID: '1599613340050c8nu6rbst9d4emnnbsq', + MenuNo: 's_sms_qxM', + MenuName: '濂囦簯鐭俊妯℃澘', }] }, { MenuID: 'systemPayManage', diff --git a/src/views/interface/api/index.js b/src/views/interface/api/index.js new file mode 100644 index 0000000..59f4941 --- /dev/null +++ b/src/views/interface/api/index.js @@ -0,0 +1,175 @@ +import axios from 'axios' +import md5 from 'md5' +import jsSHA from 'jssha' +import { notification } from 'antd' + +window.GLOB.WebSql = null + +if (window.openDatabase) { + let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : '' + try { + window.GLOB.WebSql = openDatabase(`mkdb${service}`, '1', 'mk-pc-database', 50 * 1024 * 1024) + window.GLOB.WebSql.transaction(tx => { + tx.executeSql('CREATE TABLE IF NOT EXISTS INTERFACES (uuid varchar(50), createDate varchar(50), method varchar(50), interface text, params text, headers text, active varchar(50), raw text, formData text, CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50), CDefine4 varchar(50), CDefine5 text)', [], () => { + + }, () => { + // eslint-disable-next-line + throw 'CREATE TABLE ERROR' + }) + }) + } catch (e) { + console.warn('WebSql 鍒濆鍖栧け璐ワ紒') + window.GLOB.WebSql = null + } +} + +axios.defaults.crossDomain = true +axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' +axios.defaults.withCredentials = false + +axios.interceptors.request.use((config) => { + return config +}, (error) => { + return Promise.reject(error) +}) + +axios.interceptors.response.use((response) => { + return Promise.resolve(response) +}, (error) => { + return Promise.reject(error) +}) + +class Api { + /** + * @description 鐧诲綍绯荤粺, 鑾峰彇鐢ㄦ埛淇℃伅 + */ + dologon (url, method, header, n) { + let config = { + url, + method + } + + if (header) { + config.headers = header + } + + if (n) { + let _param = JSON.parse(n) + let param = {} + + Object.keys(_param).forEach(key => { + param[key.toLowerCase()] = _param[key] + }) + + if (param.type && param.username && param.password && param.timestamp) { + if (param.type === 'S') { + let shaObj = new jsSHA('SHA-1', 'TEXT') + shaObj.update(param.password) + param.password = shaObj.getHash('HEX').toUpperCase() + param.password = md5(param.username + param.password + param.timestamp) + } else if (/^mk_/ig.test(param.type)) { + let shaObj = new jsSHA('SHA-1', 'TEXT') + shaObj.update(param.password) + param.password = shaObj.getHash('HEX').toUpperCase() + param.password = md5(param.privatekey + param.username + param.password + param.timestamp) + + delete param.privatekey + } + } + + config.data = JSON.stringify(param) + } + + return axios(config) + } + + /** + * @description 閫氱敤璇锋眰 + */ + normalRequest (url, method, header, n) { + let config = { + url, + method + } + + if (header) { + config.headers = header + } + if (n) { + config.data = n + } + + return axios(config) + } + + writeInWebSql (data) { + if (!window.GLOB.WebSql) { + notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 }) + return + } + return new Promise((resolve, reject) => { + window.GLOB.WebSql.transaction(tx => { + tx.executeSql(`INSERT INTO INTERFACES (uuid, createDate, method, interface, params, headers, active, raw, formData) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, data, (tx, results) => { + resolve(results) + }, () => { + resolve() + }) + }) + }) + } + + getInterfaces () { + if (!window.GLOB.WebSql) { + notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 }) + return + } + return new Promise((resolve, reject) => { + window.GLOB.WebSql.transaction(tx => { + tx.executeSql(`SELECT * FROM INTERFACES`, [], (tx, results) => { + // let paramItem = results.rows[0] + resolve(results) + }, () => { + window.GLOB.WebSql = null + reject() + }) + }) + }) + } + + delInterface (uuid) { + if (!window.GLOB.WebSql) { + notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 }) + return + } + return new Promise((resolve, reject) => { + window.GLOB.WebSql.transaction(tx => { + tx.executeSql(`DELETE FROM INTERFACES where uuid = '${uuid}'`, [], (tx, results) => { + resolve(results) + }, () => { + resolve() + }) + }) + }) + } + + /** + * @description 娓呯┖鎺ュ彛璋冪敤璁板綍 + */ + clearInterfaces () { + if (!window.GLOB.WebSql) { + notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 }) + return + } + return new Promise((resolve, reject) => { + window.GLOB.WebSql.transaction(tx => { + tx.executeSql(`DELETE FROM INTERFACES`, [], (tx, results) => { + resolve(results) + }, () => { + resolve() + }) + }) + }) + } +} + +export default new Api() \ No newline at end of file diff --git a/src/views/interface/header/index.jsx b/src/views/interface/header/index.jsx new file mode 100644 index 0000000..03804df --- /dev/null +++ b/src/views/interface/header/index.jsx @@ -0,0 +1,45 @@ +import React, {Component} from 'react' +import { withRouter } from 'react-router-dom' + +import Utils from '@/utils/utils.js' +import options from '@/store/options.js' +import avatar from '@/assets/img/avatar.jpg' +import MainLogo from '@/assets/img/main-logo.png' +import './index.scss' + +class Header extends Component { + state = { + userName: sessionStorage.getItem('CloudUserName'), + avatar: Utils.getrealurl(sessionStorage.getItem('CloudAvatar')), + } + + UNSAFE_componentWillMount() { + if (options.sysType !== 'local' || !sessionStorage.getItem('LoginUID')) { + sessionStorage.clear() + this.props.history.replace('/login') + } + } + + close = () => { + window.close() + } + + render () { + + return ( + <header className="interface-header-container"> + <div className="header-logo"><img src={MainLogo} alt=""/></div> + <div className="title">鎺ュ彛璋冭瘯</div> + <div className="header-setting"> + <span className="close" onClick={this.close}>鍏抽棴</span> + <img src={this.state.avatar || avatar} alt=""/> + <span> + <span className="username">{this.state.userName}</span> + </span> + </div> + </header> + ) + } +} + +export default withRouter(Header) \ No newline at end of file diff --git a/src/views/interface/header/index.scss b/src/views/interface/header/index.scss new file mode 100644 index 0000000..36f8765 --- /dev/null +++ b/src/views/interface/header/index.scss @@ -0,0 +1,63 @@ +.interface-header-container { + position: fixed; + z-index: 20; + left: 0; + top: 0; + font-weight: bold!important; + width: 100%; + height: 48px; + background: #000; + + .header-logo { + float: left; + width: 180px; + line-height: 48px; + text-align: center; + padding-left: 5px; + box-sizing: border-box; + opacity: 1; + img { + max-width: 100%; + max-height: 40px; + } + } + + .title { + position: absolute; + top: 10px; + left: 50%; + transform: translateX(-50%); + color: #ffffff; + font-size: 18px; + } + + .header-setting { + float: right; + line-height: 48px; + margin-right: 10px; + .close { + margin-right: 20px; + cursor: pointer; + padding: 10px; + } + img { + width: 29px; + height: 29px; + border-radius: 30px; + margin-right: 7px; + } + span { + color: #ffffff; + font-size: 0.95rem; + .username { + display: inline-block; + height: 30px; + max-width: 95px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + } +} + diff --git a/src/views/interface/history/index.jsx b/src/views/interface/history/index.jsx new file mode 100644 index 0000000..9b0952c --- /dev/null +++ b/src/views/interface/history/index.jsx @@ -0,0 +1,290 @@ +import React, {Component} from 'react' +import { fromJS } from 'immutable' +import { Input, Modal, Icon } from 'antd' +import moment from 'moment' + +import Api from '@/views/interface/api' +import Utils from '@/utils/utils.js' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const { Search } = Input +const { confirm } = Modal + +class History extends Component { + state = { + list: [], + historys: [], + searchKey: '' + } + + componentDidMount() { + MKEmitter.addListener('insertInterface', this.insertInterface) + setTimeout(() => { + Api.getInterfaces().then(res => { + if (!res || !res.rows) return + + let rows = [...res.rows] + rows.sort((a,b) => { + return a.createDate < b.createDate ? 1 : -1 + }) + + let list = [] + let item = null + + rows.forEach(m => { + let date = m.createDate.substring(0, 10) + + if (m.params) { + try { + m.params = JSON.parse(m.params) + } catch { + m.params = [] + } + } else { + m.params = [] + } + + if (m.headers) { + try { + m.headers = JSON.parse(m.headers) + } catch { + m.headers = [] + } + } else { + m.headers = [] + } + + if (m.formData) { + try { + m.formData = JSON.parse(m.formData) + } catch { + m.formData = [] + } + } else { + m.formData = [] + } + + if (item && item.date !== date) { + list.push(item) + item = null + } + + if (!item) { + item = {date, sublist: []} + item.sublist.push(m) + } else if (item && item.date === date) { + item.sublist.push(m) + } + }) + + if (item) { + list.push(item) + } + + this.setState({list, historys: fromJS(list).toJS()}) + }) + }, 200) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('insertInterface', this.insertInterface) + } + + clear = () => { + const _this = this + confirm({ + content: 'Are you sure you want to clear all your history requests?', + onOk() { + Api.clearInterfaces().then(res => { + if (res && res.rows.length === 0) { + _this.setState({list: [], historys: []}) + Modal.success({ + title: '娓呴櫎鎴愬姛銆�' + }) + } else { + Modal.error({ + title: '娓呴櫎澶辫触锛佽鍒锋柊閲嶈瘯銆�' + }) + } + }) + }, + onCancel() {} + }) + } + + delete = (m) => { + const { searchKey } = this.state + Api.delInterface(m.uuid).then(res => { + if (res) { + let list = this.state.list.filter(item => { + item.sublist = item.sublist.filter(cell => cell.uuid !== m.uuid) + + return item.sublist.length > 0 + }) + + let historys = fromJS(list).toJS() + if (searchKey) { + historys = historys.filter(item => { + item.sublist = item.sublist.filter(cell => cell.interface.indexOf(searchKey) > -1) + + return item.sublist.length > 0 + }) + } + + this.setState({list, historys}) + } else { + Modal.error({ + title: '鍒犻櫎澶辫触锛佽鍒锋柊閲嶈瘯銆�' + }) + } + }) + } + + insertInterface = (item) => { + item.uuid = Utils.getuuid() + item.createDate = moment().format('YYYY-MM-DD HH:mm:ss') + + Api.writeInWebSql([item.uuid, item.createDate, item.method, item.interface, JSON.stringify(item.params), JSON.stringify(item.headers), item.active, item.raw, JSON.stringify(item.formData)]).then(res => { + if (res) { + let list = fromJS(this.state.list).toJS() + + if (list[0]) { + if (list[0].date === item.createDate.substring(0, 10)) { + list[0].sublist.unshift(item) + } else { + list.unshift({ + date: item.createDate.substring(0, 10), + sublist: [item] + }) + } + } else { + list.push({ + date: item.createDate.substring(0, 10), + sublist: [item] + }) + } + + let historys = fromJS(list).toJS() + if (this.state.searchKey) { + historys = historys.filter(item => { + item.sublist = item.sublist.filter(cell => cell.interface.indexOf(this.state.searchKey) > -1) + + return item.sublist.length > 0 + }) + } + + this.setState({ list, historys }) + } else { + Modal.error({ + title: '娣诲姞澶辫触锛佽鍒锋柊閲嶈瘯銆�' + }) + } + }) + } + + use = (m) => { + MKEmitter.emit('useInterface', fromJS(m).toJS()) + } + + uselogon = () => { + let m = { + active: 'raw', + createDate: '', + formData: [], + headers: [], + interface: 'dologon / logon', + method: 'POST', + params: [], + raw: "{\n \"UserName\":\"******\",\n \"Password\":\"******\",\n \"systemType\":\"local\",\n \"Type\":\"鍏挜\",\n \"privatekey\":\"绉侀挜\",\n \"timestamp\":\"YYYY-MM-DD HH:mm:ss\",\n \"appkey\":\"******\"\n}", + uuid: 'dologon' + } + MKEmitter.emit('useInterface', m) + } + + usedostars = () => { + let m = { + active: 'raw', + createDate: '', + formData: [], + headers: [], + interface: 'dostars', + method: 'POST', + params: [], + raw: "{\n \"LoginUID\":\"******\",\n \"UserID\":\"******\",\n \"func\":\"******\"\n}", + uuid: 'dologon' + } + MKEmitter.emit('useInterface', m) + } + + changeSearch = (value) => { + const { list } = this.state + + let historys = fromJS(list).toJS() + if (value) { + historys = historys.filter(item => { + item.sublist = item.sublist.filter(cell => cell.interface.indexOf(value) > -1) + + return item.sublist.length > 0 + }) + } + + this.setState({searchKey: value, historys}) + } + + render () { + const { historys } = this.state + + return ( + <aside className="interface-side-menu"> + <Search placeholder="Filter" onSearch={value => this.changeSearch(value)}/> + <div className="title"> + History + <span onClick={this.clear}>Clear all</span> + </div> + <div className="list-view"> + {historys.map((item, index) => ( + <div className="list-line" key={index}> + <div className="line-title">{item.date}</div> + {item.sublist.map(m => ( + <div className="line-item" key={m.uuid}> + <div className="method">POST</div> + <div className="inter">{m.interface}</div> + <div className="action"> + <Icon type="delete" onClick={() => this.delete(m)} /> + <Icon type="right" onClick={() => this.use(m)} /> + </div> + </div> + ))} + </div> + ))} + <div className="list-line" key="example"> + <div className="line-title">绀轰緥</div> + <div className="line-item" key="dologon"> + <div className="method">POST</div> + <div className="inter" style={{lineHeight: '40px'}}>dologon / logon</div> + <div className="action" style={{paddingLeft: '40px'}}> + <Icon type="right" onClick={this.uselogon} /> + </div> + </div> + <div className="line-item" key="dostars"> + <div className="method">POST</div> + <div className="inter" style={{lineHeight: '40px'}}>dostars</div> + <div className="action" style={{paddingLeft: '40px'}}> + <Icon type="right" onClick={this.usedostars} /> + </div> + </div> + </div> + </div> + </aside> + ) + } +} + +export default History \ No newline at end of file diff --git a/src/views/interface/history/index.scss b/src/views/interface/history/index.scss new file mode 100644 index 0000000..012eebb --- /dev/null +++ b/src/views/interface/history/index.scss @@ -0,0 +1,113 @@ +.interface-side-menu { + display: inline-block; + width: 300px; + border-right: 2px solid #e8e8e8; + height: 100%; + + .ant-input-search { + margin: 10px 20px; + width: calc(100% - 40px); + .ant-input { + border-radius: 20px; + } + } + .title { + padding-left: 20px; + font-size: 16px; + border-bottom: 1px solid #e8e8e8; + padding-bottom: 3px; + span { + font-size: 14px; + float: right; + color: #fa541c; + margin-right: 10px; + cursor: pointer; + } + } + .list-view { + .ant-empty { + margin-top: 50px; + } + .list-line { + border-bottom: 1px solid #e8e8e8; + .line-title { + padding: 5px 15px; + color: rgba(0, 0, 0, 0.85); + } + .line-item { + position: relative; + display: flex; + padding-left: 25px; + margin-bottom: 8px; + transition: all 0.3s; + .method { + width: 42px; + color: #faad14; + font-size: 12px; + font-weight: 600; + line-height: 40px; + } + .inter { + width: 225px; + height: 42px; + word-break: break-all; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } + .action { + width: 70px; + position: absolute; + line-height: 40px; + right: 0px; + height: 42px; + background: #ffffff; + padding-left: 15px; + opacity: 0; + transition: all 0.3s; + i { + cursor: pointer; + } + i:first-child { + margin-right: 12px; + } + .anticon-delete { + color: #fa541c; + } + .anticon-right { + color: #1890ff; + } + } + } + .line-item:hover { + background: #e9e9e9; + .action { + opacity: 1; + background: #e9e9e9; + } + } + } + } + + .list-view { + height: calc(100vh - 128px); + overflow-x: hidden; + overflow-y: auto; + } + .list-view::-webkit-scrollbar { + width: 5px; + } + .list-view::-webkit-scrollbar-thumb { + border-radius: 5px; + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.09); + background: rgba(0, 0, 0, 0.09); + } + .list-view::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); + border-radius: 3px; + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0); + } +} \ No newline at end of file diff --git a/src/views/interface/index.jsx b/src/views/interface/index.jsx new file mode 100644 index 0000000..573e87c --- /dev/null +++ b/src/views/interface/index.jsx @@ -0,0 +1,28 @@ +import React, {Component} from 'react' +import { ConfigProvider } from 'antd' +import enUS from 'antd/es/locale/en_US' +import zhCN from 'antd/es/locale/zh_CN' + +import Header from './header' +import History from './history' +import WorkSpace from './workspace' + +import './index.scss' + +const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS + +class Interface extends Component { + render () { + return ( + <div className="interface-view"> + <ConfigProvider locale={_locale}> + <Header key="header"/> + <History key="history"/> + <WorkSpace key="workspace"/> + </ConfigProvider> + </div> + ) + } +} + +export default Interface \ No newline at end of file diff --git a/src/views/interface/index.scss b/src/views/interface/index.scss new file mode 100644 index 0000000..6c53933 --- /dev/null +++ b/src/views/interface/index.scss @@ -0,0 +1,6 @@ +.interface-view { + padding-top: 48px; + width: 100vw; + height: 100vh; + overflow: hidden; +} \ No newline at end of file diff --git a/src/views/interface/workspace/editTable/index.jsx b/src/views/interface/workspace/editTable/index.jsx new file mode 100644 index 0000000..dc5ff0f --- /dev/null +++ b/src/views/interface/workspace/editTable/index.jsx @@ -0,0 +1,249 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Table, Input, 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 { dataIndex } = this.props + + if (!dataIndex) return + + 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, { + 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 { dataIndex, title, record, index, handleSave, children, ...restProps } = this.props + return ( + <td {...restProps}> + <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer> + </td> + ) + } +} + +class EditTable extends Component { + static propTpyes = { + data: PropTypes.array, + onChange: PropTypes.func + } + + state = { + dataSource: [], + selectedRowKeys: [], + count: 0, + columns: [{ + dataIndex: 'key', + title: 'KEY', + width: '33%' + }, { + dataIndex: 'value', + title: 'VALUE', + width: '33%' + }, { + dataIndex: 'description', + title: 'DESCRIPTION', + className: 'no-border', + width: '33%' + }, { + dataIndex: '', + title: '', + width: '20px', + render: (text, record) => { + return (<Icon type="close" onClick={() => this.delete(record)}/>) + } + }] + } + + UNSAFE_componentWillMount () { + const { data } = this.props + + let _data = data || [] + let selectedRowKeys = [] + if (_data && _data.length > 0) { + _data.forEach(item => { + if (item.selected) { + selectedRowKeys.push(item.uuid) + } + }) + } else { + _data = [{ + uuid: Utils.getuuid(), + key: '', + value: '', + description: '', + selected: true + }] + selectedRowKeys.push(_data[0].uuid) + this.props.onChange(_data) + } + + this.setState({ + dataSource: _data, + selectedRowKeys + }) + } + + handleDelete = key => { + const { dataSource } = this.state + let _data = dataSource.filter(item => item.key !== key) + + this.setState({ dataSource: _data }, () => { + this.props.onChange(_data) + }) + } + + delete = (item) => { + const { dataSource, selectedRowKeys } = this.state + + let _data = dataSource.filter(cell => cell.uuid !== item.uuid) + let _keys = selectedRowKeys.filter(key => key !== item.uuid) + + if (_data.length === 0) { + _data = [{ + uuid: Utils.getuuid(), + key: '', + value: '', + description: '', + selected: true + }] + _keys = [_data[0].uuid] + this.props.onChange(_data) + } + + this.setState({ + dataSource: _data, + selectedRowKeys: _keys + }, () => { + this.props.onChange(_data) + }) + } + + handleSave = row => { + let newData = this.state.dataSource.map(item => { + if (row.uuid === item.uuid) return row + return item + }) + + let selectedRowKeys = this.state.selectedRowKeys + + let last = newData[newData.length - 1] + if (last.key || last.value || last.description) { + const item = { + uuid: Utils.getuuid(), + key: '', + value: '', + description: '', + selected: true + } + + newData = [...newData, item] + selectedRowKeys = [...selectedRowKeys, item.uuid] + } + + this.setState({ dataSource: newData, selectedRowKeys }, () => { + this.props.onChange(newData) + }) + } + + onChange = selectedRowKeys => { + const newData = this.state.dataSource.map(item => { + item.selected = selectedRowKeys.includes(item.uuid) + return item + }) + + this.setState({ dataSource: newData, selectedRowKeys }, () => { + this.props.onChange(newData) + }) + } + + render() { + const { dataSource, selectedRowKeys } = this.state + const components = { + body: { + row: EditableFormRow, + cell: EditableCell + } + } + const columns = this.state.columns.map(col => { + return { + ...col, + onCell: record => ({ + record, + dataIndex: col.dataIndex, + title: col.title, + handleSave: this.handleSave, + }) + } + }) + return ( + <div className="params-edit-table"> + <Table + rowKey="uuid" + components={components} + bordered + dataSource={dataSource} + columns={columns} + rowSelection={{ type: 'checkbox', selectedRowKeys, onChange: this.onChange }} + pagination={false} + /> + </div> + ) + } +} + +export default EditTable \ No newline at end of file diff --git a/src/views/interface/workspace/editTable/index.scss b/src/views/interface/workspace/editTable/index.scss new file mode 100644 index 0000000..10cd1a4 --- /dev/null +++ b/src/views/interface/workspace/editTable/index.scss @@ -0,0 +1,85 @@ +.params-edit-table { + .add-row { + position: absolute; + z-index: 1; + right: 10px; + top: 0px; + padding: 5px; + font-size: 22px; + color: #26C281; + } + .ant-table table { + border-radius: 0; + } + .no-border { + border-right: 0!important; + } + .ant-table-thead > tr { + > th { + padding: 10px 10px; + } + .ant-table-selection-column { + .ant-table-header-column { + display: none; + } + } + } + .ant-table-tbody { + > tr { + > td { + background: #ffffff!important; + padding: 2px 10px; + .ant-input { + height: 28px; + } + .ant-form-item { + height: 30px; + line-height: 30px; + .ant-form-item-control { + line-height: 30px; + } + } + .anticon-close { + opacity: 0; + } + } + } + > tr:hover { + > td { + background: #ffffff!important; + .anticon-close { + opacity: 1; + } + } + } + } + .editable-cell-value-wrap { + cursor: pointer; + height: 36px; + width: 300px; + 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-form-explain { + font-size: 12px; + } +} diff --git a/src/views/interface/workspace/index.jsx b/src/views/interface/workspace/index.jsx new file mode 100644 index 0000000..f02ba5d --- /dev/null +++ b/src/views/interface/workspace/index.jsx @@ -0,0 +1,123 @@ +import React, {Component} from 'react' +import { Icon, Tabs } from 'antd' + +import Utils from '@/utils/utils.js' +import MKEmitter from '@/utils/events.js' +import Request from './request' +import './index.scss' +import { fromJS } from 'immutable' + + +class WorkSpace extends Component { + state = { + tabviews: [{ + uuid: Utils.getuuid(), + createDate: '', + method: 'POST', + interface: '', + params: [], + headers: [], + active: 'raw', + raw: '', + formData: [] + }] + } + + componentDidMount() { + MKEmitter.addListener('useInterface', this.useInterface) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('useInterface', this.useInterface) + } + + useInterface = (item) => { + item.uuid = Utils.getuuid() + + this.setState({tabviews: [...this.state.tabviews, item]}, () => { + let div = document.getElementById(item.uuid) + div && div.click && div.click() + }) + } + + handleTabview = (view) => { + let tabviews = fromJS(this.state.tabviews).toJS() + tabviews = tabviews.filter(item => item.uuid !== view.uuid) + + this.setState({tabviews}, () => { + if (tabviews.length > 0) return + + setTimeout(() => { + this.setState({tabviews: [{ + uuid: Utils.getuuid(), + createDate: '', + method: 'POST', + interface: '', + params: [], + headers: [], + active: 'raw', + raw: '', + formData: [] + }]}) + }, 300) + }) + } + + handleAdd = () => { + let item = { + uuid: Utils.getuuid(), + createDate: '', + method: 'POST', + interface: '', + params: [], + headers: [], + active: 'raw', + raw: '', + formData: [] + } + this.setState({tabviews: [...this.state.tabviews, item]}, () => { + let div = document.getElementById(item.uuid) + div && div.click && div.click() + }) + } + + render () { + const { tabviews } = this.state + + return ( + <div className="workspace-wrap"> + <Icon className="add-view" type="plus" onClick={this.handleAdd} /> + <Tabs type="card"> + {tabviews.map(view => { + return ( + <Tabs.TabPane + tab={ + <span className="control" id={view.uuid || ''}> + <span className="method"> + {view.method || 'POST'} + </span> + <span className="interface"> + {view.interface || 'Untitled Request'} + </span> + <Icon type="close" onClick={() => this.handleTabview(view)}/> + </span> + } + key={view.uuid} + > + <Request config={view} /> + </Tabs.TabPane> + ) + })} + </Tabs> + </div> + ) + } +} + +export default WorkSpace \ No newline at end of file diff --git a/src/views/interface/workspace/index.scss b/src/views/interface/workspace/index.scss new file mode 100644 index 0000000..7078d44 --- /dev/null +++ b/src/views/interface/workspace/index.scss @@ -0,0 +1,52 @@ +.workspace-wrap { + display: inline-block; + width: calc(100vw - 300px); + height: 100%; + vertical-align: top; + padding-top: 10px; + position: relative; + .add-view { + position: absolute; + right: 25px; + top: 12px; + z-index: 2; + padding: 5px; + cursor: pointer; + font-size: 22px; + color: #26C281; + } + + .ant-tabs.ant-tabs-card .ant-tabs-card-bar { + >.ant-tabs-nav-container { + margin-right: 100px; + } + padding-left: 5px; + .ant-tabs-tab { + margin-right: 7px; + padding: 0 10px; + .method { + color: #faad14; + font-size: 12px; + font-weight: 600; + margin-right: 5px; + vertical-align: top; + } + .interface { + display: inline-block; + color: rgba(0, 0, 0, 0.65); + width: 200px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + vertical-align: top; + } + .anticon-close { + color:rgba(0, 0, 0, 0.65); + margin: 0; + } + } + .ant-tabs-tab.ant-tabs-tab-active { + border-top-color: #fa541c; + } + } +} \ No newline at end of file diff --git a/src/views/interface/workspace/request/index.jsx b/src/views/interface/workspace/request/index.jsx new file mode 100644 index 0000000..90672df --- /dev/null +++ b/src/views/interface/workspace/request/index.jsx @@ -0,0 +1,310 @@ +import React, {Component} from 'react' +import { fromJS } from 'immutable' +import md5 from 'md5' +import { Input, Select, Button, Tabs, Radio, Modal, Spin } from 'antd' + +import Api from '@/views/interface/api' +import Utils from '@/utils/utils.js' +import EditTable from '../editTable' +import CodeMirror from '@/templates/zshare/codemirror' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const InputGroup = Input.Group +const { Option } = Select + +class Request extends Component { + state = { + active: 'raw', + body: null, + response: null, + status: '', + loading: false + } + + UNSAFE_componentWillMount() { + const { config } = this.props + + this.setState({active: config.active, config: fromJS(config).toJS()}) + } + + componentDidMount() { + + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + onChange = (e) => { + const { config } = this.state + + this.setState({active: e.target.value, config: {...config, active: e.target.value}}) + } + + rawChange = (val) => { + const { config } = this.state + + this.setState({config: {...config, raw: val}}) + } + + changeFormData = (vals) => { + const { config } = this.state + + this.setState({config: {...config, formData: vals}}) + } + + changeHeader = (vals) => { + const { config } = this.state + + this.setState({config: {...config, headers: vals}}) + } + + changeParams = (vals) => { + const { config } = this.state + + this.setState({config: {...config, params: vals}}) + } + + changeMethod = (val) => { + const { config } = this.state + + this.setState({config: {...config, method: val}}) + } + + changeInter = (e) => { + const { config } = this.state + + this.setState({config: {...config, interface: e.target.value}}) + } + + send = () => { + const { config } = this.state + + let raws = null + if (!config.interface) { + Modal.error({ + title: '璇峰~鍏ユ帴鍙e湴鍧�锛�' + }) + return + } else if (config.active === 'raw') { + if (config.raw) { + try { + raws = JSON.parse(config.raw) + } catch { + Modal.error({ + title: '鍙傛暟鏍煎紡閿欒锛屽繀椤讳负JSON鏍煎紡锛�' + }) + return + } + } + } + + let url = config.interface + + let m = [] + config.params.forEach(item => { + if (!item.selected || !item.key) return + m.push(`${item.key}=${item.value}`) + }) + + m = m.join('&') + + if (m) { + if (/\?/ig.test(url)) { + url = url + '&' + m + } else { + url = url + '?' + m + } + } + + let header = null + config.headers.forEach(item => { + if (!item.selected || !item.key) return + + header = header || {} + + header[item.key] = item.value + }) + + let n = null + if (config.active === 'raw' && raws) { + n = JSON.stringify(raws) + } else if (config.active === 'formData') { + config.formData.forEach(item => { + if (!item.selected || !item.key) return + + n = n || {} + + n[item.key] = item.value + }) + n = JSON.stringify(n) + } + + this.setState({loading: true}) + + if (/logon/ig.test(url)) { + Api.dologon(url, config.method, header, n).then(res => { + this.handleResponse(res) + }, (err) => { + this.handleResponse(err) + }) + } else if (/dostars/ig.test(url)) { + if (n) { + n = JSON.parse(n) + n = this.encryptParam(n) + n = JSON.stringify(n) + } + Api.normalRequest(url, config.method, header, n).then(res => { + this.handleResponse(res) + }, (err) => { + this.handleResponse(err) + }) + } else { + Api.normalRequest(url, config.method, header, n).then(res => { + this.handleResponse(res) + }, (err) => { + this.handleResponse(err) + }) + } + } + + handleResponse = (res) => { + let body = null + + if (res && res.data) { + try { + body = JSON.stringify(res.data, null, 2) + + body = body.replace(/\n/ig, '<br/>') + body = body.replace(/\s/ig, ' ') + } catch { + body = null + } + } + + let status = '' + if (res.status) { + status = res.status + res.statusText + } else if (res.name === 'Error') { + status = res.message + body = `璇锋眰寮傚父${status === 'Network Error' ? '锛屽彲鑳藉師鍥狅細1銆佺綉缁滃紓甯革紱2銆佹帴鍙h法鍩熴��' : '锛�'}` + } + + this.setState({response: res, body, status, loading: false}) + } + + encryptParam (param) { + param.nonc = Utils.getuuid() + + let keys = Object.keys(param).sort() + let values = '' + keys.forEach(key => { + if (key.toLowerCase() === 'rduri') return + if (key.toLowerCase() === 't' || key.toLowerCase() === 'sign' || param[key] === undefined) { + delete param[key] + return + } + + if (typeof(param[key]) === 'object') { + values += key + JSON.stringify(param[key]) + } else { + if (param[key] && /: =$/.test(param[key])) { + param[key] = param[key].replace(/: =$/, '==') + } + values += key + param[key] + } + }) + param.sign = md5(values) + param.t = new Date().getTime() + + return param + } + + save = () => { + const { config } = this.state + + if (!config.interface) { + Modal.error({ + title: '璇峰~鍏ユ帴鍙e湴鍧�锛�' + }) + return + } + + MKEmitter.emit('insertInterface', config) + } + + render () { + const { active, config, response, body, status, loading } = this.state + + let hasParam = config.params.filter(item => item.selected && item.key).length > 0 + let hasHeader = config.headers.filter(item => item.selected && item.key).length + let hasBody = false + + if (active === 'raw' && config.raw) { + hasBody = true + } else if (active === 'formData' && config.formData.filter(item => item.selected && item.key).length > 0) { + hasBody = true + } + + return ( + <div className="request-wrap"> + <div className="request-interface"> + <InputGroup compact> + <Select defaultValue={config.method} onChange={this.changeMethod}> + <Option value="POST">POST</Option> + <Option value="GET">GET</Option> + </Select> + <Input placeholder="Enter request URL" defaultValue={config.interface} onChange={this.changeInter}/> + </InputGroup> + <Button type="primary" onClick={this.send}>Send</Button> + <Button onClick={this.save}>Save</Button> + </div> + <Tabs animated={false} defaultActiveKey={hasBody ? 'Body' : 'Params'}> + <Tabs.TabPane forceRender={true} tab={<span className={hasParam ? 'active' : ''}>Params</span>} key="Params"> + <EditTable data={config.params} onChange={this.changeParams}/> + </Tabs.TabPane> + <Tabs.TabPane forceRender={true} tab={<span>Headers{hasHeader ? <span className="number">{`(${hasHeader})`}</span> : ''}</span>} key="Headers"> + <EditTable data={config.headers} onChange={this.changeHeader}/> + </Tabs.TabPane> + <Tabs.TabPane forceRender={true} tab={<span className={hasBody ? 'active' : ''}>Body</span>} key="Body"> + <div className="body-class"> + <Radio.Group onChange={this.onChange} value={active}> + <Radio value={'none'}>none</Radio> + <Radio value={'formData'}>formData</Radio> + <Radio value={'raw'}>raw</Radio> + </Radio.Group> + </div> + <div className={'body-content ' + (active === 'none' ? 'show' : '')}> + <div className="no-body">This request does not have a body</div> + </div> + <div className={'body-content ' + (active === 'formData' ? 'show' : '')}> + <EditTable data={config.formData} onChange={this.changeFormData}/> + </div> + <div className={'body-content ' + (active === 'raw' ? 'show' : '')}> + <CodeMirror value={config.raw} mode="text/javascript" onChange={this.rawChange} /> + </div> + </Tabs.TabPane> + </Tabs> + <div className="response"> + {response ? <div className="header"> + {body ? 'Body' : 'Response'} + {status ? <span className="status">Status: <span className={status === '200OK' ? 'green' : 'yellow'}>{status}</span></span> : null} + </div> : <div className="header"> + Response + <span className="empty">Hit the Send button to get a response.</span> + </div>} + <div style={{paddingLeft: '3px', paddingTop: '3px'}} dangerouslySetInnerHTML={{__html: body}}></div> + {loading ? <div className="pending"><Spin size="large"/></div> : null} + </div> + </div> + ) + } +} + +export default Request \ No newline at end of file diff --git a/src/views/interface/workspace/request/index.scss b/src/views/interface/workspace/request/index.scss new file mode 100644 index 0000000..7dfc719 --- /dev/null +++ b/src/views/interface/workspace/request/index.scss @@ -0,0 +1,162 @@ +.request-wrap { + position: relative; + padding: 0px 10px; + height: calc(100vh - 115px); + overflow-x: hidden; + overflow-y: auto; + + .request-interface { + background: #ffffff; + margin-bottom: 10px; + + .ant-input-group.ant-input-group-compact > *:not(:last-child) { + border-right-width: 0px; + } + .ant-select-selection { + height: 40px; + width: 90px; + } + .ant-select-selection__rendered { + line-height: 40px; + } + .ant-input { + height: 40px; + width: calc(100% - 100px); + } + .ant-input-group { + display: inline-block; + width: calc(100% - 210px); + vertical-align: top; + } + .ant-btn { + height: 40px; + width: 90px; + } + .ant-btn-primary { + margin-right: 10px; + } + } + .ant-tabs.ant-tabs-line { + .ant-tabs-top-bar { + margin-bottom: 0px; + border: 0; + .ant-tabs-nav { + .ant-tabs-tab { + color: rgba(0, 0, 0, 0.65); + padding-bottom: 5px; + span { + position: relative; + } + .number { + color: #26C281; + margin-left: 3px; + font-size: 13px; + } + span.active::after { + content: ' '; + display: block; + position: absolute; + right: -12px; + top: 2px; + width: 8px; + height: 8px; + border-radius: 8px; + background-color: #26C281; + } + } + .ant-tabs-tab.ant-tabs-tab-active { + color: rgba(0, 0, 0, 0.85); + } + } + .ant-tabs-ink-bar { + background-color: #fa541c; + } + } + } + .body-class { + height: 40px; + line-height: 40px; + padding-left: 15px; + border-top: 1px solid #e8e8e8; + .ant-radio-wrapper { + margin-right: 20px; + } + } + .body-content { + display: none; + .no-body { + color: rgba(0, 0, 0, 0.45); + border-top: 1px solid #e8e8e8; + border-bottom: 1px solid #e8e8e8; + text-align: center; + height: 40px; + line-height: 40px; + } + .CodeMirror { + height: 200px; + line-height: 1.5; + } + } + .body-content.show { + display: block; + } + .anticon-fullscreen { + display: none; + } + .code-mirror-wrap .code-mirror-area { + border-radius: 0; + } + .response { + position: relative; + min-height: 400px; + border-left: 1px solid #e8e8e8; + border-right: 1px solid #e8e8e8; + .header { + position: relative; + height: 40px; + background-color: #fafafa; + line-height: 40px; + padding-left: 10px; + border-bottom: 1px solid #e8e8e8; + .empty { + position: absolute; + top: 150px; + left: 50%; + transform: translateX(-50%); + font-size: 20px; + color:rgba(0, 0, 0, 0.45) + } + .status { + font-size: 13px; + float: right; + margin-right: 40px; + span.green { + color: #26C281; + } + span.yellow { + color: #fa541c; + } + } + } + .pending { + position: absolute; + left: 50%; + top: 160px; + } + } +} + +.request-wrap::-webkit-scrollbar { + width: 5px; +} +.request-wrap::-webkit-scrollbar-thumb { + border-radius: 5px; + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.09); + background: rgba(0, 0, 0, 0.09); +} +.request-wrap::-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/views/login/index.jsx b/src/views/login/index.jsx index 996d2b8..e7045ff 100644 --- a/src/views/login/index.jsx +++ b/src/views/login/index.jsx @@ -66,12 +66,6 @@ dict: item === 'zh-CN' ? zhCN : enUS }) } - - md5Password (pwd) { - // md5瀵嗙爜鍔犲瘑 - const salt = 'minkesoft' - return md5(md5(pwd + salt)) - } handleSubmit = () => { this.loginformRef.handleConfirm().then(res => { @@ -375,7 +369,11 @@ navBar: res.menu_type } - sessionStorage.setItem('home_background', res.index_background_color) + sessionStorage.setItem('home_background', res.index_background_color || '') + if (res.sys_datetime) { + sessionStorage.setItem('sys_datetime', res.sys_datetime) + sessionStorage.setItem('app_datetime', new Date().getTime()) + } // url鏍囬 document.title = systemMsg.platTitle diff --git a/src/views/login/index.scss b/src/views/login/index.scss index 031f932..236e2ad 100644 --- a/src/views/login/index.scss +++ b/src/views/login/index.scss @@ -26,61 +26,6 @@ } } - .ant-tabs.ant-tabs-card { - .ant-tabs-card-bar { - border-bottom: 0; - .ant-tabs-nav-container { - height: 50px; - line-height: 50px; - } - margin-bottom: 10px; - .ant-tabs-nav-scroll { - .ant-tabs-nav { - display: block; - > div { - display: flex; - > .ant-tabs-tab { - height: 50px; - line-height: 50px; - flex: 1; - } - } - } - } - .ant-tabs-tab { - display: block; - margin-right: 0; - border-radius: 0; - text-align: center; - font-size: 17px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - border-top: 0; - } - .ant-tabs-tab:first-child { - border-left: 0; - } - .ant-tabs-tab:last-child { - border-right: 0; - } - .ant-tabs-tab.ant-tabs-tab-active { - cursor: default; - } - } - } - .login-form-1 { - .ant-tabs.ant-tabs-card { - .ant-tabs-card-bar { - .ant-tabs-tab { - font-size: 18px; - text-align: left!important; - padding-left: 1.6vw!important; - line-height: 60px!important; - } - } - } - } .login-middle { position: relative; height: calc(100vh - 194px); @@ -102,6 +47,47 @@ overflow: hidden; border: 1px solid #bfbfbf; + .login-way-wrap { + height: 50px; + line-height: 50px; + margin-bottom: 10px; + display: flex; + .login-way { + flex: 1; + width: 50%; + font-size: 17px; + text-align: center; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + padding: 0 16px; + transition: all 0.3s; + border: 1px solid transparent; + border-top: 0!important; + } + .login-way.active, .login-way:hover { + color: #1890ff; + } + .login-way:not(.active) { + cursor: pointer; + background: #fafafa; + border: 1px solid #e8e8e8; + } + .login-way:first-child { + border-left: 0; + } + .login-way:last-child { + border-right: 0; + } + } + .login-way-wrap.simple { + .login-way { + font-size: 18px; + text-align: left!important; + padding-left: 1.6vw!important; + line-height: 60px!important; + } + } .form-item-wrap { padding: 0.6vw 1.6vw 1.6vw; } @@ -123,6 +109,19 @@ margin-bottom: 3vh; height: 40px; } + .ant-form-item.vercode { + .ant-input-group { + border: 1px solid #d9d9d9; + border-radius: 4px; + .ant-input { + border: 0; + border-right: 1px solid #d9d9d9; + } + .ant-input-group-addon { + border: 0; + } + } + } .btn-login { margin-bottom: 3vh; clear: both; diff --git a/src/views/login/loginform.jsx b/src/views/login/loginform.jsx index 0bf62a6..9eb898c 100644 --- a/src/views/login/loginform.jsx +++ b/src/views/login/loginform.jsx @@ -199,30 +199,61 @@ return } - let param = { - func: 'MSN_sms_send_code', + let _param = { + func: 'mes_sms_send_code_sso', send_type: 'login', mob: _phone, - timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), ID: smsId } + _param.LText = 'minke' + _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + _param.secretkey = md5(`${_param.LText}mingke${_param.timestamp}`) + + _param.userid = sessionStorage.getItem('visitorUserID') || '' + _param.LoginUID = sessionStorage.getItem('visitorLoginUID') || '' - param.LText = md5(`${_phone}mingke${window.GLOB.appkey}${param.timestamp}`) - param.secretkey = md5(`${param.LText}mingke${param.timestamp}`) + Api.getSystemConfig(_param).then(res => { + if (!res.status || !res.n_id) { + message.warning(res.message || '楠岃瘉鐮佽幏鍙栧け璐ワ紒') + return + } - param.userid = sessionStorage.getItem('visitorUserID') || '' - param.LoginUID = sessionStorage.getItem('visitorLoginUID') || '' + let param = { + func: 'MSN_sms_send_code', + send_type: 'login', + mob: _phone, + timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), + ID: smsId, + n_id: res.n_id + } + + param.LText = md5(`${_phone}mingke${window.GLOB.appkey}${param.timestamp}`) + param.secretkey = md5(`${param.LText}mingke${param.timestamp}`) - this.setState({ - verdisabled: true, - delay: 60 - }) - LoginVerCodeTimer = setTimeout(this.resetVerCodeDelay, 1000) - - Api.getSystemConfig(param).then(res => { - if (res.status) { - - } else { + param.rduri = 'http://sso.mk9h.cn/webapi/dostars' + param.userid = 'bh0bapabtd45epsgra79segbch6c1ibk' + param.LoginUID = 'bh0bapabtd45epsgra79segbch6c1ibk' + + this.setState({ + verdisabled: true, + delay: 60 + }) + LoginVerCodeTimer = setTimeout(this.resetVerCodeDelay, 1000) + + Api.getLocalConfig(param).then(res => { + if (res.status) { + + } else { + if (LoginVerCodeTimer) { + clearTimeout(LoginVerCodeTimer) + } + this.setState({ + verdisabled: false, + delay: null + }) + message.warning(res.message) + } + }, () => { if (LoginVerCodeTimer) { clearTimeout(LoginVerCodeTimer) } @@ -230,15 +261,6 @@ verdisabled: false, delay: null }) - message.warning(res.message) - } - }, () => { - if (LoginVerCodeTimer) { - clearTimeout(LoginVerCodeTimer) - } - this.setState({ - verdisabled: false, - delay: null }) }) } @@ -314,7 +336,7 @@ /> )} </Form.Item> : null} - {activeKey === 'sms_vcode' ? <Form.Item> + {activeKey === 'sms_vcode' ? <Form.Item className="vercode"> {getFieldDecorator('vercode', { initialValue: '', rules: [ @@ -356,7 +378,7 @@ {this.props.dict['login.submit']} </Button> </Form.Item> : null} - {options.sysType === 'cloud' ? <Form.Item className="register-line"> + {options.sysType === 'cloud' && options.cdomain.indexOf('mk9h') > -1 ? <Form.Item className="register-line"> <a href="http://minkesoft.com/#/signup" target="_blank" rel="noopener noreferrer" className="register">娉ㄥ唽</a> <a href="http://minkesoft.com/#/forgotPwd" target="_blank" rel="noopener noreferrer" className="forgot">蹇樿瀵嗙爜锛�</a> </Form.Item> : null} diff --git a/src/views/menudesign/homeform/index.jsx b/src/views/menudesign/homeform/index.jsx index 6ca64be..ba1e5d7 100644 --- a/src/views/menudesign/homeform/index.jsx +++ b/src/views/menudesign/homeform/index.jsx @@ -1,7 +1,9 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Radio, Icon, Tooltip, InputNumber } from 'antd' +import { Form, Row, Col, Radio, Icon, Tooltip, InputNumber, notification } from 'antd' +import Api from '@/api' +import options from '@/store/options.js' import './index.scss' class CustomMenuForm extends Component { @@ -11,6 +13,71 @@ updateConfig: PropTypes.func } + state = { + menulist: [] + } + + UNSAFE_componentWillMount () { + let _param = {func: 's_get_pc_menus', systemType: options.sysType, debug: 'Y'} + _param.pro_sys = window.GLOB.systemType === 'production' ? 'Y' : '' + + Api.getSystemConfig(_param).then(result => { + if (result.status) { + let menulist = result.fst_menu.map(fst => { + let fstItem = { + MenuID: fst.MenuID, + MenuName: fst.MenuName, + value: fst.MenuID, + label: fst.MenuName, + isLeaf: false, + children: [] + } + + if (fst.snd_menu) { + fstItem.children = fst.snd_menu.map(snd => { + let sndItem = { + ParentId: fst.MenuID, + MenuID: snd.MenuID, + MenuName: snd.MenuName, + value: snd.MenuID, + label: snd.MenuName, + children: [] + } + + if (snd.trd_menu) { + sndItem.children = snd.trd_menu.map(trd => { + let trdItem = { + FstId: fst.MenuID, + ParentId: snd.MenuID, + MenuID: trd.MenuID, + MenuName: trd.MenuName, + MenuNo: trd.MenuNo, + EasyCode: trd.EasyCode, + value: trd.MenuID, + label: trd.MenuName, + disabled: false + } + + return trdItem + }) + } + return sndItem + }) + } + return fstItem + }) + + sessionStorage.setItem('fstMenuList', JSON.stringify(menulist)) + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }) + } + // 涓�浜岀骇鑿滃崟鍒囨崲 selectChange = (key, value) => { const { config } = this.props diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx index 84cee4d..85e7fe4 100644 --- a/src/views/menudesign/index.jsx +++ b/src/views/menudesign/index.jsx @@ -8,7 +8,7 @@ import Api from '@/api' import options from '@/store/options.js' -import Utils from '@/utils/utils.js' +import Utils, { setGLOBFuncs } from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' import antdEnUS from 'antd/es/locale/en_US' @@ -34,6 +34,7 @@ const PasteController = asyncComponent(() => import('@/menu/pastecontroller')) const PaddingController = asyncComponent(() => import('@/menu/padcontroller')) const StyleController = asyncComponent(() => import('@/menu/stylecontroller')) +const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) const SysInterface = asyncComponent(() => import('@/menu/sysinterface')) const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent')) const PictureController = asyncComponent(() => import('@/menu/picturecontroller')) @@ -44,6 +45,7 @@ sessionStorage.setItem('isEditState', 'true') sessionStorage.setItem('editMenuType', 'menu') // 缂栬緫鑿滃崟绫诲瀷 +sessionStorage.setItem('appType', '') // 搴旂敤绫诲瀷 document.body.className = '' window.GLOB.UserComponentMap = new Map() // 缂撳瓨鐢ㄦ埛鑷畾涔夌粍浠� window.GLOB.urlFields = [] // url鍙橀噺 @@ -66,7 +68,8 @@ config: null, popBtn: null, // 寮圭獥鏍囩椤� visible: false, - customComponents: [] + customComponents: [], + comloading: false } UNSAFE_componentWillMount() { @@ -105,6 +108,7 @@ setTimeout(() => { this.updateCustomComponent() this.getAppPictures() + setGLOBFuncs() }, 1000) } @@ -152,6 +156,7 @@ updateCustomComponent = () => { Api.getSystemConfig({ func: 's_get_custom_components', + typename: '', typecharone: '' }).then(res => { let coms = [] @@ -199,10 +204,11 @@ }) this.setState({ - config: {...config, components: []} + config: {...config, components}, + comloading: true }, () => { this.setState({ - config: {...config, components: components} + comloading: false }) }) } @@ -393,6 +399,13 @@ buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) + }) + } else if (item.type === 'balcony') { + item.elements && item.elements.forEach(cell => { + if (cell.eleType !== 'button') return + this.checkBtn(cell) + buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) + _sort++ }) } else if (item.type === 'line' || item.type === 'bar') { item.action && item.action.forEach(btn => { @@ -645,7 +658,8 @@ if (res.status) { config.open_edition = res.open_edition || '' this.setState({ - oriConfig: fromJS(config).toJS() + config, + oriConfig: fromJS(config).toJS(), }) if (btnParam.LText) { @@ -763,10 +777,10 @@ copyButtons: [], thawButtons: [], menuloading: false, - config: {...config, components: []} + comloading: true }, () => { this.setState({ - config: {...this.state.config, components: this.state.oriConfig.components} + comloading: false }) }) notification.success({ @@ -827,28 +841,48 @@ } verifyConfig = (show) => { - const { config, MenuType } = this.state + const { config } = this.state let error = '' - config.components.forEach(item => { - if (error) return - if (['propcard', 'brafteditor', 'sandbox'].includes(item.subtype) && item.wrap.datatype === 'static') return + let check = (components) => { + components.forEach(item => { + if (error) return + if (item.type === 'tabs') { + item.subtabs.forEach(tab => { + check(tab.components) + }) + return + } else if (item.type === 'group') { + check(item.components) + return + } + if (['propcard', 'brafteditor', 'sandbox', 'stepform'].includes(item.subtype) && item.wrap.datatype === 'static') return + if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return + + if (item.setting) { + if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` + } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` + } else if (!item.setting.primaryKey) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆涓婚敭锛乣 + } + } + if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') { + if (!item.plot.Xaxis) { + error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒` + } + } else if (item.type === 'dashboard' && !item.plot.valueField) { + error = `缁勪欢銆�${item.name}銆嬫樉绀哄�煎皻鏈缃紒` + } else if (item.type === 'scatter' && (!item.plot.Xaxis || !item.plot.Yaxis || !item.plot.gender)) { + error = `缁勪欢銆�${item.name}銆嬪潗鏍囪酱灏氭湭璁剧疆锛乣 + } else if (item.type === 'tree' && (!item.wrap.valueField || !item.wrap.labelField || !item.wrap.parentField)) { + error = `缁勪欢銆�${item.name}銆嬪熀鏈俊鎭皻鏈缃紒` + } + }) + } - if (item.setting) { - if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` - } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` - } else if (item.setting.interType && !item.setting.primaryKey && MenuType !== 'billPrint') { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆涓婚敭锛乣 - } - } - if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') { - if (!item.plot.Xaxis) { - error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒` - } - } - }) + check(config.components) if (show && error) { notification.warning({ @@ -869,6 +903,18 @@ window.GLOB.customMenu = config } + resetConfig = (config) => { + this.setState({ + config, + comloading: true + }, () => { + this.setState({ + comloading: false + }) + }) + window.GLOB.customMenu = config + } + insert = (item) => { let config = fromJS(this.state.config).toJS() @@ -879,7 +925,7 @@ } render () { - const { activeKey, MenuType, popBtn, visible, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading, customComponents } = this.state + const { activeKey, comloading, MenuType, popBtn, visible, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading, customComponents } = this.state return ( <ConfigProvider locale={_locale}> @@ -901,10 +947,6 @@ MenuNo={MenuNo} updateConfig={this.updateConfig} /> : null} - {config && MenuType === 'custom' ? <UrlFieldComponent - config={config} - updateConfig={this.updateConfig} - /> : null} {config && MenuType === 'home' ? <HomeForm dict={dict} config={config} @@ -912,6 +954,10 @@ /> : null} {config && MenuType === 'billPrint' ? <PrintMenuForm dict={dict} + config={config} + updateConfig={this.updateConfig} + /> : null} + {config ? <UrlFieldComponent config={config} updateConfig={this.updateConfig} /> : null} @@ -938,16 +984,17 @@ <div> {config && config.MenuName} </div> } bordered={false} extra={ <div> + <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/> <SysInterface config={config} updateConfig={this.updateConfig}/> <PictureController/> <StyleCombControlButton menu={config} /> <PasteController type="menu" Tab={null} insert={this.insert} /> <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config && config.enabled} onChange={this.onEnabledChange} /> <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> - <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> + <Button type="default" onClick={this.closeView}>鍏抽棴</Button> </div> } style={{ width: '100%' }}> - {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} + {config && !comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} </Card> </div> </div> diff --git a/src/views/menudesign/index.scss b/src/views/menudesign/index.scss index 65fadca..b9b5812 100644 --- a/src/views/menudesign/index.scss +++ b/src/views/menudesign/index.scss @@ -1,7 +1,7 @@ .pc-menu-view { background: #000; min-height: 100vh; - .menu-body { + >.menu-body { width: 100vw; height: 100vh; overflow-x: hidden; diff --git a/src/views/menudesign/printmenuform/index.jsx b/src/views/menudesign/printmenuform/index.jsx index a6de29a..b9204e6 100644 --- a/src/views/menudesign/printmenuform/index.jsx +++ b/src/views/menudesign/printmenuform/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, InputNumber, Select, Radio } from 'antd' +import { Form, Row, Col, InputNumber, Select, Radio, Tooltip, Icon } from 'antd' import './index.scss' @@ -25,6 +25,20 @@ this.props.updateConfig({...this.props.config, everyPCount: val}) } + changePrintWidth = (val) => { + if (typeof(val) !== 'number') { + val = '' + } + this.props.updateConfig({...this.props.config, printWidth: val}) + } + + changePrintHeight = (val) => { + if (typeof(val) !== 'number') { + val = '' + } + this.props.updateConfig({...this.props.config, printHeight: val}) + } + changeLastCount = (val) => { if (typeof(val) !== 'number') { val = '' @@ -34,14 +48,67 @@ pageSizeChange = (val) => { this.props.updateConfig({...this.props.config, pageSize: val}) + this.resetPage() } onLayoutChange = (val) => { this.props.updateConfig({...this.props.config, pageLayout: val}) + this.resetPage() } onPaddingChange = (val) => { this.props.updateConfig({...this.props.config, pagePadding: val}) + this.resetPage() + } + + onPrintCustomChange = (val) => { + this.props.updateConfig({...this.props.config, printCustom: val}) + this.resetPage() + } + + resetPage = () => { + this.setState({}, () => { + const { config } = this.props + + if (config.printCustom !== 'true') return + + let pageSize = config.pageSize || 'A4' + let pageLayout = config.pageLayout !== 'horizontal' ? 'vertical' : 'horizontal' + let pagePadding = config.pagePadding !== 'without' ? 'default' : 'without' + + let pageParam = { + A4: { + vertical: 980, + horizontal: 1200, + verticaldefault: 1.455, + verticalwithout: 1.411, + horizontaldefault: 0.679, + horizontalwithout: 0.701, + }, + A3: { + vertical: 1200, + horizontal: 1600, + verticaldefault: 1.441, + verticalwithout: 1.410, + horizontaldefault: 0.688, + horizontalwithout: 0.703, + }, + A5: { + vertical: 700, + horizontal: 1000, + verticaldefault: 1.478, + verticalwithout: 1.413, + horizontaldefault: 0.669, + horizontalwithout: 0.700, + } + } + + let width = pageParam[pageSize][pageLayout] + let height = Math.floor(width * pageParam[pageSize][pageLayout + pagePadding]) + + this.props.updateConfig({...config, printHeight: height, printWidth: width}) + this.props.form.setFieldsValue({printHeight: height, printWidth: width}) + }) } render() { @@ -149,6 +216,37 @@ })(<InputNumber min={1} max={1000} precision={0} onChange={this.changeLastCount}/>)} </Form.Item> </Col> + <Col span={24}> + <Form.Item label={ + <Tooltip placement="topLeft" title="閽堝涓嶈鍒欑焊寮狅紝鍙嚜瀹氫箟璁剧疆鎵撳嵃楂樺害鍜屽搴︼紝娉細鍚屾椂璁剧疆鎵撳嵃瀹藉害鍜岄珮搴﹀悗鏂瑰彲鐢熸晥銆�"> + <Icon type="question-circle" /> + 鑷畾涔� + </Tooltip> + }> + {getFieldDecorator('printCustom', { + initialValue: config.printCustom || 'false' + })( + <Radio.Group onChange={(e) => {this.onPrintCustomChange(e.target.value)}}> + <Radio value="false">涓嶅惎鐢�</Radio> + <Radio value="true">鍚敤</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {config.printCustom === 'true' ? <Col span={24}> + <Form.Item label="鎵撳嵃瀹藉害"> + {getFieldDecorator('printWidth', { + initialValue: config.printWidth || '' + })(<InputNumber min={10} max={9999} precision={0} onChange={this.changePrintWidth}/>)} + </Form.Item> + </Col> : null} + {config.printCustom === 'true' ? <Col span={24}> + <Form.Item label="鎵撳嵃楂樺害"> + {getFieldDecorator('printHeight', { + initialValue: config.printHeight || '' + })(<InputNumber min={10} max={9999} precision={0} onChange={this.changePrintHeight}/>)} + </Form.Item> + </Col> : null} </Row> </Form> ) diff --git a/src/views/menudesign/printmenuform/index.scss b/src/views/menudesign/printmenuform/index.scss index 0c9f8a8..0295f37 100644 --- a/src/views/menudesign/printmenuform/index.scss +++ b/src/views/menudesign/printmenuform/index.scss @@ -2,4 +2,9 @@ .ant-input-number { width: 100%; } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } } \ No newline at end of file diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx index 677496a..e983907 100644 --- a/src/views/mobdesign/index.jsx +++ b/src/views/mobdesign/index.jsx @@ -5,10 +5,10 @@ import { is, fromJS } from 'immutable' import moment from 'moment' import HTML5Backend from 'react-dnd-html5-backend' -import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin } from 'antd' +import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Icon } from 'antd' import Api from '@/api' -import Utils from '@/utils/utils.js' +import Utils, { setGLOBFuncs } from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' import antdEnUS from 'antd/es/locale/en_US' @@ -25,15 +25,19 @@ const Header = asyncComponent(() => import('@/mob/header')) const MenuForm = asyncComponent(() => import('./menuform')) const MobShell = asyncComponent(() => import('@/mob/mobshell')) +const CreateView = asyncComponent(() => import('@/pc/createview')) +const Transfer = asyncComponent(() => import('@/pc/transfer')) const SourceWrap = asyncComponent(() => import('@/mob/modulesource')) const BgController = asyncComponent(() => import('@/pc/bgcontroller')) +const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) const SysInterface = asyncComponent(() => import('@/menu/sysinterface')) const Quotecomponent = asyncComponent(() => import('@/pc/quotecomponent')) const PasteController = asyncComponent(() => import('@/menu/pastecontroller')) const StyleController = asyncComponent(() => import('@/menu/stylecontroller')) const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent')) const PictureController = asyncComponent(() => import('@/menu/picturecontroller')) -const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller')) +const ModalController = asyncComponent(() => import('@/mob/modalconfig/controller')) +const SearchController = asyncComponent(() => import('@/mob/searchconfig/controller')) const StyleCombController = asyncComponent(() => import('@/menu/stylecombcontroller')) const StyleCombControlButton = asyncComponent(() => import('@/menu/stylecombcontrolbutton')) const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) @@ -55,15 +59,15 @@ MenuId: '', MenuName: '', MenuNo: '', - delButtons: [], - copyButtons: [], - thawButtons: [], - activeKey: 'basedata', + activeKey: 'component', menuloading: false, oriConfig: null, config: null, - visible: false, customComponents: [], + direction: 'vertical', + settingshow: true, + controlshow: true, + comloading: false } UNSAFE_componentWillMount() { @@ -75,9 +79,9 @@ sessionStorage.setItem('appId', param.ID || '') sessionStorage.setItem('lang', param.lang || 'zh-CN') sessionStorage.setItem('kei_no', param.kei_no || '') - sessionStorage.setItem('link_type', param.link_type || 'true') sessionStorage.setItem('role_type', param.role_type || 'true') - sessionStorage.setItem('login_types', param.login_types || 'true') + sessionStorage.setItem('login_types', param.login_types || 'false') + sessionStorage.setItem('typename', param.typename || 'mob') this.setState({ localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS, @@ -85,6 +89,18 @@ }) this.getAppMessage() } else if (param.type === 'view') { + window.GLOB.winWidth = 420 + window.GLOB.winHeight = 738 + window.GLOB.shellWidth = 376 + window.GLOB.shellHeight = 680 + + if (sessionStorage.getItem('typename') === 'pad') { + window.GLOB.winWidth = 736 + window.GLOB.winHeight = 945 + window.GLOB.shellWidth = 640 + window.GLOB.shellHeight = 853 + } + this.setState({ MenuId: param.MenuID }, () => { @@ -115,15 +131,14 @@ document.getElementById('mk-mob-design-view').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh; height: 100vh; background: #fff;">鏈簲鐢ㄦ病鏈塒C绔〉闈㈢殑缂栬緫鏉冮檺锛岃鑱旂郴绠$悊鍛橈紒</div>' return } - MKEmitter.addListener('delButtons', this.delButtons) - MKEmitter.addListener('thawButtons', this.thawButtons) - MKEmitter.addListener('copyButtons', this.copyButtons) MKEmitter.addListener('changeEditMenu', this.changeEditMenu) MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent) setTimeout(() => { this.updateCustomComponent() this.getAppPictures() + this.getSmStemp() + setGLOBFuncs() }, 1000) } @@ -134,12 +149,42 @@ this.setState = () => { return } - MKEmitter.removeListener('delButtons', this.delButtons) - MKEmitter.removeListener('thawButtons', this.thawButtons) - MKEmitter.removeListener('copyButtons', this.copyButtons) MKEmitter.removeListener('changeEditMenu', this.changeEditMenu) MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) MKEmitter.removeListener('updateCustomComponent', this.updateCustomComponent) + } + + getSmStemp = () => { + let _sql = `select ID,TemplateCode,SignName from (select * from bd_msn_sms_temp where deleted=0 and status=20 ) a + inner join (select openid from sapp where id='${window.GLOB.appkey}') b + on a.openid=b.openid` + + _sql = Utils.formatOptions(_sql) + + let param = { + func: 'sPC_Get_SelectedList', + LText: _sql, + obj_name: 'data', + arr_field: 'ID,TemplateCode,SignName' + } + + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉 + + Api.getSystemConfig(param).then(res => { + let msgs = [] + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } else if (res.data) { + msgs = res.data + } + sessionStorage.setItem('msgTemplate', JSON.stringify(msgs)) + }) } changeEditMenu = (menu) => { @@ -160,11 +205,8 @@ type: 'view' } - if (menu.fixed && menu.MenuNo && menu.MenuName) { - param.fixed = true - param.MenuNo = menu.MenuNo - param.MenuName = menu.MenuName - } + param.MenuNo = menu.MenuNo || '' + param.MenuName = menu.MenuName || '' param = window.btoa(window.encodeURIComponent(JSON.stringify(param))) @@ -233,13 +275,11 @@ }) } else { sessionStorage.setItem('appViewList', JSON.stringify(appViewList)) - sessionStorage.setItem('appHomeId', homeId) this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'})))) } }) } else { sessionStorage.setItem('appViewList', JSON.stringify(appViewList)) - sessionStorage.setItem('appHomeId', homeId) this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'})))) } }) @@ -276,6 +316,7 @@ updateCustomComponent = () => { Api.getSystemConfig({ func: 's_get_custom_components', + typename: sessionStorage.getItem('typename'), typecharone: '' }).then(res => { let coms = [] @@ -323,29 +364,13 @@ }) this.setState({ - config: {...config, components: []} + config: {...config, components}, + comloading: true }, () => { this.setState({ - config: {...config, components: components} + comloading: false }) }) - } - - delButtons = (items) => { - const { copyButtons, delButtons } = this.state - - this.setState({ - delButtons: [...delButtons, ...items], - copyButtons: copyButtons.filter(item => !items.includes(item.uuid)) - }) - } - - copyButtons = (items) => { - this.setState({copyButtons: [...this.state.copyButtons, ...items]}) - } - - thawButtons = (item) => { - this.setState({thawButtons: [...this.state.thawButtons, item]}) } closeView = () => { @@ -376,7 +401,7 @@ let param = { func: 'sPC_Get_LongParam', TypeCharOne: sessionStorage.getItem('kei_no'), - typename: 'mob', + typename: sessionStorage.getItem('typename'), MenuID: MenuId } @@ -410,8 +435,8 @@ MenuID: MenuId, Template: 'webPage', enabled: false, - MenuName: '', - MenuNo: '', + MenuName: urlParam.MenuName || '', + MenuNo: urlParam.MenuNo || '', tables: [], components: [], viewType: 'menu', @@ -426,12 +451,6 @@ config.open_edition = result.open_edition || '' window.GLOB.urlFields = config.urlFields || [] - if (urlParam.fixed) { - config.fixed = true - config.MenuName = urlParam.MenuName - config.MenuNo = urlParam.MenuNo - } - let indeComs = [] config.components.forEach(item => { if (item.type === 'navbar') { @@ -443,6 +462,7 @@ this.setState({ oriConfig: isCreate ? null : config, config: fromJS(config).toJS(), + activeKey: isCreate ? 'basedata' : 'component', loading: false }) window.GLOB.customMenu = config @@ -458,7 +478,7 @@ let _param = { func: 's_get_app_menus', TypeCharOne: sessionStorage.getItem('kei_no'), - typename: 'mob', + typename: sessionStorage.getItem('typename'), LText: `select '${window.GLOB.appkey}'`, timestamp: moment().format('YYYY-MM-DD HH:mm:ss') } @@ -490,7 +510,7 @@ let param = { func: 'sPC_Get_LongParam', TypeCharOne: sessionStorage.getItem('kei_no'), - typename: 'mob', + typename: sessionStorage.getItem('typename'), MenuID: urlParam.copyMenuId } @@ -545,6 +565,8 @@ config.uuid = MenuId config.MenuID = MenuId config.open_edition = '' + config.MenuName = urlParam.MenuName || '' + config.MenuNo = urlParam.MenuNo || '' let indeComs = [] config.components.forEach(item => { @@ -573,7 +595,7 @@ Api.getSystemConfig({ func: 'sPC_Get_LongParam', TypeCharOne: sessionStorage.getItem('kei_no'), - typename: 'mob', + typename: sessionStorage.getItem('typename'), MenuID: item.uuid }).then(res => { res.uuid = item.uuid @@ -632,6 +654,7 @@ this.setState({ oriConfig: isCreate ? null : fromJS(config).toJS(), + activeKey: isCreate ? 'basedata' : 'component', config: config, loading: false }) @@ -641,64 +664,123 @@ getMenuMessage = () => { const { config } = this.state - let buttons = [] - let _sort = 1 - + let traversal = (components) => { - components.forEach(item => { + let list = components.map(item => { + let m = { + key: item.uuid, + title: item.name, + children: [] + } if (item.type === 'tabs') { + let tabs = [] item.subtabs.forEach(tab => { - traversal(tab.components) + let s = traversal(tab.components) + + if (s.length === 0) return + + tabs.push({ + key: tab.uuid, + title: tab.label, + children: s + }) }) + + if (tabs.length > 0) { + m.children = tabs + } } else if (item.type === 'group') { - traversal(item.components) + m.children = traversal(item.components) } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) { item.action && item.action.forEach(btn => { this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: btn.uuid, + title: btn.label, + }) }) item.subcards.forEach(card => { card.elements && card.elements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) - buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: cell.uuid, + title: cell.label, + }) }) card.backElements && card.backElements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) - buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: cell.uuid, + title: cell.label, + }) }) }) - } else if (item.type === 'line' || item.type === 'bar') { - item.action && item.action.forEach(btn => { - this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + } else if (item.type === 'carousel') { + item.subcards.forEach(card => { + card.elements && card.elements.forEach(cell => { + if (cell.eleType !== 'button') return + this.checkBtn(cell) + m.children.push({ + key: cell.uuid, + title: cell.label, + }) + }) + }) + } else if (item.type === 'balcony') { + item.elements && item.elements.forEach(cell => { + if (cell.eleType !== 'button') return + this.checkBtn(cell) + m.children.push({ + key: cell.uuid, + title: cell.label, + }) + }) + } else if (item.type === 'menubar') { + if (item.wrap.title) { + m.title = item.wrap.title + } + + m.children = item.subMenus.map(menu => { + return { + key: menu.uuid, + title: menu.setting.name + } }) } else if (item.type === 'table' && item.subtype === 'normaltable') { item.action && item.action.forEach(btn => { this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: btn.uuid, + title: btn.label, + }) }) item.cols && item.cols.forEach(col => { if (col.type !== 'action') return col.elements.forEach(btn => { this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: btn.uuid, + title: btn.label, + }) }) }) } + + if (m.children.length === 0) return null + + return m }) + + list = list.filter(Boolean) + + return list } - traversal(config.components) + let trees = traversal(config.components) - return buttons + return trees } checkBtn = (btn) => { @@ -739,7 +821,6 @@ } submitConfig = () => { - const { delButtons, copyButtons, thawButtons } = this.state let config = fromJS(this.state.config).toJS() if (!config.MenuName || !config.MenuNo || (config.cacheUseful === 'true' && !config.cacheTime)) { @@ -749,6 +830,7 @@ duration: 5 }) this.setState({ + settingshow: true, activeKey: 'basedata' }) return @@ -765,47 +847,30 @@ config.enabled = false } - let parMenuId = sessionStorage.getItem('kei_no') + 'pc' + sessionStorage.getItem('lang') + let roleParam = {type: 'view', key: config.uuid, title: config.MenuName, children: []} + roleParam.children = this.getMenuMessage() + let param = { func: 'sPC_TrdMenu_AddUpt', - FstID: parMenuId, - SndID: parMenuId, - ParentID: parMenuId, + FstID: 'mk_app', + SndID: 'mk_app', + ParentID: 'mk_app', MenuID: config.uuid, MenuNo: config.MenuNo || '', EasyCode: '', Template: 'webPage', TypeCharOne: sessionStorage.getItem('kei_no'), - Typename: 'mob', + Typename: sessionStorage.getItem('typename'), MenuName: config.MenuName || '', PageParam: JSON.stringify({Template: 'webPage'}), open_edition: config.open_edition, + menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))), LText: '', LTexttb: '' } param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') param.secretkey = Utils.encrypt('', param.timestamp) - - let btnParam = { // 娣诲姞鑿滃崟鎸夐挳 - func: 'sPC_Button_AddUpt', - Type: 40, // 娣诲姞鑿滃崟涓嬬殑鎸夐挳type涓�40锛屾寜閽笅鐨勬寜閽畉ype涓�60 - ParentID: config.uuid, - MenuNo: config.MenuNo, - Template: 'webPage', - PageParam: '', - LongParam: '', - LText: [] - } - - btnParam.LText = this.getMenuMessage() - btnParam.LText = btnParam.LText.join(' union all ') - - let btnIds = btnParam.LText // 鐢ㄤ簬澶嶅埗鎸夐挳鐨勮繃婊� - - btnParam.LText = Utils.formatOptions(btnParam.LText) - btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp) new Promise(resolve => { let _config = fromJS(config).toJS() @@ -836,20 +901,35 @@ return } + let roles = { + type: 'navbar', + key: item.uuid, + title: item.name, + children: [] + } + + roles.children = item.menus.map(menu => { + return { + key: menu.MenuID, + title: menu.name + } + }) + let _param = { func: 'sPC_TrdMenu_AddUpt', - FstID: parMenuId, - SndID: parMenuId, - ParentID: parMenuId, + FstID: 'mk_app', + SndID: 'mk_app', + ParentID: 'mk_app', MenuID: item.uuid, - MenuNo: item.wrap.MenuNo || '', + MenuNo: item.wrap.MenuNo || Utils.getuuid(), EasyCode: '', Template: item.type, TypeCharOne: sessionStorage.getItem('kei_no'), - Typename: 'mob', + Typename: sessionStorage.getItem('typename'), MenuName: item.name || '', PageParam: JSON.stringify({Template: item.type}), open_edition: item.open_edition || '', + menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roles))), LText: '', LTexttb: '' } @@ -857,96 +937,28 @@ _param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(item))) _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') _param.secretkey = Utils.encrypt('', _param.timestamp) - - let appMenuParam = null - if (item.type === 'navbar') { - appMenuParam = { - func: 's_appmenus_addupt', - exec_type: 'y' - } - - appMenuParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - appMenuParam.secretkey = Utils.encrypt('', _param.timestamp) - - let LText = [] - let app_param = [] - let kei_no = sessionStorage.getItem('kei_no') - let userid = sessionStorage.getItem('CloudUserID') || '' - - item.menus.forEach((fst, findex) => { - // LText.push(`select '${fst.MenuID}','${fst.name}','','0','${sessionStorage.getItem('appId')}','0','${(findex + 1) * 10}','10','','${userid}','${window.GLOB.appkey}','${fst.MenuNo || ''}','${kei_no}','pc'`) - LText.push(`select '${fst.MenuID}','${fst.name}','','0','0','0','${(findex + 1) * 10}','10','','${userid}','${window.GLOB.appkey}','${fst.MenuNo || ''}','${kei_no}','pc'`) - app_param.push(`select '${window.GLOB.appkey}','${fst.MenuID}','${userid}','${(findex + 1) * 10}','','${fst.name}','${fst.MenuNo || ''}','0','10','${kei_no}','pc'`) - if (fst.property === 'classify' && fst.sublist.length > 0) { - fst.sublist.forEach(scd => { - LText.push(`select '${scd.MenuID}','${scd.name}','','0','${fst.MenuID}','0','${(findex + 1) * 10}','20','','${userid}','${window.GLOB.appkey}','${scd.MenuNo || ''}','${kei_no}','pc'`) - app_param.push(`select '${window.GLOB.appkey}','${scd.MenuID}','${userid}','${(findex + 1) * 10}','','${scd.name}','${scd.MenuNo || ''}','${fst.MenuID}','20','${kei_no}','pc'`) - - if (scd.property === 'classify' && scd.sublist.length > 0) { - scd.sublist.forEach(thd => { - LText.push(`select '${thd.MenuID}','${thd.name}','','0','${scd.MenuID}','0','${(findex + 1) * 10}','20','','${userid}','${window.GLOB.appkey}','${thd.MenuNo || ''}','${kei_no}','pc'`) - app_param.push(`select '${window.GLOB.appkey}','${thd.MenuID}','${userid}','${(findex + 1) * 10}','','${thd.name}','${thd.MenuNo || ''}','${scd.MenuID}','20','${kei_no}','pc'`) - }) - } - }) - } - }) - appMenuParam.LText = Utils.formatOptions(LText.join(' union ')) - appMenuParam.LText1 = Utils.formatOptions(app_param.join(' union ')) - } - - if (appMenuParam) { - Api.getSystemConfig(appMenuParam).then(_res => { - if (!_res.status) { - notification.warning({ - top: 92, - message: _res.message, - duration: 5 - }) - this.setState({ menuloading: false }) - return - } - - Api.getSystemConfig(_param).then(res => { - if (!res.status) { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - this.setState({ menuloading: false }) - return - } - - new_open_edition[item.uuid] = res.open_edition || '' - - resolve() + + Api.getSystemConfig(_param).then(res => { + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 }) - }) - } else { - Api.getSystemConfig(_param).then(res => { - if (!res.status) { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - this.setState({ menuloading: false }) - return - } - - new_open_edition[item.uuid] = res.open_edition || '' - resolve() - }) - } + this.setState({ menuloading: false }) + return + } + + new_open_edition[item.uuid] = res.open_edition || '' + resolve() + }) }) }) Promise.all(deffers).then(() => { let appViewList = sessionStorage.getItem('appViewList') appViewList = JSON.parse(appViewList) - let _length = appViewList.length + let _appViewList = fromJS(appViewList).toJS() let appIndeList = appViewList.map(item => item.keys_id).join(',') - config.components = config.components.map(item => { if (item.type === 'navbar') { @@ -962,12 +974,19 @@ keys_type: 'navbar', remark: item.name }) + } else { + appViewList = appViewList.map(view => { + if (view.keys_id === item.uuid) { + view.remark = item.name + } + return view + }) } } return item }) - if (appViewList.length > _length) { + if (!is(fromJS(appViewList), fromJS(_appViewList))) { let param = { func: 's_kei_link_keyids_addupt', BID: sessionStorage.getItem('appId'), @@ -1000,191 +1019,38 @@ } }) } - }).then(res => { // 鎸夐挳鎴栬彍鍗曞垹闄� - if (!res) return - - if (delButtons.length === 0) { - return { status: true, nonexec: true } - } else { - let appHomeId = sessionStorage.getItem('appHomeId') - let _param = { - func: 'sPC_MainMenu_Del', - MenuID: delButtons.filter(id => id !== appHomeId).join(',') - } - return Api.getSystemConfig(_param) - } - }).then(res => { // 鎸夐挳瑙i櫎鍐荤粨 - if (!res) return - if (!res.status) { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - return false - } else if (!res.nonexec) { // 鎵ц鍒犻櫎鍚庡埛鏂拌彍鍗曞垪琛� - this.getAppMenus() - } - - let ids = thawButtons.filter(item => btnIds.indexOf(item) !== -1) - if (ids.length === 0) { - return { status: true } - } else { - return Api.getSystemConfig({ - func: 'sPC_MainMenu_ReDel', - MenuID: ids.join(',') - }) - } }).then(res => { // 椤甸潰淇濆瓨 if (!res) return - if (res.status) { - return Api.getSystemConfig(param) - } else { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - return false - } - }).then(res => { // 椤甸潰鎸夐挳鍏崇郴淇濆瓨 + return Api.getSystemConfig(param) + }).then(res => { if (!res) return if (res.status) { config.open_edition = res.open_edition || '' - + this.setState({ + config, oriConfig: fromJS(config).toJS(), - }) - - if (btnParam.LText) { - return Api.getSystemConfig(btnParam) - } else { - return { - status: true - } - } - } else { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - return false - } - }).then(res => { // 鎸夐挳澶嶅埗 - if (!res) return - if (!res.status) { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - return false - } - - if (copyButtons.length === 0) { - return { - status: true - } - } else { - return new Promise(resolve => { - let deffers = copyButtons.map(item => { - return new Promise(resolve => { - if (btnIds.indexOf(item.uuid) === -1) { // 澶嶅埗鐨勬寜閽凡鍒犻櫎 - resolve({ - status: true - }) - return - } - - Api.getSystemConfig({ - func: 'sPC_Get_LongParam', - MenuID: item.$originUuid - }).then(result => { - if (result.status) { - let _conf = '' - - try { - _conf = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : '' - } catch (e) { - console.warn('Parse Failure') - _conf = '' - } - - if (_conf) { - _conf.components = MenuUtils.resetConfig(_conf.components) - _conf.uuid = item.uuid - _conf.MenuID = item.uuid - _conf.Template = 'webPage' - } else { - resolve({ - status: true - }) - return - } - - let _param = { - func: 'sPC_ButtonParam_AddUpt', - ParentID: config.uuid, - MenuID: item.uuid, - MenuNo: '', - Template: 'webPage', - MenuName: item.label, - PageParam: JSON.stringify({Template: 'webPage'}), - LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_conf))) - } - - Api.getSystemConfig(_param).then(response => { - resolve(response) - }) - } - }) - }) - }) - Promise.all(deffers).then(result => { - let error = null - result.forEach(response => { - if (!response.status) { - error = response - } - }) - - if (error) { - notification.warning({ - top: 92, - message: error.message, - duration: 5 - }) - resolve(false) - } else { - resolve({ - status: true - }) - } - }) - }) - } - }).then(res => { - if (res && res.status) { - this.setState({ - delButtons: [], - copyButtons: [], - thawButtons: [], menuloading: false, - config: {...config, components: []} + comloading: true }, () => { this.setState({ - config: {...this.state.config, components: this.state.oriConfig.components} + comloading: false }) }) + notification.success({ top: 92, message: '淇濆瓨鎴愬姛', duration: 2 }) } else { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) this.setState({ menuloading: false }) @@ -1241,25 +1107,46 @@ const { config } = this.state let error = '' - config.components.forEach(item => { - if (error) return - if (['propcard', 'brafteditor', 'sandbox'].includes(item.subtype) && item.wrap.datatype === 'static') return + let check = (components) => { + components.forEach(item => { + if (error) return + if (item.type === 'tabs') { + item.subtabs.forEach(tab => { + check(tab.components) + }) + return + } else if (item.type === 'group') { + check(item.components) + return + } else if (item.type === 'navbar' && !item.wrap.MenuNo) { + error = `瀵艰埅鏍忋��${item.name}銆嬫湭璁剧疆鑿滃崟鍙傛暟锛乣 + } - if (item.setting) { - if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` - } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` - } else if (item.setting.interType && !item.setting.primaryKey) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆涓婚敭锛乣 + if (['propcard', 'brafteditor', 'sandbox', 'tabbar', 'stepform'].includes(item.subtype) && item.wrap.datatype === 'static') return + if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return + + if (item.setting) { + if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` + } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` + } else if (!item.setting.primaryKey) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆涓婚敭锛乣 + } } - } - if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') { - if (!item.plot.Xaxis) { - error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒` + if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') { + if (!item.plot.Xaxis) { + error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒` + } + } else if (item.type === 'dashboard' && !item.plot.valueField) { + error = `缁勪欢銆�${item.name}銆嬫樉绀哄�煎皻鏈缃紒` + } else if (item.type === 'scatter' && (!item.plot.Xaxis || !item.plot.Yaxis || !item.plot.gender)) { + error = `缁勪欢銆�${item.name}銆嬪潗鏍囪酱灏氭湭璁剧疆锛乣 } - } - }) + }) + } + + check(config.components) if (show && error) { notification.warning({ @@ -1301,11 +1188,6 @@ }) return } - - // Api.getSystemConfig({ - // func: 'sPC_MainMenu_Del', - // MenuID: '1614740497468ku800sbg853vupf65v4' - // }) sessionStorage.removeItem('sysRoles') sessionStorage.removeItem('permFuncField') @@ -1366,7 +1248,6 @@ duration: 5 }) } else { - sessionStorage.setItem('appHomeId', config.MenuID) sessionStorage.setItem('appViewList', JSON.stringify(appViewList)) } }) @@ -1375,20 +1256,59 @@ }) } + changeView = (val) => { + if (val !== 'vertical') { + window.GLOB.winWidth = 992 + window.GLOB.winHeight = 690 + window.GLOB.shellWidth = 853 + window.GLOB.shellHeight = 640 + } else { + window.GLOB.winWidth = 736 + window.GLOB.winHeight = 945 + window.GLOB.shellWidth = 640 + window.GLOB.shellHeight = 853 + } + + this.setState({ + direction: val, + comloading: true + }, () => { + this.setState({ comloading: false }) + }) + } + + resetConfig = (config) => { + this.setState({ + config: config, + comloading: true + }, () => { + this.setState({ + comloading: false + }) + }) + + window.GLOB.customMenu = config + } + + render () { - const { localedict, loading, activeKey, dict, MenuId, config, menuloading, customComponents } = this.state + const { localedict, comloading, loading, settingshow, controlshow, activeKey, dict, MenuId, config, menuloading, customComponents } = this.state return ( <ConfigProvider locale={localedict}> <div className="mk-mob-view" id="mk-mob-design-view"> - <Header /> + <Header changeView={this.changeView}/> {loading ? <Spin className="view-spin" size="large" /> : null} <DndProvider backend={HTML5Backend}> - <div className="menu-setting"> + <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}> + <div className="draw"> + {settingshow ? <Icon onClick={() => {this.setState({settingshow: false})}} type="double-left" /> : null} + {!settingshow ? <Icon onClick={() => {this.setState({settingshow: true})}} type="double-right" /> : null} + </div> <div className="pc-setting-tools"> <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> {/* 鍩烘湰淇℃伅 */} - <Panel header={dict['mob.basemsg']} key="basedata"> + <Panel header={dict['mob.basemsg']} forceRender key="basedata"> {/* 鑿滃崟淇℃伅 */} {config ? <MenuForm dict={dict} @@ -1413,9 +1333,14 @@ </Collapse> </div> </div> - <div className="menu-control"> + <div className={'menu-control ' + (!controlshow ? 'hidden' : '')}> + <div className="draw"> + {controlshow ? <Icon onClick={() => {this.setState({controlshow: false})}} type="double-right" /> : null} + {!controlshow ? <Icon onClick={() => {this.setState({controlshow: true})}} type="double-left" /> : null} + </div> <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config && config.enabled} onChange={this.onEnabledChange} /> + <CreateView resetmenu={this.getAppMenus} /> <PasteController type="menu" Tab={null} insert={this.insert} /> <StyleCombControlButton menu={config} /> <SysInterface config={config} updateConfig={this.updateConfig}/> @@ -1423,17 +1348,20 @@ <Quotecomponent config={config} updateConfig={this.updateConfig}/> <Button className="mk-border-green" icon="home" onClick={this.setHomeView}>璁句负棣栭〉</Button> <Button className="mk-border-danger" icon="redo" onClick={this.refreshView}>寮哄埗鍒锋柊</Button> - <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> + <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/> + <Transfer MenuID={MenuId} /> + <Button type="default" onClick={this.closeView}>鍏抽棴</Button> </div> - <div className={'menu-body' + (menuloading ? 'saving' : '')}> - <div className="mob-shell"> - {config ? <MobShell menu={config} handleList={this.updateConfig} /> : null} - </div> + <div className={'menu-body menu-view' + (menuloading ? 'saving' : '')}> + {config && !comloading ? <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}> + <MobShell menu={config} handleList={this.updateConfig} /> + </div> : null} </div> </DndProvider> <StyleController /> <StyleCombController /> <ModalController /> + <SearchController /> </div> </ConfigProvider> ) diff --git a/src/views/mobdesign/index.scss b/src/views/mobdesign/index.scss index 7699f0b..82ae4e6 100644 --- a/src/views/mobdesign/index.scss +++ b/src/views/mobdesign/index.scss @@ -17,6 +17,20 @@ z-index: 10; transition: left 0.3s; + .draw { + position: absolute; + z-index: 1; + background: #ffffff; + right: -20px; + top: 0px; + box-shadow: 0 0 1px #959595; + border-radius: 0 2px 2px 0px; + + i { + padding: 12px 3px; + } + } + .pc-setting-tools { height: calc(100vh - 48px); width: 300px; @@ -102,36 +116,33 @@ background: rgba(0, 0, 0, 0); } } + .menu-setting.hidden { + left: -300px; + } .mob-shell { - width: 375px; - height: 680px; margin: 0 auto; background: #000000; background-size: 100% 100%; padding: 25px 13px 40px; border-radius: 30px; - - .mob-shell-inner { - width: 100%; - height: 100%; - overflow-y: auto; - overflow-x: hidden; - background: #ffffff; - box-shadow: 0px 0px 2px #000000; - } - .mob-shell-inner::-webkit-scrollbar { - width: 2px; - } - .mob-shell-inner::-webkit-scrollbar-thumb { - box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); - background: rgba(0, 0, 0, 0.23); - border-radius: 5px; - } - .mob-shell-inner::-webkit-scrollbar-track { - box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); - border: 1px solid rgba(0, 0, 0, 0.07); - background: rgba(0, 0, 0, 0); - border-radius: 3px; + .main-search-edit-list { + .page-card > div > .ant-form-item { + display: flex; + >.ant-form-item-label { + width: 70px; + } + >.ant-form-item-control-wrapper { + flex: 1; + } + .ant-form-item-label > label::after { + content: ' '; + + } + } + .page-card.date .ant-form-item, .page-card.datemonth .ant-form-item { + // box-shadow: 0px 1px 1px #f0f0f0; + border-bottom: 1px solid #f0f0f0; + } } } .menu-control { @@ -143,6 +154,20 @@ background: #ffffff; z-index: 10; transition: right 0.3s; + + .draw { + position: absolute; + z-index: 1; + background: #ffffff; + left: -21px; + top: 0px; + box-shadow: 0 0 1px #959595; + border-radius: 0 2px 2px 0px; + + i { + padding: 12px 3px; + } + } div:not(.draw), button:not(.ant-switch) { display: block!important; @@ -163,6 +188,9 @@ height: 22px; } } + .menu-control.hidden { + right: -130px; + } .menu-body { width: 100vw; @@ -172,12 +200,9 @@ background: #959595; padding: 50px 0px 0px; overflow-y: auto; - .menu-shell-inner { - min-height: 100vh; - margin: 0 auto; - } + } - .menu-body.saving { + .menu-body.saving, .menu-view.saving { .anticon-tool { display: none; } diff --git a/src/views/mobdesign/menuform/index.jsx b/src/views/mobdesign/menuform/index.jsx index 2335bcf..cedb3a5 100644 --- a/src/views/mobdesign/menuform/index.jsx +++ b/src/views/mobdesign/menuform/index.jsx @@ -69,7 +69,7 @@ message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.name'] + '!' } ] - })(<Input placeholder="" disabled={!!(config.fixed && config.MenuName)} autoComplete="off" onChange={this.changeName}/>)} + })(<Input placeholder="" autoComplete="off" onChange={this.changeName}/>)} </Form.Item> </Col> <Col span={24}> @@ -82,7 +82,7 @@ message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.param'] + '!' } ] - })(<Input placeholder="" disabled={!!(config.fixed && config.MenuName)} autoComplete="off" onChange={this.changeNo}/>)} + })(<Input placeholder="" autoComplete="off" onChange={this.changeNo}/>)} </Form.Item> </Col> <Col span={24}> diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx index 29818ec..bde0d56 100644 --- a/src/views/pcdesign/index.jsx +++ b/src/views/pcdesign/index.jsx @@ -8,7 +8,7 @@ import { ConfigProvider, notification, Modal, Collapse, Switch, Button, Icon, message, Spin } from 'antd' import Api from '@/api' -import Utils from '@/utils/utils.js' +import Utils, { setGLOBFuncs } from '@/utils/utils.js' import zhCN from '@/locales/zh-CN/mob.js' import enUS from '@/locales/en-US/mob.js' import antdEnUS from 'antd/es/locale/en_US' @@ -23,12 +23,16 @@ const { confirm } = Modal const MenuForm = asyncComponent(() => import('./menuform')) +const Transfer = asyncComponent(() => import('@/pc/transfer')) +const PopviewController = asyncComponent(() => import('@/menu/popview')) const MenuShell = asyncComponent(() => import('@/pc/menushell')) const SourceWrap = asyncComponent(() => import('@/pc/modulesource')) +const CreateView = asyncComponent(() => import('@/pc/createview')) const BgController = asyncComponent(() => import('@/pc/bgcontroller')) const Quotecomponent = asyncComponent(() => import('@/pc/quotecomponent')) const PasteController = asyncComponent(() => import('@/menu/pastecontroller')) const StyleController = asyncComponent(() => import('@/menu/stylecontroller')) +const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) const SysInterface = asyncComponent(() => import('@/menu/sysinterface')) const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent')) const PictureController = asyncComponent(() => import('@/menu/picturecontroller')) @@ -40,6 +44,7 @@ sessionStorage.setItem('isEditState', 'true') sessionStorage.setItem('editMenuType', 'menu') // 缂栬緫鑿滃崟绫诲瀷 sessionStorage.setItem('appType', 'pc') // 搴旂敤绫诲瀷 +sessionStorage.setItem('typename', 'pc') document.body.className = '' window.GLOB.UserComponentMap = new Map() // 缂撳瓨鐢ㄦ埛鑷畾涔夌粍浠� window.GLOB.CacheIndependent = new Map() @@ -66,6 +71,7 @@ customComponents: [], settingshow: sessionStorage.getItem('settingshow') !== 'false', controlshow: sessionStorage.getItem('controlshow') !== 'false', + comloading: false } UNSAFE_componentWillMount() { @@ -77,9 +83,8 @@ sessionStorage.setItem('appId', param.ID || '') sessionStorage.setItem('lang', param.lang || 'zh-CN') sessionStorage.setItem('kei_no', param.kei_no || '') - sessionStorage.setItem('link_type', param.link_type || 'true') sessionStorage.setItem('role_type', param.role_type || 'true') - sessionStorage.setItem('login_types', param.login_types || 'true') + sessionStorage.setItem('login_types', param.login_types || 'false') this.setState({ localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS, @@ -127,6 +132,8 @@ setTimeout(() => { this.updateCustomComponent() this.getAppPictures() + this.getSmStemp() + setGLOBFuncs() }, 1000) } @@ -164,15 +171,15 @@ type: 'view' } - if (menu.fixed && menu.MenuNo && menu.MenuName) { - param.fixed = true - param.MenuNo = menu.MenuNo - param.MenuName = menu.MenuName - } + param.MenuNo = menu.MenuNo || '' + param.MenuName = menu.MenuName || '' param = window.btoa(window.encodeURIComponent(JSON.stringify(param))) - if (param === this.props.match.params.param) return + if (param === this.props.match.params.param) { + window.location.reload() + return + } this.props.history.push('/pcdesign/' + param) } @@ -237,15 +244,46 @@ }) } else { sessionStorage.setItem('appViewList', JSON.stringify(appViewList)) - sessionStorage.setItem('appHomeId', homeId) this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'})))) } }) } else { sessionStorage.setItem('appViewList', JSON.stringify(appViewList)) - sessionStorage.setItem('appHomeId', homeId) this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'})))) } + }) + } + + getSmStemp = () => { + let _sql = `select ID,TemplateCode,SignName from (select * from bd_msn_sms_temp where deleted=0 and status=20 ) a + inner join (select openid from sapp where id='${window.GLOB.appkey}') b + on a.openid=b.openid` + + _sql = Utils.formatOptions(_sql) + + let param = { + func: 'sPC_Get_SelectedList', + LText: _sql, + obj_name: 'data', + arr_field: 'ID,TemplateCode,SignName' + } + + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉 + + Api.getSystemConfig(param).then(res => { + let msgs = [] + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } else if (res.data) { + msgs = res.data + } + sessionStorage.setItem('msgTemplate', JSON.stringify(msgs)) }) } @@ -261,6 +299,12 @@ }).then(res => { if (res.status) { sessionStorage.setItem('app_pictures', JSON.stringify(res.data || [])) + } else if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) } Api.getSystemConfig({ @@ -272,6 +316,12 @@ }).then(res => { if (res.status) { sessionStorage.setItem('app_videos', JSON.stringify(res.data || [])) + } else if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) } }) }) @@ -280,10 +330,17 @@ updateCustomComponent = () => { Api.getSystemConfig({ func: 's_get_custom_components', + typename: 'pc', typecharone: '' }).then(res => { let coms = [] - if (res.cus_list && res.cus_list.length > 0) { + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } else if (res.cus_list && res.cus_list.length > 0) { res.cus_list.forEach(item => { let config = '' @@ -314,6 +371,14 @@ }) } + handleBack = () => { + this.setState({popBtn: null, delButtons: [], copyButtons: [], thawButtons: []}, () => { + sessionStorage.setItem('editMenuType', 'menu') + window.GLOB.customMenu = this.state.config + this.setState({visible: false}) + }) + } + updateComponentStyle = (parentId, keys, style) => { const { config } = this.state @@ -327,10 +392,11 @@ }) this.setState({ - config: {...config, components: []} + config: {...config, components}, + comloading: true }, () => { this.setState({ - config: {...config, components: components} + comloading: false }) }) } @@ -434,8 +500,8 @@ MenuID: MenuId, Template: 'webPage', enabled: false, - MenuName: '', - MenuNo: '', + MenuName: urlParam.MenuName || '', + MenuNo: urlParam.MenuNo || '', tables: [], components: [], viewType: 'menu', @@ -444,17 +510,11 @@ } } } - + config.uuid = MenuId config.MenuID = MenuId config.open_edition = result.open_edition || '' window.GLOB.urlFields = config.urlFields || [] - - if (urlParam.fixed) { - config.fixed = true - config.MenuName = urlParam.MenuName - config.MenuNo = urlParam.MenuNo - } let indeComs = [] config.components.forEach(item => { @@ -570,6 +630,8 @@ config.uuid = MenuId config.MenuID = MenuId config.open_edition = '' + config.MenuName = urlParam.MenuName || '' + config.MenuNo = urlParam.MenuNo || '' let indeComs = [] config.components.forEach(item => { @@ -666,64 +728,149 @@ getMenuMessage = () => { const { config } = this.state - let buttons = [] - let _sort = 1 + let nodes = {type: 'view', key: config.uuid, title: config.MenuName, children: []} + let popviews = [] let traversal = (components) => { - components.forEach(item => { + let list = components.map(item => { + let m = { + key: item.uuid, + title: item.name, + children: [] + } if (item.type === 'tabs') { + let tabs = [] item.subtabs.forEach(tab => { - traversal(tab.components) + let s = traversal(tab.components) + + if (s.length === 0) return + + tabs.push({ + key: tab.uuid, + title: tab.label, + children: s + }) }) + + if (tabs.length > 0) { + m.children = tabs + } } else if (item.type === 'group') { - traversal(item.components) + m.children = traversal(item.components) } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) { item.action && item.action.forEach(btn => { this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: btn.uuid, + title: btn.label, + }) + if (btn.OpenType === 'popview') { + popviews.push(btn.uuid) + } }) item.subcards.forEach(card => { card.elements && card.elements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) - buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: cell.uuid, + title: cell.label, + }) + if (cell.OpenType === 'popview') { + popviews.push(cell.uuid) + } }) card.backElements && card.backElements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) - buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: cell.uuid, + title: cell.label, + }) + if (cell.OpenType === 'popview') { + popviews.push(cell.uuid) + } }) }) - } else if (item.type === 'line' || item.type === 'bar') { - item.action && item.action.forEach(btn => { - this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + } else if (item.type === 'carousel') { + item.subcards.forEach(card => { + card.elements && card.elements.forEach(cell => { + if (cell.eleType !== 'button') return + this.checkBtn(cell) + m.children.push({ + key: cell.uuid, + title: cell.label, + }) + if (cell.OpenType === 'popview') { + popviews.push(cell.uuid) + } + }) + }) + } else if (item.type === 'balcony') { + item.elements && item.elements.forEach(cell => { + if (cell.eleType !== 'button') return + this.checkBtn(cell) + m.children.push({ + key: cell.uuid, + title: cell.label, + }) + if (cell.OpenType === 'popview') { + popviews.push(cell.uuid) + } + }) + } else if (item.type === 'menubar') { + if (item.wrap.title) { + m.title = item.wrap.title + } + + m.children = item.subMenus.map(menu => { + return { + key: menu.uuid, + title: menu.setting.name + } }) } else if (item.type === 'table' && item.subtype === 'normaltable') { item.action && item.action.forEach(btn => { this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: btn.uuid, + title: btn.label, + }) + if (btn.OpenType === 'popview') { + popviews.push(btn.uuid) + } }) item.cols && item.cols.forEach(col => { if (col.type !== 'action') return col.elements.forEach(btn => { this.checkBtn(btn) - buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) - _sort++ + m.children.push({ + key: btn.uuid, + title: btn.label, + }) + if (btn.OpenType === 'popview') { + popviews.push(btn.uuid) + } }) }) } + + if (m.children.length === 0) return null + + return m }) + + list = list.filter(Boolean) + + return list } - traversal(config.components) + let trees = traversal(config.components) - return buttons + nodes.children = trees + nodes.popviews = popviews + + return nodes } checkBtn = (btn) => { @@ -792,12 +939,13 @@ config.enabled = false } - let parMenuId = sessionStorage.getItem('kei_no') + 'pc' + sessionStorage.getItem('lang') + let roleParam = this.getMenuMessage() + let param = { func: 'sPC_TrdMenu_AddUpt', - FstID: parMenuId, - SndID: parMenuId, - ParentID: parMenuId, + FstID: 'mk_app', + SndID: 'mk_app', + ParentID: 'mk_app', MenuID: config.uuid, MenuNo: config.MenuNo || '', EasyCode: '', @@ -806,6 +954,7 @@ Typename: 'pc', MenuName: config.MenuName || '', PageParam: JSON.stringify({Template: 'webPage'}), + menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))), open_edition: config.open_edition, LText: '', LTexttb: '' @@ -813,26 +962,6 @@ param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') param.secretkey = Utils.encrypt('', param.timestamp) - - let btnParam = { // 娣诲姞鑿滃崟鎸夐挳 - func: 'sPC_Button_AddUpt', - Type: 40, // 娣诲姞鑿滃崟涓嬬殑鎸夐挳type涓�40锛屾寜閽笅鐨勬寜閽畉ype涓�60 - ParentID: config.uuid, - MenuNo: config.MenuNo, - Template: 'webPage', - PageParam: '', - LongParam: '', - LText: [] - } - - btnParam.LText = this.getMenuMessage() - btnParam.LText = btnParam.LText.join(' union all ') - - let btnIds = btnParam.LText // 鐢ㄤ簬澶嶅埗鎸夐挳鐨勮繃婊� - - btnParam.LText = Utils.formatOptions(btnParam.LText) - btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp) new Promise(resolve => { let _config = fromJS(config).toJS() @@ -863,19 +992,51 @@ return } + let roles = { + type: 'navbar', + key: item.uuid, + title: item.name, + children: [] + } + + roles.children = item.menus.map(fst => { + if (fst.property === 'classify' && fst.sublist.length > 0) { + return { + key: fst.MenuID, + title: fst.name, + children: fst.sublist.map(scd => { + if (scd.property === 'classify' && scd.sublist.length > 0) { + return { + key: scd.MenuID, + title: scd.name, + children: scd.sublist.map(thd => { + return { key: thd.MenuID, title: thd.name } + }) + } + } else { + return { key: scd.MenuID, title: scd.name } + } + }) + } + } else { + return { key: fst.MenuID, title: fst.name } + } + }) + let _param = { func: 'sPC_TrdMenu_AddUpt', - FstID: parMenuId, - SndID: parMenuId, - ParentID: parMenuId, + FstID: 'mk_app', + SndID: 'mk_app', + ParentID: 'mk_app', MenuID: item.uuid, - MenuNo: item.wrap.MenuNo || '', + MenuNo: item.wrap.MenuNo || Utils.getuuid(), EasyCode: '', Template: item.type, TypeCharOne: sessionStorage.getItem('kei_no'), Typename: 'pc', MenuName: item.name || '', PageParam: JSON.stringify({Template: item.type}), + menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roles))), open_edition: item.open_edition || '', LText: '', LTexttb: '' @@ -885,95 +1046,27 @@ _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') _param.secretkey = Utils.encrypt('', _param.timestamp) - let appMenuParam = null - if (item.type === 'navbar') { - appMenuParam = { - func: 's_appmenus_addupt', - exec_type: 'y' - } - - appMenuParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - appMenuParam.secretkey = Utils.encrypt('', _param.timestamp) - - let LText = [] - let app_param = [] - let kei_no = sessionStorage.getItem('kei_no') - let userid = sessionStorage.getItem('CloudUserID') || '' - - item.menus.forEach((fst, findex) => { - // LText.push(`select '${fst.MenuID}','${fst.name}','','0','${sessionStorage.getItem('appId')}','0','${(findex + 1) * 10}','10','','${userid}','${window.GLOB.appkey}','${fst.MenuNo || ''}','${kei_no}','pc'`) - LText.push(`select '${fst.MenuID}','${fst.name}','','0','0','0','${(findex + 1) * 10}','10','','${userid}','${window.GLOB.appkey}','${fst.MenuNo || ''}','${kei_no}','pc'`) - app_param.push(`select '${window.GLOB.appkey}','${fst.MenuID}','${userid}','${(findex + 1) * 10}','','${fst.name}','${fst.MenuNo || ''}','0','10','${kei_no}','pc'`) - if (fst.property === 'classify' && fst.sublist.length > 0) { - fst.sublist.forEach(scd => { - LText.push(`select '${scd.MenuID}','${scd.name}','','0','${fst.MenuID}','0','${(findex + 1) * 10}','20','','${userid}','${window.GLOB.appkey}','${scd.MenuNo || ''}','${kei_no}','pc'`) - app_param.push(`select '${window.GLOB.appkey}','${scd.MenuID}','${userid}','${(findex + 1) * 10}','','${scd.name}','${scd.MenuNo || ''}','${fst.MenuID}','20','${kei_no}','pc'`) - - if (scd.property === 'classify' && scd.sublist.length > 0) { - scd.sublist.forEach(thd => { - LText.push(`select '${thd.MenuID}','${thd.name}','','0','${scd.MenuID}','0','${(findex + 1) * 10}','20','','${userid}','${window.GLOB.appkey}','${thd.MenuNo || ''}','${kei_no}','pc'`) - app_param.push(`select '${window.GLOB.appkey}','${thd.MenuID}','${userid}','${(findex + 1) * 10}','','${thd.name}','${thd.MenuNo || ''}','${scd.MenuID}','20','${kei_no}','pc'`) - }) - } - }) - } - }) - appMenuParam.LText = Utils.formatOptions(LText.join(' union ')) - appMenuParam.LText1 = Utils.formatOptions(app_param.join(' union ')) - } - - if (appMenuParam) { - Api.getSystemConfig(appMenuParam).then(_res => { - if (!_res.status) { - notification.warning({ - top: 92, - message: _res.message, - duration: 5 - }) - this.setState({ menuloading: false }) - return - } - - Api.getSystemConfig(_param).then(res => { - if (!res.status) { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - this.setState({ menuloading: false }) - return - } - - new_open_edition[item.uuid] = res.open_edition || '' - - resolve() + Api.getSystemConfig(_param).then(res => { + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 5 }) - }) - } else { - Api.getSystemConfig(_param).then(res => { - if (!res.status) { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - this.setState({ menuloading: false }) - return - } - - new_open_edition[item.uuid] = res.open_edition || '' - resolve() - }) - } + this.setState({ menuloading: false }) + return + } + + new_open_edition[item.uuid] = res.open_edition || '' + resolve() + }) }) }) Promise.all(deffers).then(() => { let appViewList = sessionStorage.getItem('appViewList') appViewList = JSON.parse(appViewList) - let _length = appViewList.length + let _appViewList = fromJS(appViewList).toJS() let appIndeList = appViewList.map(item => item.keys_id).join(',') - config.components = config.components.map(item => { if (item.type === 'navbar') { @@ -989,27 +1082,34 @@ keys_type: 'navbar', remark: item.name }) + } else { + appViewList = appViewList.map(view => { + if (view.keys_id === item.uuid) { + view.remark = item.name + } + return view + }) } } return item }) - if (appViewList.length > _length) { - let param = { + if (!is(fromJS(appViewList), fromJS(_appViewList))) { + let kparam = { func: 's_kei_link_keyids_addupt', BID: sessionStorage.getItem('appId'), exec_type: 'y', LText: '' } - param.LText = appViewList.map(item => `select '${item.keys_id}','${item.keys_type}','${item.kei_no}','${item.appkey}','${item.bid}','${sessionStorage.getItem('CloudUserID')}','${item.remark}'`) - param.LText = param.LText.join(' union all ') - param.LText = Utils.formatOptions(param.LText) + kparam.LText = appViewList.map(item => `select '${item.keys_id}','${item.keys_type}','${item.kei_no}','${item.appkey}','${item.bid}','${sessionStorage.getItem('CloudUserID')}','${item.remark}'`) + kparam.LText = kparam.LText.join(' union all ') + kparam.LText = Utils.formatOptions(kparam.LText) - param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') - param.secretkey = Utils.encrypt('', param.timestamp) + kparam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + kparam.secretkey = Utils.encrypt('', kparam.timestamp) - Api.getSystemConfig(param).then(result => { + Api.getSystemConfig(kparam).then(result => { if (!result.status) { notification.warning({ top: 92, @@ -1033,10 +1133,9 @@ if (delButtons.length === 0) { return { status: true, nonexec: true } } else { - let appHomeId = sessionStorage.getItem('appHomeId') let _param = { func: 'sPC_MainMenu_Del', - MenuID: delButtons.filter(id => id !== appHomeId).join(',') + MenuID: delButtons.join(',') } return Api.getSystemConfig(_param) } @@ -1053,13 +1152,12 @@ this.getAppMenus() } - let ids = thawButtons.filter(item => btnIds.indexOf(item) !== -1) - if (ids.length === 0) { + if (thawButtons.length === 0) { return { status: true } } else { return Api.getSystemConfig({ func: 'sPC_MainMenu_ReDel', - MenuID: ids.join(',') + MenuID: thawButtons.join(',') }) } }).then(res => { // 椤甸潰淇濆瓨 @@ -1082,15 +1180,12 @@ config.open_edition = res.open_edition || '' this.setState({ + config, oriConfig: fromJS(config).toJS(), }) - if (btnParam.LText) { - return Api.getSystemConfig(btnParam) - } else { - return { - status: true - } + return { + status: true } } else { notification.warning({ @@ -1119,7 +1214,7 @@ return new Promise(resolve => { let deffers = copyButtons.map(item => { return new Promise(resolve => { - if (btnIds.indexOf(item.uuid) === -1) { // 澶嶅埗鐨勬寜閽凡鍒犻櫎 + if (delButtons.includes(item.uuid)) { // 澶嶅埗鐨勬寜閽凡鍒犻櫎 resolve({ status: true }) @@ -1200,10 +1295,10 @@ copyButtons: [], thawButtons: [], menuloading: false, - config: {...config, components: []} + comloading: true }, () => { this.setState({ - config: {...this.state.config, components: this.state.oriConfig.components} + comloading: false }) }) notification.success({ @@ -1268,25 +1363,45 @@ const { config } = this.state let error = '' - config.components.forEach(item => { - if (error) return - if (['propcard', 'brafteditor', 'sandbox'].includes(item.subtype) && item.wrap.datatype === 'static') return + let check = (components) => { + components.forEach(item => { + if (error) return + if (item.type === 'tabs') { + item.subtabs.forEach(tab => { + check(tab.components) + }) + return + } else if (item.type === 'group') { + check(item.components) + return + } + if (['propcard', 'brafteditor', 'sandbox', 'stepform'].includes(item.subtype) && item.wrap.datatype === 'static') return + if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return + + if (item.setting) { + if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` + } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` + } else if (!item.setting.primaryKey) { + error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆涓婚敭锛乣 + } + } + if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') { + if (!item.plot.Xaxis) { + error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒` + } + } else if (item.type === 'dashboard' && !item.plot.valueField) { + error = `缁勪欢銆�${item.name}銆嬫樉绀哄�煎皻鏈缃紒` + } else if (item.type === 'scatter' && (!item.plot.Xaxis || !item.plot.Yaxis || !item.plot.gender)) { + error = `缁勪欢銆�${item.name}銆嬪潗鏍囪酱灏氭湭璁剧疆锛乣 + } else if (item.type === 'tree' && (!item.wrap.valueField || !item.wrap.labelField || !item.wrap.parentField)) { + error = `缁勪欢銆�${item.name}銆嬪熀鏈俊鎭皻鏈缃紒` + } + }) + } - if (item.setting) { - if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` - } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒` - } else if (item.setting.interType && !item.setting.primaryKey) { - error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆涓婚敭锛乣 - } - } - if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') { - if (!item.plot.Xaxis) { - error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒` - } - } - }) + check(config.components) if (show && error) { notification.warning({ @@ -1303,6 +1418,19 @@ updateConfig = (config) => { this.setState({ config: config + }) + + window.GLOB.customMenu = config + } + + resetConfig = (config) => { + this.setState({ + config: config, + comloading: true + }, () => { + this.setState({ + comloading: false + }) }) window.GLOB.customMenu = config @@ -1328,11 +1456,6 @@ }) return } - - // Api.getSystemConfig({ - // func: 'sPC_MainMenu_Del', - // MenuID: '1614740497468ku800sbg853vupf65v4' - // }) sessionStorage.removeItem('sysRoles') sessionStorage.removeItem('permFuncField') @@ -1393,7 +1516,6 @@ duration: 5 }) } else { - sessionStorage.setItem('appHomeId', config.MenuID) sessionStorage.setItem('appViewList', JSON.stringify(appViewList)) } }) @@ -1403,13 +1525,13 @@ } render () { - const { localedict, loading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents } = this.state + const { localedict, loading, visible, popBtn, comloading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents } = this.state return ( <ConfigProvider locale={localedict}> <div className={'mk-pc-view '} id="mk-pc-design-view"> {loading ? <Spin className="view-spin" size="large" /> : null} - <DndProvider backend={HTML5Backend}> + {!popBtn && !visible ? <DndProvider backend={HTML5Backend}> <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}> <div className="draw"> {settingshow ? <Icon onClick={() => {sessionStorage.setItem('settingshow', 'false'); this.setState({settingshow: false})}} type="double-left" /> : null} @@ -1450,6 +1572,7 @@ </div> <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config && config.enabled} onChange={this.onEnabledChange} /> + <CreateView resetmenu={this.getAppMenus} /> <PasteController type="menu" Tab={null} insert={this.insert} /> <StyleCombControlButton menu={config} /> <SysInterface config={config} updateConfig={this.updateConfig}/> @@ -1457,12 +1580,15 @@ <Quotecomponent config={config} updateConfig={this.updateConfig}/> <Button className="mk-border-green" icon="home" onClick={this.setHomeView}>璁句负棣栭〉</Button> <Button className="mk-border-danger" icon="redo" onClick={this.refreshView}>寮哄埗鍒锋柊</Button> - <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> + <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/> + <Transfer MenuID={MenuId} /> + <Button type="default" onClick={this.closeView}>鍏抽棴</Button> </div> - <div className={'menu-body ' + (menuloading ? 'saving' : '')}> - {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} + <div className={'menu-body menu-view' + (menuloading ? 'saving' : '')}> + {config && !comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} </div> - </DndProvider> + </DndProvider> : null} + {popBtn && visible ? <PopviewController btn={popBtn} handleBack={this.handleBack}/> : null} <StyleController /> <StyleCombController /> <ModalController /> diff --git a/src/views/pcdesign/index.scss b/src/views/pcdesign/index.scss index 01fc2a0..3cf126b 100644 --- a/src/views/pcdesign/index.scss +++ b/src/views/pcdesign/index.scss @@ -182,7 +182,7 @@ margin: 0 auto; } } - .menu-body.saving { + .menu-body.saving, .menu-view.saving { .anticon-tool { display: none; } diff --git a/src/views/pcdesign/menuform/index.jsx b/src/views/pcdesign/menuform/index.jsx index 2335bcf..cedb3a5 100644 --- a/src/views/pcdesign/menuform/index.jsx +++ b/src/views/pcdesign/menuform/index.jsx @@ -69,7 +69,7 @@ message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.name'] + '!' } ] - })(<Input placeholder="" disabled={!!(config.fixed && config.MenuName)} autoComplete="off" onChange={this.changeName}/>)} + })(<Input placeholder="" autoComplete="off" onChange={this.changeName}/>)} </Form.Item> </Col> <Col span={24}> @@ -82,7 +82,7 @@ message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.param'] + '!' } ] - })(<Input placeholder="" disabled={!!(config.fixed && config.MenuName)} autoComplete="off" onChange={this.changeNo}/>)} + })(<Input placeholder="" autoComplete="off" onChange={this.changeNo}/>)} </Form.Item> </Col> <Col span={24}> diff --git a/src/views/printTemplate/index.jsx b/src/views/printTemplate/index.jsx index e6e46a6..af5cce2 100644 --- a/src/views/printTemplate/index.jsx +++ b/src/views/printTemplate/index.jsx @@ -681,12 +681,6 @@ } else if (res.type === 'qrcode') { res.url = qrurl } else if (res.type === 'image') { - if (res.value && res.value.length > 0) { - let url = res.value[0].url || res.value[0].response - res.value = url || '' - } else { - res.value = '' - } res.url = imgurl } diff --git a/src/views/printTemplate/mutilform/index.jsx b/src/views/printTemplate/mutilform/index.jsx index f26ae33..120c3fd 100644 --- a/src/views/printTemplate/mutilform/index.jsx +++ b/src/views/printTemplate/mutilform/index.jsx @@ -1,12 +1,14 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Form, Row, Col, Input, InputNumber, Select } from 'antd' +import { Form, Row, Col, Input, InputNumber, Select, Tooltip, Icon } from 'antd' import { formRule } from '@/utils/option.js' -import FileUpload from '@/tabviews/zshare/fileupload' +// import FileUpload from '@/tabviews/zshare/fileupload' +import asyncComponent from '@/utils/asyncComponent' import './index.scss' const { TextArea } = Input +const FileUpload = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) class MainSearch extends Component { static propTpyes = { @@ -52,6 +54,9 @@ formlist: nextProps.formlist.map(item => { if (item.key === 'cusfield' && isCusField) { item.hidden = false + } else if (item.key === 'value' && item.type === 'fileupload') { + item.hidden = true + item.initval = fieldsvalue.value } return item @@ -60,15 +65,17 @@ if (!isCusField) { delete fieldsvalue.cusfield } - if (nextProps.editItem.type === 'image' && fieldsvalue.value) { - fieldsvalue.value = [{ - uid: '1', - name: fieldsvalue.value, - status: 'done', - url: fieldsvalue.value - }] - } else if (nextProps.editItem.type === 'image') { - fieldsvalue.value = [] + if (nextProps.editItem.type === 'image') { + this.setState({ + formlist: this.state.formlist.map(item => { + if (item.key === 'value' && item.type === 'fileupload') { + item.hidden = false + } + + return item + }) + }) + delete fieldsvalue.value } this.props.form.setFieldsValue(fieldsvalue) @@ -112,19 +119,6 @@ this.handleSubmit() } - updateImg = (list) => { - if (list && list.length > 0) { - let url = list[0].url || list[0].response - if (url) { - this.props.form.setFieldsValue({ value: list }) - this.handleSubmit() - } - } else { - this.props.form.setFieldsValue({ value: [] }) - this.handleSubmit() - } - } - resetForm = (param) => { let _param = JSON.parse(JSON.stringify(param)) delete _param.type @@ -134,15 +128,9 @@ if (_param.field !== 'other_field') { delete _param.cusfield } - if (param.type === 'image' && param.value) { - _param.value = [{ - uid: '1', - name: param.value, - status: 'done', - url: param.value - }] - } else if (param.type === 'image') { - _param.value = [] + + if (param.type === 'image') { + delete _param.value } this.props.form.setFieldsValue(_param) @@ -238,21 +226,16 @@ </Col> ) } else if (item.type === 'fileupload') { - let filelist = [] - if (item.initval) { - filelist = [{ - uid: '1', - name: item.initval, - status: 'done', - url: item.initval - }] - } - fields.push( <Col span={24} key={index}> - <Form.Item label={item.label}> + <Form.Item label={ + item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> {getFieldDecorator(item.key, { - initialValue: filelist, + initialValue: item.initval || '', rules: [ { required: item.required, @@ -260,7 +243,7 @@ } ] })( - <FileUpload maxFile={1} fileType={'text'} onChange={this.updateImg} /> + <FileUpload type="picture" placement="right" onChange={this.handleSubmit} /> )} </Form.Item> </Col> @@ -268,7 +251,12 @@ } else if (item.type === 'textarea') { fields.push( <Col span={24} key={index}> - <Form.Item label={item.label} > + <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: [ @@ -298,7 +286,6 @@ if (!err) { values.uuid = this.props.editItem.uuid values.type = this.props.editItem.type - resolve(values) } }) diff --git a/src/views/printTemplate/mutilform/index.scss b/src/views/printTemplate/mutilform/index.scss index 2b92a82..006a247 100644 --- a/src/views/printTemplate/mutilform/index.scss +++ b/src/views/printTemplate/mutilform/index.scss @@ -21,6 +21,20 @@ // width: 89.5%; // } // } + .mk-source-wrap { + >.ant-radio-group { + >.ant-radio-button-wrapper:last-child { + display: none; + } + >.ant-radio-button-wrapper:not(:first-child) { + border-radius: 0 4px 4px 0; + } + } + } + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } .ant-input-number { width: 100%; } diff --git a/src/views/printTemplate/option.js b/src/views/printTemplate/option.js index 3731a2b..1671000 100644 --- a/src/views/printTemplate/option.js +++ b/src/views/printTemplate/option.js @@ -795,6 +795,14 @@ required: false }, { + type: 'textarea', + key: 'productValue', + label: '姝e紡鍦板潃', + initval: item.productValue || '', + tooltip: '姝e紡绯荤粺浣跨敤鐨勫浘鐗囷紝涓虹┖鏃朵娇鐢ㄥ浘鐗囧湴鍧�銆�', + required: false + }, + { type: 'select', key: 'field', label: '鍏宠仈瀛楁', diff --git a/src/views/printTemplate/print.js b/src/views/printTemplate/print.js index b2cbe6f..4247780 100644 --- a/src/views/printTemplate/print.js +++ b/src/views/printTemplate/print.js @@ -382,7 +382,7 @@ if (image.complete) { context.drawImage(image, _left, _top, element.imgWidth, element.imgHeight) - + context.restore() // 閲嶇疆鐢诲竷 if (elements.length > 0) { this.sketchothers(context, elements, selectId, ratio, resolve) @@ -401,6 +401,14 @@ } } } + image.onerror = () => { + context.restore() // 閲嶇疆鐢诲竷 + if (elements.length > 0) { + this.sketchothers(context, elements, selectId, ratio, resolve) + } else { + this.cachesketch(context, resolve) + } + } } } diff --git a/src/views/rolemanage/header/index.jsx b/src/views/rolemanage/header/index.jsx new file mode 100644 index 0000000..d49edb8 --- /dev/null +++ b/src/views/rolemanage/header/index.jsx @@ -0,0 +1,32 @@ +import React, {Component} from 'react' + +import avatar from '@/assets/img/avatar.jpg' +import MainLogo from '@/assets/img/main-logo.png' +import './index.scss' + +class AppManageHeader extends Component { + state = { + avatar: sessionStorage.getItem('CloudAvatar') || avatar, + userName: sessionStorage.getItem('CloudUserName') + } + + render () { + const { app } = this.props + return ( + <header className="app-manage-header-container"> + <div className="header-logo"><img src={MainLogo} alt=""/></div> + <div className="title"> + {`${app.remark} ${app.typename}`} + </div> + <div className="header-user"> + <img src={this.state.avatar} alt=""/> + <span> + <span className="username">{this.state.userName}</span> + </span> + </div> + </header> + ) + } +} + +export default AppManageHeader \ No newline at end of file diff --git a/src/views/rolemanage/header/index.scss b/src/views/rolemanage/header/index.scss new file mode 100644 index 0000000..84580f7 --- /dev/null +++ b/src/views/rolemanage/header/index.scss @@ -0,0 +1,58 @@ +.app-manage-header-container { + width: 100%; + height: 48px; + color: rgba(255, 255, 255, 0.65); + position: fixed; + top: 0px; + z-index: 10; + padding-right: 0px; + left: 0; + + background: #001529; + border-bottom: 1px solid #000; + + .header-logo { + float: left; + width: 180px; + line-height: 48px; + text-align: center; + padding-left: 5px; + box-sizing: border-box; + opacity: 1; + img { + max-width: 100%; + max-height: 40px; + } + } + .header-user { + float: right; + line-height: 48px; + margin-right: 10px; + img { + width: 29px; + height: 29px; + border-radius: 30px; + margin-right: 7px; + } + span { + color: #ffffff; + font-size: 0.95rem; + .username { + display: inline-block; + height: 30px; + max-width: 95px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + } + .title { + position: absolute; + left: 50%; + top: 10px; + color: #ffffff; + font-size: 18px; + transform: translateX(-50%); + } +} \ No newline at end of file diff --git a/src/views/rolemanage/index.jsx b/src/views/rolemanage/index.jsx new file mode 100644 index 0000000..e9164c3 --- /dev/null +++ b/src/views/rolemanage/index.jsx @@ -0,0 +1,813 @@ +import React, {Component} from 'react' +import { fromJS } from 'immutable' +import { Spin, notification, Button, Table, Modal, ConfigProvider, Tree, Input, Empty } from 'antd' +import moment from 'moment' +import md5 from 'md5' +import enUS from 'antd/es/locale/en_US' +import zhCN from 'antd/es/locale/zh_CN' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const { confirm } = Modal +const { TreeNode } = Tree +const { Search } = Input + +const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS +const Header = asyncComponent(() => import('./header')) +const TransferForm = asyncComponent(() => import('@/templates/zshare/basetransferform')) + +sessionStorage.setItem('isEditState', 'true') + +class RoleManage extends Component { + state = { + app: null, + loading: false, + menulist: [], + columns: [ + { title: '鑿滃崟鍚嶇О', dataIndex: 'MenuName', key: 'MenuName', align: 'center' }, + { + title: '鎿嶄綔', + key: 'action', + align: 'center', + render: (text, record) => ( + <div> + <Button type="link" onClick={() => this.deleteMenu(record)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button> + </div> + ), + }, + ], + selectApp: null, + selectSubApp: null, + visible: false, + thawmenulist: [], + confirmLoading: false, + targetKeys: [], + trees: null, + expandedKeys: [], + searchkey: '' + } + + oriTrees = null + + UNSAFE_componentWillMount() { + let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param))) + + this.setState({app: param}, () => { + this.getTreeList() + this.getMenuList() + }) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + getMenuList = (reset) => { + const { app } = this.state + let param = { + func: 's_get_app_menus', + TypeCharOne: app.kei_no, + typename: app.typename, + LText: `select '${window.GLOB.appkey}'`, + timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), + lang: app.lang + } + + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + + this.setState({ + loading: true + }) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + this.setState({ + menulist: result.menus.map(item => { + item.nodes = '' + item.type = 'view' + if (item.menus_rolelist) { + try { + let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist))) + item.nodes = pageParam + if (pageParam.type === 'navbar') { + item.type = 'navbar' + } + } catch { + item.nodes = '' + } + } + + return item + }) + }, () => { + if (reset && (!this.oriTrees || this.oriTrees.length === 0)) { + this.initMenutree() + } else if (!reset && this.oriTrees && this.oriTrees.length === 0) { + this.initMenutree() + } + this.setState({loading: false}) + }) + } else { + this.setState({ + loading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }) + } + + getTreeList = () => { + const { app } = this.state + let param = { + func: 's_get_menus_roles_tree', + typecharone: app.kei_no, + lang: app.lang + } + + param.upid = md5(window.GLOB.appkey + app.kei_no + app.typename + app.lang) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + if (!result.data || result.data.length === 0) { + this.oriTrees = [] + if (this.state.menulist.length > 0) { + this.initMenutree() + } + this.setState({trees: [], loading: false}) + } else { + this.oriTrees = result.data + this.initTrees(result.data) + this.setState({loading: false}) + } + } else { + this.setState({ + loading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }) + } + + initTrees = (data) => { + let trees = [] + let map = new Map() + let _data = data.sort((a, b) => { + return a.sort - b.sort + }) + + _data.forEach(menu => { + if (menu.ParentID === 'top') { + trees.push({ + key: menu.MenuID, + title: menu.MenuName, + children: [] + }) + } else { + map.set(menu.MenuID, menu) + } + }) + + let reset = (m) => { + return m.map(n => { + [...map.keys()].forEach(key => { + if (map.get(key).ParentID === n.key) { + let c = map.get(key) + n.children.push({ + key: c.MenuID, + title: c.MenuName, + children: [] + }) + map.delete(key) + } + }) + if (n.children.length > 0) { + n.children = reset(n.children) + } + return n + }) + } + + trees = reset(trees) + + let expandedKeys = this.getExpandedKeys(trees, 0, []) + + this.setState({trees, expandedKeys}) + } + + getExpandedKeys = (trees, i, keys) => { + if (i >= 3 || !trees[0]) return keys + + keys.push(trees[0].key) + + i++ + + if (trees[0].children && trees[0].children.length > 0) { + keys = this.getExpandedKeys(trees[0].children, i, keys) + } + + return keys + } + + initMenutree = (resolve) => { + const { menulist } = this.state + + if (!menulist || menulist.length === 0) { + this.setState({trees: [], expandedKeys: []}, () => { + if (resolve) { + this.execSave(resolve) + } + }) + + return + } + + let navbars = [] + let map = new Map() + + fromJS(menulist).toJS().forEach(menu => { + if (!menu.nodes) return + + if (menu.type === 'navbar') { + navbars.push(menu.nodes) + } else { + map.set(menu.MenuID, menu.nodes) + } + }) + + let data = [] + + if (navbars.length === 0) { + data = [...map.values()] + } else { + let reset = (m) => { + return m.map(n => { + if (n.children && n.children.length > 0) { + n.children = reset(n.children) + } else if (map.has(n.key)) { + let p = map.get(n.key) + if (p.children && p.children.length > 0) { + n.children = reset(p.children) + } + map.delete(n.key) + } + return n + }) + } + + data = reset(navbars) + data = [...data, ...map.values()] + } + + let expandedKeys = this.getExpandedKeys(data, 0, []) + + this.setState({trees: [], expandedKeys: []}, () => { + this.setState({trees: data, expandedKeys}, () => { + if (resolve) { + this.execSave(resolve) + } + }) + }) + } + + getThawMenulist = () => { + const { app } = this.state + + Api.getCloudConfig({ + func: 'sPC_Get_FrozenMenu', + ParentID: 'mk_app', + TypeCharOne: app.kei_no, + typename: app.typename, + lang: app.lang + }).then(res => { + if (res.status) { + this.setState({ + thawmenulist: res.data.map(menu => { + return { + key: menu.MenuID, + title: menu.MenuName + } + }) + }) + } else { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } + }) + } + + deleteMenu = (record) => { + const { app } = this.state + const _this = this + + let param = { + func: 'sPC_MainMenu_Del', + MenuID: record.MenuID, + TypeCharOne: app.kei_no, + typename: app.typename, + lang: app.lang + } + + if (app.typename === 'pc' && record.nodes && record.nodes.popviews && record.nodes.popviews.length > 0) { + param.MenuID = param.MenuID + ',' + record.nodes.popviews.join(',') + } + + confirm({ + content: '纭畾鍒犻櫎璇ヨ彍鍗曞悧锛�', + onOk() { + return new Promise(resolve => { + Api.getCloudConfig(param).then(result => { + if (result.status) { + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛锛�', + duration: 3 + }) + _this.getMenuList(true) + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + resolve() + }, () => { + resolve() + }) + }) + }, + onCancel() {} + }) + } + + thawSubmit = () => { + const { targetKeys, app } = this.state + + if (targetKeys.length === 0) { + notification.warning({ + top: 92, + message: '璇烽�夋嫨瑙i櫎鍐荤粨鐨勮彍鍗曪紒', + duration: 5 + }) + return + } + + this.setState({ + confirmLoading: true + }) + + Api.getSystemConfig({ + func: 'sPC_MainMenu_ReDel', + MenuID: targetKeys.join(','), + TypeCharOne: app.kei_no, + typename: app.typename, + lang: app.lang + }).then(res => { + if (!res.status) { + notification.warning({ + top: 92, + message: res.message, + duration: 2 + }) + this.setState({ + confirmLoading: false + }) + } else { + let param = { + func: 's_get_app_menus', + TypeCharOne: app.kei_no, + typename: app.typename, + LText: `select '${window.GLOB.appkey}'`, + timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), + lang: app.lang + } + + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + let list = [] + this.setState({ + menulist: result.menus.map(item => { + item.nodes = '' + item.type = 'view' + if (item.menus_rolelist) { + try { + let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist))) + item.nodes = pageParam + if (pageParam.type === 'navbar') { + item.type = 'navbar' + } + } catch { + item.nodes = '' + } + } + + if (targetKeys.includes(item.MenuID) && item.nodes && item.nodes.popviews && item.nodes.popviews.length > 0) { + list = [...list, ...item.nodes.popviews] + } + + return item + }) + }, () => { + if (!this.oriTrees || this.oriTrees.length === 0) { + this.initMenutree() + } + }) + + if (app.typename === 'pc' && list.length > 0) { + Api.getSystemConfig({ + func: 'sPC_MainMenu_ReDel', + MenuID: list.join(','), + TypeCharOne: app.kei_no, + typename: app.typename, + lang: app.lang + }).then(response => { + if (!response.status) { + notification.warning({ + top: 92, + message: response.message, + duration: 2 + }) + this.setState({ + confirmLoading: false + }) + } else { + this.setState({ + confirmLoading: false, + visible: false, + targetKeys: [] + }) + } + }) + } else { + this.setState({ + confirmLoading: false, + visible: false, + targetKeys: [] + }) + } + } else { + this.setState({ + confirmLoading: false + }) + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + }) + } + }) + } + + onDrop = info => { + const dropKey = info.node.props.eventKey + const dragKey = info.dragNode.props.eventKey + const dropPos = info.node.props.pos.split('-') + const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]) + + const loop = (data, key, callback) => { + data.forEach((item, index, arr) => { + if (item.key === key) { + return callback(item, index, arr) + } + if (item.children) { + return loop(item.children, key, callback) + } + }) + } + const data = [...this.state.trees] + + let dragObj + loop(data, dragKey, (item, index, arr) => { + arr.splice(index, 1) + dragObj = item + }) + + if (!info.dropToGap) { + loop(data, dropKey, item => { + item.children = item.children || [] + + item.children.push(dragObj) + }) + } else if ((info.node.props.children || []).length > 0 && info.node.props.expanded && dropPosition === 1 ) { + loop(data, dropKey, item => { + item.children = item.children || [] + + item.children.unshift(dragObj) + }) + } else { + let ar; + let i; + + loop(data, dropKey, (item, index, arr) => { + ar = arr + i = index + }) + + if (dropPosition === -1) { + ar.splice(i, 0, dragObj) + } else { + ar.splice(i + 1, 0, dragObj) + } + } + + this.setState({ + trees: data + }) + } + + renderNode = data => { + return data.map(item => { + if (item.children && item.children.length) { + return ( + <TreeNode key={item.key} title={item.title}> + {this.renderNode(item.children)} + </TreeNode> + ) + } + return <TreeNode key={item.key} title={item.title} /> + }) + } + + initTree = () => { + const _this = this + confirm({ + content: '鍒濆鍖栦細鏍规嵁鑿滃崟閲嶇疆鏉冮檺鏍戯紝纭畾鎵ц鍚楋紵', + onOk() { + return new Promise(resolve => { + _this.initMenutree(resolve) + }) + }, + onCancel() {} + }) + } + + syncTree = () => { + const _this = this + + confirm({ + content: '鍚屾浼氭牴鎹彍鍗曞垹闄ゆ垨鏂板鑺傜偣锛岀‘瀹氭墽琛屽悧锛�', + onOk() { + return new Promise(resolve => { + _this.syncMenutree(resolve) + }) + }, + onCancel() {} + }) + } + + saveTree = () => { + const { trees } = this.state + const _this = this + + if (!trees || trees.length === 0) { + notification.warning({ + top: 92, + message: '鏈幏鍙栧埌鏉冮檺淇℃伅锛�', + duration: 5 + }) + return + } + + confirm({ + content: '纭畾鎵ц鍚楋紵', + onOk() { + return new Promise(resolve => { + _this.execSave(resolve) + }) + }, + onCancel() {} + }) + } + + syncMenutree = (resolve) => { + const { menulist } = this.state + + if (menulist.length === 0) { + this.setState({trees: [], expandedKeys: []}, () => { + this.execSave(resolve) + }) + + return + } + + let navbars = [] + let map = new Map() + + fromJS(menulist).toJS().forEach(menu => { + if (!menu.nodes) return + + if (menu.type === 'navbar') { + navbars.push(menu.nodes) + } else { + map.set(menu.MenuID, menu.nodes) + } + }) + + let re = {} + this.oriTrees && this.oriTrees.forEach(item => { + if (item.ParentID === 'top') return + if (!re[item.ParentID]) { + re[item.ParentID] = [] + } + re[item.ParentID].push(item.MenuID) + }) + + let data = [] + + if (navbars.length === 0) { + data = [...map.values()] + } else { + let reset = (m) => { + return m.map(n => { + if (n.children && n.children.length > 0) { + n.children = reset(n.children) + } else if (map.has(n.key)) { + let p = map.get(n.key) + if (p.children && p.children.length > 0) { + n.children = reset(p.children) + } + map.delete(n.key) + } + if (re[n.key]) { + n.children = n.children || [] + re[n.key].forEach(c => { + if (map.has(c)) { + let p = map.get(c) + if (p.children && p.children.length > 0) { + p.children = reset(p.children) + } + map.delete(c) + n.children.push(p) + } + }) + } + return n + }) + } + + data = reset(navbars) + data = [...data, ...map.values()] + } + + let expandedKeys = this.getExpandedKeys(data, 0, []) + + this.setState({trees: [], expandedKeys: []}, () => { + this.setState({trees: data, expandedKeys}, () => { + this.execSave(resolve) + }) + }) + } + + execSave = (resolve) => { + const { trees, app } = this.state + + let lines = [] + let i = 0 + let reset = (m) => { + m.children.forEach(n => { + lines.push(`'${n.key}','${n.title}','${m.key}',${i}`) + i++ + if (n.children) { + reset(n) + } + }) + } + + trees.forEach(g => { + lines.push(`'${g.key}','${g.title}','top',${i}`) + i++ + if (g.children) { + reset(g) + } + }) + + let param = { + func: 's_menus_roles_tree_adduptdel', + typecharone: app.kei_no, + typename: app.typename, + lang: app.lang + } + + lines = lines.join(';') + + param.upid = md5(window.GLOB.appkey + param.typecharone + param.typename + param.lang) + param.menus_roles_longtext = window.btoa(window.encodeURIComponent(lines)) + + Api.getCloudConfig(param).then(result => { + if (result.status) { + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛锛�', + duration: 3 + }) + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + resolve() + }, () => { + resolve() + }) + } + + triggerThaw = () => { + this.getThawMenulist() + this.setState({ visible: true, targetKeys: [] }) + } + + render () { + const { app, loading, columns, menulist, trees, searchkey } = this.state + let _menulist = menulist + + if (searchkey) { + _menulist = _menulist.filter(item => item.MenuName.toLowerCase().indexOf(searchkey.toLowerCase()) > -1) + } + + return ( + <div className="mk-role-manage"> + <ConfigProvider locale={_locale}> + <Header app={app} /> + {loading ? + <div className="loading-mask"> + <Spin size="large" /> + </div> : null + } + <div className="view-wrap"> + <div className="left-view"> + <div className="app-table"> + <div className="app-action"> + <Button className="mk-green" onClick={this.triggerThaw}>瑙e喕鑿滃崟</Button> + <Search placeholder="缁煎悎鎼滅储" onSearch={value => this.setState({ searchkey: value })} enterButton /> + </div> + <Table + rowKey="MenuID" + columns={columns} + dataSource={_menulist} + pagination={false} + /> + </div> + </div> + <div className="right-view"> + <div className="app-action"> + <Button className="mk-primary" onClick={this.initTree}>鍒濆鍖�</Button> + <Button className="mk-purple" onClick={this.syncTree}>鍚屾</Button> + <Button className="mk-green save" onClick={this.saveTree}>淇濆瓨</Button> + </div> + {trees && trees.length ? <Tree + className="draggable-tree" + defaultExpandedKeys={this.state.expandedKeys} + // showLine + draggable + blockNode + onDrop={this.onDrop} + > + {this.renderNode(trees)} + </Tree> : <div className="empty"> + <Empty /> + </div>} + </div> + </div> + <Modal + title="瑙i櫎鍐荤粨" + visible={this.state.visible} + width={600} + onOk={this.thawSubmit} + confirmLoading={this.state.confirmLoading} + onCancel={() => this.setState({visible: false, targetKeys: []})} + destroyOnClose + > + <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/> + </Modal> + </ConfigProvider> + </div> + ) + } +} + +export default RoleManage \ No newline at end of file diff --git a/src/views/rolemanage/index.scss b/src/views/rolemanage/index.scss new file mode 100644 index 0000000..277ceb0 --- /dev/null +++ b/src/views/rolemanage/index.scss @@ -0,0 +1,90 @@ +.mk-role-manage { + background: #fff; + min-height: 100vh; + padding: 70px 30px; + + .loading-mask { + position: fixed; + top: 0px; + bottom: 0px; + left: 0px; + right: 0px; + z-index: 2; + background: rgba(255, 255, 255, 0.35); + + .ant-spin { + position: absolute; + left: 50%; + top: 50%; + } + } + .mob-header-container { + padding-right: 0px; + z-index: 10; + left: 0; + } + .view-wrap { + width: 100%; + position: relative; + display: flex; + + .left-view { + flex: 1; + width: 50%; + padding-right: 5px; + .ant-table-tbody > tr > td { + padding: 8px 16px; + } + } + .right-view { + width: 50%; + padding-left: 20px; + + .draggable-tree { + border: 1px solid #e8e8e8; + padding: 10px 10px 30px; + min-height: 400px; + border-radius: 4px; + .ant-tree-title { + max-width: 100%; + display: inline-block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + } + .empty { + border: 1px solid #e8e8e8; + padding: 100px 10px 30px; + min-height: 400px; + border-radius: 4px; + } + } + } + .ant-table-wrapper { + .ant-table-body { + border: 1px solid #e8e8e8; + border-bottom: 0; + border-radius: 4px; + } + .ant-table-tbody { + > tr.ant-table-row-selected td { + background: #bae7ff; + } + } + } + .app-action { + >button { + margin-bottom: 10px; + margin-right: 15px; + } + .ant-input-search { + width: 250px; + float: right; + } + .save { + float: right; + margin-right: 0px; + } + } +} -- Gitblit v1.8.0