king
2021-01-15 76a4300654a18d228838c3f27455dc8e7a8cd616
Merge branch 'master' into bms
5 文件已重命名
133个文件已修改
15个文件已添加
20个文件已删除
10957 ■■■■ 已修改文件
package-lock.json 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/index.html 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/editor/index.jsx 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/editor/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/resetpwd/index.jsx 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tabview/index.jsx 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tabview/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/main.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/main.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/model.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/bgcontroller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/card.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.jsx 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/wrapsetting/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/prop-card/index.jsx 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/table-card/index.jsx 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.jsx 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupsetting/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/normal-group/index.jsx 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/search/main-search/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/dragaction/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/logcomponent/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/markcomponent/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/markcomponent/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/markcomponent/markform/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/markcomponent/markform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/pastecomponent/index.jsx 81 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/searchcomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/usercomponent/index.jsx 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/usercomponent/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/usercomponent/settingform/index.jsx 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/usercomponent/settingform/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.scss 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.jsx 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/customscript/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/settingform/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/header/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/dragsource/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/dragsource/index.scss 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/index.jsx 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/option.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/pastecontroller/index.jsx 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/popview/index.jsx 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontrolbutton/index.jsx 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontrolbutton/index.scss 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontroller/index.jsx 566 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontroller/index.scss 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontroller/styleInput/index.jsx 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecombcontroller/styleInput/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/utils/menuUtils.js 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/colorsketch/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/colorsketch/index.scss 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/controller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/contupdate/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/datasource/verifycard/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/header/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/calendar/index.jsx 118 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/calendar/index.scss 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 381 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.scss 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/secretKeyTable/actionList/index.jsx 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/secretKeyTable/actionList/index.scss 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/secretKeyTable/config.jsx 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/secretKeyTable/index.jsx 367 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/secretKeyTable/index.scss 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardItem/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 75 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.jsx 143 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/prop-card/index.jsx 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/table-card/index.jsx 86 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.jsx 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.scss 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-pie/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/formtab/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/iframe/index.jsx 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/rolemanage/index.jsx 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/scriptmanage/index.jsx 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/scriptmanage/topSearch/index.jsx 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/scriptmanage/topSearch/index.scss 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 138 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtabtable/index.jsx 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/tabmanage/index.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/treepage/index.jsx 312 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/treepage/index.scss 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/verupmanage/index.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/verupmanage/subtabtable/index.jsx 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/verupmanage/topSearch/index.jsx 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/verupmanage/topSearch/index.scss 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/asyncButtonComponent.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/changeuserbutton/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/excelInbutton/index.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/exceloutbutton/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.jsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/newpagebutton/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/popupbutton/index.jsx 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/popupbutton/index.scss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/tabbutton/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/cardcomponent/index.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/chartcomponent/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/fileupload/index.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/pageMessage/index.jsx 353 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/pageMessage/index.scss 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/settingcomponent/editTable/index.jsx 322 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/settingcomponent/editTable/index.scss 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/settingcomponent/index.jsx 460 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/settingcomponent/index.scss 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/index.jsx 346 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/index.scss 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/actionform/index.jsx 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/columnform/index.jsx 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/columnform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/index.jsx 570 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/index.scss 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printform/index.jsx 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.jsx 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.jsx 101 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editfirstmenu/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editfirstmenu/menuform/index.jsx 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editsecmenu/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editthdmenu/index.jsx 114 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editthdmenu/menuform/index.jsx 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/menuform/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/treepageconfig/index.jsx 463 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customform/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customscript/index.jsx 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-datamanage.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.scss 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 264 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.scss 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/printTemplate/index.jsx 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/printTemplate/index.scss 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -4201,9 +4201,9 @@
      }
    },
    "braft-extensions": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/braft-extensions/-/braft-extensions-0.1.0.tgz",
      "integrity": "sha512-i7/GjJY2FCJUKqdHiFeohasWQvY1BMK1BU4KGDZo+K+d3i55sIsiBmmRRDrOazDLWBVqYi1rBu2uqFQvxJu1jw==",
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/braft-extensions/-/braft-extensions-0.1.1.tgz",
      "integrity": "sha512-lmqGA6TIMqejQfeQ5NvqNsD+pbyqJjWPh6CMcRL2hKd+3yo5Oc9dv6uTWx+f8ICnxXJEs6LZHYOA58zcP2cnJQ==",
      "requires": {
        "@babel/runtime": "^7.0.0",
        "braft-convert": "^2.1.10",
package.json
@@ -20,7 +20,7 @@
    "babel-plugin-named-asset-import": "^0.3.3",
    "babel-preset-react-app": "9.0.0",
    "braft-editor": "^2.3.9",
    "braft-extensions": "^0.1.0",
    "braft-extensions": "^0.1.1",
    "browserslist": "^4.13.0",
    "camelcase": "^5.2.0",
    "caniuse-lite": "^1.0.30001102",
public/index.html
@@ -5,6 +5,7 @@
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link rel="shortcut icon" href="#">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title></title>
  </head>
src/api/index.js
@@ -70,8 +70,6 @@
  }
}
window.GLOB.CacheMap = new Map()
axios.interceptors.response.use((response) => {
  if (response.data.ErrCode === 'LoginError') {
    if (window.debugger === true) {
@@ -622,6 +620,46 @@
  }
  /**
   * @description 获取本地系统配置
   * @param {Object}  param   请求参数
   */
  getLocalCacheConfig (param) {
    param.userid = sessionStorage.getItem('UserID') || ''
    param.lang = localStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
    param.LoginUID = sessionStorage.getItem('LoginUID') || ''
    param.appkey = window.GLOB.appkey || ''
    if (window.GLOB.mainSystemApi) {
      param.rduri = window.GLOB.mainSystemApi
    }
    let _param  = md5(JSON.stringify(param))
    if (mkDataBase) {
      return new Promise(resolve => {
        mkDataBase.transaction(tx => {
          tx.executeSql(`SELECT * FROM CONFIGS WHERE menuid='${param.MenuID}' and userid='${param.userid}'`, [], (tx, results) => {
            let paramItem = results.rows[0]
            if (paramItem) {
              resolve({ ErrCode: 'S', ErrMesg: '', LongParam: paramItem.LongParam, message: '', status: true })
            } else {
              resolve({ ErrCode: 'S', ErrMesg: '', LongParam: '', message: '', status: false })
            }
          }, (tx, results) => {
            mkDataBase = null
            resolve({ErrCode: 'S', ErrMesg: '', LongParam: '', message: '', status: false})
          })
        })
      })
    } else if (window.GLOB.CacheMap.has(_param)) {
      return Promise.resolve(window.GLOB.CacheMap.get(_param))
    } else {
      return Promise.resolve({ErrCode: 'S', ErrMesg: '', LongParam: '', message: '', status: false})
    }
  }
  /**
   * @description 将数据写入websql
   */
  writeInWebSql (data) {
src/assets/css/main.scss
@@ -255,10 +255,35 @@
  }
}
.popview-modal {
.ant-modal.popview-modal {
  top: 70px;
  .ant-modal-body {
    min-height: 250px;
    max-height: calc(100vh - 190px);
    max-height: calc(100vh - 210px);
    overflow-y: auto;
  }
  .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);
  }
}
.ant-modal-wrap.popview-modal {
  .ant-modal {
    top: 70px;
  }
  .ant-modal-body {
    min-height: 250px;
    max-height: calc(100vh - 210px);
    overflow-y: auto;
  }
  .ant-modal-body::-webkit-scrollbar {
src/components/editor/index.jsx
New file
@@ -0,0 +1,41 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import 'braft-editor/dist/index.css'
import 'braft-extensions/dist/table.css'
import BraftEditor from 'braft-editor'
import Table from 'braft-extensions/dist/table'
import './index.scss'
BraftEditor.use(Table())
class NormalEditor extends Component {
  static propTpyes = {
    card: PropTypes.object,  // 条码设置
    value: PropTypes.any,    // 条码值
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps))
  }
  handleEditorChange = () => {
  }
  submitContent = () => {
  }
  render() {
    return (
      <div className="normal-braft-editor">
        <BraftEditor value={'<p></p>'} onChange={this.handleEditorChange} onSave={this.submitContent}/>
      </div>
    )
  }
}
export default NormalEditor
src/components/editor/index.scss
src/components/header/index.jsx
@@ -25,6 +25,7 @@
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
import Resetpwd from './resetpwd'
import LoginForm from './loginform'
import './index.scss'
@@ -747,7 +748,7 @@
    return (
      <header className="header-container ant-menu-dark" id="main-header-container">
        <div className={'header-logo ' + (collapse ? 'collapse' : '')}><img src={this.state.logourl} alt=""/></div>
        <div className={'header-logo ' + (collapse ? 'collapse' : '')}><img src={!this.props.editState ? this.state.logourl : MainLogo} alt=""/></div>
        <div className={'header-collapse ' + (collapse ? 'collapse' : '')}>
          {menulist && menulist.length ? <Icon type={collapse ? 'menu-unfold' : 'menu-fold'} onClick={this.handleCollapse}/> : null}
        </div>
src/components/header/resetpwd/index.jsx
@@ -15,7 +15,29 @@
  onEnterSubmit = (e) => {
    // 表单回车提交
    if (e.key !== 'Enter') return
    this.props.resetPwdSubmit()
    if (!this.props.form.getFieldValue('originpwd')) {
      this.focusInput('originpwd')
    } else if (!this.props.form.getFieldValue('password')) {
      this.focusInput('password')
    } else if (!this.props.form.getFieldValue('confirm')) {
      this.focusInput('confirm')
    } else {
      this.props.resetPwdSubmit()
    }
  }
  focusInput = (selectId) => {
    let _form = document.getElementById('reset-password-form')
    let _inputs = _form.getElementsByTagName('input')
    _inputs = [..._inputs]
    _inputs.forEach(input => {
      if (!input || input.id !== selectId) return
      if (input.focus) {
        input.focus()
      }
    })
  }
  handleConfirm = () => {
@@ -68,7 +90,7 @@
    }
    return (
      <Form {...formItemLayout} onKeyDown={this.onEnterSubmit}>
      <Form {...formItemLayout} onKeyDown={this.onEnterSubmit} id="reset-password-form">
        <Form.Item label={this.props.dict['main.password.origin']}>
          {getFieldDecorator('originpwd', {
            rules: [
@@ -77,7 +99,7 @@
                message: this.props.dict['main.password.origin.required']
              }
            ]
          })(<Input.Password />)}
          })(<Input.Password autoFocus/>)}
        </Form.Item>
        <Form.Item label={this.props.dict['main.password.new']} hasFeedback>
          {getFieldDecorator('password', {
src/components/tabview/index.jsx
@@ -2,14 +2,13 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import {Tabs, Icon, Button, message, BackTop} from 'antd'
import {Tabs, Icon, BackTop} from 'antd'
import moment from 'moment'
import 'moment/locale/zh-cn'
import { modifyTabview, toggleIsiframe } from '@/store/action'
import asyncComponent from '@/utils/asyncLoadComponent'
import NotFount from '@/components/404'
import options from '@/store/options.js'
import mzhCN from '@/locales/zh-CN/main.js'
import menUS from '@/locales/en-US/main.js'
import MKEmitter from '@/utils/events.js'
@@ -47,7 +46,6 @@
    tabviews: null, // 标签集
    iFrameHeight: 0,
    dict: localStorage.getItem('lang') !== 'en-US' ? mzhCN : menUS,
    debug: sessionStorage.getItem('debug') === 'true'
  }
  handleTabview = (e, menu) => {
@@ -141,22 +139,10 @@
    } 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') {
      return (<Iframe key={view.MenuID} title={view.MenuName} MenuName={view.MenuName} url={service + view.LinkUrl}/>)
      return (<Iframe key={view.MenuID} MenuID={view.MenuID} MenuNo={view.MenuNo} title={view.MenuName} MenuName={view.MenuName} url={service + view.LinkUrl}/>)
    } else {
      return (<NotFount key={view.MenuID} />)
    }
  }
  copyMenuNo = (e) => {
    e.stopPropagation()
    let oInput = document.createElement('input')
    oInput.value = e.target.dataset.menuno || ''
    document.body.appendChild(oInput)
    oInput.select()
    document.execCommand('Copy')
    oInput.className = 'oInput'
    oInput.style.display = 'none'
    message.success(this.state.dict['main.copy.success'])
  }
  UNSAFE_componentWillMount () {
@@ -173,7 +159,7 @@
  componentDidMount () {
    let home = {
      MenuID: 'home_page_id',
      MenuName: '首页',
      MenuName: this.state.dict['main.homepage'],
      selected: true,
      type: 'Home'
    }
@@ -224,8 +210,7 @@
  }
  render () {
    const { menuType } = this.props
    const { tabviews, activeId, debug } = this.state
    const { tabviews, activeId } = this.state
    return (
      <section className={'flex-container content-box' + (this.props.collapse ? ' collapsed' : '')}>
@@ -237,9 +222,7 @@
                  <Tabs.TabPane
                    tab={
                      <span className="tab-control">
                        {['CommonTable', 'FormTab', 'TreePage', 'CalendarPage', 'CustomPage', 'ManageTable', 'VerupTable'].includes(view.type) ?
                          <Icon type="redo" onClick={(e) => {this.refreshTabview(e, view)}}/> : null
                        }
                        <Icon type="redo" onClick={(e) => {this.refreshTabview(e, view)}}/>
                        <span className="tab-name" onClick={(e) => {this.changeTab(e, view)}}>
                          {view.MenuName}
                        </span>
@@ -251,15 +234,6 @@
                    key={view.MenuID}
                  >
                    {this.selectcomponent(view)}
                    {debug && options.sysType !== 'cloud' && menuType !== 'HS' && !['CommonTable', 'TreePage', 'ManageTable', 'CalendarPage', 'Home'].includes(view.type) ?
                      <Button
                        icon="copy"
                        shape="circle"
                        className={'main-copy ' + (view.type === 'iframe' ? 'ifr-copy' : '')}
                        data-menuno={view.MenuNo}
                        onClick={this.copyMenuNo}
                      /> : null
                    }
                    <BackTop>
                      <div className="ant-back-top">
                        <div className="ant-back-top-content">
@@ -280,7 +254,6 @@
const mapStateToProps = (state) => {
  return {
    menuType: state.editLevel,
    tabviews: state.tabviews,
    collapse: state.collapse,
    isiframe: state.isiframe
src/components/tabview/index.scss
@@ -56,6 +56,11 @@
      }
      >.ant-tabs-content {
        height: 100%;
        .ant-tabs-tabpane:first-child {
          .page-setting-wrap, .page-message-wrap {
            display: none;
          }
        }
      }
    }
    .ant-tabs .ant-tabs-top-content.ant-tabs-content-animated {
src/index.js
@@ -235,6 +235,9 @@
      value: GLOB
    })
    window.GLOB.CacheMap = new Map()     // 缓存配置信息
    window.GLOB.UserCacheMap = new Map() // 缓存用户自定义设置
    render(Route)
  })
src/locales/en-US/main.js
@@ -10,6 +10,7 @@
  'main.cancel': 'Cancel',
  'main.logout': 'Logout',
  'main.doc': '文档中心',
  'main.homepage': '首页',
  'main.logout.hint': 'Are you sure you want to log out?',
  'main.verup': 'Version upgrade',
  'main.password': 'Change the password',
src/locales/zh-CN/main.js
@@ -10,6 +10,7 @@
  'main.cancel': '取消',
  'main.logout': '退出',
  'main.doc': '文档中心',
  'main.homepage': '首页',
  'main.logout.hint': '您确定要退出吗?',
  'main.verup': '版本升级',
  'main.password': '修改密码',
src/locales/zh-CN/model.js
@@ -98,7 +98,7 @@
  'header.form.refresh.maingrid': '刷新主表(行)',
  'header.form.refresh.equaltab': '刷新同级标签',
  'header.form.refresh.subgrid': '刷新子表',
  'header.form.popClose': '标签关闭',
  'header.form.popClose': '关闭后',
  'header.form.toolbar': '工具栏',
  'header.form.grid': '表格',
  'header.form.intertype': '接口类型',
src/menu/bgcontroller/index.jsx
@@ -116,7 +116,7 @@
            <ColorSketch value={backgroundColor} onChange={this.changeBackgroundColor} />
          </Form.Item>
          <Form.Item colon={false} label="图片">
            <FileUpload value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
            <FileUpload accept=".jpg,.png,.gif,.svg" value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
            <Input placeholder="" value={backgroundImage} autoComplete="off" onChange={this.changeImage}/>
          </Form.Item>
        </Form>
src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -8,6 +8,7 @@
import demo3 from '@/assets/img/demo3.jpg'
import demo4 from '@/assets/img/demo4.jpg'
import demo5 from '@/assets/img/demo5.jpg'
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -16,9 +17,9 @@
const BarCode = asyncComponent(() => import('@/components/barcode'))
const QrCode = asyncComponent(() => import('@/components/qrcode'))
const Video = asyncComponent(() => import('@/components/video'))
const MarkColumn = asyncIconComponent(() => import('@/menu/components/table/normal-table/columns/markcolumn'))
const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent'))
const Card = ({ id, fields, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, updateMarks }) => {
const Card = ({ id, parent, fields, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, updateMarks }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'action', id, originalIndex },
@@ -131,6 +132,13 @@
    }
  }
  const clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'cardcell') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', card, parent, 'cardcell')
    }
  }
  return (
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
@@ -138,11 +146,11 @@
        <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'].includes(card.eleType) ? <MarkColumn columns={fields} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null }
        {['text', 'number', 'slider'].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}>
        <div style={_style}>
        <div style={_style} onClick={clickComponent} id={card.uuid}>
          {getContent()}
        </div>
      </div>
src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -8,7 +8,7 @@
import Action from './action'
import './index.scss'
const Container = ({list, fields, handleList, handleMenu, deleteMenu, profileAction, handleStyle, updateMarks, dropButton, handleSubConfig }) => {
const Container = ({list, parent, fields, handleList, handleMenu, deleteMenu, profileAction, handleStyle, updateMarks, dropButton, handleSubConfig }) => {
  const [cards, setCards] = useState(list)
  const moveCard = (id, atIndex) => {
    const { card, index } = findCard(id)
@@ -38,14 +38,16 @@
    let copycard = fromJS(card).toJS()
    let _cards = fromJS(cards).toJS()
    copycard.uuid = Utils.getuuid()
    copycard.copyType = 'customCardElement'
    copycard.focus = true
    let _val = ''
    let _val = fromJS(copycard).toJS()
    copycard.uuid = Utils.getuuid()
    copycard.originCard = card
    try {
      _val = window.btoa(window.encodeURIComponent(JSON.stringify(copycard)))
      _val = window.btoa(window.encodeURIComponent(JSON.stringify(_val)))
    } catch {
      console.warn('Stringify Failure')
      _val = ''
@@ -78,9 +80,7 @@
  const doubleClickCard = id => {
    const { card } = findCard(id)
    if (card.OpenType === 'pop') {
      handleSubConfig(card)
    }
    handleSubConfig(card)
  }
  const delCard = id => {
@@ -106,6 +106,7 @@
              id={card.uuid}
              key={card.uuid}
              card={card}
              parent={parent}
              moveCard={moveCard}
              editCard={editCard}
              changeStyle={changeStyle}
@@ -121,6 +122,7 @@
              id={card.uuid}
              key={card.uuid}
              card={card}
              parent={parent}
              fields={fields}
              moveCard={moveCard}
              copyCard={copyCard}
src/menu/components/card/cardcellcomponent/index.jsx
@@ -59,6 +59,7 @@
    MKEmitter.addListener('cardAddElement', this.cardAddElement)
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('submitModal', this.handleSave)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -87,6 +88,28 @@
    MKEmitter.removeListener('cardAddElement', this.cardAddElement)
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('submitModal', this.handleSave)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { cardCell } = this.props
    if (!cardCell || cardCell.uuid !== parentId) return
    const { elements } = this.state
    let _elements = elements.map(item => {
      if (keys.includes(item.uuid)) {
        return this.resetCardStyle(item, {...item.style, ...style})
      }
      return item
    })
    this.setState({
      elements: _elements
    }, () => {
      this.props.updateElement(_elements)
    })
  }
  cardAddElement = (ids, element) => {
@@ -132,6 +155,21 @@
    if (comIds.length !== 3 || comIds[0] !== cards.uuid || comIds[1] !== cardCell.uuid) return
    let _card = this.resetCardStyle(card, style)
    let _elements = elements.map(cell => {
      if (cell.uuid === _card.uuid) return _card
      return cell
    })
    this.setState({
      elements: _elements
    }, () => {
      this.props.updateElement(_elements)
    })
  }
  resetCardStyle = (card, style) => {
    let _card = fromJS(card).toJS()
    
    if (_card.eleType === 'text' || _card.eleType === 'number') {
@@ -205,16 +243,7 @@
      _card.style = style
    }
    let _elements = elements.map(cell => {
      if (cell.uuid === _card.uuid) return _card
      return cell
    })
    this.setState({
      elements: _elements
    }, () => {
      this.props.updateElement(_elements)
    })
    return _card
  }
  /**
@@ -471,12 +500,12 @@
    const { cards } = this.props
    let btn = fromJS(item).toJS()
    if (btn.eleType !== 'button') return
    if (btn.eleType !== 'button' || (sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') !== 'false')) return
    if (btn.OpenType === 'pop') {
      if (!btn.modal) {
        btn.modal = {
          setting: { title: btn.label, width: 60, cols: '2', container: 'tab', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' },
          setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' },
          tables: [],
          groups: [],
          fields: []
@@ -549,13 +578,14 @@
  }
  render() {
    const { cards } = this.props
    const { cards, cardCell } = this.props
    const { elements, visible, actvisible, profVisible, card, dict } = this.state
    return (
      <div className="model-menu-card-cell-list">
        <DragElement
          list={elements}
          parent={{...cardCell, components: elements}}
          fields={cards.columns}
          updateMarks={this.updateMarks}
          handleList={this.handleList}
src/menu/components/card/cardcomponent/index.jsx
@@ -206,6 +206,13 @@
    })
  }
  clickComponent = (e) => {
    if ((sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'propcard') && this.props.cards.subtype === 'propcard') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.card, this.props.cards, 'propcard')
    }
  }
  render() {
    const { cards, offset } = this.props
    const { card, elements, side, settingVisible, dict } = this.state
@@ -229,7 +236,7 @@
    return (
      <Col span={card.setting.width || 6} offset={offset || 0}>
        <div className="card-item" style={_style}>
        <div className="card-item" style={_style} onClick={this.clickComponent} 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={
@@ -244,8 +251,8 @@
                    <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)}>
                  <Icon type="swap" id={card.uuid}/>
                } 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}
                {card.setting.type === 'multi' ? <Switch size="small" onClick={this.changeSide} defaultChecked /> : null}
src/menu/components/card/data-card/index.jsx
@@ -18,6 +18,7 @@
const CardComponent = asyncComponent(() => import('../cardcomponent'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
@@ -41,24 +42,29 @@
    const { card } = this.props
    if (card.isNew) {
      let subcards = null
      if (card.config) {
        subcards = JSON.parse(card.config)
        subcards = subcards.map(scard => {
          scard.uuid = Utils.getuuid()
          scard.elements = scard.elements.map(elem => {
            elem.uuid = Utils.getuuid()
            return elem
          })
          scard.backElements = scard.backElements.map(elem => {
            elem.uuid = Utils.getuuid()
            return elem
          })
          return scard
        })
      } else {
        subcards = [{
      let _card = {
        uuid: card.uuid,
        type: card.type,
        floor: card.floor,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        format: 'array',   // 组件属性 - 数据格式
        pageable: true,    // 组件属性 - 是否可分页
        switchable: true,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: card.width || 24, title: '', pagestyle: 'page', switch: 'false' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        action: [],
        search: [],
        btnlog: [],
        subcards: [{
          uuid: Utils.getuuid(),
          setting: { width: 6, type: 'simple'},
          style: {
@@ -72,29 +78,36 @@
        }]
      }
      let _card = {
        uuid: card.uuid,
        type: card.type,
        floor: card.floor,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        format: 'array',   // 组件属性 - 数据格式
        pageable: true,    // 组件属性 - 是否可分页
        switchable: true,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: 24,
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: 24, title: '', pagestyle: 'page', switch: 'false' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        action: [],
        btnlog: [],
        subcards: subcards
      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.subcards = config.subcards.map(scard => {
          scard.uuid = Utils.getuuid()
          scard.elements = scard.elements.map(elem => {
            elem.uuid = Utils.getuuid()
            return elem
          })
          scard.backElements = scard.backElements.map(elem => {
            elem.uuid = Utils.getuuid()
            return elem
          })
          return scard
        })
        _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
      })
@@ -102,6 +115,7 @@
    } else {
      card.action = card.action || [] // 兼容
      card.search = card.search || [] // 兼容
      this.setState({
        card: fromJS(card).toJS()
      })
@@ -284,7 +298,7 @@
    if (btn.OpenType === 'pop') {
      if (!btn.modal) {
        btn.modal = {
          setting: { title: btn.label, width: 60, cols: '2', container: 'tab', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' },
          setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' },
          tables: [],
          groups: [],
          fields: []
@@ -360,6 +374,13 @@
    }
  }
  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
@@ -376,7 +397,7 @@
    }
    return (
      <div className="menu-data-card-edit-box" style={{...card.style}}>
      <div className="menu-data-card-edit-box" style={{...card.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">
@@ -387,6 +408,7 @@
            <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} />
            <UserComponent config={card}/>
            <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
          </div>
src/menu/components/card/data-card/wrapsetting/index.jsx
@@ -55,7 +55,7 @@
    return (
      <div className="model-menu-setting-wrap">
        <Icon type="edit" onClick={() => this.editDataSource()} />
        <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="popview-modal"
          title={config.type === 'table' ? '表格设置' : '卡片设置'}
src/menu/components/card/prop-card/index.jsx
@@ -19,6 +19,7 @@
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 UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const { confirm } = Modal
@@ -40,11 +41,49 @@
    const { card } = this.props
    if (card.isNew) {
      let subcards = null
      let _card = {
        uuid: card.uuid,
        type: card.type,
        floor: card.floor,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: true,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: card.width || 24, title: '', addable: 'false', switch: 'false', datatype: 'static' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        subcards: [{
          uuid: Utils.getuuid(),
          setting: { width: 6, type: 'simple'},
          style: {
            borderWidth: '1px', borderColor: '#e8e8e8',
            paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px',
            marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
          },
          backStyle: {},
          elements: [],
          backElements: []
        }],
        btnlog: [],
      }
      if (card.config) {
        subcards = JSON.parse(card.config)
        subcards = subcards.map(scard => {
        let config = fromJS(card.config).toJS()
        _card.wrap = config.wrap
        _card.wrap.name = card.name
        _card.style = config.style
        _card.headerStyle = config.headerStyle
        _card.subcards = config.subcards.map(scard => {
          scard.uuid = Utils.getuuid()
          scard.elements = scard.elements.map(elem => {
            elem.uuid = Utils.getuuid()
@@ -56,42 +95,6 @@
          })
          return scard
        })
      } else {
        subcards = [{
          uuid: Utils.getuuid(),
          setting: { width: 6, type: 'simple'},
          style: {
            borderWidth: '1px', borderColor: '#e8e8e8',
            paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px',
            marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
          },
          backStyle: {},
          elements: [],
          backElements: []
        }]
      }
      let _card = {
        uuid: card.uuid,
        type: card.type,
        floor: card.floor,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: true,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: 24,
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: 24, title: '', addable: 'false', switch: 'false', datatype: 'static' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        subcards: subcards,
        btnlog: [],
      }
      this.setState({
        card: _card
@@ -107,6 +110,7 @@
  componentDidMount () {
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('logButton', this.logButton)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -122,6 +126,24 @@
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('logButton', this.logButton)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { card } = this.state
    if (card.uuid !== parentId) return
    let subcards = card.subcards.map(item => {
      if (keys.includes(item.uuid)) {
        item.style = {...item.style, ...style}
      }
      return item
    })
    this.setState({card: {...card, subcards: []}}, () => {
      this.updateComponent({...card, subcards: subcards})
    })
  }
  logButton = (id, item) => {
@@ -279,8 +301,10 @@
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      this.setState({ card: {...card, subcards: []} }, () => {
        this.setState({ card })
        this.props.updateConfig(card)
      })
      if (!done) {
        notification.warning({
          top: 92,
@@ -326,6 +350,13 @@
    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
@@ -342,7 +373,7 @@
    }
    return (
      <div className="menu-prop-card-edit-box" style={{...card.style}}>
      <div className="menu-prop-card-edit-box" style={{...card.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">
@@ -352,6 +383,7 @@
            <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} />
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            <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}
src/menu/components/card/table-card/index.jsx
@@ -19,6 +19,7 @@
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 UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const { confirm } = Modal
@@ -40,29 +41,6 @@
    const { card } = this.props
    if (card.isNew) {
      let subcards = null
      if (card.config) {
        subcards = JSON.parse(card.config)
        subcards = subcards.map(scard => {
          scard.uuid = Utils.getuuid()
          scard.elements = scard.elements.map(elem => {
            elem.uuid = Utils.getuuid()
            return elem
          })
          return scard
        })
      } else {
        subcards = [{
          uuid: Utils.getuuid(),
          setting: { width: 24, type: 'simple'},
          style: {
            paddingTop: '5px', paddingBottom: '5px', paddingLeft: '15px', paddingRight: '15px',
          },
          elements: []
        }]
      }
      let _card = {
        uuid: card.uuid,
        type: card.type,
@@ -73,20 +51,48 @@
        pageable: true,     // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: 12,
        width: card.width || 12,
        search: [],
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: 12, title: '' },
        wrap: { name: card.name, width: card.width || 12, title: '' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        subcards: subcards,
        subcards: [{
          uuid: Utils.getuuid(),
          setting: { width: 24, type: 'simple'},
          style: {
            paddingTop: '5px', paddingBottom: '5px', paddingLeft: '15px', paddingRight: '15px',
          },
          elements: []
        }],
        btnlog: [],
      }
      
      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.subcards = config.subcards.map(scard => {
          scard.uuid = Utils.getuuid()
          scard.elements = scard.elements.map(elem => {
            elem.uuid = Utils.getuuid()
            return elem
          })
          return scard
        })
        _card.search = config.search.map(col => {
          col.uuid = Utils.getuuid()
          return col
        })
      }
      this.setState({
        card: _card
      })
@@ -309,11 +315,18 @@
    }
  }
  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
    return (
      <div className="menu-table-card-edit-box" style={{...card.style, height: card.wrap.height}}>
      <div className="menu-table-card-edit-box" style={{...card.style, height: card.wrap.height}} 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">
@@ -324,6 +337,7 @@
            <PasteComponent config={card} options={['cardcell', 'search', 'form']} updateConfig={this.updateComponent} />
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            <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}
          </div>
src/menu/components/chart/antv-bar/chartcompile/index.jsx
@@ -492,7 +492,7 @@
    return (
      <div className="line-chart-drawer-form">
        <Icon type="edit" onClick={this.showDrawer} />
        <Icon type="edit" title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
src/menu/components/chart/antv-bar/index.jsx
@@ -23,6 +23,7 @@
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'))
class antvBarLineChart extends Component {
  static propTpyes = {
@@ -46,7 +47,7 @@
        enabled: 'false',     // 是否使用自定义设置
        datatype: 'query',    // 数据类型查询或统计
        customs: [],
        width: 24,
        width: card.width || 24,
        height: 400,
        barSize: 35,
        name: card.name
@@ -90,6 +91,24 @@
        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
      })
@@ -103,8 +122,8 @@
  componentDidMount () {
    this.viewrender()
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -118,15 +137,15 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
    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)
      let _element = document.getElementById(card.uuid + 'canvas')
      if (_element) {
        _element.innerHTML = ''
      }
@@ -202,14 +221,14 @@
        dv.transform({
          type: 'map',
          callback(row) {
            row.key = transfield[row.key]
            row.key = transfield[row.key] || row.key
            return row
          },
        })
      }
      const chart = new Chart({
        container: card.uuid,
        container: card.uuid + 'canvas',
        autoFit: true,
        height: plot.height || 400
      })
@@ -272,12 +291,12 @@
        .line()
        .position(`${X_axis}*value`)
        .shape(plot.shape || 'smooth')
        .tooltip(`${X_axis}*value`, (name, value) => {
        .tooltip(`${X_axis}*value*key`, (name, value, type) => {
          if (plot.show === 'percent') {
            value = value + '%'
          }
          return {
            name: name,
            name: type,
            value: value
          }
        })
@@ -408,7 +427,7 @@
    })
    const chart = new Chart({
      container: card.uuid,
      container: card.uuid + 'canvas',
      autoFit: true,
      height: plot.height || 400
    })
@@ -460,12 +479,12 @@
          .position(`${plot.Xaxis}*${item.name}`)
          .color(item.color)
          .shape(item.shape)
          .tooltip(`${plot.Xaxis}*${item.name}`, (name, value) => {
          .tooltip(`${item.name}`, (value) => {
            if (plot.show === 'percent') {
              value = value + '%'
            }
            return {
              name: name,
              name: item.name,
              value: value
            }
          })
@@ -492,12 +511,12 @@
          .position(`${plot.Xaxis}*${item.name}`)
          .color(item.color)
          .shape(item.shape)
          .tooltip(`${plot.Xaxis}*${item.name}`, (name, value) => {
          .tooltip(`${item.name}`, (value) => {
            if (plot.show === 'percent') {
              value = value + '%'
            }
            return {
              name: name,
              name: item.name,
              value: value
            }
          })
@@ -564,14 +583,14 @@
        dv.transform({
          type: 'map',
          callback(row) {
            row.key = transfield[row.key]
            row.key = transfield[row.key] || row.key
            return row
          },
        })
      }
      const chart = new Chart({
        container: card.uuid,
        container: card.uuid + 'canvas',
        autoFit: true,
        height: plot.height || 400
      })
@@ -636,12 +655,12 @@
            }
          ])
          .shape(plot.shape || 'rect')
          .tooltip(`${X_axis}*value`, (name, value) => {
          .tooltip(`${X_axis}*value*key`, (name, value, key) => {
            if (plot.show === 'percent') {
              value = value + '%'
            }
            return {
              name: name,
              name: key,
              value: value
            }
          })
@@ -682,12 +701,12 @@
          .position(`${X_axis}*value`)
          .adjust('stack')
          .shape(plot.shape || 'rect')
          .tooltip(`${X_axis}*value`, (name, value) => {
          .tooltip(`${X_axis}*value*key`, (name, value, type) => {
            if (plot.show === 'percent') {
              value = value + '%'
            }
            return {
              name: name,
              name: type,
              value: value
            }
          })
@@ -733,8 +752,8 @@
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    let refresh = false
    if (!is(fromJS(component.plot), fromJS(card.plot))) {
      let _element = document.getElementById(card.uuid)
    if (!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 = ''
      }
@@ -819,11 +838,12 @@
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    // this.setState({
    //   card: _card
    // })
    
    this.props.updateConfig(_card)
    this.updateComponent(_card)
    // this.props.updateConfig(_card)
  }
  handleLog = (type, logs, item) => {
@@ -852,11 +872,18 @@
    }
  }
  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
    return (
      <div className="menu-line-chart-edit-box" style={{...card.style, height: card.plot.height || 400}}>
      <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}/>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
@@ -867,6 +894,7 @@
            <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} />
            <UserComponent config={card}/>
            <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent}/>
          </div>
@@ -878,7 +906,7 @@
          config={card}
          updateaction={this.updateComponent}
        />
        <div className="canvas" id={card.uuid}></div>
        <div className="canvas" id={card.uuid + 'canvas'}></div>
      </div>
    )
  }
src/menu/components/chart/antv-pie/chartcompile/index.jsx
@@ -318,7 +318,7 @@
    return (
      <div className="line-chart-drawer-form">
        <Icon type="edit" onClick={this.showDrawer} />
        <Icon type="edit" title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
src/menu/components/chart/antv-pie/index.jsx
@@ -21,6 +21,7 @@
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'))
class antvBarLineChart extends Component {
  static propTpyes = {
@@ -41,7 +42,7 @@
    if (card.isNew) {
      let _plot = {
        shape: card.subtype, // 图表类型
        width: 12,
        width: card.width || 12,
        height: 400,
        label: 'outer',
        name: card.name
@@ -77,6 +78,21 @@
        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.search = config.search.map(col => {
          col.uuid = Utils.getuuid()
          return col
        })
      }
      this.props.updateConfig(_card)
      this.setState({
        card: _card
@@ -113,7 +129,7 @@
    const { card } = this.state
    if (parentId === card.parentId) {
      let _element = document.getElementById(card.uuid)
      let _element = document.getElementById(card.uuid + 'canvas')
      if (_element) {
        _element.innerHTML = ''
      }
@@ -162,7 +178,7 @@
    const dv = ds.createView().source(data)
    
    const chart = new Chart({
      container: card.uuid,
      container: card.uuid + 'canvas',
      autoFit: true,
      height: plot.height || 400
    })
@@ -334,8 +350,8 @@
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    let refresh = false
    if (!is(fromJS(component.plot), fromJS(card.plot))) {
      let _element = document.getElementById(card.uuid)
    if (!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 = ''
      }
@@ -391,11 +407,7 @@
    let _card = {...card, style}
    this.setState({
      card: _card
    })
    this.props.updateConfig(_card)
    this.updateComponent(_card)
  }
  handleLog = (type, logs, item) => {
@@ -424,11 +436,18 @@
    }
  }
  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
    return (
      <div className="menu-pie-chart-edit-box" style={{...card.style, height: card.plot.height || 400}}>
      <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}/>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
@@ -438,13 +457,14 @@
            <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} />
            <UserComponent config={card}/>
            <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent}/>
          </div>
        } trigger="hover">
          <Icon type="tool" />
        </Popover>
        <div className="canvas" id={card.uuid}></div>
        <div className="canvas" id={card.uuid + 'canvas'}></div>
      </div>
    )
  }
src/menu/components/group/groupsetting/index.jsx
@@ -54,7 +54,7 @@
    return (
      <div className="model-menu-setting-wrap">
        <Icon type="edit" onClick={() => this.editDataSource()} />
        <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} />
        <Modal
          wrapClassName="popview-modal"
          title={'标签页配置'}
src/menu/components/group/normal-group/index.jsx
@@ -63,8 +63,9 @@
  }
  componentDidMount () {
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
  /**
@@ -74,8 +75,28 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { group } = this.state
    if (group.uuid !== parentId) return
    let components = group.components.map(item => {
      if (keys.includes(item.uuid)) {
        item.style = {...item.style, ...style}
      }
      return item
    })
    this.setState({
      group: {...group, components: []}
    }, () => {
      this.updateComponent({...group, components: components})
    })
  }
  changeStyle = () => {
@@ -109,8 +130,8 @@
  updateComponent = (component) => {
    const { group } = this.state
    if (!is(fromJS(group.setting), fromJS(component.setting))) {
      // 注册事件-标签变化,通知标签内元素
    if (!is(fromJS(group.setting), fromJS(component.setting)) || !is(fromJS(group.style), fromJS(component.style))) {
      // 注册事件-标签变化,通知组内元素
      MKEmitter.emit('tabsChange', group.uuid)
    }
@@ -132,11 +153,18 @@
    this.props.updateConfig(group)
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.group)
    }
  }
  render() {
    const { group } = this.state
    return (
      <div className="menu-group-edit-box" style={group.style}>
      <div className="menu-group-edit-box" style={group.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} />
src/menu/components/search/main-search/index.jsx
@@ -256,6 +256,7 @@
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: res.dataSource
        }
@@ -263,7 +264,7 @@
        
        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.secretkey = Utils.encrypt('', param.timestamp)
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          param.rduri = window.GLOB.mainSystemApi
@@ -339,11 +340,18 @@
    })
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.card)
    }
  }
  render() {
    const { dict, card, visible, sqlVerifing } = this.state
    return (
      <div className={`main-search-edit-list ${card.wrap.float} ${card.wrap.show}`} style={card.style}>
      <div className={`main-search-edit-list ${card.wrap.float} ${card.wrap.show || ''}`} onClick={this.clickComponent} id={card.uuid} style={card.style}>
        <DragElement
          list={card.search}
          handleList={this.handleList}
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -8,12 +8,12 @@
const { TextArea } = Input
const actionTypeOptions = {
  pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'syncComponent', 'width'],
  prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'syncComponent', 'width'],
  exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'syncComponent', 'width'],
  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'sheet', 'execSuccess', 'execError', 'syncComponent', 'width'],
  excelOut: ['label', 'OpenType', 'intertype', 'show', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search', 'width'],
  popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'popClose', 'width'],
  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'],
  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'],
  tab: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'linkmenu', 'width'],
  innerpage: ['label', 'Ot', 'OpenType', 'pageTemplate', 'show', 'icon', 'class', 'width'],
  funcbutton: ['label', 'OpenType', 'funcType', 'show', 'icon', 'class', 'width']
@@ -137,7 +137,7 @@
      }
    } else if (_opentype === 'funcbutton') {
      if (_funcType === 'print') {
        _options.push('execMode', 'intertype', 'Ot', 'execSuccess', 'execError')
        _options.push('execMode', 'intertype', 'Ot', 'execSuccess', 'execError', 'resetPageIndex')
        if (_intertype === 'outer') {
          _options.push('innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc')
        } else if (_intertype === 'inner') {
@@ -221,7 +221,7 @@
      }, () => {
        if (value === 'excelIn') {
          _fieldval.label = this.props.dict['model.form.excelIn']
          _fieldval.class = 'border-dgreen'
          _fieldval.class = 'dgreen'
        } else if (value === 'excelOut') {
          _fieldval.label = this.props.dict['model.form.excelOut']
          _fieldval.class = 'dgreen'
src/menu/components/share/actioncomponent/dragaction/index.jsx
@@ -54,19 +54,19 @@
  const copyCard = id => {
    const { card } = findCard(id)
    let copycard = fromJS(card).toJS()
    copycard.uuid = Utils.getuuid()
    copycard.origin = false
    copycard.copyType = 'action'
    copycard.focus = true
    copycard.originCard = card
    let _val = fromJS(copycard).toJS()
    copycard.uuid = Utils.getuuid()
    copycard.originCard = card
    try {
      _val.uuid = Utils.getuuid()
      _val = window.btoa(window.encodeURIComponent(JSON.stringify(_val)))
    } catch {
      console.warn('Stringify Failure')
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -44,15 +44,16 @@
  ]
  if (type === 'chart') {
    opentypes = [
      {
        value: 'excelIn',
        text: Formdict['model.form.excelIn']
      }, {
        value: 'excelOut',
        text: Formdict['model.form.excelOut']
      }
    ]
    opentypes = opentypes.filter(item => item.value === 'excelIn' || item.value === 'excelOut')
  }
  let refresh = []
  if (sessionStorage.getItem('editMenuType') === 'popview') { // 弹窗标签
    opentypes = opentypes.filter(item => item.value !== 'popview' && item.value !== 'funcbutton')
    refresh.push({
      value: 'popclose',
      text: '标签刷新'
    })
  }
  let forms = [
@@ -226,45 +227,72 @@
      options: menulist
    },
    {
      type: 'radio',
      type: 'select',
      key: 'execSuccess',
      label: Formdict['model.form.afterSuccess'],
      initVal: card.execSuccess || 'never',
      tooltip: refresh.length ? '执行标签刷新时,会同步刷新当前组件和上级组件-行。' : '刷新上级组件-行时,会同步刷新当前组件,注:上级组件在数据源中添加。',
      required: true,
      options: [{
        value: 'grid',
        text: Formdict['header.form.refresh']
      }, {
        value: 'never',
        text: Formdict['header.form.refresh.never']
      }]
      }, {
        value: 'grid',
        text: '刷新当前组件'
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      },
      ...refresh]
    },
    {
      type: 'radio',
      type: 'select',
      key: 'execError',
      label: Formdict['model.form.afterError'],
      initVal: card.execError || 'never',
      tooltip: refresh.length ? '执行标签关闭刷新时,会同步刷新当前组件和上级组件-行。' : '刷新上级组件-行时,会同步刷新当前组件,注:上级组件在数据源中添加。',
      required: true,
      options: [{
        value: 'grid',
        text: Formdict['header.form.refresh']
      }, {
        value: 'never',
        text: Formdict['header.form.refresh.never']
      }]
      }, {
        value: 'grid',
        text: '刷新当前组件'
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      },
      ...refresh]
    },
    {
      type: 'radio',
      type: 'select',
      key: 'popClose',
      label: Formdict['header.form.popClose'],
      initVal: card.popClose || 'never',
      required: true,
      options: [{
        value: 'grid',
        text: Formdict['header.form.refresh']
      }, {
        value: 'never',
        text: Formdict['header.form.refresh.never']
      }, {
        value: 'grid',
        text: '刷新当前组件'
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }]
    },
    {
      type: 'radio',
      key: 'resetPageIndex',
      label: '刷新时',
      initVal: card.resetPageIndex || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '重置页码'
      }, {
        value: 'false',
        text: '不重置'
      }]
    },
    {
src/menu/components/share/actioncomponent/index.jsx
@@ -229,10 +229,10 @@
          if (btn.class !== item.class || btn.show !== item.show || !btn.btnstyle.color) {
            if (btn.show === 'link' || btn.show === 'icon') {
              btn.btnstyle.color = color[btn.class]
              btn.btnstyle.background = 'transparent'
              btn.btnstyle.backgroundColor = 'transparent'
            } else {
              btn.btnstyle.color = '#ffffff'
              btn.btnstyle.background = color[btn.class]
              btn.btnstyle.backgroundColor = color[btn.class]
            }
          }
          return btn
@@ -404,6 +404,8 @@
   * @description 按钮双击触发子配置
   */
  btnDoubleClick = (element) => {
    if (sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') !== 'false') return
    if (element.OpenType === 'pop' || element.OpenType === 'popview') {
      this.props.setSubConfig(element)
    } else {
src/menu/components/share/logcomponent/index.jsx
@@ -5,6 +5,7 @@
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { confirm } = Modal
@@ -71,6 +72,7 @@
    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)
  }
@@ -99,7 +101,7 @@
    return (
      <div className="btn-log-wrap">
        <Icon type="rollback" onClick={this.trigger} />
        <Icon type="rollback" title="解除冻结" onClick={this.trigger} />
        <Modal
          wrapClassName="popview-modal"
          title="历史记录"
src/menu/components/share/markcomponent/index.jsx
File was renamed from src/menu/components/table/normal-table/columns/markcolumn/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Icon, Modal } from 'antd'
import { Icon, Modal, Col } from 'antd'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
@@ -127,6 +127,7 @@
  resetMark = () => {
    const { marks, columns, type } = this.props
    let markColumns = fromJS(this.state.markColumns).toJS()
    let options = columns.map(col => {
      return {
@@ -251,12 +252,18 @@
    if (type === 'line') {
      signs.pop()
    } else if (type === 'slider') {
      markColumns = markColumns.filter(col => {
        col.width = '20%'
        return col.dataIndex !== 'signType'
      })
      signs = []
    }
    this.setState({
      visible: true,
      marks: marks ? fromJS(marks).toJS() : [],
      markColumns: this.state.markColumns.map(col => {
      markColumns: markColumns.map(col => {
        if (col.dataIndex === 'field') {
          col.options = options
        } else if (col.dataIndex === 'signType') {
@@ -276,7 +283,7 @@
    })
    let marks = this.state.marks.map(item => {
      if (item.signType[0] === 'background') {
      if (item.signType && item.signType[0] === 'background') {
        try {
          let colors = item.color.match(/\d+/g)
          if ((colors[0] * 0.299 + colors[1] * 0.578 + colors[2] * 0.114) * colors[3] < 192) {
@@ -313,6 +320,7 @@
          destroyOnClose
        >
          <MarkForm dict={dict} signs={signs} columns={options} markChange={this.markChange}/>
          <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>注:从上到下,匹配第一个符合条件的标记。</Col>
          <EditTable actions={['edit', 'move', 'del']} data={marks} columns={markColumns} onChange={(marks) => this.setState({marks})}/>
        </Modal>
      </div>
src/menu/components/share/markcomponent/index.scss
src/menu/components/share/markcomponent/markform/index.jsx
File was renamed from src/menu/components/table/normal-table/columns/markcolumn/markform/index.jsx
@@ -68,7 +68,7 @@
                <Select>
                  <Select.Option value="="> = </Select.Option>
                  <Select.Option value="!="> != </Select.Option>
                  <Select.Option value=">"> > </Select.Option>
                  <Select.Option value=">"> &gt; </Select.Option>
                  <Select.Option value="<"> &lt; </Select.Option>
                  <Select.Option value="like"> like </Select.Option>
                </Select>
@@ -101,7 +101,7 @@
              )}
            </Form.Item>
          </Col>
          <Col span={6}>
          {signs.length ? <Col span={6}>
            <Form.Item label="标记方式">
              {getFieldDecorator('signType', {
                initialValue: [],
@@ -115,8 +115,8 @@
                <Cascader options={signs} placeholder=""/>
              )}
            </Form.Item>
          </Col>
          <Col span={18} style={{textAlign: 'right', marginBottom: 10}}>
          </Col> : null}
          <Col span={signs.length ? 18 : 24} style={{textAlign: 'right'}}>
            <Button onClick={this.handleConfirm} type="primary" className="mk-green">
              添加
            </Button>
src/menu/components/share/markcomponent/markform/index.scss
src/menu/components/share/pastecomponent/index.jsx
@@ -4,6 +4,7 @@
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'
@@ -23,8 +24,19 @@
    this.setState({visible: true})
  }
  resetconfig = (item) => {
    item.uuid = Utils.getuuid()
  resetconfig = (item, copyBtns) => {
    let _uuid = Utils.getuuid()
    if (item.OpenType === 'popview') {
      let _cell = fromJS(item).toJS()
      _cell.$originUuid = _cell.uuid
      _cell.uuid = _uuid
      copyBtns.set(_uuid, _cell)
    }
    if (item.uuid) {
      item.uuid = _uuid
    }
    if (item.copyType === 'cardcell') {
      item.setting = item.setting || {}
@@ -42,7 +54,7 @@
          return cell
        })
      }
    } else if (item.copyType === 'table') {
    } else if (item.copyType === 'cols') {
      let loopCol = (col) => {
        col.subcols = col.subcols.map(c => {
          c.uuid = Utils.getuuid()
@@ -54,11 +66,6 @@
              cell.uuid = Utils.getuuid()
              return cell
            })
          } else if (c.type === 'action' && c.elements) {
            c.elements = c.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          }
          return c
        })
@@ -66,19 +73,30 @@
        return col
      }
      if (item.type === 'colspan' && item.subcols) {
        item = loopCol(item)
      } else if (item.type === 'custom' && item.elements) {
        item.elements = item.elements.map(cell => {
          cell.uuid = Utils.getuuid()
          return cell
        })
      } else if (item.type === 'action' && item.elements) {
        item.elements = item.elements.map(cell => {
          cell.uuid = Utils.getuuid()
          return cell
        })
      }
      item.cols = item.cols.map(_item => {
        _item.uuid = Utils.getuuid()
        if (_item.type === 'colspan' && _item.subcols) {
          _item = loopCol(_item)
        } else if (_item.type === 'custom' && _item.elements) {
          _item.elements = _item.elements.map(cell => {
            cell.uuid = Utils.getuuid()
            return cell
          })
        } else if (_item.type === 'action' && _item.elements) {
          _item.elements = _item.elements.map(cell => {
            let _uuid = Utils.getuuid()
            if (cell.OpenType === 'popview') {
              let _cell = fromJS(cell).toJS()
              _cell.$originUuid = _cell.uuid
              _cell.uuid = _uuid
              copyBtns.set(_uuid, _cell)
            }
            cell.uuid = _uuid
            return cell
          })
        }
        return _item
      })
    }
    return item
@@ -98,15 +116,22 @@
      let type = res.copyType
      let config = fromJS(this.props.config).toJS()
      let copyBtns = new Map()
      res = this.resetconfig(res)
      res = this.resetconfig(res, copyBtns)
      delete res.copyType
      copyBtns = [...copyBtns.values()]
      if (copyBtns.length > 0) {
        MKEmitter.emit('copyButtons', copyBtns)
      }
      if (type === 'action') {
        config.action = config.action || []
        config.action = config.action.filter(item => !item.origin)
        config.action.push(res)
        MKEmitter.emit('addButton', config.uuid, res)
      } else if (type === 'search' || type === 'form') {
        config.search = config.search || []
        config.search = config.search.filter(item => !item.origin)
@@ -137,6 +162,16 @@
        config.search.push(res)
      } else if (type === 'cardcell') {
        config.subcards.push(res)
      } else if (type === 'cols') {
        config.cols = config.cols.filter(col => !col.origin)
        let keys = config.cols.map(col => (col.field || '$empty'))
        res.cols.forEach(col => {
          if (!keys.includes(col.field)) {
            config.cols.push(col)
          }
        })
      }
      this.props.updateConfig(config)
src/menu/components/share/searchcomponent/index.jsx
@@ -218,6 +218,7 @@
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: res.dataSource
        }
@@ -225,7 +226,7 @@
        
        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.secretkey = Utils.encrypt('', param.timestamp)
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          param.rduri = window.GLOB.mainSystemApi
src/menu/components/share/usercomponent/index.jsx
New file
@@ -0,0 +1,219 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Icon, Modal, notification } from 'antd'
import html2canvas from 'html2canvas'
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 UserForm from './settingform'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class DataSource extends Component {
  static propTpyes = {
    btnlog: PropTypes.array,
    handlelog: PropTypes.func
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    visible: false,
    loading: false,
    name: '',
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  trigger = () => {
    const { config } = this.props
    this.setState({
      visible: true,
      loading: false,
      name: window.GLOB.UserComponentMap.get(config.uuid) || config.name || ''
    })
  }
  getUserComponent = () => {
    let config = fromJS(this.props.config).toJS()
    let _config = {}
    _config.wrap = config.wrap || {}
    _config.type = config.type || ''
    _config.subtype = config.subtype || ''
    _config.style = config.style || {}
    _config.subcards = config.subcards || []
    _config.headerStyle = config.headerStyle || {}
    _config.action = config.action || []
    _config.search = config.search || []
    _config.cols = config.cols || []
    _config.plot = config.plot || {}
    _config.width = _config.wrap.width || _config.plot.width || config.width || 24
    _config.subcards = _config.subcards.map(card => {
      if (card.elements) {
        card.elements = card.elements.map(item => this.resetElement(item))
      }
      if (card.backElements) {
        card.backElements = card.backElements.map(item => this.resetElement(item))
      }
      return card
    })
    _config.action = _config.action.map(item => {
      item.verify = null
      return item
    })
    _config.search = _config.search.map(item => {
      if (item.resourceType === '1') {
        item.resourceType = '0'
        item.dataSource = ''
        item.valueText = ''
        item.valueText = ''
        item.options = ''
      }
      item.blacklist = []
      return item
    })
    _config.cols = _config.cols.map(col => {
      if (col.type === 'colspan' && col.subcols) {
        col = this.loopCol(col)
      } else if (col.type === 'custom' && col.elements) {
        col.elements = col.elements.map(cell => this.resetElement(cell))
      } else if (col.type === 'action' && col.elements) {
        col.elements = col.elements.map(cell => {
          cell.verify = null
          return cell
        })
      }
      col.marks = null
      return col
    })
    return _config
  }
  loopCol = (col) => {
    col.subcols = col.subcols.map(c => {
      if (c.type === 'colspan' && c.subcols) {
        c = this.loopCol(c)
      } else if (c.type === 'custom' && c.elements) {
        c.elements = c.elements.map(cell => this.resetElement(cell))
      }
      c.marks = null
      return c
    })
    return col
  }
  resetElement = (item) => {
    item.marks = null
    item.verify = null
    if (item.datatype === 'dynamic') {
      if (item.eleType ===  'icon') {
        item.tooltip = item.field
      } else if (item.eleType === 'slider') {
        item.value = 50
      } else {
        item.value = item.field
      }
      item.datatype = 'static'
      item.field = ''
    }
    if (item.link === 'dynamic') {
      item.link = 'static'
    }
    return item
  }
  submit = () => {
    const { config } = this.props
    this.verifyRef.handleConfirm().then(res => {
      document.getElementsByClassName('menu-view')[0].classList.add('saving')
      this.setState({loading: true})
      setTimeout(() => {
        let template = this.getUserComponent()
        html2canvas(document.getElementById(config.uuid)).then(canvas => {
          let img = canvas.toDataURL('image/png') // 获取生成的图片
          Api.fileuploadbase64(img, 'cloud').then(result => {
            if (result.status) {
              Api.getSystemConfig({
                func: 's_custom_components_adduptdel',
                c_id: config.uuid,
                images: Utils.getcloudurl(result.Images),
                c_name: res.name,
                long_param: window.btoa(window.encodeURIComponent(JSON.stringify(template))),
                del_type: ''
              }).then(response => {
                if (response.status) {
                  this.setState({loading: false, visible: false})
                  notification.success({
                    top: 92,
                    message: '保存成功',
                    duration: 2
                  })
                  document.getElementsByClassName('menu-view')[0].classList.remove('saving')
                  MKEmitter.emit('updateCustomComponent')
                } else {
                  this.setState({loading: false})
                  notification.warning({
                    top: 92,
                    message: response.message,
                    duration: 5
                  })
                }
              })
            } else {
              this.setState({loading: false})
              notification.warning({
                top: 92,
                message: result.ErrMesg,
                duration: 5
              })
            }
          })
        })
      }, 300)
    })
  }
  cancel = () => {
    this.setState({ visible: false })
    document.getElementsByClassName('menu-view')[0].classList.remove('saving')
  }
  render () {
    const { visible, dict, loading, name } = this.state
    return (
      <div className="user-component-wrap">
        <Icon type="user" title="生成自定义组件" onClick={this.trigger} />
        <Modal
          wrapClassName="popview-modal"
          title="自定义组件"
          visible={visible}
          width={500}
          maskClosable={false}
          confirmLoading={loading}
          onOk={this.submit}
          onCancel={this.cancel}
          destroyOnClose
        >
          <UserForm dict={dict} name={name} inputSubmit={this.submit} wrappedComponentRef={(inst) => this.verifyRef = inst}/>
        </Modal>
      </div>
    )
  }
}
export default DataSource
src/menu/components/share/usercomponent/index.scss
New file
@@ -0,0 +1,7 @@
.user-component-wrap {
  display: inline-block;
  >.anticon-user {
    color: purple;
  }
}
src/menu/components/share/usercomponent/settingform/index.jsx
New file
@@ -0,0 +1,88 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Tooltip, Icon } from 'antd'
import './index.scss'
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,       // 字典项
    name: PropTypes.string,       // 组件名称
    inputSubmit: PropTypes.func   // 回车事件
  }
  state = {}
  UNSAFE_componentWillMount () {
  }
  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 { 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={22}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="用于组件间的区分。">
                  <Icon type="question-circle" />
                  组件名称
                </Tooltip>
              }>
                {getFieldDecorator('name', {
                  initialValue: this.props.name || '',
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '组件名称!'
                    },
                    {
                      max: 15,
                      message: '组件名称最多15个字符!'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit}/>)}
              </Form.Item>
            </Col>
          </Row>
        </Form>
      </div>
    )
  }
}
export default Form.create()(SettingForm)
src/menu/components/share/usercomponent/settingform/index.scss
New file
@@ -0,0 +1,8 @@
.model-menu-setting-form {
  position: relative;
  .anticon-question-circle {
    color: #c49f47;
    margin-right: 3px;
  }
}
src/menu/components/table/normal-table/columns/index.jsx
@@ -14,7 +14,7 @@
const { confirm } = Modal
const EditColumn = asyncIconComponent(() => import('./editColumn'))
const MarkColumn = asyncIconComponent(() => import('./markcolumn'))
const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent'))
const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent'))
class HeaderCol extends Component {
@@ -395,8 +395,8 @@
    let oInput = document.createElement('input')
    let val = {
      copyType: 'columns',
      columns: columns
      copyType: 'cols',
      cols: columns.filter(col => !col.origin)
    }
    oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
@@ -504,6 +504,7 @@
        <DndProvider>
          <Table
            rowKey="uuid"
            size={config.wrap.size || 'middle'}
            rowClassName="editable-row"
            bordered={config.wrap.bordered !== 'false'}
            components={components}
src/menu/components/table/normal-table/columns/index.scss
@@ -2,17 +2,20 @@
  position: relative;
  .ant-table-body {
    overflow-x: auto;
    padding-bottom: 20px;
    tr td:not(.ant-table-selection-column) {
      position: relative;
      padding: 12px 8px;
      background: #ffffff;
      >.profile {
        position: absolute;
        top: 2px;
        right: 2px;
        color: purple;
        font-size: 12px;
    tr {
      td {
        background: #ffffff;
      }
      td:not(.ant-table-selection-column) {
        position: relative;
        padding: 12px 8px;
        >.profile {
          position: absolute;
          top: 2px;
          right: 2px;
          color: purple;
          font-size: 12px;
        }
      }
    }
    .action-column {
@@ -66,6 +69,9 @@
      color: purple;
    }
  }
  .ant-table-small > .ant-table-content > .ant-table-body {
    margin: 0;
  }
}
.normal-table-columns.false {
  .ant-pagination {
src/menu/components/table/normal-table/index.jsx
@@ -19,6 +19,7 @@
const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
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 PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const ColumnComponent = asyncComponent(() => import('./columns'))
@@ -53,7 +54,7 @@
        pageable: true,     // 组件属性 - 是否可分页
        switchable: true,   // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: 24,
        width: card.width || 24,
        search: [
          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'text', match: 'like' },
          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'select', match: 'equal' },
@@ -67,7 +68,7 @@
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: 24, bordered: 'true', tableType: 'checkbox' },
        wrap: { name: card.name, width: card.width || 24, bordered: 'true', tableType: 'checkbox' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
@@ -78,6 +79,41 @@
        ],
        scripts: [],
        btnlog: [],
      }
      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.action = config.action.map(item => {
          item.uuid = Utils.getuuid()
          return item
        })
        _card.search = config.search.map(item => {
          item.uuid = Utils.getuuid()
          return item
        })
        _card.cols = config.cols.map(col => {
          col.uuid = Utils.getuuid()
          if (col.type === 'colspan' && col.subcols) {
            col = this.loopCol(col)
          } else if (col.type === 'custom' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          } else if (col.type === 'action' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          }
          return col
        })
      }
      
      this.setState({
@@ -111,6 +147,23 @@
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('submitModal', this.handleSave)
    MKEmitter.removeListener('logButton', this.logButton)
  }
  loopCol = (col) => {
    col.subcols = col.subcols.map(c => {
      c.uuid = Utils.getuuid()
      if (c.type === 'colspan' && c.subcols) {
        c = this.loopCol(c)
      } else if (c.type === 'custom' && c.elements) {
        c.elements = c.elements.map(cell => {
          cell.uuid = Utils.getuuid()
          return cell
        })
      }
      return c
    })
    return col
  }
  /**
@@ -245,7 +298,7 @@
    if (btn.OpenType === 'pop') {
      if (!btn.modal) {
        btn.modal = {
          setting: { title: btn.label, width: 60, cols: '2', container: 'tab', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' },
          setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' },
          tables: [],
          groups: [],
          fields: []
@@ -318,11 +371,18 @@
    }
  }
  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
    return (
      <div className="menu-normal-table-edit-box" style={{...card.style, height: card.wrap.height}}>
      <div className="menu-normal-table-edit-box" style={{...card.style, height: card.wrap.height}} 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">
@@ -331,9 +391,10 @@
            <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" />
            <WrapComponent config={card} updateConfig={this.updateComponent} />
            <CopyComponent type="normaltable" card={card}/>
            <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} />
            <PasteComponent config={card} options={['action', 'search', 'form', 'cols']} updateConfig={this.updateComponent} />
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            <UserComponent config={card}/>
            <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
          </div>
src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx
@@ -136,6 +136,19 @@
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label="表格大小">
                {getFieldDecorator('size', {
                  initialValue: wrap.size || 'middle'
                })(
                  <Radio.Group style={{whiteSpace: 'nowrap'}}>
                    <Radio key="default" value="default"> 大 </Radio>
                    <Radio key="middle" value="middle"> 中 </Radio>
                    <Radio key="small" value="small"> 小 </Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
            <Col span={12} style={{height: '64px'}}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="默认值 #e8e8e8。">
                  <Icon type="question-circle" />
src/menu/components/tabs/antv-tabs/index.jsx
@@ -74,8 +74,9 @@
  }
  componentDidMount () {
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
  /**
@@ -85,8 +86,42 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { tabs } = this.state
    if (tabs.subtabs.findIndex(tab => tab.uuid === parentId) === -1) return
    let _tabs = fromJS(tabs).toJS()
    let _tabs_ = fromJS(tabs).toJS()
    let components = []
    _tabs.subtabs.forEach(tab => {
      if (tab.uuid === parentId) {
        components = tab.components.map(item => {
          if (keys.includes(item.uuid)) {
            item.style = {...item.style, ...style}
          }
          return item
        })
        tab.components = []
      }
    })
    _tabs_.subtabs = _tabs_.subtabs.map(tab => {
      if (tab.uuid === parentId) {
        tab.components = components
      }
      return tab
    })
    this.setState({tabs: _tabs}, () => {
      this.updateComponent(_tabs_)
    })
  }
  changeStyle = () => {
@@ -120,7 +155,7 @@
  updateComponent = (component) => {
    const { tabs } = this.state
    if (!is(fromJS(tabs.setting), fromJS(component.setting))) {
    if (!is(fromJS(tabs.setting), fromJS(component.setting)) || !is(fromJS(tabs.style), fromJS(component.style))) {
      // 注册事件-标签变化,通知标签内元素
      MKEmitter.emit('tabsChange', tabs.uuid)
    }
@@ -253,11 +288,17 @@
    this.props.updateConfig(tabs)
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.tabs)
    }
  }
  render() {
    const { tabs, dict, labelvisible, editab } = this.state
    return (
      <div className="menu-tabs-edit-box" style={tabs.style}>
      <div className="menu-tabs-edit-box" style={tabs.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={
src/menu/datasource/verifycard/customscript/index.jsx
@@ -220,7 +220,7 @@
          </Col>
          <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              id, bid, loginuid, sessionuid, userid, username, fullname, appkey, time_id{usefulFields ? ', ' + usefulFields : ''}
              id, bid, loginuid, sessionuid, userid, username, fullname, appkey, time_id, orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}
            </Form.Item>
          </Col>
          <Col span={10} style={{width: '43%'}}>
src/menu/datasource/verifycard/index.jsx
@@ -594,11 +594,12 @@
      let param = {
        func: 's_debug_sql',
        exec_type: 'y',
        LText: result.sql
      }
      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.secretkey = Utils.encrypt('', param.timestamp)
      
      Api.getLocalConfig(param).then(result => {
        if (result.status) {
src/menu/datasource/verifycard/settingform/index.jsx
@@ -340,7 +340,7 @@
              <Form.Item label={
                <Tooltip placement="topLeft" title={'该组件如果受其他组件控制,请选项相应的组件,没有时选“无”。'}>
                  <Icon type="question-circle" />
                  上级模块
                  上级组件
                </Tooltip>
              }>
                {getFieldDecorator('supModule', {
@@ -348,7 +348,7 @@
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.select'] + '上级模块!'
                      message: this.props.dict['form.required.select'] + '上级组件!'
                    }
                  ]
                })(
src/menu/header/index.jsx
@@ -2,11 +2,11 @@
import { is, fromJS } from 'immutable'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
import './index.scss'
class MenuHeader extends Component {
  state = {
    logourl: window.GLOB.mainlogo,
    avatar: sessionStorage.getItem('CloudAvatar') || avatar,
    userName: sessionStorage.getItem('CloudUserName')
  }
@@ -19,7 +19,7 @@
    return (
      <header className="menu-header-container">
        <div className="header-logo"><img src={this.state.logourl} alt=""/></div>
        <div className="header-logo"><img src={MainLogo} alt=""/></div>
          <div className="header-setting">
            <img src={this.state.avatar} alt=""/>
            <span>
src/menu/modalconfig/index.jsx
@@ -313,6 +313,7 @@
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: res.dataSource
        }
@@ -320,7 +321,7 @@
        
        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.secretkey = Utils.encrypt('', param.timestamp)
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          param.rduri = window.GLOB.mainSystemApi
src/menu/modelsource/dragsource/index.jsx
@@ -1,13 +1,14 @@
import React from 'react'
import { useDrag } from 'react-dnd'
import { Icon } from 'antd'
import './index.scss'
const MobSourceElement = ({content}) => {
  const [, drag] = useDrag({ item: content })
const MobSourceElement = ({item, triggerDel}) => {
  const [, drag] = useDrag({ item })
  return (
    <div className="menu-source-item">
      <div className="property"><span>{content.title}</span></div>
      <img ref={drag} src={content.url} alt=""/>
      <div className="property"><span>{item.title}</span>{item.config ? <Icon onClick={() => triggerDel(item)} type="close-circle" /> : null}</div>
      <img ref={drag} src={item.url} alt=""/>
    </div>
  )
}
src/menu/modelsource/dragsource/index.scss
@@ -3,14 +3,20 @@
  width: 100%;
  margin-bottom: 15px;
  height: auto;
  // background-size: cover;
  // background-position: top center;
  // background-repeat: no-repeat;
  min-height: 70px;
  .property {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.65);
    margin-bottom: 2px;
    .anticon-close-circle {
      opacity: 0;
      cursor: pointer;
      padding: 0 3px;
      color: #ff4d4f;
      transition: all 0.3s;
    }
  }
  img {
@@ -26,6 +32,12 @@
  }
}
.menu-source-item:hover .property {
  .anticon-close-circle {
    opacity: 1;
  }
}
.menu-source-tooltip-box {
  margin-left: 20px;
  .ant-tooltip-content {
src/menu/modelsource/index.jsx
@@ -1,18 +1,29 @@
import React, {Component} from 'react'
import { is, fromJS } from 'immutable'
import { Modal, notification } from 'antd'
import Api from '@/api'
import { menuOptions } from './option'
import SourceWrap from './dragsource'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { confirm } = Modal
class ModelSource extends Component {
  state = {
    menuOptions: null
    menuOptions: null,
  }
  UNSAFE_componentWillMount () {
    const { MenuType } = this.props
    let options = fromJS(menuOptions).toJS()
    const { MenuType, components } = this.props
    let options = []
    if (components) {
      options = fromJS(components).toJS()
    } else {
      options = fromJS(menuOptions).toJS()
    }
    options = options.filter(item => !item.forbid || !item.forbid.includes(MenuType))
@@ -21,8 +32,53 @@
    })
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (nextProps.components && !is(fromJS(this.props.components), fromJS(nextProps.components))) {
      this.setState({
        menuOptions: fromJS(nextProps.components).toJS()
      })
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  triggerDel = (item) => {
    confirm({
      title: `确定删除<${item.title}>吗?`,
      content: '',
      onOk() {
        return new Promise(resolve => {
          Api.getSystemConfig({
            func: 's_custom_components_adduptdel',
            c_id: item.uuid,
            images: '',
            c_name: item.title,
            long_param: '',
            del_type: 'Y'
          }).then(result => {
            if (result.status) {
              notification.success({
                top: 92,
                message: '删除成功!',
                duration: 5
              })
              MKEmitter.emit('updateCustomComponent')
            } else {
              notification.warning({
                top: 92,
                message: result.message,
                duration: 5
              })
            }
            resolve()
          })
        })
      },
      onCancel() {}
    })
  }
  render() {
@@ -30,7 +86,7 @@
    return (
      <div className="mob-card-source-box">
        {menuOptions.map((item, index) => (<SourceWrap key={index} content={item} />))}
        {menuOptions.map((item, index) => (<SourceWrap key={index} item={item} triggerDel={this.triggerDel} />))}
      </div>
    )
  }
src/menu/modelsource/option.jsx
@@ -16,17 +16,17 @@
// 组件配置信息
export const menuOptions = [
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '标签页', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡', config: `[{"uuid":"160135809128212dm7i29fim9ksto9od","setting":{"width":6},"style":{"paddingTop":"15px","marginTop":"4px","paddingRight":"15px","marginRight":"8px","marginLeft":"8px","backgroundColor":"rgba(255, 255, 255, 1)","borderColor":"#e8e8e8","paddingLeft":"15px","marginBottom":"4px","borderWidth":"1px","paddingBottom":"10px"},"backStyle":{},"elements":[{"datatype":"static","width":12,"marks":null,"height":1,"value":"关单","style":{},"prefix":"","postfix":"","format":"","eleType":"text","uuid":"160231860159931untbea62sgokunc5s"},{"datatype":"static","width":12,"marks":null,"style":{"color":"rgba(250, 219, 20, 1)","textAlign":"right"},"btnstyle":{},"eleType":"icon","icon":"question-circle","field":"","uuid":"1602318768361nv8ql4t47sgcsn88b0u"},{"datatype":"static","width":24,"marks":null,"height":1,"innerHeight":36,"value":"100","style":{"fontSize":"24px","fontWeight":"500","color":"rgba(0, 0, 0, 1)"},"prefix":"","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602318817884v70gtgb65ubnm8mbcvv"},{"color":"#1890ff","width":24,"marks":null,"maxValue":100,"style":{"color":"rgba(250, 140, 22, 1)","paddingTop":"20px","paddingBottom":"10px"},"btnstyle":{},"eleType":"slider","field":"int1","uuid":"16023188871233rkktuvpp1h077igrsu"},{"eleType":"splitline","width":24,"color":"#e8e8e8","uuid":"1602320017038n31bk9o831ggug0tu0b","marks":null,"style":{"marginTop":"10px","marginBottom":"10px"},"btnstyle":{}},{"datatype":"static","width":12,"marks":null,"height":1,"value":"100","style":{"marginTop":"6px"},"prefix":"关单","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602320061243drd7lf3agvn04kgr175"}],"backElements":[]}]` },
  { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '属性卡', config: `[{"uuid":"1603681387259qaqf1127f72esmtchge","setting":{"width":6,"type":"simple"},"style":{"paddingTop":"15px","marginTop":"8px","paddingRight":"15px","marginRight":"8px","marginLeft":"8px","borderColor":"#e8e8e8","paddingLeft":"15px","marginBottom":"8px","borderWidth":"1px","paddingBottom":"15px"},"backStyle":{},"elements":[{"datatype":"static","width":12,"marks":null,"height":1,"value":"超时工单","style":{"color":"rgba(67, 67, 67, 0.51)"},"prefix":"","postfix":"","format":"","eleType":"text","uuid":"1603681402945qnkgm7q8cng65evn5ev"},{"eleType":"icon","datatype":"static","width":12,"icon":"question-circle","tooltip":"超时工单","uuid":"1603681473384i2crkbtofg4pu76k06a","marks":null,"style":{"textAlign":"right","color":"rgba(250, 219, 20, 1)"}},{"datatype":"static","width":24,"marks":null,"height":1,"innerHeight":36,"value":"100","style":{"fontSize":"24px","color":"rgba(0, 0, 0, 1)"},"prefix":"","postfix":"","format":"","eleType":"number","uuid":"1603681539870d704ufqf98kc6t7537t"},{"color":"rgba(250, 219, 20, 1)","datatype":"static","width":24,"marks":null,"maxValue":100,"value":50,"style":{"paddingTop":"10px","paddingBottom":"10px"},"eleType":"slider","uuid":"1603683067556mvupau0odvrtv45u7o8"},{"eleType":"splitline","width":24,"color":"#e8e8e8","uuid":"1603683117981t9k55k8an430fuppmci","marks":null,"style":{"paddingTop":"5px","paddingBottom":"5px"}},{"datatype":"static","width":12,"marks":null,"height":1,"value":"100","style":{"color":"rgba(0, 0, 0, 0.65)","marginTop":"10px"},"prefix":"超时工单  ","postfix":"","format":"","eleType":"text","uuid":"1603683136553uvsmkfohkft9idbfkhu"}],"backElements":[]}]` },
  { 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: NormalTable, component: 'table', subtype: 'normaltable', title: '常用表', width: 24 },
  { type: 'menu', url: TableCard, component: 'table', subtype: 'tablecard', title: '表格', width: 12 },
  { type: 'menu', url: line, component: 'line', subtype: 'line', title: '折线图' },
  { type: 'menu', url: line1, component: 'line', subtype: 'line1', title: '阶梯折线图' },
  { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '柱状图' },
  { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '条形图' },
  { type: 'menu', url: 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: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 },
  { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24, forbid: ['billPrint'] },
]
src/menu/pastecontroller/index.jsx
@@ -1,8 +1,10 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Icon, Modal, Button, notification } from 'antd'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
@@ -23,7 +25,7 @@
    this.setState({visible: true})
  }
  resetconfig = (item, Tab, isgroup) => {
  resetconfig = (item, Tab, isgroup, copyBtns) => {
    item.uuid = Utils.getuuid()
    item.floor = Tab ? (Tab.floor + 1) : 1
@@ -49,22 +51,47 @@
        }
        tab.components = tab.components.map(cell => {
          cell = this.resetconfig(cell, tab)
          cell = this.resetconfig(cell, tab, copyBtns)
          return cell
        })
      })
    } else if (item.type === 'group') {
      item.components = item.components.map(cell => {
        cell = this.resetconfig(cell, item, true, copyBtns)
        return cell
      })
    } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) {
      item.subcards.forEach(card => {
        card.uuid = Utils.getuuid()
        if (card.elements) {
          if (sessionStorage.getItem('editMenuType') === 'popview') {
            card.elements = card.elements.filter(b => b.OpenType !== 'popview' && b.OpenType !== 'funcbutton')
          }
          card.elements = card.elements.map(cell => {
            cell.uuid = Utils.getuuid()
            let _uuid = Utils.getuuid()
            if (cell.OpenType === 'popview') {
              let _cell = fromJS(cell).toJS()
              _cell.$originUuid = _cell.uuid
              _cell.uuid = _uuid
              copyBtns.set(_uuid, _cell)
            }
            cell.uuid = _uuid
            return cell
          })
        }
        if (card.backElements) {
          if (sessionStorage.getItem('editMenuType') === 'popview') {
            card.elements = card.elements.filter(b => b.OpenType !== 'popview' && b.OpenType !== 'funcbutton')
          }
          card.backElements = card.backElements.map(cell => {
            cell.uuid = Utils.getuuid()
            let _uuid = Utils.getuuid()
            if (cell.OpenType === 'popview') {
              let _cell = fromJS(cell).toJS()
              _cell.$originUuid = _cell.uuid
              _cell.uuid = _uuid
              copyBtns.set(_uuid, _cell)
            }
            cell.uuid = _uuid
            return cell
          })
        }
@@ -77,11 +104,6 @@
          if (c.type === 'colspan' && c.subcols) {
            c = loopCol(c)
          } else if (c.type === 'custom' && c.elements) {
            c.elements = c.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
            })
          } else if (c.type === 'action' && c.elements) {
            c.elements = c.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              return cell
@@ -104,8 +126,18 @@
            return cell
          })
        } else if (col.type === 'action' && col.elements) {
          if (sessionStorage.getItem('editMenuType') === 'popview') {
            col.elements = col.elements.filter(c => c.OpenType !== 'popview' && c.OpenType !== 'funcbutton')
          }
          col.elements = col.elements.map(cell => {
            cell.uuid = Utils.getuuid()
            let _uuid = Utils.getuuid()
            if (cell.OpenType === 'popview') {
              let _cell = fromJS(cell).toJS()
              _cell.$originUuid = _cell.uuid
              _cell.uuid = _uuid
              copyBtns.set(_uuid, _cell)
            }
            cell.uuid = _uuid
            return cell
          })
        }
@@ -118,8 +150,18 @@
    }
    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 => {
        cell.uuid = Utils.getuuid()
        let _uuid = Utils.getuuid()
        if (cell.OpenType === 'popview') {
          let _cell = fromJS(cell).toJS()
          _cell.$originUuid = _cell.uuid
          _cell.uuid = _uuid
          copyBtns.set(_uuid, _cell)
        }
        cell.uuid = _uuid
        return cell
      })
    }
@@ -168,11 +210,20 @@
        return
      }
      res = this.resetconfig(res, Tab, isgroup)
      let copyBtns = new Map()
      res = this.resetconfig(res, Tab, isgroup, copyBtns)
      delete res.copyType
      this.props.insert(res, Tab)
      copyBtns = [...copyBtns.values()]
      if (copyBtns.length > 0) {
        MKEmitter.emit('copyButtons', copyBtns)
      }
      this.setState({visible: false})
      notification.success({
src/menu/popview/index.jsx
@@ -24,7 +24,9 @@
const SourceWrap = asyncComponent(() => import('@/menu/modelsource'))
const MenuShell = asyncComponent(() => import('@/menu/menushell'))
const BgController = asyncComponent(() => import('@/menu/bgcontroller'))
const PasteController = asyncComponent(() => import('@/menu/pastecontroller'))
const PaddingController = asyncComponent(() => import('@/menu/padcontroller'))
const StyleCombControlButton = asyncComponent(() => import('@/menu/stylecombcontrolbutton'))
const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
sessionStorage.setItem('isEditState', 'true')
@@ -47,6 +49,7 @@
    oriConfig: null,
    openEdition: '',
    config: null,
    customComponents: []
  }
  UNSAFE_componentWillMount() {
@@ -61,6 +64,9 @@
  componentDidMount () {
    MKEmitter.addListener('delButtons', this.delButtons)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
    MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent)
    this.updateCustomComponent()
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -75,6 +81,64 @@
      return
    }
    MKEmitter.removeListener('delButtons', this.delButtons)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
    MKEmitter.removeListener('updateCustomComponent', this.updateCustomComponent)
  }
  updateCustomComponent = () => {
    Api.getSystemConfig({
      func: 's_get_custom_components',
      typecharone: ''
    }).then(res => {
      let coms = []
      if (res.cus_list && res.cus_list.length > 0) {
        res.cus_list.forEach(item => {
          let config = ''
          try {
            config = JSON.parse(window.decodeURIComponent(window.atob(item.long_param)))
          } catch (e) {
            console.warn('Parse Failure')
            config = ''
          }
          if (!config || !item.c_name) return
          window.GLOB.UserComponentMap.set(item.c_id, item.c_name)
          coms.push({
            uuid: item.c_id,
            type: 'menu',
            title: item.c_name,
            url: item.images,
            component: config.type,
            subtype: config.subtype,
            config
          })
        })
      }
      this.setState({customComponents: coms})
    })
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { config } = this.state
    if (config.uuid !== parentId) return
    let components = config.components.map(item => {
      if (keys.includes(item.uuid)) {
        item.style = {...item.style, ...style}
      }
      return item
    })
    this.setState({
      config: {...config, components: []}
    }, () => {
      this.setState({
        config: {...config, components: components}
      })
    })
  }
  delButtons = (items) => {
@@ -147,6 +211,7 @@
        } else {
          config.uuid = MenuId
          config.MenuID = MenuId
          config.Template = 'CustomPage'
        }
        this.setState({
@@ -154,6 +219,8 @@
          config: fromJS(config).toJS(),
          openEdition: result.open_edition || '',
        })
        this.props.modifyCustomMenu(config)
      } else {
        notification.warning({
          top: 92,
@@ -241,6 +308,7 @@
  }
  submitConfig = () => {
    const { btn } = this.props
    const { openEdition, delButtons } = this.state
    let config = fromJS(this.state.config).toJS()
@@ -262,14 +330,15 @@
    let _config = fromJS(config).toJS()
    delete _config.tableFields
    let _name = (btn.component.name ? btn.component.name + '-' : '') + btn.label
    let param = {
      func: 'sPC_Tab_AddUpt',
      func: 'sPC_ButtonParam_AddUpt',
      ParentID: btn.config.uuid,
      MenuID: _config.uuid,
      MenuNo: _config.MenuNo,
      MenuNo: _config.MenuNo || '',
      Template: 'CustomPage',
      MenuName: _config.MenuName,
      Remark: '',
      Sort: 0,
      MenuName: _name,
      PageParam: JSON.stringify({Template: 'CustomPage'}),
      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
    }
@@ -459,9 +528,18 @@
    this.props.modifyCustomMenu(config)
  }
  insert = (item) => {
    let config = fromJS(this.state.config).toJS()
    config.components.push(item)
    this.setState({config})
    this.props.modifyCustomMenu(config)
  }
  render () {
    const { btn } = this.props
    const { activeKey, MenuType, dict, config, menuloading } = this.state
    const { activeKey, MenuType, dict, config, menuloading, customComponents } = this.state
    return (
      <DndProvider backend={HTML5Backend}>
@@ -479,6 +557,9 @@
              <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>
@@ -492,6 +573,8 @@
              <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>
src/menu/stylecombcontrolbutton/index.jsx
New file
@@ -0,0 +1,156 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Button } from 'antd'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class StyleCombControlButton extends Component {
  static propTpyes = {
    menu: PropTypes.any
  }
  state = {
    label: '调整',
    parent: null,
    type: '',
    components: []
  }
  componentDidMount () {
    sessionStorage.setItem('style-control', 'false')
    MKEmitter.addListener('clickComponent', this.clickComponent)
    MKEmitter.addListener('submitCombineStyle', this.submitCombineStyle)
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('clickComponent', this.clickComponent)
    MKEmitter.removeListener('submitCombineStyle', this.submitCombineStyle)
  }
  submitCombineStyle = (style) => {
    const { components, parent } = this.state
    let keys = components.map(item => item.uuid)
    MKEmitter.emit('submitComponentStyle', parent.uuid, keys, style)
    setTimeout(() => {
      keys.forEach(key => {
        document.getElementById(key).classList.add('selected-control-element')
      })
    }, 100)
  }
  clickComponent = (card, _p, _type) => {
    const { menu } = this.props
    const { parent, type } = this.state
    let components = fromJS(this.state.components).toJS()
    if (!parent) {
      let _parent = null
      if (_type === 'propcard') {
        _parent = _p
        MKEmitter.emit('changeCombineStyle', ['margin', 'padding', 'border', 'background', 'shadow'])
      } else if (_type === 'cardcell') {
        _parent = _p
        MKEmitter.emit('changeCombineStyle', ['margin', 'padding', 'border', 'background', 'font'])
      } else {
        let getParents = (box) => {
          box.components.forEach(item => {
            if (item.type === 'tabs') {
              item.subtabs.forEach(tab => {
                if (tab.components.findIndex(cell => cell.uuid === card.uuid) > -1) {
                  _parent = tab
                } else {
                  getParents(tab)
                }
              })
            } else if (item.type === 'group') {
              if (item.components.findIndex(cell => cell.uuid === card.uuid) > -1) {
                _parent = item
              }
            }
          })
        }
        if (menu.components.findIndex(cell => cell.uuid === card.uuid) > -1) {
          _parent = menu
        } else {
          getParents(menu)
        }
        MKEmitter.emit('changeCombineStyle', ['margin', 'padding', 'border', 'background'])
      }
      document.getElementById(card.uuid).classList.add('selected-control-element')
      sessionStorage.setItem('style-control', (_type ? _type : 'component'))
      this.setState({
        type: _type ? _type : 'component',
        parent: _parent,
        components: [card]
      })
    } else {
      if (components.findIndex(cell => cell.uuid === card.uuid) > -1) {
        components = components.filter(cell => cell.uuid !== card.uuid)
        document.getElementById(card.uuid).classList.remove('selected-control-element')
      } else if (type !== 'propcard' && parent.components.findIndex(cell => cell.uuid === card.uuid) > -1) {
        components.push(card)
        document.getElementById(card.uuid).classList.add('selected-control-element')
      } else if (type === 'propcard' && parent.subcards.findIndex(cell => cell.uuid === card.uuid) > -1) {
        components.push(card)
        document.getElementById(card.uuid).classList.add('selected-control-element')
      }
      if (components.length === 0) {
        MKEmitter.emit('closeCombineStyle')
        sessionStorage.setItem('style-control', 'true')
      }
      this.setState({
        components: components,
        parent: components.length ? parent : null
      })
    }
  }
  triggerStyleChange = () => {
    const { label, components } = this.state
    if (label === '调整') {
      document.body.className = 'style-control'
      sessionStorage.setItem('style-control', 'true')
      this.setState({label: '退出'})
    } else {
      document.body.className = ''
      sessionStorage.setItem('style-control', 'false')
      components.forEach(item => {
        document.getElementById(item.uuid).classList.remove('selected-control-element')
      })
      MKEmitter.emit('closeCombineStyle')
      this.setState({label: '调整', parent: null, components: []})
    }
  }
  render() {
    const { label } = this.state
    return (
      <Button className="style-control-button" type="link" icon="font-colors" title="调整样式" onClick={this.triggerStyleChange}>{label}</Button>
    )
  }
}
export default StyleCombControlButton
src/menu/stylecombcontrolbutton/index.scss
New file
@@ -0,0 +1,41 @@
.style-control-button.ant-btn-link, .style-control-button.ant-btn-link:hover, .style-control-button.ant-btn-link:focus {
  color: orange;
  position: relative;
  z-index: 13;
  background: #ffffff;
}
body.style-control {
  .pc-menu-view::before {
    content: ' ';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    z-index: 12;
    background:rgba(0, 0, 0, 0.3);
  }
  .menu-body .menu-view >.ant-card >.ant-card-body {
    position: relative;
    z-index: 13;
    .anticon-tool {
      display: none;
    }
  }
  .mk-popover-control-wrap {
    display: none;
  }
  .selected-control-element {
    box-shadow: 0px 0px 4px orange!important;
  }
  .selected-control-element:hover {
    box-shadow: 0px 0px 4px orange!important;
  }
  .normal-table-columns {
    .col-control {
      display: none;
    }
  }
}
src/menu/stylecombcontroller/index.jsx
New file
@@ -0,0 +1,566 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Collapse, Form, Col, Icon, InputNumber, Select, Radio, Drawer, Button } from 'antd'
import MKEmitter from '@/utils/events.js'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import ColorSketch from '@/mob/colorsketch'
import StyleInput from './styleInput'
import './index.scss'
const { Panel } = Collapse
const { Option } = Select
class MobController extends Component {
  static propTpyes = {
    editElem: PropTypes.any,
    updateStyle: PropTypes.func,
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    options: [],
    style: {},
    borposition: 'outer'
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentDidMount () {
    MKEmitter.addListener('changeCombineStyle', this.initStyle)
    MKEmitter.addListener('closeCombineStyle', this.closeStyle)
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('changeCombineStyle', this.initStyle)
    MKEmitter.removeListener('closeCombineStyle', this.closeStyle)
  }
  closeStyle = () => {
    this.setState({
      visible: false,
      options: []
    })
  }
  initStyle = (options) => {
    this.setState({
      visible: true,
      style: {},
      options: options,
      borposition: 'outer'
    })
  }
  onCloseDrawer = () => {
    MKEmitter.emit('submitCombineStyle', this.state.style)
  }
  updateStyle = (style) => {
    this.setState({style: {...this.state.style, ...style}})
  }
  /**
   * @description 字体大小切换,超出范围忽略
   */
  changeFontSize = (val) => {
    let value = parseInt(val)
    if (isNaN(value) || value < 12 || value > 100) return
    this.updateStyle({fontSize: `${value}px`})
  }
  /**
   * @description 修改行间距,超出范围忽略
   */
  changeLineHeight = (val) => {
    let value = parseFloat(val)
    if (isNaN(value) || value < 1 || value > 10) return
    this.updateStyle({lineHeight: value})
  }
  /**
   * @description 字体间距修改,超出范围忽略
   */
  changeLetterSpacing = (val) => {
    let value = parseFloat(val)
    if (isNaN(value) || value < 0 || value > 100) return
    this.updateStyle({letterSpacing: `${value}px`})
  }
  /**
   * @description 修改字体粗细
   */
  boldChange = (val) => {
    this.updateStyle({fontWeight: val})
  }
  /**
   * @description 修改字体颜色 ,颜色控件
   */
  changeFontColor = (val) => {
    this.updateStyle({color: val})
  }
  /**
   * @description 字体对齐
   */
  changeTextAlign = (e) => {
    this.updateStyle({textAlign: e.target.value})
  }
  /**
   * @description 字体样式,倾斜
   */
  changeFontStyle = (e) => {
    this.updateStyle({fontStyle: e.target.value})
  }
  /**
   * @description 字体装饰,下划线、贯穿线、上划线
   */
  changeTextDecoration = (e) => {
    this.updateStyle({textDecoration: e.target.value})
  }
  /**
   * @description 修改背景颜色 ,颜色控件
   */
  changeBackgroundColor = (val) => {
    this.updateStyle({backgroundColor: val})
  }
  /**
   * @description 修改阴影颜色 ,颜色控件
   */
  changeShadowColor = (val) => {
    this.updateStyle({shadow: val})
  }
  changeBorderStyle = (val) => {
    const { borposition } = this.state
    let _style = {}
    if (borposition === 'outer') {
      _style.borderStyle = val
    } else if (borposition === 'left') {
      _style.borderLeftStyle = val
    } else if (borposition === 'right') {
      _style.borderRightStyle = val
    } else if (borposition === 'top') {
      _style.borderTopStyle = val
    } else if (borposition === 'bottom') {
      _style.borderBottomStyle = val
    }
    this.updateStyle(_style)
  }
  changeBorderWidth = (val) => {
    const { borposition } = this.state
    let _style = {}
    if (borposition === 'outer') {
      _style.borderWidth = val
    } else if (borposition === 'left') {
      _style.borderLeftWidth = val
    } else if (borposition === 'right') {
      _style.borderRightWidth = val
    } else if (borposition === 'top') {
      _style.borderTopWidth = val
    } else if (borposition === 'bottom') {
      _style.borderBottomWidth = val
    }
    this.updateStyle(_style)
  }
  changeBorderColor = (val) => {
    const { borposition } = this.state
    let _style = {}
    if (borposition === 'outer') {
      _style.borderColor = val
    } else if (borposition === 'left') {
      _style.borderLeftColor = val
    } else if (borposition === 'right') {
      _style.borderRightColor = val
    } else if (borposition === 'top') {
      _style.borderTopColor = val
    } else if (borposition === 'bottom') {
      _style.borderBottomColor = val
    }
    this.updateStyle(_style)
  }
  changeHeight = (val) => {
    let _val = val
    if (_val === '0px') {
      _val = 'auto'
    }
    this.updateStyle({height: _val})
  }
  changeNormalStyle = (val, type) => {
    this.updateStyle({[type]: val})
  }
  render () {
    const { options, borposition } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <Drawer
        title={
          <div className="header-logo">
            <img src={window.GLOB.mainlogo} alt=""/>
          </div>
        }
        placement="left"
        width="300"
        mask={false}
        closable={false}
        className="menu-style-drawer"
        visible={this.state.visible}
        destroyOnClose
      >
        <div className="menu-combine-style-controller">
          <Form {...formItemLayout}>
            <Collapse expandIconPosition="right" destroyInactivePanel={true} defaultActiveKey={options[0]}>
              {options.includes('height') ? <Panel header="高度" key="height">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="高度" type="column-height" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px']} onChange={this.changeHeight}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('font') ? <Panel header="字体" key="font">
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="字体大小" type="font-size" />}>
                    <InputNumber defaultValue={''} min={12} max={100} precision={0} onChange={this.changeFontSize} />
                  </Form.Item>
                </Col>
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="字体粗细" type="bold" />}>
                    <Select defaultValue={''} onChange={this.boldChange}>
                      <Option value="normal">normal</Option>
                      <Option value="bold">bold</Option>
                      <Option value="bolder">bolder</Option>
                      <Option value="lighter">lighter</Option>
                      <Option value="100">100</Option>
                      <Option value="200">200</Option>
                      <Option value="300">300</Option>
                      <Option value="400">400</Option>
                      <Option value="500">500</Option>
                      <Option value="600">600</Option>
                      <Option value="700">700</Option>
                      <Option value="800">800</Option>
                      <Option value="900">900</Option>
                    </Select>
                  </Form.Item>
                </Col>
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="行高" type="line-height" />}>
                    <InputNumber defaultValue={''} min={1} max={10} precision={1} onChange={this.changeLineHeight} />
                  </Form.Item>
                </Col>
                <Col span={12}>
                  <Form.Item colon={false} label={<Icon title="字间距" type="column-width" />}>
                    <InputNumber defaultValue={''} min={0} max={100} precision={0} onChange={this.changeLetterSpacing}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="字体颜色" type="font-colors" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <ColorSketch onChange={this.changeFontColor} />
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={' '}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <Radio.Group defaultValue={''} onChange={this.changeFontStyle}>
                      <Radio.Button value="normal"><span title="标准">N</span></Radio.Button>
                      <Radio.Button value="italic"><Icon title="斜体" type="italic" /></Radio.Button>
                      <Radio.Button value="oblique" style={{fontStyle: 'oblique'}}><span title="倾斜">B</span></Radio.Button>
                    </Radio.Group>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={' '}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <Radio.Group className="text-align" defaultValue={''} onChange={this.changeTextAlign}>
                      <Radio.Button value="left"><Icon title="左对齐" type="align-left" /></Radio.Button>
                      <Radio.Button value="center"><Icon title="居中对齐" type="align-center" /></Radio.Button>
                      <Radio.Button value="right"><Icon title="右对齐" type="align-right" /></Radio.Button>
                    </Radio.Group>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={' '}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <Radio.Group className="text-decoration" defaultValue={''} onChange={this.changeTextDecoration}>
                      <Radio.Button value="none"><span title="标准">N</span></Radio.Button>
                      <Radio.Button value="underline"><Icon title="下划线" type="underline" /></Radio.Button>
                      <Radio.Button value="line-through"><Icon title="中划线" type="strikethrough" /></Radio.Button>
                      <Radio.Button value="overline" style={{textDecoration: 'overline'}}><span title="上划线">O</span></Radio.Button>
                    </Radio.Group>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('background') ? <Panel header="背景" key="background">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="背景颜色" type="bg-colors" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <ColorSketch onChange={this.changeBackgroundColor} />
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('border') ? <Panel header="边框" key="border">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="边框位置" type="border" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <Radio.Group className="border-position" defaultValue={'outer'} onChange={(e) => this.setState({borposition: e.target.value})}>
                      <Radio value="outer"><Icon title="外边框" type="border-outer" /></Radio>
                      <Radio value="left"><Icon title="左边框" type="border-left" /></Radio>
                      <Radio value="right"><Icon title="右边框" type="border-right" /></Radio>
                      <Radio value="top"><Icon title="上边框" type="border-top" /></Radio>
                      <Radio value="bottom"><Icon title="下边框" type="border-bottom" /></Radio>
                    </Radio.Group>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="边框样式" type="border-outer" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    {borposition === 'outer' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'left' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'right' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'top' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                    {borposition === 'bottom' ? <Select defaultValue={'solid'} onChange={this.changeBorderStyle}>
                      <Option value="solid">实线</Option>
                      <Option value="dotted">点划线</Option>
                      <Option value="dashed">虚线</Option>
                      <Option value="double">双线</Option>
                    </Select> : null}
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="边框宽度" type="column-width" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    {borposition === 'outer' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'left' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'right' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'top' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                    {borposition === 'bottom' ? <StyleInput defaultValue={''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="边框颜色" type="bg-colors" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    {borposition === 'outer' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'left' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'right' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'top' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                    {borposition === 'bottom' ? <ColorSketch onChange={this.changeBorderColor} /> : null}
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="圆角" type="radius-setting" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={'0px'} options={['px', '%']} onChange={(val) => this.changeNormalStyle(val, 'borderRadius')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('shadow') ? <Panel header="阴影" key="shadow">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="阴影颜色" type="bg-colors" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <ColorSketch onChange={this.changeShadowColor} />
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('margin') ? <Panel header="外边距" key="margin">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="上边距" type="arrow-up"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="下边距" type="arrow-down"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="左边距" type="arrow-left"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="右边距" type="arrow-right"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('padding') ? <Panel header="内边距" key="padding">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="上边距" type="arrow-up"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="下边距" type="arrow-down"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="左边距" type="arrow-left"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/>
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="右边距" type="arrow-right"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <StyleInput defaultValue={''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/>
                  </Form.Item>
                </Col>
              </Panel> : null}
              {options.includes('float') ? <Panel header="浮动" key="float">
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<Icon title="浮动" type="swap" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <Radio.Group defaultValue={''} onChange={(e) => this.changeNormalStyle(e.target.value, 'float')}>
                      <Radio value="left">左浮动</Radio>
                      <Radio value="right">右浮动</Radio>
                      <Radio value="none">不浮动</Radio>
                    </Radio.Group>
                  </Form.Item>
                </Col>
              </Panel> : null}
            </Collapse>
          </Form>
          <div style={{textAlign: 'right'}}>
            <Button style={{margin: '30px 10px 30px 0px'}} onClick={this.onCloseDrawer}>确定</Button>
          </div>
        </div>
      </Drawer>
    )
  }
}
export default MobController
src/menu/stylecombcontroller/index.scss
New file
@@ -0,0 +1,216 @@
.menu-combine-style-controller {
  width: 100%;
  overflow: hidden;
  >.ant-form >.ant-collapse {
    border: 0;
    background: #262E3F;
    > .ant-collapse-item {
      border-color: #202735;
      > .ant-collapse-header {
        padding: 7px 40px 7px 16px;
        background: #262E3F;
        color: rgba(255, 255, 255, 0.85);
      }
      >.ant-collapse-content {
        color: rgba(255, 255, 255, 0.85);
        background-color: #202735;
        border-top: 1px solid #202735;
        .ant-collapse-content-box {
          padding: 5px 10px;
        }
        .ant-collapse-content-box::after {
          content: ' ';
          display: block;
          clear: both;
        }
        .ant-input-number {
          width: 100%;
        }
        .ant-form-item {
          margin-bottom: 2px;
          .ant-form-item-label > label {
            color: rgba(255, 255, 255, 0.85);
            .anticon {
              vertical-align: middle;
              font-size: 18px;
            }
          }
          .ant-form-item-control-wrapper  {
            .ant-form-item-control {
              .border-position {
                .ant-radio-wrapper {
                  margin-right: 0px;
                  span.ant-radio + * {
                    padding-left: 4px;
                  }
                }
              }
              input {
                background: transparent;
                color: rgba(255, 255, 255, 0.65);
              }
              .ant-input {
                height: 28px;
              }
              .ant-input-number {
                height: 28px;
                background: transparent;
                .ant-input-number-input {
                  height: 28px;
                }
              }
              .ant-input-group-addon {
                background: transparent;
              }
              .ant-select-selection {
                background: transparent;
                color: rgba(255, 255, 255, 0.65);
              }
              .color-sketch-block {
                position: relative;
                top: 10px;
              }
              .color-sketch-block + .ant-input {
                float: right;
                width: 70%;
                margin-top: 9px;
                padding-right: 5px;
                padding-left: 5px;
              }
              .ant-select-arrow {
                color: inherit;
              }
              .ant-input-number-handler-wrap {
                background: transparent;
                .ant-input-number-handler {
                  color: rgba(255, 255, 255, 0.65);
                  .ant-input-number-handler-up-inner, .ant-input-number-handler-down-inner {
                    color: rgba(255, 255, 255, 0.65);
                  }
                }
                .ant-input-number-handler:active {
                  background: transparent;
                }
              }
              .ant-radio-group {
                span {
                  color: rgba(255, 255, 255, 0.65);
                }
                .ant-radio-button-wrapper {
                  background: transparent;
                  color: rgba(255, 255, 255, 0.65);
                  height: 27px;
                  line-height: 25px;
                  span {
                    font-style: inherit;
                  }
                }
              }
              .fileupload-form-container {
                .ant-btn {
                  height: 28px;
                }
                .ant-upload-list-item {
                  .ant-upload-list-item-info {
                    background: transparent;
                    color: rgba(255, 255, 255, 0.85);
                    i {
                      color: rgba(255, 255, 255, 0.85);
                    }
                  }
                  .anticon-close {
                    color: rgba(255, 255, 255, 0.85);
                  }
                  .anticon-close:hover {
                    color: rgba(255, 255, 255, 0.85);
                  }
                }
                .ant-upload-list-item:hover .ant-upload-list-item-info {
                  background: transparent;
                }
              }
            }
          }
        }
      }
    }
  }
}
.margin-popover {
  padding-top: 0px;
  .ant-popover-inner-content {
    width: 90px;
    padding: 0px 5px;
    .ant-menu-root.ant-menu-vertical {
      border: 0;
      .ant-menu-item {
        height: 30px;
        cursor: pointer;
        line-height: 30px;
      }
      .ant-menu-item:not(:last-child) {
        margin-bottom: 0px;
      }
      .ant-menu-item:first-child {
        margin-top: 10px;
      }
      .ant-menu-item:last-child {
        margin-bottom: 10px;
      }
    }
  }
  .ant-popover-arrow {
    display: none;
  }
}
.menu-style-drawer {
  .ant-drawer-body {
    height: calc(100vh - 50px);
    overflow-y: auto;
  }
  .ant-drawer-body::-webkit-scrollbar {
    display: none;
  }
  .ant-drawer-wrapper-body {
    background: #262E3F;
    .ant-drawer-header {
      background: #001529;
      padding: 0px;
      height: 48px;
      border-radius: 0;
      border: 0;
      .header-logo {
        width: 180px;
        line-height: 48px;
        height: 48px;
        img {
          max-width: 100%;
          max-height: 100%;
        }
      }
      .ant-drawer-close {
        height: 48px;
        width: 48px;
        line-height: 48px;
        color: #ffffff;
      }
    }
  }
  .ant-drawer-body {
    padding: 0;
    .color-sketch-block {
      .color-sketch-block-inner {
        box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.5);
      }
      .color-sketch-value {
        color: rgba(255, 255, 255, 0.65);
      }
    }
  }
}
src/menu/stylecombcontroller/styleInput/index.jsx
New file
@@ -0,0 +1,153 @@
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 { defaultValue, value, options } = this.props
    let val = ''
    let unit = ''
    let _options = ['px']
    if (value !== undefined) {
      val = value
    } else if (defaultValue !== undefined) {
      val = defaultValue
    }
    if (options && options.length > 0) {
      _options = options
    }
    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 = parseInt(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 !== undefined && nextProps.value !== this.state.value) {
      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 = parseInt(val)
      if (isNaN(_val)) {
        _val = ''
      }
      this.setState({value: _val, unit})
    }
  }
  componentDidMount () {}
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  changeValue = (e) => {
    const { unit } = this.state
    let val = e.target.value
    let _val = parseInt(val)
    if (isNaN(_val)) {
      _val = ''
    }
    this.setState({
      value: _val,
    })
    if (this.props.onChange) {
      if (!_val) {
        this.props.onChange('0px')
      } else {
        this.props.onChange(`${_val}${unit}`)
      }
    }
  }
  changeUnit = (val) => {
    const { value } = this.state
    this.setState({unit: val})
    if (value && this.props.onChange) {
      this.props.onChange(`${value}${val}`)
    }
  }
  render () {
    const { value, options, unit } = this.state
    return (
      <div className="style-input-box">
        <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
src/menu/stylecombcontroller/styleInput/index.scss
New file
@@ -0,0 +1,11 @@
.style-input-box {
  line-height: 32px;
  .ant-select {
    width: 60px!important;
  }
  .single-unit {
    width: 38px;
    text-align: left;
    color: rgba(255, 255, 255, 0.65);
  }
}
src/menu/stylecontroller/index.jsx
@@ -415,7 +415,7 @@
                    label={<Icon title="背景图片" type="picture" />}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <FileUpload value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
                    <FileUpload accept=".jpg,.png,.gif,.svg" value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
                    <Input placeholder="" value={backgroundImage} autoComplete="off" onChange={this.changeBackgroundImageInput} />
                  </Form.Item>
                </Col> : null}
src/menu/utils/menuUtils.js
@@ -226,4 +226,132 @@
    return uuids
  }
  /**
   * @description 生成32位uuid string + 时间
   * @return {String}  uuid
   */
  static getuuid () {
    let uuid = []
    let timestamp = new Date().getTime()
    let _options = '0123456789abcdefghigklmnopqrstuv'
    for (let i = 0; i < 19; i++) {
      uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
    }
    uuid = timestamp + uuid.join('')
    return uuid
  }
  /**
   * @description 重置菜单配置
   * @return {String}  components 配置信息
   */
  static resetConfig = (components) => {
    return components.map(item => {
      item.uuid = this.getuuid()
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          tab.uuid = this.getuuid()
          tab.parentId = item.uuid
          tab.components = tab.components.map(cell => {
            cell.tabId = tab.uuid
            cell.parentId = item.uuid
            return cell
          })
          tab.components = this.resetConfig(tab.components)
        })
      } else if (item.type === 'group') {
        item.components = item.components.map(cell => {
          cell.parentId = item.uuid
          return cell
        })
        item.components = this.resetConfig(item.components)
      } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) {
        item.subcards.forEach(card => {
          card.uuid = this.getuuid()
          if (card.elements) {
            card.elements = card.elements.map(cell => {
              cell.uuid = this.getuuid()
              return cell
            })
          }
          if (card.backElements) {
            card.backElements = card.backElements.map(cell => {
              cell.uuid = this.getuuid()
              return cell
            })
          }
        })
      } else if (item.type === 'table' && item.subtype === 'normaltable' && item.cols) {
        let loopCol = (col) => {
          col.subcols = col.subcols.map(c => {
            c.uuid = this.getuuid()
            if (c.type === 'colspan' && c.subcols) {
              c = loopCol(c)
            } else if (c.type === 'custom' && c.elements) {
              c.elements = c.elements.map(cell => {
                cell.uuid = this.getuuid()
                return cell
              })
            } else if (c.type === 'action' && c.elements) {
              c.elements = c.elements.map(cell => {
                cell.uuid = this.getuuid()
                return cell
              })
            }
            return c
          })
          return col
        }
        item.cols = item.cols.map(col => {
          col.uuid = this.getuuid()
          if (col.type === 'colspan' && col.subcols) {
            col = loopCol(col)
          } else if (col.type === 'custom' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = this.getuuid()
              return cell
            })
          } else if (col.type === 'action' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = this.getuuid()
              return cell
            })
          }
          return col
        })
      }
      if (item.btnlog) {
        item.btnlog = []
      }
      if (item.action) {
        item.action = item.action.map(cell => {
          cell.uuid = this.getuuid()
          return cell
        })
      }
      if (item.search) {
        item.search = item.search.map(cell => {
          cell.uuid = this.getuuid()
          return cell
        })
      }
      if (item.columns) {
        item.columns = item.columns.map(cell => {
          cell.uuid = this.getuuid()
          return cell
        })
      }
      return item
    })
  }
}
src/mob/colorsketch/index.jsx
@@ -39,7 +39,7 @@
  handleChange = (color) => {
    let _color = `rgba(${ color.rgb.r }, ${ color.rgb.g }, ${ color.rgb.b }, ${ color.rgb.a })`
    this.setState({ color: _color }, () => {
      this.props.onChange && this.props.onChange(_color)
    })
src/mob/colorsketch/index.scss
@@ -3,11 +3,10 @@
  width: 100%;
  .color-sketch-block-box {
    // border-radius: 4px;
    display: inline-block;
    width: calc(100% - 160px);
    height: 100%;
    border-radius: 2px;
    border-radius: 4px;
    background: #ffffff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==') left center;
  }
  .color-sketch-block-inner {
src/mob/controller/index.jsx
@@ -375,7 +375,7 @@
                  label={<Icon title="背景图片" type="picture" />}
                  labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                >
                  <FileUpload value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
                  <FileUpload accept=".jpg,.png,.gif,.svg" value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
                  <Input placeholder="" value={backgroundImage} autoComplete="off" onBlur={this.submitBackgroundImage} onPressEnter={this.submitBackgroundImage} onChange={this.changeBackgroundImageInput} />
                </Form.Item>
              </Col>
src/mob/contupdate/index.jsx
@@ -110,7 +110,7 @@
        {deletable !== false ? <Icon type="delete" onClick={this.deleteElement} /> : null}
        <Popover content={
          <div>
            {element.eleType === 'img' ? <FileUpload value={images} maxFile={1} fileType="text" onChange={this.imgChange}/> : null}
            {element.eleType === 'img' ? <FileUpload accept=".jpg,.png,.gif,.svg" value={images} maxFile={1} fileType="text" onChange={this.imgChange}/> : null}
            {getFieldDecorator('content', {
              initialValue: element.content
            })(element.eleType !== 'textarea' ?
src/mob/datasource/verifycard/index.jsx
@@ -426,11 +426,12 @@
    if ((setting.interType === 'system' && setting.execute !== 'false') || _scripts.length > 0) {
      let param = {
        func: 's_debug_sql',
        exec_type: 'y',
        LText: SettingUtils.getDebugSql(setting, _scripts, columns, searches)
      }
      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.secretkey = Utils.encrypt('', param.timestamp)
      
      Api.getLocalConfig(param).then(result => {
        if (result.status) {
src/mob/header/index.jsx
@@ -9,6 +9,7 @@
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
import './index.scss'
const { confirm } = Modal
@@ -23,7 +24,6 @@
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    logourl: window.GLOB.mainlogo,
    avatar: sessionStorage.getItem('CloudAvatar') || avatar,
    userName: sessionStorage.getItem('CloudUserName')
  }
@@ -52,7 +52,7 @@
    return (
      <header className="mob-header-container">
        <div className="header-logo"><img src={this.state.logourl} alt=""/></div>
        <div className="header-logo"><img src={MainLogo} alt=""/></div>
        {view === 'manage' ?
          <div className="mob-manage-title">
            应用管理
src/tabviews/calendar/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Modal, Button, message, Tree, Typography } from 'antd'
import { notification, Spin, Modal, Button } from 'antd'
import moment from 'moment'
import Api from '@/api'
@@ -20,9 +20,7 @@
const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
const CalendarComponent = asyncSpinComponent(() => import('@/tabviews/zshare/calendar'))
const SubTabTable = asyncSpinComponent(() => import('@/tabviews/subtabtable'))
const { TreeNode } = Tree
const { Paragraph } = Typography
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
class NormalTable extends Component {
  static propTpyes = {
@@ -49,9 +47,7 @@
    search: '',           // 搜索条件数组,使用时需分场景处理
    visible: false,       // 标签页控制
    triggerTime: '',      // 点击时间
    treevisible: false,   // 菜单结构树弹框显示隐藏控制
    calendarYear: moment().format('YYYY'), // 日历年份
    debug: sessionStorage.getItem('debug') === 'true'
  }
  /**
@@ -113,6 +109,9 @@
        if (config.tab && !permAction[config.tab.linkTab]) {
          config.tab = null
        }
      }
      if (config.tab) {
        config.tab.uuid = Utils.getuuid()
      }
      if (_curUserConfig) {
@@ -454,65 +453,6 @@
    })
  }
  handleviewconfig = (e) => {
    e.stopPropagation()
    const { MenuNo } = this.props
    const { config } = this.state
    if (config && config.funcs && config.funcs.length > 0) {
      this.setState({
        treevisible: true
      })
    } else {
      let oInput = document.createElement('input')
      oInput.value = MenuNo || ''
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      document.body.removeChild(oInput)
      message.success(this.state.dict['main.copy.success'])
    }
  }
  getTreeNode = (data) => {
    let _type = {
      view: '页面',
      btn: '按钮',
      tab: '标签'
    }
    return data.map(item => {
      let _title = _type[item.subtype]
      let _others = []
      _others.push(
        (item.menuNo ? item.menuNo + '(菜单参数)' : ''),
        (item.tableName ? item.tableName + '(表名) ' : ''),
        (item.innerFunc ? item.innerFunc + '(内部函数) ' : ''),
        (item.outerFunc ? item.outerFunc + '(外部函数)' : '')
      )
      _others = _others.filter(Boolean)
      _others = _others.join('、')
      if (item.label) {
        _title = _title + '(' + item.label + ')'
      }
      if (_others) {
        _title = _title + ': ' + _others
      }
      if (item.subfuncs && item.subfuncs.length > 0) {
        return (
          <TreeNode title={_title} key={item.uuid} dataRef={item} selectable={false}>
            {this.getTreeNode(item.subfuncs)}
          </TreeNode>
        )
      }
      return <TreeNode key={item.uuid} title={_title} isLeaf selectable={false} />
    })
  }
  reloadMenuView = (menuId) => {
    const { MenuID } = this.props
@@ -543,7 +483,9 @@
  }
  componentDidMount () {
    MKEmitter.addListener('openNewTab', this.closeTab)
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.addListener('refreshPopButton', this.refreshPopButton)
  }
  /**
@@ -553,13 +495,17 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('openNewTab', this.closeTab)
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.removeListener('refreshPopButton', this.refreshPopButton)
  }
  changeDate = (value) => {
    this.setState({calendarYear: value}, () => {
      this.loadmaindata()
    })
  refreshPopButton = (tabId) => {
    const { config } = this.props
    if (!config.tab || config.tab.uuid !== tabId) return
    this.loadmaindata()
  }
  triggerDate = (item) => {
@@ -582,7 +528,7 @@
  render() {
    const { menuType } = this.props
    const { debug, BID, searchlist, loadingview, viewlost, config, loading, data, triggerTime } = this.state
    const { BID, searchlist, loadingview, viewlost, config, loading, data, triggerTime } = this.state
    return (
      <div className="calendar-page" id={this.state.ContainerId}>
@@ -591,32 +537,7 @@
          <MainSearch BID={BID} searchlist={searchlist} menuType={menuType} refreshdata={this.refreshbysearch}/> : null
        }
        {config && config.calendar ? <CalendarComponent calendar={config.calendar} loading={loading} data={data} triggerDate={this.triggerDate} changeDate={this.changeDate}/> : null}
        {debug && options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="common-table-copy"
          onClick={this.handleviewconfig}
        /> : null}
        <Modal
          className="menu-tree-modal"
          title={'菜单结构树'}
          width={'650px'}
          maskClosable={false}
          visible={this.state.treevisible}
          onCancel={() => this.setState({treevisible: false})}
          footer={[
            <Button key="close" onClick={() => this.setState({treevisible: false})}>{this.state.dict['main.close']}</Button>
          ]}
          destroyOnClose
        >
          <div className="menu-header">
            <span>菜单名称:{this.props.MenuName}</span>
            <span>菜单参数:{<Paragraph copyable>{this.props.MenuNo}</Paragraph>}</span>
          </div>
          {this.state.treevisible ? <Tree defaultExpandAll showLine={true}>
            {this.getTreeNode(config.funcs)}
          </Tree> : null}
        </Modal>
        {menuType !== 'HS' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        <Modal
          title={config.tab ? config.tab.label : ''}
          width={'80vw'}
@@ -629,13 +550,10 @@
          destroyOnClose
        >
          {config.tab ? <SubTabTable
            type="calendar"
            BID={triggerTime}
            Tab={config.tab}
            SupMenuID={this.props.MenuID}
            MenuID={config.tab.linkTab}
            refreshSupView={() => this.loadmaindata()}
            closeModalView={this.closeTab}
            SupMenuID={this.props.MenuID}
          /> : null}
        </Modal>
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
src/tabviews/calendar/index.scss
@@ -41,22 +41,4 @@
  }
}
.menu-tree-modal {
  .ant-modal-body {
    min-height: 300px;
    .menu-header {
      text-align: center;
      span {
        font-weight: 600;
        margin-right: 20px;
      }
      .ant-typography {
        font-weight: 600;
        display: inline-block;
      }
    }
    .ant-tree li .ant-tree-node-content-wrapper {
      cursor: default;
    }
  }
}
src/tabviews/commontable/index.jsx
@@ -2,10 +2,9 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Tabs, Icon, Switch, Modal, Button, message, Tree, Typography, Row, Col } from 'antd'
import { notification, Spin, Tabs, Icon, Switch, Row, Col } from 'antd'
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'
@@ -25,10 +24,9 @@
const SubTable = asyncSpinComponent(() => import('@/tabviews/subtable'))
const CardComponent = asyncSpinComponent(() => import('@/tabviews/zshare/cardcomponent'))
const ChartComponent = asyncSpinComponent(() => import('@/tabviews/zshare/chartcomponent'))
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
const { TabPane } = Tabs
const { TreeNode } = Tree
const { Paragraph } = Typography
class NormalTable extends Component {
  static propTpyes = {
@@ -46,13 +44,13 @@
    viewlost: false,      // 页面丢失:1、未获取到配置-页面丢失;2、页面未启用
    lostmsg: '',          // 页面丢失时的提示信息
    config: {},           // 页面配置信息,包括按钮、搜索、显示列、标签等
    userConfig: null,     // 用户自定义设置
    shortcuts: null,      // 快捷键
    searchlist: null,     // 搜索条件
    actions: null,        // 按钮集
    columns: null,        // 显示列
    arr_field: '',        // 使用 sPC_Get_TableData 时的查询字段集
    setting: null,        // 页面全局设置:数据源、按钮及显示列固定、主键等
    data: null,           // 列表数据集
    data: [],             // 列表数据集
    selectedData: [],     // 已选表格数据
    total: 0,             // 总数
    loading: false,       // 列表数据加载中
@@ -62,13 +60,10 @@
    search: '',           // 搜索条件数组,使用时需分场景处理
    BIDs: {},             // 上级表id
    pickup: false,        // 主表数据隐藏显示切换
    treevisible: false,   // 菜单结构树弹框显示隐藏控制
    tabActive: null,      // 标签页展开控制
    chartId: '',          // 展开图表ID
    statFields: [],       // 合计字段
    statFValue: [],       // 合计值
    absFields: [],        // 绝对值字段
    debug: sessionStorage.getItem('debug') === 'true'
  }
  /**
@@ -85,11 +80,12 @@
    if (result.status) {
      let config = ''
      let userConfig = null
      let _curUserConfig = ''
      let shortcuts = []
      try { // 配置信息解析
        config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
        config.MenuID = this.props.MenuID
        config.MenuName = MenuName
      } catch (e) {
        console.warn('Parse Failure')
        config = ''
@@ -98,11 +94,36 @@
      // HS不使用自定义设置
      if (result.LongParamUser && this.props.menuType !== 'HS') {
        try { // 配置信息解析
          userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
          _curUserConfig = userConfig[this.props.MenuID]
          let userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
          if (userConfig && !userConfig.version) {
            Object.keys(userConfig).forEach(key => {
              let component = userConfig[key]
              if (!component.action) return
              Object.keys(component.action).forEach(uuid => {
                let item = {uuid: uuid, parentId: key, shortcut: component.action[uuid].shortcut}
                let printer = component.action[uuid].printer
                if (item.shortcut) {
                  item.$shortcut = item.shortcut.join('+')
                  shortcuts.push(item)
                }
                if (printer) {
                  item.printer = printer.defaultPrinter || ''
                  item.printerList = printer.printerList || ''
                  window.GLOB.UserCacheMap.set(key + uuid, item)
                }
              })
            })
          } else if (userConfig) {
            shortcuts = userConfig.action
            userConfig.printers.forEach(item => {
              window.GLOB.UserCacheMap.set(item.parentId + item.uuid, item)
            })
          }
        } catch (e) {
          console.warn('Parse Failure')
          userConfig = null
        }
      }
@@ -221,36 +242,6 @@
        }
      }
      if (_curUserConfig) {
        config.easyCode = _curUserConfig.easyCode || config.easyCode || ''
        config.action = config.action.map(item => {
          if (_curUserConfig.action[item.uuid]) {
            delete _curUserConfig.action[item.uuid].label
            item = {...item, ..._curUserConfig.action[item.uuid]}
          }
          if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify && item.printer) {
            item.verify.defaultPrinter = item.printer.defaultPrinter || ''
            if (item.verify.printerTypeList && item.printer.printerList) {
              item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                cell.printer = item.printer.printerList[cell.Value] || ''
                return cell
              })
            }
          }
          return item
        })
      }
      let _tabActive = {} // 筛选展开的tab页
      config.tabgroups.forEach(group => {
        _tabActive[group.uuid] = group.sublist[0].uuid
      })
      let _arrField = []     // 字段集
      let _columns = []      // 显示列
      let _hideCol = []      // 隐藏及合并列中字段的uuid集
@@ -264,6 +255,22 @@
      config.action.forEach(item => {
        item.logLabel = MenuName + '-' + item.label // 用于sPC_TableData_InUpDe记录操作按钮
        item.$menuId = this.props.MenuID
        if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify) { // 打印机设置
          let _item = window.GLOB.UserCacheMap.get(this.props.MenuID + item.uuid)
          if (_item) {
            item.printer = _item.printer || ''
            item.verify.defaultPrinter = _item.printer || ''
            if (item.verify.printerTypeList && _item.printerList) {
              item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                cell.printer = _item.printerList[cell.Value] || ''
                return cell
              })
            }
          }
        }
        
        if (item.position === 'toolbar') {
          _actions.push(item)
@@ -316,8 +323,10 @@
              subcols.push(colMap.get(sub))
            }
          })
          _col.subcols = subcols
          _columns.push(_col)
          if (subcols.length > 0) {
            _col.subcols = subcols
            _columns.push(_col)
          }
        } else {
          _columns.push(col)
        }
@@ -338,29 +347,13 @@
        return _item
      })
      if (_curUserConfig) {
        _columns = _columns.map(item => {
          if (_curUserConfig.columns[item.uuid]) {
            delete _curUserConfig.columns[item.uuid].label
            item = {...item, ..._curUserConfig.columns[item.uuid]}
          }
          return item
        })
        _columns.sort((pre, next) => {
          return pre.sort - next.sort
        })
      }
      this.setState({
        loadingview: false,
        absFields,
        chartId,
        config,
        statFields,
        userConfig,
        tabActive: _tabActive,
        shortcuts,
        setting: config.setting,
        searchlist: config.search,
        actions: _actions,
@@ -389,8 +382,12 @@
  }
  setShortcut = () => {
    const { actions, userConfig, config } = this.state
    if (!userConfig) return
    const { shortcuts } = this.state
    if (!shortcuts || shortcuts.length === 0) {
      document.onkeydown = () => {}
      return
    }
    document.onkeydown = (event) => {
      let e = event || window.event
@@ -405,56 +402,21 @@
        preKey = 'alt'
      }
      if (!preKey) return
      if (!preKey || !keyCode) return
      let triggerId = ''
      let _shortcut = `${preKey}+${keyCode}`
      actions.some(item => {
        if (Array.isArray(item.shortcut) && preKey === item.shortcut[0] && keyCode === item.shortcut[1]) {
          e.preventDefault()
          triggerId = item.uuid
      shortcuts.some(item => {
        if (item.$shortcut === _shortcut) {
          MKEmitter.emit('triggerBtnId', item.uuid)
          let element = item.parentId && item.parentId !== this.props.MenuID ? document.getElementById(item.parentId) : '' // 标签切换
          if (element && element.click) {
            element.click()
          }
          return true
        }
        return false
      })
      if (triggerId) {
        MKEmitter.emit('triggerBtnId', triggerId)
        return
      }
      Object.keys(userConfig).some(key => {
        if (key === this.props.MenuID || !userConfig[key].action) return false
        let _actions = userConfig[key].action
        Object.keys(_actions).some(btnkey => {
          let item = _actions[btnkey]
          if (Array.isArray(item.shortcut) && preKey === item.shortcut[0] && keyCode === item.shortcut[1]) {
            e.preventDefault()
            triggerId = btnkey
            let _groupId = ''
            let _ActiveTabId = ''
            config.tabgroups.forEach(group => {
              let _tab = group.sublist.filter(tab => tab.uuid === key)[0]
              if (!_tab) return
              _groupId = group.uuid
              _ActiveTabId = _tab.uuid
            })
            if (_ActiveTabId && this.state.tabActive[_groupId] === _ActiveTabId) {
              MKEmitter.emit('triggerBtnId', triggerId)
              return true
            }
          }
          return false
        })
        if (triggerId) return true
        return false
      })
    }
@@ -513,6 +475,9 @@
          }
          item.key = index
          item.$$uuid = item[setting.primaryKey] || ''
          item.$$BID = BID || ''
          return item
        }),
        total: result.total,
@@ -567,6 +532,9 @@
          data = data.map(item => {
            if (item[setting.primaryKey] === _data[setting.primaryKey]) {
              _data.key = item.key
              _data.$$uuid = _data[setting.primaryKey] || ''
              _data.$$BID = BID || ''
              return _data
            } else {
              return item
@@ -719,20 +687,11 @@
   */
  reloadview = () => {
    this.setState({ loadingview: true, viewlost: false, config: {}, setting: null,
      data: null, total: 0, loading: false, pageIndex: 1,
      data: null, total: 0, loading: false, pageIndex: 1, shortcuts: null,
      pageSize: 10, orderBy: '', search: '', BIDs: {}, pickup: false
    }, () => {
      this.loadconfig()
    })
  }
  /**
   * @description 按钮操作完成后(成功或失败),页面刷新,重置页码及选择项
   */
  refreshbyaction = (position, btn) => {
    if (position === 'grid' || position === 'view') {
      this.reloadtable(btn)
    }
  }
  /**
@@ -784,65 +743,6 @@
    })
  }
  handleviewconfig = (e) => {
    e.stopPropagation()
    const { MenuNo } = this.props
    const { config } = this.state
    if (config && config.funcs && config.funcs.length > 0) {
      this.setState({
        treevisible: true
      })
    } else {
      let oInput = document.createElement('input')
      oInput.value = MenuNo || ''
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      document.body.removeChild(oInput)
      message.success(this.state.dict['main.copy.success'])
    }
  }
  getTreeNode = (data) => {
    let _type = {
      view: '页面',
      btn: '按钮',
      tab: '标签'
    }
    return data.map(item => {
      let _title = _type[item.subtype]
      let _others = []
      _others.push(
        (item.menuNo ? item.menuNo + '(菜单参数)' : ''),
        (item.tableName ? item.tableName + '(表名) ' : ''),
        (item.innerFunc ? item.innerFunc + '(内部函数) ' : ''),
        (item.outerFunc ? item.outerFunc + '(外部函数)' : '')
      )
      _others = _others.filter(Boolean)
      _others = _others.join('、')
      if (item.label) {
        _title = _title + '(' + item.label + ')'
      }
      if (_others) {
        _title = _title + ': ' + _others
      }
      if (item.subfuncs && item.subfuncs.length > 0) {
        return (
          <TreeNode title={_title} key={item.uuid} dataRef={item} selectable={false}>
            {this.getTreeNode(item.subfuncs)}
          </TreeNode>
        )
      }
      return <TreeNode key={item.uuid} title={_title} isLeaf selectable={false} />
    })
  }
  /**
   * @description 图表视图切换
   */
@@ -884,6 +784,20 @@
    this.setShortcut()
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    this.reloadtable(btn)
  }
  UNSAFE_componentWillMount () {
    // 组件加载时,获取菜单数据
    this.loadconfig()
@@ -915,6 +829,7 @@
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu)
    MKEmitter.addListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
@@ -929,19 +844,20 @@
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu)
    MKEmitter.removeListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  render() {
    const { menuType, MenuName } = this.props
    const { debug, BID, setting, searchlist, pageSize, actions, columns, loadingview, viewlost, pickup, config, userConfig, tabActive, chartId, search, selectedData } = this.state
    const { menuType } = this.props
    const { BID, setting, searchlist, pageSize, actions, columns, loadingview, viewlost, pickup, config, chartId, search, selectedData, shortcuts } = this.state
    return (
      <div className="commontable" id={this.state.ContainerId}>
        {loadingview && <Spin size="large" />}
        {loadingview ? <Spin size="large" /> : null}
        {searchlist && searchlist.length ?
          <MainSearch BID={BID} searchlist={searchlist} menuType={this.props.menuType} refreshdata={this.refreshbysearch}/> : null
        }
        {setting && setting.onload !== 'false' ? <Row className="chart-view" gutter={16}>
        {setting ? <Row className="chart-view" gutter={16}>
          {/* 视图组 */}
          {!config.expand ? <Tabs activeKey={chartId} onChange={this.changeChart}>
            {config.charts.map(item => (
@@ -965,26 +881,14 @@
                      MenuID={this.props.MenuID}
                      selectedData={selectedData}
                      ContainerId={this.state.ContainerId}
                      refreshdata={this.refreshbyaction}
                    />
                  </div>
                  <div className="main-table-box">
                    {this.props.menuType !== 'HS' ? <SettingComponent
                      config={config}
                      columns={columns}
                      MenuName={MenuName}
                      dict={this.state.dict}
                      MenuID={this.props.MenuID}
                      permAction={this.props.permAction}
                      userConfig={this.state.userConfig}
                      reloadview={this.reloadview}
                    /> : null}
                    {(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
                    }
                    <MainTable
                      tableId="mainTable"
                      BID={BID}
                      pickup={pickup}
                      setting={setting}
                      columns={columns}
@@ -994,11 +898,10 @@
                      total={this.state.total}
                      MenuID={this.props.MenuID}
                      loading={this.state.loading}
                      refreshdata={this.refreshbytable}
                      statFValue={this.state.statFValue}
                      handleTableId={this.handleTableId}
                      ContainerId={this.state.ContainerId}
                      refreshbyaction={this.refreshbyaction}
                      refreshdata={this.refreshbytable}
                      handleTableId={this.handleTableId}
                      chgSelectData={this.changeSelectedData}
                    />
                  </div>
@@ -1017,7 +920,6 @@
                    MenuID={this.props.MenuID}
                    loading={this.state.loading}
                    ContainerId={this.state.ContainerId}
                    refreshdata={this.refreshbyaction}
                    handleTableId={this.handleTableId}
                  />
                </Col>
@@ -1037,60 +939,33 @@
            }
          })}
        </Row> : null }
        {setting && setting.onload !== 'false' &&
          config.tabgroups.map(group => (
            <Tabs key={group.uuid} onChange={(key) => this.setState({tabActive: {...tabActive, [group.uuid]: key}})}>
              {group.sublist.map(_tab => {
                return (
                  <TabPane tab={
                    <span>
                      {_tab.icon ? <Icon type={_tab.icon} /> : null}
                      {_tab.label}
                    </span>
                  } key={_tab.uuid}>
                    <SubTable
                      Tab={_tab}
                      MenuID={_tab.linkTab}
                      mainSearch={_tab.searchPass === 'true' ? search : null}
                      userConfig={userConfig ? userConfig[_tab.uuid] : null}
                      SupMenuID={this.props.MenuID}
                      ContainerId={this.state.ContainerId}
                      BID={this.state.BIDs[_tab.supMenu] || ''}
                      BData={this.state.BIDs[_tab.supMenu + 'data'] || ''}
                      handleTableId={this.handleTableId}
                    />
                  </TabPane>
                )
              })}
            </Tabs>)
          )
        {setting && config.tabgroups.map(group => (
          <Tabs key={group.uuid}>
            {group.sublist.map(_tab => {
              return (
                <TabPane tab={
                  <span id={_tab.uuid}>
                    {_tab.icon ? <Icon type={_tab.icon} /> : null}
                    {_tab.label}
                  </span>
                } key={_tab.uuid}>
                  <SubTable
                    Tab={_tab}
                    MenuID={_tab.linkTab}
                    mainSearch={_tab.searchPass === 'true' ? search : null}
                    SupMenuID={this.props.MenuID}
                    ContainerId={this.state.ContainerId}
                    BID={this.state.BIDs[_tab.supMenu] || ''}
                    BData={this.state.BIDs[_tab.supMenu + 'data'] || ''}
                    handleTableId={this.handleTableId}
                  />
                </TabPane>
              )
            })}
          </Tabs>))
        }
        {debug && options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="common-table-copy"
          onClick={this.handleviewconfig}
        /> : null}
        <Modal
          className="menu-tree-modal"
          title={'菜单结构树'}
          width={'650px'}
          maskClosable={false}
          visible={this.state.treevisible}
          onCancel={() => this.setState({treevisible: false})}
          footer={[
            <Button key="close" onClick={() => this.setState({treevisible: false})}>{this.state.dict['main.close']}</Button>
          ]}
          destroyOnClose
        >
          <div className="menu-header">
            <span>菜单名称:{this.props.MenuName}</span>
            <span>菜单参数:{<Paragraph copyable>{this.props.MenuNo}</Paragraph>}</span>
          </div>
          {this.state.treevisible ? <Tree defaultExpandAll showLine={true}>
            {this.getTreeNode(config.funcs)}
          </Tree> : null}
        </Modal>
        {menuType !== 'HS' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {menuType !== 'HS' && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
src/tabviews/commontable/index.scss
@@ -63,18 +63,9 @@
    position: relative;
    .main-pickup {
      position: absolute;
      right: 35px;
      right: 0px;
      top: -22px;
      z-index: 1;
    }
    .custom-control {
      position: absolute;
      z-index: 1;
      right: 0px;
      top: -23px;
      font-size: 18px;
      padding: 3px;
      cursor: pointer;
    }
    >.async-spin {
      line-height: 150px!important;
@@ -90,14 +81,6 @@
    .ant-tabs-tab.ant-tabs-tab-active {
      cursor: default;
    }
  }
  .common-table-copy {
    position: fixed;
    z-index: 2;
    bottom: 65px;
    right: 30px;
    width: 40px;
    height: 40px;
  }
  .ant-table-fixed-left, .ant-table-fixed-right {
    z-index: 1;
@@ -152,26 +135,6 @@
    }
    .canvas {
      clear: both;
    }
  }
}
.menu-tree-modal {
  .ant-modal-body {
    min-height: 300px;
    .menu-header {
      text-align: center;
      span {
        font-weight: 600;
        margin-right: 20px;
      }
      .ant-typography {
        font-weight: 600;
        display: inline-block;
      }
    }
    .ant-tree li .ant-tree-node-content-wrapper {
      cursor: default;
    }
  }
}
src/tabviews/commontable/secretKeyTable/actionList/index.jsx
File was deleted
src/tabviews/commontable/secretKeyTable/actionList/index.scss
File was deleted
src/tabviews/commontable/secretKeyTable/config.jsx
File was deleted
src/tabviews/commontable/secretKeyTable/index.jsx
File was deleted
src/tabviews/commontable/secretKeyTable/index.scss
File was deleted
src/tabviews/custom/components/card/cardItem/index.jsx
@@ -15,7 +15,6 @@
    cards: PropTypes.object,    // 卡片行配置信息
    card: PropTypes.object,     // 卡片配置信息
    data: PropTypes.object,
    updateStatus: PropTypes.func  // 状态更新
  }
  state = {
@@ -48,9 +47,9 @@
    return (
      <div className="card-item-box" style={card.style}>
        <CardCellComponent data={data} cards={cards} cardCell={card} elements={card.elements} updateStatus={this.props.updateStatus}/>
        <CardCellComponent data={data} cards={cards} cardCell={card} elements={card.elements}/>
        {card.setting.type === 'multi' ? <div className={'back-side ' + card.setting.transform} style={card.backStyle}>
          <CardCellComponent data={data} cards={cards} cardCell={card} elements={card.backElements} updateStatus={this.props.updateStatus}/>
          <CardCellComponent data={data} cards={cards} cardCell={card} elements={card.backElements}/>
        </div> : null}
      </div>
    )
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -31,7 +31,6 @@
    cardCell: PropTypes.object,
    data: PropTypes.object,
    elements: PropTypes.array,       // 元素集
    updateStatus: PropTypes.func,    // 状态更新
  }
  state = {
@@ -180,7 +179,7 @@
        }
      }
      if (result) {
      if (result && mark.signType) {
        if (mark.signType[0] === 'font') {
          style.color = mark.color
        } else if (mark.signType[0] === 'background') {
@@ -207,6 +206,60 @@
    })
    return content
  }
  getColor = (marks) => {
    const { data } = this.props
    let color = ''
    marks.some(mark => {
      let originVal = data[mark.field[0]] + ''
      let contrastVal = ''
      let result = false
      if (mark.field[1] === 'static') {
        contrastVal = mark.contrastValue + ''
      } else {
        contrastVal = data[mark.field[2]] + ''
      }
      if (mark.match === '=') {
        result = originVal === contrastVal
      } else if (mark.match === '!=') {
        result = originVal !== contrastVal
      } else if (mark.match === 'like') {
        result = originVal.indexOf(contrastVal) > -1
      } else if (mark.match === '>') {
        try {
          originVal = parseFloat(originVal)
          contrastVal = parseFloat(contrastVal)
        } catch {
          originVal = NaN
        }
        if (!isNaN(originVal) && !isNaN(contrastVal) && originVal > contrastVal) {
          result = true
        }
      } else if (mark.match === '<') {
        try {
          originVal = parseFloat(originVal)
          contrastVal = parseFloat(contrastVal)
        } catch {
          originVal = NaN
        }
        if (!isNaN(originVal) && !isNaN(contrastVal) && originVal < contrastVal) {
          result = true
        }
      }
      if (result) {
        color = mark.color
      }
      return result
    })
    return color
  }
  getContent = (card) => {
@@ -327,6 +380,7 @@
      )
    } else if (card.eleType === 'slider') {
      let val = 0
      let color = card.color
      if (card.datatype === 'static') {
        val = card.value
@@ -347,14 +401,19 @@
        _val = `${val}%`
      }
      if (card.marks) {
        let _color = this.getColor(card.marks)
        color = _color ? _color : color
      }
      return (
        <Col key={card.uuid} span={card.width}>
          <div style={card.style}>
            <div className="ant-mk-slider">
              <div className="ant-mk-slider-rail"></div>
              <div className="ant-mk-slider-track" style={{width: _val, backgroundColor: card.color}}></div>
              <div className="ant-mk-slider-track" style={{width: _val, backgroundColor: color}}></div>
              <Tooltip title={`${val}%`}>
                <div className="ant-mk-slider-handle" style={{left: _val, borderColor: card.color}}></div>
                <div className="ant-mk-slider-handle" style={{left: _val, borderColor: color}}></div>
              </Tooltip>
            </div>
          </div>
@@ -484,7 +543,6 @@
                setting={cards.setting}
                columns={cards.columns}
                selectedData={[data]}
                updateStatus={this.props.updateStatus}
              />
            </div>
          </Col>
@@ -500,7 +558,6 @@
                style={card.btnstyle}
                setting={cards.setting}
                selectedData={[data]}
                updateStatus={this.props.updateStatus}
              />
            </div>
          </Col>
@@ -515,7 +572,6 @@
                show={card.show}
                style={card.btnstyle}
                setting={cards.setting}
                updateStatus={this.props.updateStatus}
              />
            </div>
          </Col>
@@ -531,7 +587,6 @@
                style={card.btnstyle}
                setting={cards.setting}
                selectedData={[data]}
                updateStatus={this.props.updateStatus}
              />
            </div>
          </Col>
@@ -546,7 +601,6 @@
                style={card.btnstyle}
                setting={cards.setting}
                selectedData={[data]}
                updateStatus={this.props.updateStatus}
              />
            </div>
          </Col>
@@ -561,7 +615,6 @@
                style={card.btnstyle}
                setting={cards.setting}
                selectedData={[data]}
                updateStatus={this.props.updateStatus}
              />
            </div>
          </Col>
@@ -578,7 +631,6 @@
                  style={card.btnstyle}
                  setting={cards.setting}
                  selectedData={[data]}
                  updateStatus={this.props.updateStatus}
                />
              </div>
            </Col>
@@ -594,7 +646,6 @@
                  style={card.btnstyle}
                  setting={cards.setting}
                  selectedData={[data]}
                  updateStatus={this.props.updateStatus}
                />
              </div>
            </Col>
src/tabviews/custom/components/card/data-card/index.jsx
@@ -100,8 +100,10 @@
  }
  componentDidMount () {
    MKEmitter.addListener('syncRefreshComponentId', this.reload)
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -138,20 +140,48 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('syncRefreshComponentId', this.reload)
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  reload = (syncId) => {
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { config, BID } = this.state
    if (config.uuid !== menuId) return
    this.loadData(btn)                                                         // 数据刷新
    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'))
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      config.setting.supModule && MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  reloadData = (menuId, id) => {
    const { config } = this.state
    if (syncId && syncId !== config.uuid) return
    if (config.uuid !== menuId) return
    if (id === 'empty') return
    this.setState({
      pageIndex: 1
    }, () => {
    if (!id) {
      this.loadData()
    })
    } else {
      this.loadLinedata(id)
    }
  }
  resetParentParam = (MenuID, id, data) => {
@@ -163,6 +193,33 @@
        this.loadData()
      })
    }
  }
  /**
   * @description 导出Excel时,获取页面搜索排序等参数
   */
  getexceloutparam = (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) { // 主表搜索条件
      let keys = searches.map(item => item.key.toLowerCase())
      mainSearch.forEach(item => {
        if (!keys.includes(item.key.toLowerCase())) {
          searches.push(item)
        }
      })
    }
    MKEmitter.emit('execExcelout', config.uuid, btnId, {
      arr_field: arr_field,
      orderBy: config.setting.order || '',
      search: searches,
      menuName: config.name
    })
  }
  async loadData () {
@@ -226,17 +283,69 @@
    }
  }
  updateStatus = (type, position, btn) => {
    const { config } = this.state
  /**
   * @description 获取单行数据
   */
  async loadLinedata (id) {
    const { mainSearch, menuType } = this.props
    const { config, arr_field, pageIndex, search, BID } = this.state
    if (type === 'refresh' && position === 'grid') {
      this.loadData()
      if (btn && btn.syncComponent && btn.syncComponent[0]) {
        let syncId = btn.syncComponent.slice(-1)[0]
        if (config.uuid !== syncId) {
          MKEmitter.emit('syncRefreshComponentId', syncId)
    let searches = fromJS(search).toJS()
    if (mainSearch && mainSearch.length > 0) { // 主表搜索条件
      let keys = searches.map(item => item.key.toLowerCase())
      mainSearch.forEach(item => {
        if (!keys.includes(item.key.toLowerCase())) {
          searches.push(item)
        }
      })
    }
    this.setState({
      loading: true
    })
    let _orderBy = config.setting.order || ''
    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID, menuType, id)
    if (param.func === 'sPC_Get_TableData') {
      param.menuname = config.name || ''
    }
    let result = await Api.genericInterface(param)
    if (result.status) {
      let data = fromJS(this.state.data).toJS()
      if (result.data && result.data[0]) {
        let _data = result.data[0]
        try {
          data = data.map(item => {
            if (item[config.setting.primaryKey] === _data[config.setting.primaryKey]) {
              _data.key = item.key
              _data.$$uuid = _data[config.setting.primaryKey] || ''
              _data.$$BID = BID || ''
              return _data
            } else {
              return item
            }
          })
        } catch {
          console.warn('数据查询错误')
        }
      }
      this.setState({
        data: data,
        loading: false
      })
    } else {
      this.setState({
        loading: false
      })
      notification.error({
        top: 92,
        message: result.message,
        duration: 10
      })
    }
  }
@@ -367,7 +476,7 @@
          {data && data.length > 0 ? <div className="card-row-list">
            {data.map((item, index) => (
              <Col className={activeKey === index ? 'active' : (selectKeys.indexOf(index) > -1 ? 'selected' : '')} key={index} span={card.setting.width} offset={!index ? offset : 0} onClick={() => {this.changeCard(index, item)}}>
                <CardItem card={card} cards={config} data={item} updateStatus={this.updateStatus}/>
                <CardItem card={card} cards={config} data={item}/>
              </Col>
            ))}
          </div> : null}
src/tabviews/custom/components/card/prop-card/index.jsx
@@ -106,8 +106,9 @@
  }
  componentDidMount () {
    MKEmitter.addListener('syncRefreshComponentId', this.reload)
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -118,8 +119,9 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('syncRefreshComponentId', this.reload)
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
@@ -151,6 +153,31 @@
    }
  }
  /**
   * @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'))
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      config.setting.supModule && MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  resetParentParam = (MenuID, id) => {
    const { config } = this.state
@@ -162,10 +189,10 @@
    }
  }
  reload = (syncId) => {
  reloadData = (menuId) => {
    const { config } = this.state
    if (syncId && syncId !== config.uuid) return
    if (menuId !== config.uuid) return
    this.loadData()
  }
@@ -227,20 +254,6 @@
    }
  }
  updateStatus = (type, position, btn) => {
    const { config } = this.state
    if (type === 'refresh' && position === 'grid') {
      this.loadData()
      if (btn && btn.syncComponent && btn.syncComponent[0]) {
        let syncId = btn.syncComponent.slice(-1)[0]
        if (config.uuid !== syncId) {
          MKEmitter.emit('syncRefreshComponentId', syncId)
        }
      }
    }
  }
  changeCard = (index, item) => {
    const { config, data, activeKey } = this.state
@@ -268,7 +281,7 @@
        <div className={`card-row-list ${config.wrap.cardType || ''} ${config.wrap.scale || ''}`}>
          {config.subcards.map((item, index) => (
            <Col className={activeKey === index ? 'active' : ''} key={index} span={item.setting.width || 6} offset={item.offset || 0} onClick={() => {this.changeCard(index, item)}}>
              <CardItem card={item} cards={config} data={data} updateStatus={this.updateStatus}/>
              <CardItem card={item} cards={config} data={data}/>
            </Col>
          ))}
        </div>
src/tabviews/custom/components/card/table-card/index.jsx
@@ -102,8 +102,10 @@
  }
  componentDidMount () {
    MKEmitter.addListener('syncRefreshComponentId', this.reload)
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -114,8 +116,10 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('syncRefreshComponentId', this.reload)
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
@@ -147,6 +151,31 @@
    }
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { config, BID } = this.state
    if (config.uuid !== menuId) return
    this.loadData(btn)                                                         // 数据刷新
    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'))
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      config.setting.supModule && MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  resetParentParam = (MenuID, id) => {
    const { config } = this.state
@@ -158,15 +187,38 @@
    }
  }
  reload = (syncId) => {
  reloadData = (menuId) => {
    const { config } = this.state
    if (syncId && syncId !== config.uuid) return
    if (config.uuid !== menuId) return
    this.setState({
      pageIndex: 1
    }, () => {
      this.loadData()
    this.loadData()
  }
   /**
   * @description 导出Excel时,获取页面搜索排序等参数
   */
  getexceloutparam = (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) { // 主表搜索条件
      let keys = searches.map(item => item.key.toLowerCase())
      mainSearch.forEach(item => {
        if (!keys.includes(item.key.toLowerCase())) {
          searches.push(item)
        }
      })
    }
    MKEmitter.emit('execExcelout', config.uuid, btnId, {
      arr_field: arr_field,
      orderBy: config.setting.order || '',
      search: searches,
      menuName: config.name
    })
  }
@@ -183,7 +235,7 @@
      return
    }
    let searches = fromJS(search).toJS()
    let searches = search ? fromJS(search).toJS() : []
    if (mainSearch && mainSearch.length > 0) { // 主表搜索条件
      let keys = searches.map(item => item.key)
      mainSearch.forEach(item => {
@@ -230,20 +282,6 @@
    }
  }
  updateStatus = (type, position, btn) => {
    const { config } = this.state
    if (type === 'refresh' && position === 'grid') {
      this.loadData()
      if (btn && btn.syncComponent && btn.syncComponent[0]) {
        let syncId = btn.syncComponent.slice(-1)[0]
        if (config.uuid !== syncId) {
          MKEmitter.emit('syncRefreshComponentId', syncId)
        }
      }
    }
  }
  changePageIndex = (page) => {
    this.setState({
      pageIndex: page
@@ -283,7 +321,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} updateStatus={this.updateStatus}/>
            <CardCellComponent seq={seq} data={data} cards={config} cardCell={item} elements={item.elements}/>
          </div>
        </Col>
      )
src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -232,7 +232,10 @@
  }
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
@@ -242,7 +245,43 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
   * @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'))
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      config.setting.supModule && MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
  reloadData = (menuId) => {
    const { config } = this.state
    if (config.uuid !== menuId) return
    this.loadData()
  }
  resetParentParam = (MenuID, id) => {
@@ -254,6 +293,33 @@
        this.loadData()
      })
    }
  }
  /**
   * @description 导出Excel时,获取页面搜索排序等参数
   */
  getexceloutparam = (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) { // 主表搜索条件
      let keys = searches.map(item => item.key.toLowerCase())
      mainSearch.forEach(item => {
        if (!keys.includes(item.key.toLowerCase())) {
          searches.push(item)
        }
      })
    }
    MKEmitter.emit('execExcelout', config.uuid, btnId, {
      arr_field: arr_field,
      orderBy: config.setting.order || '',
      search: searches,
      menuName: config.name
    })
  }
  /**
@@ -272,7 +338,7 @@
      return
    }
    let searches = fromJS(search).toJS()
    let searches = search ? fromJS(search).toJS() : []
    if (mainSearch && mainSearch.length > 0) { // 主表搜索条件
      let keys = searches.map(item => item.key)
      mainSearch.forEach(item => {
@@ -1288,7 +1354,6 @@
                    btn={item}
                    show="icon"
                    setting={config.setting}
                    updateStatus={() => {}}
                  />
                )
              } else {
@@ -1299,7 +1364,6 @@
                    btn={item}
                    show="icon"
                    setting={config.setting}
                    updateStatus={() => {}}
                  />
                )
              }
src/tabviews/custom/components/chart/antv-bar-line/index.scss
@@ -11,9 +11,12 @@
    position: relative;
    .chart-action {
      position: absolute;
      top: 2px;
      top: 0px;
      right: 5px;
      z-index: 1;
      .ant-btn {
        float: right;
      }
    }
  }
src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -113,6 +113,7 @@
  }
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
  }
@@ -123,9 +124,18 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
  }
  reloadData = (menuId) => {
    const { config } = this.state
    if (config.uuid !== menuId) return
    this.loadData()
  }
  resetParentParam = (MenuID, id) => {
    const { config } = this.state
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -170,7 +170,7 @@
  }
  render() {
    let { col, config, record, className, style, triggerLink, updateStatus, ...resProps } = this.props
    let { col, config, record, className, style, triggerLink, ...resProps } = this.props
    if (!col) return (<td {...resProps} className={className} style={style}/>)
    
@@ -347,12 +347,12 @@
    } else if (col.type === 'custom') {
      style.padding = '0px'
      resProps.children = (
        <CardCellComponent data={record} cards={config} elements={col.elements} updateStatus={this.props.updateStatus}/>
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    } else if (col.type === 'action') {
      style.padding = '0px 5px'
      resProps.children = (
        <CardCellComponent data={record} cards={config} elements={col.elements} updateStatus={this.props.updateStatus}/>
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    }
@@ -376,7 +376,6 @@
    loading: PropTypes.bool,         // 表格加载中
    refreshdata: PropTypes.func,     // 表格中排序列、页码的变化时刷新
    chgSelectData: PropTypes.func,   // 数据切换
    refreshbyaction: PropTypes.func, // 按钮执行完成后刷新
  }
  state = {
@@ -442,8 +441,7 @@
              record,
              col: item,
              config: item.type === 'custom' || item.type === 'action' ? {setting, columns: fields} : null,
              triggerLink: this.triggerLink,
              updateStatus: this.updateStatus
              triggerLink: this.triggerLink
            })
          }
        }
@@ -498,12 +496,6 @@
      return
    }
    MKEmitter.removeListener('resetTable', this.resetTable)
  }
  updateStatus = (type, positon, btn) => {
    if (type === 'refresh') {
      this.props.refreshbyaction(positon, btn)
    }
  }
  // 字段透视
@@ -803,8 +795,8 @@
          <Switch title="收起" className="main-pickup" checkedChildren="开" unCheckedChildren="关" defaultChecked={pickup} onChange={this.pickupChange} /> : null
        }
        <Table
          size="middle"
          components={components}
          size={setting.size || 'middle'}
          bordered={setting.bordered !== 'false'}
          rowSelection={rowSelection}
          columns={this.state.columns}
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -399,41 +399,38 @@
  }
  /**
   * @description 按钮操作完成后(成功或失败),页面刷新,重置页码及选择项
   */
  refreshbyaction = (position, btn) => {
    if (position === 'grid' || position === 'view') {
      this.reloadtable(btn)
    }
  }
  /**
   * @description 导出Excel时,获取页面搜索排序等参数
   */
  getexceloutparam = (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) { // 主表搜索条件
      let keys = searches.map(item => item.key.toLowerCase())
      mainSearch.forEach(item => {
        if (!keys.includes(item.key.toLowerCase())) {
          searches.push(item)
        }
      })
    }
    MKEmitter.emit('execExcelout', config.uuid, btnId, {
      arr_field: arr_field,
      orderBy: orderBy || setting.order,
      search: search,
      search: searches,
      menuName: config.name
    })
  }
  reloadData = (menuId, id, btn) => {
  reloadData = (menuId, id) => {
    const { config } = this.state
    if (config.uuid !== menuId) return
    if (id === 'empty') return
    if (id === 'formtab') { // 表单标签页刷新
      this.reloadtable(btn)
      return
    }
    if (!id) {
      this.reloadtable()
    } else {
@@ -454,6 +451,31 @@
        this.loadmaindata(true, 'true')
        this.getStatFieldsValue()
      })
    }
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { config, BID } = this.state
    if (config.uuid !== menuId) return
    this.reloadtable(btn)                                                      // 数据刷新
    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'))
    } else if (position === 'popclose') {                                      // 标签关闭刷新
      config.setting.supModule && MKEmitter.emit('reloadData', config.setting.supModule, (BID || 'empty'))
      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
  }
@@ -490,6 +512,7 @@
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
@@ -502,6 +525,7 @@
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  render() {
@@ -520,7 +544,6 @@
          BData={this.state.BData}
          columns={config.columns}
          selectedData={selectedData}
          refreshdata={this.refreshbyaction}
        />
        <div className={'main-table-box ' + (!actions || actions.length === 0 ? 'no-action' : '')}>
          <MainTable
@@ -534,7 +557,6 @@
            loading={this.state.loading}
            refreshdata={this.refreshbytable}
            statFValue={this.state.statFValue}
            refreshbyaction={this.refreshbyaction}
            chgSelectData={(selects) => this.setState({selectedData: selects})}
          />
        </div>
src/tabviews/custom/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Row, Col, Button, message } from 'antd'
import { notification, Spin, Row, Col } from 'antd'
import moment from 'moment'
import md5 from 'md5'
@@ -26,10 +26,13 @@
const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
const NormalTable = asyncComponent(() => import('./components/table/normal-table'))
const NormalGroup = asyncComponent(() => import('./components/group/normal-group'))
const SettingComponent = asyncComponent(() => import('@/tabviews/zshare/settingcomponent'))
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
class CustomPage extends Component {
  static propTpyes = {
    param: PropTypes.any,        // 其他页面传递的参数
    Tab: PropTypes.string,       // 弹窗标签
    MenuID: PropTypes.string,    // 菜单Id
    MenuNo: PropTypes.string,    // 菜单参数
    MenuName: PropTypes.string   // 菜单名称
@@ -49,7 +52,7 @@
    loading: false,       // 列表数据加载中
    visible: false,       // 标签页控制
    treevisible: false,   // 菜单结构树弹框显示隐藏控制
    debug: sessionStorage.getItem('debug') === 'true'
    shortcuts: null       // 快捷键
  }
  /**
@@ -66,7 +69,7 @@
    if (result.status) {
      let config = ''
      let userConfig = null
      let shortcuts = []
      try { // 配置信息解析
        config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
@@ -78,10 +81,15 @@
      // HS不使用自定义设置
      if (result.LongParamUser && this.props.menuType !== 'HS') {
        try { // 配置信息解析
          userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
          let userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
          if (userConfig) {
            shortcuts = userConfig.action
            userConfig.printers.forEach(item => {
              window.GLOB.UserCacheMap.set(item.parentId + item.uuid, item)
            })
          }
        } catch (e) {
          console.warn('Parse Failure')
          userConfig = null
        }
      }
@@ -153,7 +161,7 @@
      this.setState({
        BID: BID,
        userConfig: userConfig,
        shortcuts,
        config,
        mainSearch
      }, () => {
@@ -166,6 +174,10 @@
        } else {
          this.loadmaindata(params)
        }
        if (!this.props.Tab) {
          this.setShortcut()
        }
      })
    } else {
      this.setState({
@@ -176,6 +188,41 @@
        top: 92,
        message: result.message,
        duration: 5
      })
    }
  }
  setShortcut = () => {
    const { shortcuts } = this.state
    if (!shortcuts || shortcuts.length === 0) {
      document.onkeydown = () => {}
      return
    }
    document.onkeydown = (event) => {
      let e = event || window.event
      let keyCode = e.keyCode || e.which || e.charCode
      let preKey = ''
      if (e.ctrlKey) {
        preKey = 'ctrl'
      } else if (e.shiftKey) {
        preKey = 'shift'
      } else if (e.altKey) {
        preKey = 'alt'
      }
      if (!preKey || !keyCode) return
      let _shortcut = `${preKey}+${keyCode}`
      shortcuts.some(item => {
        if (item.$shortcut === _shortcut) {
          MKEmitter.emit('triggerBtnId', item.uuid)
          return true
        }
        return false
      })
    }
  }
@@ -248,90 +295,117 @@
      }
      // 权限过滤
      if (this.props.menuType !== 'HS') {
        if (item.action && item.action.length > 0) {
          item.action = item.action.filter(cell => {
            cell.logLabel = item.name + '-' + cell.label
            cell.ContainerId = this.state.ContainerId
            cell.$menuId = item.uuid
      let isHS = this.props.menuType === 'HS'
      let tabId = this.props.Tab ? this.props.Tab.uuid : '' // 弹窗标签按钮Id
      if (item.action && item.action.length > 0) {
        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.$menuId = item.uuid
          cell.$tabId = tabId
          cell.$type = 'CustomPage'
            return permAction[cell.uuid]
          })
        }
        if (item.type === 'card') {
          item.subcards.forEach(card => {
            let _hasheight = card.style.height && card.style.height !== 'auto'
          if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 打印机设置
            cell = this.getPrinter(cell, item.uuid)
          }
            if (card.style.shadow) { // 卡片阴影
              card.style.boxShadow = '0 0 4px ' + card.style.shadow
              delete card.style.shadow
            }
          return isHS || permAction[cell.uuid]
        })
      }
      if (item.type === 'card') {
        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.$menuId = item.uuid
              } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height && _hasheight) {
                cell.innerHeight = 'auto'
              }
          if (card.style.shadow) { // 卡片阴影
            card.style.boxShadow = '0 0 4px ' + card.style.shadow
            delete card.style.shadow
          }
              return cell.eleType !== 'button' || permAction[cell.uuid]
            })
            card.backElements = card.backElements.filter(cell => {
              if (cell.eleType === 'button') {
                cell.logLabel = item.name + '-' + cell.label
                cell.Ot = 'requiredSgl'
                cell.ContainerId = this.state.ContainerId
                cell.$menuId = item.uuid
              } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height && _hasheight) {
                cell.innerHeight = 'auto'
              }
              return cell.eleType !== 'button' || permAction[cell.uuid]
            })
          })
        } else if (item.type === 'table' && item.subtype === 'tablecard') {
          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.$menuId = item.uuid
              } else if (['text', 'number', 'link'].includes(cell.eleType) && !cell.height && _hasheight) {
                cell.innerHeight = 'auto'
              }
              return cell.eleType !== 'button' || permAction[cell.uuid]
            })
          })
        } else if (item.type === 'table' && item.subtype === 'normaltable') {
          item.cols = item.cols.filter(col => {
            if (col.type !== 'action') return true
            col.elements = col.elements.filter(cell => {
          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.$menuId = item.uuid
              cell.$tabId = tabId
              cell.$type = 'CustomPage'
              return permAction[cell.uuid]
            })
            return col.elements.length !== 0
              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 && _hasheight) {
              cell.innerHeight = 'auto'
            }
            return cell.eleType !== 'button' || isHS || permAction[cell.uuid]
          })
        }
      } else {
        if (item.action && item.action.length > 0) {
          item.action = item.action.map(cell => {
          card.backElements = card.backElements.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.$menuId = item.uuid
              cell.$tabId = tabId
              cell.$type = '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 && _hasheight) {
              cell.innerHeight = 'auto'
            }
            return cell.eleType !== 'button' || isHS || permAction[cell.uuid]
          })
        })
      } else if (item.type === 'table' && item.subtype === 'tablecard') {
        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.$menuId = item.uuid
              cell.$tabId = tabId
              cell.$type = '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 && _hasheight) {
              cell.innerHeight = 'auto'
            }
            return cell.eleType !== 'button' || isHS || permAction[cell.uuid]
          })
        })
      } else if (item.type === 'table' && item.subtype === 'normaltable') {
        item.cols = item.cols.filter(col => {
          if (col.type !== 'action') return true
          col.elements = col.elements.filter(cell => {
            cell.logLabel = item.name + '-' + cell.label
            cell.Ot = 'requiredSgl'
            cell.ContainerId = this.state.ContainerId
            cell.syncComponentId = cell.syncComponent ? cell.syncComponent.pop() : ''
            cell.$menuId = item.uuid
            return cell
            cell.$tabId = tabId
            cell.$type = 'CustomPage'
            if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 打印机设置
              cell = this.getPrinter(cell, item.uuid)
            }
            return isHS || permAction[cell.uuid]
          })
        }
      }
          return col.elements.length !== 0
        })
      }
      if (item.setting && item.setting.supModule) {
        let pid = item.setting.supModule.slice(-1)[0]
        let pid = item.setting.supModule.pop()
        if (pid && pid !== 'empty') {
          item.setting.supModule = pid
        } else {
@@ -349,6 +423,24 @@
    })
  }
  getPrinter = (item, parentId) => {
    let _item = window.GLOB.UserCacheMap.get(parentId + item.uuid)
    if (_item) {
      item.printer = _item.printer || ''
      item.verify.defaultPrinter = _item.printer || ''
      if (item.verify.printerTypeList && _item.printerList) {
        item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
          cell.printer = _item.printerList[cell.Value] || ''
          return cell
        })
      }
    }
    return item
  }
  getCols = (cols, roleId, permMenus) => {
    return cols.filter(col => {
      if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) {
@@ -364,7 +456,7 @@
      }
      if (col.linkmenu && col.linkmenu.length > 0) {
        let menu_id = col.linkmenu.slice(-1)[0]
        let menu_id = col.linkmenu.pop()
        col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      } else {
        col.linkThdMenu = ''
@@ -604,33 +696,20 @@
    })
  }
  handleviewconfig = (e) => {
    e.stopPropagation()
    const { MenuNo } = this.props
    const { config } = this.state
    if (config && config.funcs && config.funcs.length > 0) {
      this.setState({
        treevisible: true
      })
    } else {
      let oInput = document.createElement('input')
      oInput.value = MenuNo || ''
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      document.body.removeChild(oInput)
      message.success(this.state.dict['main.copy.success'])
    }
  }
  reloadMenuView = (menuId) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    this.reloadview()
  }
  resetActiveMenu = (menuId) => {
    const { MenuID, Tab } = this.props
    if (MenuID !== menuId || Tab) return
    this.setShortcut()
  }
  UNSAFE_componentWillMount () {
@@ -644,6 +723,7 @@
  componentDidMount () {
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu)
  }
  /**
@@ -654,6 +734,7 @@
      return
    }
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu)
  }
  reloadview = () => {
@@ -662,7 +743,8 @@
      loadingview: true,    // 页面加载中
      viewlost: false,      // 页面丢失:1、未获取到配置-页面丢失;2、页面未启用
      config: null,         // 页面配置信息,包括组件等
      loading: false        // 列表数据加载中
      loading: false,       // 列表数据加载中
      shortcuts: null
    }, () => {
      this.loadconfig()
    })
@@ -747,19 +829,15 @@
  }
  render() {
    const { menuType, MenuNo } = this.props
    const { debug, loadingview, viewlost, config, loading } = this.state
    const { menuType } = this.props
    const { loadingview, viewlost, config, loading, shortcuts } = this.state
    return (
      <div className={'custom-page-wrap ' + (loadingview || loading ? 'loading' : '')} id={this.state.ContainerId} style={config ? config.style : null}>
        {(loadingview || loading) ? <Spin className="view-spin" size="large" /> : null}
        <Row>{this.getComponents()}</Row>
        {debug && MenuNo && options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="common-table-copy"
          onClick={this.handleviewconfig}
        /> : null}
        {menuType !== 'HS' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {menuType !== 'HS' && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
src/tabviews/formtab/index.jsx
@@ -16,11 +16,12 @@
import FormGroup from './formgroup'
import FormAction from './actionList'
import NotFount from '@/components/404'
import {modifyTabview} from '@/store/action'
import { modifyTabview } from '@/store/action'
import './index.scss'
const { TabPane } = Tabs
const SubTable = asyncComponent(() => import('@/tabviews/subtable'))
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
class NormalTable extends Component {
  static propTpyes = {
@@ -689,6 +690,7 @@
            )
          })
        }
        {this.props.menuType !== 'HS' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
src/tabviews/iframe/index.jsx
@@ -1,16 +1,74 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Button, message } from 'antd'
import MKEmitter from '@/utils/events.js'
import mzhCN from '@/locales/zh-CN/main.js'
import menUS from '@/locales/en-US/main.js'
class Iframe extends Component {
  static propTypes = {
    title: PropTypes.string,
    MenuID: PropTypes.string,    // 菜单Id
    MenuNo: PropTypes.string,    // 菜单参数
    url: PropTypes.string
  }
  state = {
    visible: true,
    dict: localStorage.getItem('lang') !== 'en-US' ? mzhCN : menUS,
    debug: sessionStorage.getItem('debug') === 'true'
  }
  componentDidMount () {
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
  }
  reloadMenuView = (menuId) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    this.setState({visible: false}, () => {
      this.setState({visible: true})
    })
  }
  copyMenuNo = (e) => {
    const { MenuNo } = this.props
    e.stopPropagation()
    let oInput = document.createElement('input')
    oInput.value = MenuNo || ''
    document.body.appendChild(oInput)
    oInput.select()
    document.execCommand('Copy')
    oInput.className = 'oInput'
    oInput.style.display = 'none'
    message.success(this.state.dict['main.copy.success'])
  }
  render () {
    return (
      <iframe title={this.props.title} src={this.props.url} />
    )
    const { visible, debug } = this.state
    return (<div>
      {visible ? <iframe title={this.props.title} src={this.props.url} /> : null}
      {debug ? <Button
        icon="copy"
        shape="circle"
        className={'main-copy ifr-copy'}
        onClick={this.copyMenuNo}
      /> : null}
    </div>)
  }
}
src/tabviews/rolemanage/index.jsx
@@ -5,6 +5,7 @@
import Api from '@/api'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import zhCN from '@/locales/zh-CN/main.js'
import enUS from '@/locales/en-US/main.js'
import './index.scss'
@@ -474,9 +475,38 @@
    })
  }
  reloadMenuView = (menuId) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    this.setState({
      loading: true,
      loadingTree: false,
      roleList: null,
      selectRoleId: '',
      mainMenus: null,
      menuTrees: null,
      checkedKeys: [],
      menuOpenKeys: [],
      selectMenuTrees: null,
      selectMenuOpenKeys: [],
      primarykey: '',
      tabKey: '',
      submitloading: false,
      initCheckKeys: null
    })
    this.getRoleList()
    this.getMainMenuList()
  }
  UNSAFE_componentWillMount () {
    this.getRoleList()
    this.getMainMenuList()
  }
  componentDidMount () {
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
  }
  /**
@@ -486,6 +516,7 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
  }
  shouldComponentUpdate (nextProps, nextState) {
src/tabviews/scriptmanage/index.jsx
@@ -12,11 +12,12 @@
import { scriptMainTable, buttonConfig } from './config'
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncSpinComponent from '@/utils/asyncSpinComponent'
import TopSearch from './topSearch'
import MainAction from './actionList'
import './index.scss'
const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
const MainTable = asyncSpinComponent(() => import('@/tabviews/zshare/normalTable'))
class ScriptTable extends Component {
@@ -85,8 +86,10 @@
            subcols.push(colMap.get(sub))
          }
        })
        _col.subcols = subcols
        _columns.push(_col)
        if (subcols.length > 0) {
          _col.subcols = subcols
          _columns.push(_col)
        }
      } else {
        _columns.push(col)
      }
@@ -283,9 +286,21 @@
    })
  }
  reloadMenuView = (menuId) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    this.reloadview()
  }
  UNSAFE_componentWillMount () {
    // 组件加载时,获取菜单数据
    this.loadconfig()
  }
  componentDidMount () {
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -299,18 +314,15 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
  }
  render() {
    const { dict, searchlist, setting, actions, columns, pickup, selectedData } = this.state
    const { searchlist, setting, actions, columns, pickup, selectedData } = this.state
    return (
      <div className="script-manage-table" id={this.state.ContainerId}>
        <TopSearch
          dict={dict}
          searchlist={searchlist}
          refreshdata={this.refreshbysearch}
        />
        <MainSearch searchlist={searchlist} menuType="HS" refreshdata={this.refreshbysearch}/>
        <MainAction
          BID=""
          type="main"
src/tabviews/scriptmanage/topSearch/index.jsx
File was deleted
src/tabviews/scriptmanage/topSearch/index.scss
File was deleted
src/tabviews/subtable/index.jsx
@@ -35,7 +35,6 @@
    mainSearch: PropTypes.any,       // 主表搜索条件
    ContainerId: PropTypes.any,      // 三级菜单Container(html) ID
    handleTableId: PropTypes.func,   // 控制表格数据切换时,更新在主表中的id
    userConfig: PropTypes.any,       // 用户自定义设置
  }
  state = {
@@ -49,7 +48,7 @@
    columns: null,        // 显示列
    arr_field: '',        // 使用 sPC_Get_TableData 时的查询字段集
    setting: null,        // 页面全局设置:数据源、按钮及显示列固定、主键等
    data: null,           // 列表数据集
    data: [],             // 列表数据集
    selectedData: [],     // 已选表格数据
    total: 0,             // 总数
    loading: false,       // 列表数据加载中
@@ -92,7 +91,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, permMenus, Tab, BID, userConfig } = this.props
    const { permAction, permMenus, Tab, BID } = this.props
    let param = {
      func: 'sPC_Get_LongParam',
@@ -176,28 +175,6 @@
      let chartId = config.charts[0] ? config.charts[0].uuid : ''
      if (userConfig) {
        config.action = config.action.map(item => {
          if (userConfig.action[item.uuid]) {
            delete userConfig.action[item.uuid].label
            item = {...item, ...userConfig.action[item.uuid]}
          }
          if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify && item.printer) {
            item.verify.defaultPrinter = item.printer.defaultPrinter || ''
            if (item.verify.printerTypeList && item.printer.printerList) {
              item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                cell.printer = item.printer.printerList[cell.Value] || ''
                return cell
              })
            }
          }
          return item
        })
      }
      // 1、筛选字段集,2、过滤隐藏列及合并列中的字段uuid
      config.columns.forEach(col => {
        if (col.field) {
@@ -242,8 +219,10 @@
              subcols.push(colMap.get(sub))
            }
          })
          _col.subcols = subcols
          _columns.push(_col)
          if (subcols.length > 0) {
            _col.subcols = subcols
            _columns.push(_col)
          }
        } else {
          _columns.push(col)
        }
@@ -256,6 +235,20 @@
        item.logLabel = Tab.label + '-' + item.label // 用于sPC_TableData_InUpDe记录操作按钮
        item.$menuId = this.props.MenuID
        if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify) { // 打印机设置
          let _item = window.GLOB.UserCacheMap.get(Tab.uuid + item.uuid)
          if (_item) {
            item.verify.defaultPrinter = _item.printer || ''
            if (item.verify.printerTypeList && _item.printerList) {
              item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                cell.printer = _item.printerList[cell.Value] || ''
                return cell
              })
            }
          }
        }
        if (item.position === 'toolbar') {
          _actions.push(item)
        } else if (item.position === 'grid') {
@@ -274,22 +267,6 @@
          valid = false
        }
      })
      // 添加用户显示列设置
      if (userConfig) {
        _columns = _columns.map(item => {
          if (userConfig.columns[item.uuid]) {
            delete userConfig.columns[item.uuid].label
            item = {...item, ...userConfig.columns[item.uuid]}
          }
          return item
        })
        _columns.sort((pre, next) => {
          return pre.sort - next.sort
        })
      }
      config.setting.tabType = 'sub'
      // 数据源信息预处理
@@ -428,6 +405,9 @@
            })
          }
          item.key = index
          item.$$uuid = item[setting.primaryKey] || ''
          item.$$BID = _BID || ''
          return item
        }),
        total: result.total,
@@ -489,6 +469,9 @@
          data = data.map(item => {
            if (item[setting.primaryKey] === _data[setting.primaryKey]) {
              _data.key = item.key
              _data.$$uuid = _data[setting.primaryKey] || ''
              _data.$$BID = BID || ''
              return _data
            } else {
              return item
@@ -642,31 +625,6 @@
  }
  /**
   * @description 按钮操作完成后(成功或失败),页面刷新,重置页码及选择项
   */
  refreshbyaction = (position, btn) => {
    const { Tab, SupMenuID, BID } = this.props
    if (position === 'grid' || position === 'view') {
      this.reloadtable(btn)
    } else if (position === 'maingrid' || position === 'mainline') {
      this.reloadtable(btn)
      if (Tab.supMenu === 'mainTable') {
        MKEmitter.emit('reloadData', SupMenuID, (BID || 'empty'))   // 主表重置
      } else if (Tab.supMenu) {
        MKEmitter.emit('reloadData', Tab.supMenu, (BID || 'empty')) // 主表重置
      } else if (!Tab.supMenu && Tab.level === 0) {
        MKEmitter.emit('reloadData', SupMenuID, (BID || 'empty'))   // 树形结构,0级标签
      }
    } else if (position === 'equaltab') {
      this.reloadtable(btn)
      if (Tab.equalTab && Tab.equalTab.length > 0) {
        MKEmitter.emit('reloadData', Tab.equalTab.join(',')) // 同级标签重置
      }
    }
  }
  /**
   * @description 导出Excel时,获取页面搜索排序等参数
   */
  getexceloutparam = (menuId, btnId) => {
@@ -720,7 +678,7 @@
    this.setState({chartId: uuid})
  }
  reloadData = (menuId, id) => {
  reloadData = (menuId, id) => { // Id存在时,刷新行
    const { MenuID } = this.props
    if (menuId.indexOf(MenuID) === -1) return
@@ -730,6 +688,38 @@
      this.reloadtable()
    } else {
      this.loadmainLinedata(id)
    }
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    const { Tab, SupMenuID, BID } = this.props
    if (position === 'grid' || position === 'view') {
      this.reloadtable(btn)
    } else if (position === 'maingrid' || position === 'mainline') {
      this.reloadtable(btn)
      if (Tab.supMenu === 'mainTable') {
        MKEmitter.emit('reloadData', SupMenuID, (BID || 'empty'))   // 主表重置
      } else if (Tab.supMenu) {
        MKEmitter.emit('reloadData', Tab.supMenu, (BID || 'empty')) // 主表重置
      } else if (!Tab.supMenu && Tab.level === 0) {
        MKEmitter.emit('reloadData', SupMenuID, (BID || 'empty'))   // 树形结构,0级标签
      }
    } else if (position === 'equaltab') {
      this.reloadtable(btn)
      if (Tab.equalTab && Tab.equalTab.length > 0) {
        MKEmitter.emit('reloadData', Tab.equalTab.join(',')) // 同级标签重置
      }
    }
  }
@@ -745,6 +735,7 @@
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
@@ -756,6 +747,7 @@
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  render() {
@@ -790,7 +782,6 @@
                      BData={this.props.BData}
                      MenuID={this.props.MenuID}
                      selectedData={selectedData}
                      refreshdata={this.refreshbyaction}
                      ContainerId={this.props.ContainerId}
                    />
                  </div>
@@ -804,18 +795,16 @@
                      setting={setting}
                      columns={columns}
                      pageSize={pageSize}
                      BID={this.props.BID}
                      dict={this.state.dict}
                      data={this.state.data}
                      BData={this.props.BData}
                      total={this.state.total}
                      MenuID={this.props.MenuID}
                      loading={this.state.loading}
                      refreshdata={this.refreshbytable}
                      statFValue={this.state.statFValue}
                      handleTableId={this.handleTableId}
                      ContainerId={this.props.ContainerId}
                      refreshbyaction={this.refreshbyaction}
                      refreshdata={this.refreshbytable}
                      handleTableId={this.handleTableId}
                      chgSelectData={this.changeSelectedData}
                    />
                  </div>
@@ -835,7 +824,6 @@
                    MenuID={this.props.MenuID}
                    loading={this.state.loading}
                    tableId={this.props.Tab.uuid}
                    refreshdata={this.refreshbyaction}
                    handleTableId={this.handleTableId}
                  />
                </Col>
src/tabviews/subtabtable/index.jsx
@@ -26,15 +26,12 @@
class SubTabModalTable extends Component {
  static propTpyes = {
    type: PropTypes.any,             // 类型,calendar需特殊处理
    Tab: PropTypes.any,              // 日历标签信息或标签按钮信息
    BID: PropTypes.string,           // 上级数据ID
    BData: PropTypes.any,            // 上级数据
    MenuID: PropTypes.string,        // 菜单Id
    mainSearch: PropTypes.any,       // 主表搜索条件
    SupMenuID: PropTypes.string,     // 上级菜单Id
    refreshSupView: PropTypes.any,   // 刷新上级菜单
    closeModalView: PropTypes.any    // 关闭模态框
  }
  state = {
@@ -48,7 +45,7 @@
    columns: null,        // 显示列
    arr_field: '',        // 使用 sPC_Get_TableData 时的查询字段集
    setting: null,        // 页面全局设置:数据源、按钮及显示列固定、主键等
    data: null,           // 列表数据集
    data: [],             // 列表数据集
    selectedData: [],     // 已选表格数据
    total: 0,             // 总数
    loading: false,       // 列表数据加载中
@@ -66,7 +63,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, type, Tab } = this.props
    const { permAction, Tab } = this.props
    let param = {
      func: 'sPC_Get_LongParam',
@@ -112,26 +109,15 @@
      // 版本兼容
      config = UtilsUpdate.updateSubTable(config)
      // 仅支持exec、prompt、pop 三种类型按钮
      // 不支持funcbutton、popview 类型按钮
      let labels = []
      if (type === 'calendar') {
        config.action = config.action.filter(item => {
          if (['exec', 'prompt', 'pop', 'tab', 'excelIn', 'excelOut'].includes(item.OpenType)) return true
      config.action = config.action.filter(item => {
        if (['exec', 'prompt', 'pop', 'tab', 'excelIn', 'excelOut', 'innerpage'].includes(item.OpenType)) return true
          labels.push(item.label)
        labels.push(item.label)
          return false
        })
      } else {
        config.action = config.action.filter(item => {
          if (['exec', 'prompt', 'pop'].includes(item.OpenType)) return true
          labels.push(item.label)
          return false
        })
      }
        return false
      })
      if (window.GLOB.systemType !== 'production' && labels.length > 0) {
        notification.warning({
@@ -217,8 +203,10 @@
              subcols.push(colMap.get(sub))
            }
          })
          _col.subcols = subcols
          _columns.push(_col)
          if (subcols.length > 0) {
            _col.subcols = subcols
            _columns.push(_col)
          }
        } else {
          _columns.push(col)
        }
@@ -370,6 +358,9 @@
            })
          }
          item.key = index
          item.$$uuid = item[setting.primaryKey] || ''
          item.$$BID = BID || ''
          return item
        }),
        total: result.total,
@@ -510,18 +501,6 @@
  }
  /**
   * @description 按钮操作完成后(成功或失败),页面刷新,重置页码及选择项
   */
  refreshbyaction = (position, btn) => {
    if (position === 'grid' || position === 'view' || position === 'maingrid') {
      this.reloadtable(btn)
      this.props.refreshSupView()
    } else if (position === 'trigger') { // 日历子表触发标签点击事件
      this.props.closeModalView && this.props.closeModalView()
    }
  }
  /**
   * @description 导出Excel时,获取页面搜索排序等参数
   */
  getexceloutparam = (menuId, btnId) => {
@@ -544,6 +523,21 @@
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    this.reloadtable(btn)
    MKEmitter.emit('refreshPopButton', this.props.Tab.uuid)
  }
  /**
   * @description 图表视图切换
   */
  changeChart = (uuid) => {
@@ -561,6 +555,7 @@
  componentDidMount () {
    MKEmitter.addListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
@@ -571,6 +566,7 @@
      return
    }
    MKEmitter.removeListener('getexceloutparam', this.getexceloutparam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  render() {
@@ -606,7 +602,6 @@
                      BData={this.props.BData}
                      selectedData={selectedData}
                      MenuID={this.props.SupMenuID}
                      refreshdata={this.refreshbyaction}
                    />
                  </div>
                  <SubTable
@@ -614,7 +609,6 @@
                    setting={setting}
                    columns={columns}
                    pageSize={pageSize}
                    BID={this.props.BID}
                    data={this.state.data}
                    dict={this.state.dict}
                    BData={this.props.BData}
@@ -623,7 +617,6 @@
                    loading={this.state.loading}
                    refreshdata={this.refreshbytable}
                    statFValue={this.state.statFValue}
                    refreshbyaction={this.refreshbyaction}
                    chgSelectData={this.changeSelectedData}
                    handleTableId={() => {}}
                  />
@@ -641,7 +634,6 @@
                    data={this.state.data}
                    BData={this.props.BData}
                    loading={this.state.loading}
                    refreshdata={this.refreshbyaction}
                    handleTableId={() => {}}
                  />
                </Col>
src/tabviews/tabmanage/index.jsx
@@ -8,6 +8,7 @@
import zhCN from '@/locales/zh-CN/main.js'
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import TransferForm from './transferform'
import MutilForm from './mutilform'
import subtableurl from '@/assets/img/subtable.jpg'
@@ -83,6 +84,7 @@
  componentDidMount () {
    this.getTabs()
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -96,6 +98,25 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
  }
  reloadMenuView = (menuId) => {
    const { MenuID } = this.props
    if (MenuID !== menuId) return
    this.setState({
      searchKey: '',
      tabviews: null,
      loading: true,
      modaltype: '',
      editTab: null,
      submitloading: false,
      thawVisible: false,
      thawmenulist: null
    })
    this.getTabs()
  }
  handleTab = (tab, type) => {
src/tabviews/treepage/index.jsx
@@ -2,10 +2,9 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Tabs, Icon, Modal, Button, message, Tree, Typography, Row, Col, Card, Input, Empty } from 'antd'
import { notification, Spin, Tabs, Icon, Tree, Row, Col, Card, Input, Empty } from 'antd'
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'
@@ -16,13 +15,13 @@
import NotFount from '@/components/404'
import './index.scss'
const VerifyCard = asyncComponent(() => import('@/tabviews/zshare/verifycard'))
const SubTable = asyncSpinComponent(() => import('@/tabviews/subtable'))
const SettingComponent = asyncComponent(() => import('@/tabviews/zshare/settingcomponent'))
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
const { TabPane } = Tabs
const { TreeNode } = Tree
const { Search } = Input
const { Paragraph } = Typography
class TreePage extends Component {
  static propTpyes = {
@@ -40,22 +39,17 @@
    viewlost: false,      // 页面丢失:1、未获取到配置-页面丢失;2、页面未启用
    lostmsg: '',          // 页面丢失时的提示信息
    config: {},           // 页面配置信息,包括按钮、搜索、显示列、标签等
    userConfig: null,     // 用户自定义设置
    userParam: null,      // 保存用户编辑中的配置
    setting: null,        // 页面全局设置:数据源、按钮及显示列固定、主键等
    treedata: null,       // 列表数据集
    treeNodes: null,      // 列表数据集
    loading: false,       // 列表数据加载中
    BIDs: {},             // 上级表id
    visible: false,       // 弹框显示隐藏控制
    treevisible: false,   // 菜单结构树弹框显示隐藏控制
    confirmLoading: false,// 自定义设置模态框加载中
    revertLoading: false, // 恢复默认设置
    settingVisible: false,// 自定义设置模态框
    tabActive: null,      // 标签页展开控制
    expandedKeys: [],     // 展开的树节点
    selectedKeys: [],     // 选中的树节点
    debug: sessionStorage.getItem('debug') === 'true'
    shortcuts: null       // 快捷键
  }
  /**
@@ -72,11 +66,12 @@
    if (result.status) {
      let config = ''
      let userConfig = null
      let _curUserConfig = ''
      let shortcuts = []
      try { // 配置信息解析
        config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
        config.MenuID = this.props.MenuID
        config.MenuName = this.props.MenuName
      } catch (e) {
        console.warn('Parse Failure')
        config = ''
@@ -84,11 +79,15 @@
      
      if (result.LongParamUser) {
        try { // 配置信息解析
          userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
          _curUserConfig = userConfig[this.props.MenuID]
          let userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
          if (userConfig) {
            shortcuts = userConfig.action
            userConfig.printers.forEach(item => {
              window.GLOB.UserCacheMap.set(item.parentId + item.uuid, item)
            })
          }
        } catch (e) {
          console.warn('Parse Failure')
          userConfig = null
        }
      }
@@ -121,12 +120,6 @@
        )
      })
      if (_curUserConfig) {
        config.setting = {...config.setting, ..._curUserConfig.setting}
        config.easyCode = _curUserConfig.easyCode || config.easyCode || ''
      }
      let _tabActive = {} // 筛选展开的tab页
      let _tabgroups = []
      config.tabgroups.forEach(group => {
@@ -134,7 +127,6 @@
        _group.sublist = _group.sublist.filter(tab => tab.level === 0)
        if (_group.sublist.length > 0) {
          _tabActive[_group.uuid] = _group.sublist[0].uuid
          _tabgroups.push(_group)
        }
      })
@@ -185,10 +177,9 @@
        BID: param && param.BID ? param.BID : '',
        loadingview: false,
        config: config,
        tabActive: _tabActive,
        userConfig: userConfig,
        setting: config.setting,
        tabgroups: _tabgroups
        tabgroups: _tabgroups,
        shortcuts
      }, () => {
        this.loadmaindata()
        this.setShortcut()
@@ -207,8 +198,12 @@
  }
  setShortcut = () => {
    const { userConfig, config } = this.state
    if (!userConfig) return
    const { shortcuts } = this.state
    if (!shortcuts || shortcuts.length === 0) {
      document.onkeydown = () => {}
      return
    }
    document.onkeydown = (event) => {
      let e = event || window.event
@@ -223,45 +218,21 @@
        preKey = 'alt'
      }
      if (!preKey) return
      if (!preKey || !keyCode) return
      let triggerId = ''
      let _shortcut = `${preKey}+${keyCode}`
      Object.keys(userConfig).some(key => {
        if (key === this.props.MenuID || !userConfig[key].action) return false
      shortcuts.some(item => {
        if (item.$shortcut === _shortcut) {
          MKEmitter.emit('triggerBtnId', item.uuid)
        let _actions = userConfig[key].action
        Object.keys(_actions).some(btnkey => {
          let item = _actions[btnkey]
          if (Array.isArray(item.shortcut) && preKey === item.shortcut[0] && keyCode === item.shortcut[1]) {
            e.preventDefault()
            triggerId = btnkey
            let _groupId = ''
            let _ActiveTabId = ''
            config.tabgroups.forEach(group => {
              let _tab = group.sublist.filter(tab => tab.uuid === key)[0]
              if (!_tab) return
              _groupId = group.uuid
              _ActiveTabId = _tab.uuid
            })
            this.setState({
              tabActive: {...this.state.tabActive, [_groupId]: _ActiveTabId}
            }, () => {
              MKEmitter.emit('triggerBtnId', triggerId)
            })
            return true
          let element = item.parentId ? document.getElementById(item.parentId) : '' // 标签切换
          if (element && element.click) {
            element.click()
          }
          return false
        })
        if (triggerId) return true
          return true
        }
        return false
      })
    }
@@ -431,14 +402,12 @@
    if (selected) {
      let _tabgroups = []
      let _tabActive = {}
      config.tabgroups.forEach(group => {
        let _group = fromJS(group).toJS()
        _group.sublist = _group.sublist.filter(tab => (!tab.level && tab.level !== 0) || tab.level === _data.level)
        if (_group.sublist.length > 0) {
          _tabActive[_group.uuid] = _group.sublist[0].uuid
          _tabgroups.push(_group)
        }
      })
@@ -447,7 +416,6 @@
      this.handleTableId('mainTable', _data.key, _data)
      this.setState({
        tabgroups: _tabgroups,
        tabActive: _tabActive,
        expandedKeys: _expandedKeys,
        selectedKeys: [_data.key]
      })
@@ -467,12 +435,12 @@
      loadingview: true,
      viewlost: false,
      config: {},
      userConfig: null,
      setting: null,
      treedata: null,
      treeNodes: null,
      loading: false,
      BIDs: {},
      shortcuts: null,
      expandedKeys: [],
      selectedKeys: []
    }, () => {
@@ -492,158 +460,6 @@
        [type]: id,
        [type + 'data']: data
      }
    })
  }
  handleviewconfig = (e) => {
    e.stopPropagation()
    const { MenuNo } = this.props
    const { config } = this.state
    if (config && config.funcs && config.funcs.length > 0) {
      this.setState({
        treevisible: true
      })
    } else {
      let oInput = document.createElement('input')
      oInput.value = MenuNo || ''
      document.body.appendChild(oInput)
      oInput.select()
      document.execCommand('Copy')
      document.body.removeChild(oInput)
      message.success(this.state.dict['main.copy.success'])
    }
  }
  getTreeNode = (data) => {
    let _type = {
      view: '页面',
      btn: '按钮',
      tab: '标签'
    }
    return data.map(item => {
      let _title = _type[item.subtype]
      let _others = []
      _others.push(
        (item.menuNo ? item.menuNo + '(菜单参数)' : ''),
        (item.tableName ? item.tableName + '(表名) ' : ''),
        (item.innerFunc ? item.innerFunc + '(内部函数) ' : ''),
        (item.outerFunc ? item.outerFunc + '(外部函数)' : '')
      )
      _others = _others.filter(Boolean)
      _others = _others.join('、')
      if (item.label) {
        _title = _title + '(' + item.label + ')'
      }
      if (_others) {
        _title = _title + ': ' + _others
      }
      if (item.subfuncs && item.subfuncs.length > 0) {
        return (
          <TreeNode title={_title} key={item.uuid} dataRef={item} selectable={false}>
            {this.getTreeNode(item.subfuncs)}
          </TreeNode>
        )
      }
      return <TreeNode key={item.uuid} title={_title} isLeaf selectable={false} />
    })
  }
  controlCustomSetting = () => {
    this.setState({
      settingVisible: true,
      confirmLoading: false,
      revertLoading: false
    })
  }
  changeMenuParam = (param) => {
    this.setState({userParam: param})
  }
  settingRevert = () => {
    let param = {
      func: 's_TrdMenu_UserParam_del',
      MenuID: this.props.MenuID
    }
    this.setState({
      revertLoading: true
    })
    Api.getSystemConfig(param).then(result => {
      if (!result.status) {
        this.setState({
          revertLoading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
        return
      }
      this.setState({
        settingVisible: false,
        revertLoading: false
      }, () => {
        window.GLOB.CacheMap = new Map()
        this.reloadview()
      })
    })
  }
  settingSubmit = () => {
    const { userParam } = this.state
    let _LongParam = ''
    try {
      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(userParam)))
    } catch (e) {
      notification.warning({
        top: 92,
        message: '编译错误',
        duration: 5
      })
      return
    }
    let easyCode = userParam[this.props.MenuID] ? userParam[this.props.MenuID].easyCode : ''
    let param = {
      func: 'sPC_TrdMenu_UserParam',
      MenuID: this.props.MenuID,
      EasyCode: easyCode || '',
      LongParam: _LongParam
    }
    this.setState({
      confirmLoading: true
    })
    Api.getSystemConfig(param).then(result => {
      if (!result.status) {
        this.setState({
          confirmLoading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
        return
      }
      this.setState({
        settingVisible: false,
        confirmLoading: false
      }, () => {
        window.GLOB.CacheMap = new Map()
        this.reloadview()
      })
    })
  }
@@ -730,7 +546,7 @@
  render() {
    const { menuType } = this.props
    const { debug, setting, loadingview, viewlost, config, userConfig, tabActive, tabgroups, treeNodes, treedata, expandedKeys, selectedKeys } = this.state
    const { setting, loadingview, viewlost, config, tabgroups, treeNodes, treedata, expandedKeys, selectedKeys, shortcuts } = this.state
    return (
      <div className="tree-page" id={this.state.ContainerId}>
@@ -767,11 +583,11 @@
          </Col>
          <Col span={24 - setting.width}>
            {tabgroups.map(group => (
              <Tabs activeKey={tabActive[group.uuid]} key={group.uuid} onChange={(key) => this.setState({tabActive: {...tabActive, [group.uuid]: key}})}>
              <Tabs key={group.uuid} >
                {group.sublist.map(_tab => {
                  return (
                    <TabPane tab={
                      <span>
                      <span id={_tab.uuid}>
                        {_tab.icon ? <Icon type={_tab.icon} /> : null}
                        {_tab.label}
                      </span>
@@ -781,7 +597,6 @@
                          Tab={_tab}
                          MenuID={_tab.linkTab}
                          mainSearch={null}
                          userConfig={userConfig ? userConfig[_tab.uuid] : null}
                          SupMenuID={this.props.MenuID}
                          ContainerId={this.state.ContainerId}
                          BID={this.state.BIDs[_tab.supMenu] || ''}
@@ -795,59 +610,8 @@
            )}
          </Col>
        </Row> : null}
        {debug && options.sysType !== 'cloud' && menuType !== 'HS' ? <Button
          icon="copy"
          shape="circle"
          className="tree-page-copy"
          onClick={this.handleviewconfig}
        /> : null}
        <Modal
          className="menu-tree-modal"
          title={'菜单结构树'}
          width={'650px'}
          maskClosable={false}
          visible={this.state.treevisible}
          onCancel={() => this.setState({treevisible: false})}
          footer={[
            <Button key="close" onClick={() => this.setState({treevisible: false})}>{this.state.dict['main.close']}</Button>
          ]}
          destroyOnClose
        >
          <div className="menu-header">
            <span>菜单名称:{this.props.MenuName}</span>
            <span>菜单参数:{<Paragraph copyable>{this.props.MenuNo}</Paragraph>}</span>
          </div>
          {this.state.treevisible ? <Tree defaultExpandAll showLine={true}>
            {this.getTreeNode(config.funcs)}
          </Tree> : null}
        </Modal>
        {/* 按钮使用系统存储过程时,验证信息模态框 */}
        <Modal
          wrapClassName="common-table-custom-modal"
          title={'自定义设置'}
          maskClosable={false}
          width={950}
          visible={this.state.settingVisible}
          onCancel={() => { this.setState({ settingVisible: false }) }}
          footer={[
            <Button key="revert" type="danger" loading={this.state.revertLoading} onClick={this.settingRevert}>{this.state.dict['main.revert.default']}</Button>,
            <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['main.cancel']}</Button>,
            <Button key="confirm" type="primary" loading={this.state.confirmLoading} onClick={this.settingSubmit}>{this.state.dict['main.submit']}</Button>
          ]}
          destroyOnClose
        >
          {this.state.settingVisible ?
            <VerifyCard
              MenuID={this.props.MenuID}
              MenuName={this.props.MenuName}
              permAction={this.props.permAction}
              config={this.state.config}
              userConfig={this.state.userConfig}
              columns={[]}
              handleParam={this.changeMenuParam}
            /> : null
          }
        </Modal>
        {menuType !== 'HS' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {menuType !== 'HS' && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
src/tabviews/treepage/index.scss
@@ -149,25 +149,6 @@
  }
}
.menu-tree-modal {
  .ant-modal-body {
    min-height: 300px;
    .menu-header {
      text-align: center;
      span {
        font-weight: 600;
        margin-right: 20px;
      }
      .ant-typography {
        font-weight: 600;
        display: inline-block;
      }
    }
    .ant-tree li .ant-tree-node-content-wrapper {
      cursor: default;
    }
  }
}
.common-table-custom-modal {
  .ant-modal {
    top: 50px;
src/tabviews/verupmanage/index.jsx
@@ -9,15 +9,16 @@
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import options from '@/store/options.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncSpinComponent from '@/utils/asyncSpinComponent'
import { verupMainTable, buttonConfig } from './config'
import MKEmitter from '@/utils/events.js'
import TopSearch from './topSearch'
import MainAction from './actionList'
import './index.scss'
const SubTable = asyncSpinComponent(() => import('./subtabtable'))
const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
const MainTable = asyncSpinComponent(() => import('@/tabviews/zshare/normalTable'))
const { TabPane } = Tabs
@@ -90,8 +91,10 @@
            subcols.push(colMap.get(sub))
          }
        })
        _col.subcols = subcols
        _columns.push(_col)
        if (subcols.length > 0) {
          _col.subcols = subcols
          _columns.push(_col)
        }
      } else {
        _columns.push(col)
      }
@@ -455,15 +458,11 @@
  }
  render() {
    const { dict, searchlist, setting, actions, columns, pickup, config, selectedData } = this.state
    const { searchlist, setting, actions, columns, pickup, config, selectedData } = this.state
    return (
      <div className="veruptable" id={this.state.ContainerId}>
        <TopSearch
          dict={dict}
          searchlist={searchlist}
          refreshdata={this.refreshbysearch}
        />
        <MainSearch searchlist={searchlist} menuType="HS" refreshdata={this.refreshbysearch}/>
        <MainAction
          BID=""
          type="main"
src/tabviews/verupmanage/subtabtable/index.jsx
@@ -12,12 +12,13 @@
import { buttonConfig, tabConfig } from '../config'
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncSpinComponent from '@/utils/asyncSpinComponent'
import SubAction from '../actionList'
import SubSearch from '../topSearch'
import './index.scss'
const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
const SubTable = asyncSpinComponent(() => import('@/tabviews/zshare/normalTable'))
class VerupSubTabViewTable extends Component {
@@ -112,8 +113,10 @@
            subcols.push(colMap.get(sub))
          }
        })
        _col.subcols = subcols
        _columns.push(_col)
        if (subcols.length > 0) {
          _col.subcols = subcols
          _columns.push(_col)
        }
      } else {
        _columns.push(col)
      }
@@ -180,6 +183,7 @@
      this.setState({
        data: result.data.map((item, index) => {
          item.key = index
          item.$$BID = _BID || ''
          return item
        }),
        total: result.total,
@@ -439,12 +443,8 @@
    return (
      <div className="verup-subtable" id={'subtable' + this.props.MenuID}>
        {searchlist && searchlist.length > 0 ?
          <SubSearch
            dict={this.state.dict}
            searchlist={searchlist}
            refreshdata={this.refreshbysearch}
          /> : null
        {searchlist && searchlist.length ?
          <MainSearch searchlist={searchlist} menuType="HS" refreshdata={this.refreshbysearch}/> : null
        }
        {actions ?
          <div className="sub-action">
src/tabviews/verupmanage/topSearch/index.jsx
File was deleted
src/tabviews/verupmanage/topSearch/index.scss
File was deleted
src/tabviews/zshare/actionList/asyncButtonComponent.jsx
@@ -25,10 +25,26 @@
    render() {
      const C = this.state.component
      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
        }
      }
      return C ?
        <C {...this.props} /> :
        <Button className={'mk-btn mk-' + btn.class} icon={btn.icon} disabled={true} >{btn.label}</Button>
        <Button className={'mk-btn mk-' + btn.class} style={style} icon={btn.icon} disabled={true} >{btn.label}</Button>
    }
  }
}
src/tabviews/zshare/actionList/changeuserbutton/index.jsx
@@ -19,7 +19,6 @@
    btn: PropTypes.object,            // 按钮
    selectedData: PropTypes.any,      // 子表中选择数据
    setting: PropTypes.any,           // 页面通用设置
    updateStatus: PropTypes.func,     // 按钮状态更新
  }
  state = {
@@ -165,6 +164,7 @@
      return (
        <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          loading={loading}
          style={btn.btnstyle}
          icon={show === 'text' ? '' : (btn.icon || '')}
src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -23,7 +23,6 @@
    Tab: PropTypes.any,               // 如果当前元素为标签时,tab为标签信息
    btn: PropTypes.object,            // 按钮
    setting: PropTypes.any,           // 页面通用设置
    updateStatus: PropTypes.func,     // 按钮状态更新
  }
  state = {
@@ -145,7 +144,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.execSuccess, btn)
    if (btn.execSuccess !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
    }
  }
  /**
@@ -182,7 +183,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.execError, btn)
    if (btn.execError !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
    }
  }
  /**
@@ -410,6 +413,7 @@
      return <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}>
        <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          loading={loading}
          style={btn.btnstyle}
          icon={show === 'text' ? '' : (show === 'icon' ? (btn.icon || 'upload') : (btn.icon || ''))}
src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -676,7 +676,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.execSuccess, btn)
    if (btn.execSuccess !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
    }
  }
  /**
@@ -713,7 +715,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.execError, btn)
    if (btn.execError !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
    }
  }
  render() {
@@ -733,6 +737,7 @@
      return (
        <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          loading={loading}
          style={btn.btnstyle}
          icon={show === 'text' ? '' : (show === 'icon' ? (btn.icon || 'download') : (btn.icon || ''))}
src/tabviews/zshare/actionList/index.jsx
@@ -27,8 +27,7 @@
    actions: PropTypes.array,         // 按钮组
    columns: PropTypes.array,         // 显示列
    setting: PropTypes.any,           // 页面通用设置
    ContainerId: PropTypes.any,       // tab页面ID,用于弹窗控制
    refreshdata: PropTypes.func,      // 执行完成后数据刷新
    ContainerId: PropTypes.any        // tab页面ID,用于弹窗控制
  }
  state = {
@@ -37,14 +36,6 @@
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  updateStatus = (type, positon, btn) => {
    if (type === 'refresh') {
      this.props.refreshdata(positon, btn)
    } else if (type === 'trigger') { // 日历中的新标签页触发事件
      this.props.refreshdata('trigger')
    }
  }
  getButtonList = (actions) => {
@@ -65,7 +56,6 @@
            position="toolbar"
            ContainerId={ContainerId}
            selectedData={selectedData}
            updateStatus={this.updateStatus}
          />
        )
      } else if (item.OpenType === 'excelIn') {
@@ -79,7 +69,6 @@
            setting={setting}
            position="toolbar"
            selectedData={selectedData}
            updateStatus={this.updateStatus}
          />
        )
      } else if (item.OpenType === 'excelOut') {
@@ -92,7 +81,6 @@
            btn={item}
            setting={setting}
            position="toolbar"
            updateStatus={this.updateStatus}
          />
        )
      } else if (item.OpenType === 'popview') {
@@ -107,7 +95,6 @@
            setting={setting}
            position="toolbar"
            selectedData={selectedData}
            updateStatus={this.updateStatus}
          />
        )
      } else if (item.OpenType === 'tab' || item.OpenType === 'blank') {
@@ -120,7 +107,6 @@
            setting={setting}
            position="toolbar"
            selectedData={selectedData}
            updateStatus={this.updateStatus}
          />
        )
      } else if (item.OpenType === 'innerpage' || item.OpenType === 'outerpage') {
@@ -132,7 +118,6 @@
            setting={setting}
            position="toolbar"
            selectedData={selectedData}
            updateStatus={this.updateStatus}
          />
        )
      } else if (item.OpenType === 'funcbutton') {
@@ -146,7 +131,6 @@
              setting={setting}
              position="toolbar"
              selectedData={selectedData}
              updateStatus={this.updateStatus}
            />
          )
        } else if (item.funcType === 'print') {
@@ -162,7 +146,6 @@
              position="toolbar"
              ContainerId={ContainerId}
              selectedData={selectedData}
              updateStatus={this.updateStatus}
            />
          )
        }
src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -17,7 +17,6 @@
    btn: PropTypes.object,            // 按钮
    selectedData: PropTypes.any,      // 子表中选择数据
    setting: PropTypes.any,           // 页面通用设置
    updateStatus: PropTypes.func,     // 按钮状态更新
  }
  state = {
@@ -49,7 +48,6 @@
   */
  actionTrigger = (triggerId, record) => {
    const { setting, btn, selectedData } = this.props
    const _this = this
    if (triggerId && btn.uuid !== triggerId) return
@@ -128,10 +126,11 @@
        okText: '支付成功',
        cancelText: '支付遇到问题',
        onOk() {
          _this.props.updateStatus('refresh', 'grid')
          // 支付后刷新界面
          MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
        },
        onCancel() {
          _this.props.updateStatus('refresh', 'grid')
          MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
        },
      })
      window.open(url)
@@ -170,6 +169,7 @@
      return (
        <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          style={btn.btnstyle}
          icon={show === 'text' ? '' : (btn.icon || '')}
          onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -30,7 +30,6 @@
    columns: PropTypes.any,           // 字段列
    setting: PropTypes.any,           // 页面通用设置
    ContainerId: PropTypes.any,       // tab页面ID,用于弹窗控制
    updateStatus: PropTypes.func,     // 按钮状态更新
  }
  state = {
@@ -725,7 +724,9 @@
      this.sendMessage()
    }
    this.props.updateStatus('refresh', btn.execSuccess, btn)
    if (btn.execSuccess !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
    }
  }
  sendMessage = () => {
@@ -867,7 +868,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.execError, btn)
    if (btn.execError !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
    }
  }
  /**
@@ -1179,6 +1182,7 @@
      return <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}>
        <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          loading={loading}
          style={btn.btnstyle || style}
          icon={show === 'text' ? '' : (btn.icon || '')}
src/tabviews/zshare/actionList/popupbutton/index.jsx
@@ -11,8 +11,9 @@
import './index.scss'
const SubTabTable = asyncSpinComponent(() => import('@/tabviews/subtabtable'))
const CustomPage = asyncSpinComponent(() => import('@/tabviews/custom'))
class NormalButton extends Component {
class PopupButton extends Component {
  static propTpyes = {
    show: PropTypes.any,              // 按钮显示样式控制
    position: PropTypes.any,          // 按钮位置,工具栏为toolbar
@@ -23,7 +24,6 @@
    MenuID: PropTypes.string,         // 菜单ID
    btn: PropTypes.object,            // 按钮
    setting: PropTypes.any,           // 页面通用设置
    updateStatus: PropTypes.func,     // 按钮状态更新
  }
  state = {
@@ -44,15 +44,47 @@
    if (position === 'toolbar') {
      MKEmitter.addListener('triggerBtnId', this.actionTrigger)
    }
    MKEmitter.addListener('openNewTab', this.openNewTab)
    MKEmitter.addListener('refreshPopButton', this.refreshPopButton)
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('openNewTab', this.openNewTab)
    MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
    MKEmitter.removeListener('refreshPopButton', this.refreshPopButton)
  }
  
  /**
   * @description 打开新标签时,关闭弹窗标签页
   */
  openNewTab = () => {
    this.setState({
      visible: false,
      loading: false
    })
  }
  /**
   * @description 弹窗标签页刷新
   */
  refreshPopButton = (tabId) => {
    const { btn } = this.props
    if (btn.uuid !== tabId) return
    if (btn.$type === 'CustomPage') {
      if (btn.popClose !== 'never') {
        MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn)
      }
    } else {
      let position = btn.popClose !== 'never' ? btn.popClose : 'grid'
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, position, btn)
    }
  }
  /**
   * @description 触发按钮操作
   */
@@ -114,12 +146,6 @@
    })
  }
  // 操作后刷新主表
  reloadtable = () => {
    const { btn } = this.props
    this.props.updateStatus('refresh', 'grid', btn)
  }
  /**
   * @description 弹窗关闭
   */
@@ -131,7 +157,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.popClose, btn)
    if (btn.popClose !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn)
    }
  }
  render() {
@@ -148,15 +176,16 @@
        >{btn.label}</Button> : null}
        {show !== 'actionList' ? <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          loading={loading}
          style={btn.btnstyle}
          icon={show === 'text' ? '' : (btn.icon || '')}
          onClick={() => {this.actionTrigger()}}
        >{show === 'icon' && btn.icon ? '' : btn.label}</Button> : null}
        <Modal
          className="popview-modal"
          className={'popview-modal ' + (btn.$type === 'CustomPage' ? 'custom-popview' : '')}
          title={btn.label}
          width={'80vw'}
          width={'85vw'}
          maskClosable={false}
          visible={this.state.visible}
          onCancel={this.popclose}
@@ -165,14 +194,14 @@
          ]}
          destroyOnClose
        >
          <SubTabTable
          {btn.$type !== 'CustomPage' ? <SubTabTable
            Tab={btn}
            MenuID={btn.linkTab}
            SupMenuID={this.props.MenuID}
            BID={popData ? primaryId : this.props.BID}
            BData={popData || this.props.BData}
            SupMenuID={this.props.MenuID}
            refreshSupView={this.reloadtable}
          />
          /> : null}
          {btn.$type === 'CustomPage' ? <CustomPage Tab={btn} MenuID={btn.uuid} param={{BID: (popData ? primaryId : this.props.BID), data: (popData || this.props.BData)}} /> : null}
        </Modal>
      </div>
    )
@@ -189,4 +218,4 @@
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalButton)
export default connect(mapStateToProps, mapDispatchToProps)(PopupButton)
src/tabviews/zshare/actionList/popupbutton/index.scss
@@ -1 +1,5 @@
.custom-popview.popview-modal {
  >.ant-modal-content >.ant-modal-body {
    padding: 0;
  }
}
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -30,7 +30,6 @@
    btn: PropTypes.object,            // 按钮
    setting: PropTypes.any,           // 页面通用设置
    ContainerId: PropTypes.any,       // tab页面ID,用于弹窗控制
    updateStatus: PropTypes.func,     // 按钮状态更新
  }
  state = {
@@ -956,7 +955,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.execSuccess, btn)
    if (btn.execSuccess !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
    }
  }
  /**
@@ -993,7 +994,9 @@
      loading: false
    })
    this.props.updateStatus('refresh', btn.execError, btn)
    if (btn.execError !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
    }
  }
  /**
@@ -1284,6 +1287,7 @@
      return <div style={{display: 'inline-block'}} onClick={(e) => e.stopPropagation()}>
        <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          loading={loading}
          style={btn.btnstyle}
          icon={show === 'text' ? '' : (btn.icon || '')}
src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -18,7 +18,6 @@
    btn: PropTypes.object,            // 按钮
    selectedData: PropTypes.any,      // 子表中选择数据
    setting: PropTypes.any,           // 页面通用设置
    updateStatus: PropTypes.any
  }
  state = {
@@ -148,9 +147,7 @@
      this.props.modifyTabview(tabs)
    })
    if (this.props.updateStatus) {
      this.props.updateStatus('trigger')
    }
    MKEmitter.emit('openNewTab')
  }
  render() {
@@ -168,6 +165,7 @@
      return (
        <Button
          type="link"
          title={show === 'icon' ? btn.label : ''}
          style={btn.btnstyle}
          icon={show === 'text' ? '' : (btn.icon || '')}
          onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
src/tabviews/zshare/cardcomponent/index.jsx
@@ -30,7 +30,6 @@
    data: PropTypes.object,           // 卡片数据
    selectKey: PropTypes.string,      // 选择卡片的序号
    colMap: PropTypes.any,            // 显示列信息,用于设置标记
    refreshdata: PropTypes.func,      // 按钮操作后数据刷新
    switchCard: PropTypes.func        // 卡片切换
  }
@@ -129,14 +128,14 @@
   * @description 获取按钮元素
   */
  getActionList = (actions, show) => {
    const { BID, BData, Tab, setting, columns, ContainerId, data, MenuID } = this.props
    const { BData, Tab, setting, columns, ContainerId, data, MenuID } = this.props
    
    return actions.map(item => {
      if (['exec', 'prompt', 'pop'].includes(item.OpenType)) {
        return (
          <NormalButton
            key={item.uuid}
            BID={BID}
            BID={data.$$BID}
            Tab={Tab}
            btn={item}
            show={show}
@@ -145,21 +144,19 @@
            columns={columns}
            selectedData={[data]}
            ContainerId={ContainerId}
            updateStatus={this.props.refreshdata}
          />
        )
      } else if (item.OpenType === 'popview') {
        return (
          <PopupButton
            key={item.uuid}
            BID={BID}
            BID={data.$$BID}
            Tab={Tab}
            btn={item}
            show={show}
            BData={BData}
            setting={setting}
            selectedData={[data]}
            updateStatus={this.props.refreshdata}
          />
        )
      } else if (item.OpenType === 'tab' || item.OpenType === 'blank') {
@@ -171,7 +168,6 @@
            MenuID={MenuID}
            setting={setting}
            selectedData={[data]}
            updateStatus={this.props.refreshdata}
          />
        )
      } else if (item.OpenType === 'innerpage' || item.OpenType === 'outerpage') {
@@ -182,7 +178,6 @@
            show={show}
            setting={setting}
            selectedData={[data]}
            updateStatus={this.props.refreshdata}
          />
        )
      } else if (item.OpenType === 'funcbutton') {
@@ -190,19 +185,18 @@
          return (
            <ChangeUserButton
              key={item.uuid}
              BID={BID}
              BID={data.$$BID}
              btn={item}
              show={show}
              setting={setting}
              selectedData={[data]}
              updateStatus={this.props.refreshdata}
            />
          )
        } else if (item.funcType === 'print') {
          return (
            <PrintButton
              key={item.uuid}
              BID={BID}
              BID={data.$$BID}
              Tab={Tab}
              btn={item}
              show={show}
@@ -210,7 +204,6 @@
              setting={setting}
              selectedData={[data]}
              ContainerId={ContainerId}
              updateStatus={this.props.refreshdata}
            />
          )
        }
@@ -499,7 +492,6 @@
              columns={this.props.columns}
              selectedData={[]}
              ContainerId={this.props.ContainerId}
              updateStatus={this.props.refreshdata}
            />
          </div>
        </Card> : null}
@@ -521,7 +513,6 @@
    tableId: PropTypes.string,
    loading: PropTypes.bool,
    data: PropTypes.array,
    refreshdata: PropTypes.func,
    handleTableId: PropTypes.func
  }
@@ -747,15 +738,6 @@
    this.props.handleTableId(this.props.tableId, _id, data)
  }
  /**
   * @description 操作完成后,数据刷新
   */
  updateStatus = (type, positon, btn) => {
    if (type === 'refresh') {
      this.props.refreshdata(positon, btn)
    }
  }
  render() {
    const { plot, data, loading, BID, BData, Tab, MenuID, config, columns, ContainerId } = this.props
    const { card, colMap, selectKey, actionList } = this.state
@@ -781,7 +763,6 @@
                    show="icon"
                    btn={action}
                    setting={config.setting}
                    updateStatus={this.updateStatus}
                  />
                )
              } else {
@@ -793,7 +774,6 @@
                    show="icon"
                    btn={action}
                    setting={config.setting}
                    updateStatus={this.updateStatus}
                  />
                )
              }
@@ -817,7 +797,6 @@
              setting={config.setting}
              ContainerId={ContainerId}
              switchCard={this.switchCard}
              refreshdata={this.updateStatus}
            />
          ))
        }
@@ -834,7 +813,6 @@
            setting={config.setting}
            ContainerId={ContainerId}
            switchCard={() => {}}
            refreshdata={this.updateStatus}
          /> : null
        }
        {(loading || !card.insertAction) && (!data || data.length === 0) ? <Empty description={false}/> : null}
src/tabviews/zshare/chartcomponent/index.jsx
@@ -1091,7 +1091,6 @@
                    btn={item}
                    show="icon"
                    setting={config.setting}
                    updateStatus={() => {}}
                  />
                )
              } else {
@@ -1103,7 +1102,6 @@
                    btn={item}
                    show="icon"
                    setting={config.setting}
                    updateStatus={() => {}}
                  />
                )
              }
src/tabviews/zshare/fileupload/index.jsx
@@ -18,6 +18,7 @@
class FileUpload extends Component {
  static propTpyes = {
    value: PropTypes.array,    // 文件数组
    accept: PropTypes.any,     // 文件格式
    maxFile: PropTypes.any,    // 最大文件数
    fileType: PropTypes.string // 文件显示类型
  }
@@ -122,6 +123,27 @@
  }
  beforeUpload = (file) => {
    const { accept } = this.props
    if (accept && file.name) {
      let types = accept.split(',')
      let pass = false
      types.forEach(type => {
        if (new RegExp(type + '$', 'ig').test(file.name)) {
          pass = true
        }
      })
      if (!pass) {
        notification.warning({
          top: 92,
          message: '文件格式错误!',
          duration: 5
        })
        return
      }
    }
    this.setState({
      showprogress: true,
      percent: 0
@@ -231,7 +253,7 @@
  }
  render() {
    const { value, maxFile, fileType } = this.props
    const { value, maxFile, fileType, accept } = this.props
    const { showprogress, percent } = this.state
    let uploadable = 'fileupload-form-container '
@@ -246,6 +268,7 @@
      listType: fileType,
      fileList: value,
      action: null,
      accept: accept || '',
      method: 'post',
      multiple: false,
      onChange: this.onChange,
src/tabviews/zshare/mutilform/index.jsx
@@ -8,15 +8,17 @@
import options from '@/store/options.js'
import { formRule } from '@/utils/option.js'
import Utils from '@/utils/utils.js'
import CustomSwitch from './customSwitch'
import asyncComponent from '@/utils/asyncComponent'
import CheckCard from './checkCard'
import './index.scss'
const {MonthPicker} = DatePicker
const { MonthPicker } = DatePicker
const { TextArea } = Input
const CheckCard = asyncComponent(() => import('./checkCard'))
const CustomSwitch = asyncComponent(() => import('./customSwitch'))
const FileUpload = asyncComponent(() => import('../fileupload'))
const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
// const Editor = asyncComponent(() => import('@/components/editor'))
class MainSearch extends Component {
  static propTpyes = {
@@ -1122,7 +1124,7 @@
                  }
                ]
              })(
                <FileUpload maxFile={item.maxfile} fileType={item.fileType || 'text'} />
                <FileUpload accept={item.suffix} maxFile={item.maxfile} fileType={item.fileType || 'text'} />
              )}
            </Form.Item>
          </Col>
@@ -1341,6 +1343,7 @@
              return item
            })
          }
          resolve(search)
        } else {
          reject(err)
@@ -1370,6 +1373,7 @@
    return (
      <Form {...formItemLayout} className="ant-advanced-search-form main-form-field" id="main-form-box">
        <Row className={'cols' + cols} gutter={24}>{this.getFields()}</Row>
        {/* <Editor /> */}
      </Form>
    )
  }
src/tabviews/zshare/normalTable/index.jsx
@@ -29,7 +29,6 @@
    pickup: PropTypes.any,           // 数据收起
    columns: PropTypes.array,        // 表格列
    fields: PropTypes.array,         // 组件字段集
    BID: PropTypes.any,              // 主表Id
    ContainerId: PropTypes.any,      // 标签页外层Id
    BData: PropTypes.any,            // 主表数据
    data: PropTypes.any,             // 表格数据
@@ -38,7 +37,6 @@
    refreshdata: PropTypes.func,     // 表格中排序列、页码的变化时刷新
    handleTableId: PropTypes.func,   // 数据切换
    chgSelectData: PropTypes.func,   // 数据切换
    refreshbyaction: PropTypes.func, // 按钮执行完成后刷新
  }
  state = {
@@ -209,12 +207,6 @@
      return
    }
    MKEmitter.removeListener('resetTable', this.resetTable)
  }
  updateStatus = (type, positon, btn) => {
    if (type === 'refresh') {
      this.props.refreshbyaction(positon, btn)
    }
  }
  // 字段透视
@@ -595,13 +587,12 @@
                <NormalButton
                  key={btn.uuid}
                  btn={btn}
                  BID={this.props.BID}
                  BID={record.$$BID}
                  selectedData={[record]}
                  BData={this.props.BData}
                  setting={this.props.setting}
                  columns={this.props.fields || this.props.columns}
                  ContainerId={this.props.ContainerId}
                  updateStatus={this.updateStatus}
                />
              )
            } else if (btn.OpenType === 'popview') {
@@ -609,11 +600,10 @@
                <PopupButton
                  key={btn.uuid}
                  btn={btn}
                  BID={this.props.BID}
                  BID={record.$$BID}
                  selectedData={[record]}
                  BData={this.props.BData}
                  setting={this.props.setting}
                  updateStatus={this.updateStatus}
                />
              )
            } else if (btn.OpenType === 'tab' || btn.OpenType === 'blank') {
@@ -624,7 +614,6 @@
                  selectedData={[record]}
                  MenuID={this.props.MenuID}
                  setting={this.props.setting}
                  updateStatus={this.updateStatus}
                />
              )
            } else if (btn.OpenType === 'innerpage' || btn.OpenType === 'outerpage') {
@@ -634,7 +623,6 @@
                  btn={btn}
                  selectedData={[record]}
                  setting={this.props.setting}
                  updateStatus={this.updateStatus}
                />
              )
            }
src/tabviews/zshare/pageMessage/index.jsx
New file
@@ -0,0 +1,353 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button, Modal, Typography, Tree } from 'antd'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import options from '@/store/options.js'
import './index.scss'
const { TreeNode } = Tree
const { Paragraph } = Typography
class PageMessage extends Component {
  static propTpyes = {
    BID: PropTypes.any,          // 父级Id,用于查询下拉选择项
    dict: PropTypes.object,      // 字典
  }
  state = {
    debug: sessionStorage.getItem('debug') === 'true',
    visible: false,
    key: '',        // 更新指针
    data: []
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  handleviewconfig = (e) => {
    const { config } = this.props
    let data = []
    e.stopPropagation()
    if (config.Template === 'CustomPage') {
      data = this.getCusData(config)
    } else {
      data = this.getData(config)
    }
    this.setState({
      visible: true,
      data: data
    })
  }
  getBtnCell = (cell, item) => {
    let _cell = { uuid: cell.uuid, title: `按钮(${cell.label}):` }
    let _others = []
    let tablename = cell.OpenType === 'excelIn' ? (cell.sheet || '') : (cell.sql || '')
    if (cell.OpenType === 'excelOut' && cell.intertype === 'system') {
      tablename = item.setting.tableName || ''
    }
    if (['pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
      if (tablename) {
        _others.push(`${tablename}(表名)`)
      }
      if (cell.innerFunc) {
        _others.push(`${cell.innerFunc}(内部函数)`)
      }
      if (cell.outerFunc) {
        _others.push(`${cell.outerFunc}(外部函数)`)
      }
    } else if (cell.OpenType === 'popview') {
      _cell.sublist = []
      Api.getLocalCacheConfig({
        func: 'sPC_Get_LongParam',
        MenuID: cell.uuid
      }).then(res => {
        if (res.LongParam) {
          let _config
          try { // 配置信息解析
            _config = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
          } catch (e) {
            _config = ''
          }
          if (_config) {
            _cell.sublist = this.getCusData(_config)
            this.setState({key: cell.uuid})
          }
        }
      })
    }
    _cell.title = _cell.title + _others.join('、')
    return _cell
  }
  getCusData = (config) => {
    let data = []
    config.components.forEach(item => {
      let _item = { uuid: item.uuid, title: item.name, sublist: [] }
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          let cell = { uuid: tab.uuid, title: tab.label }
          cell.sublist = this.getCusData(tab)
          _item.sublist.push(cell)
        })
      } else if (item.type === 'group') {
        _item.sublist = this.getCusData(item)
      } else if (item.type === 'search' || (item.type === 'card' && item.subtype === 'propcard' && item.wrap.datatype === 'static')) {
        let cell = { uuid: Utils.getuuid(), title: '数据源:(无)' }
        _item.sublist.push(cell)
      } else if (item.setting) {
        let cell = { uuid: Utils.getuuid(), title: '数据源:' }
        let _others = []
        if (item.setting.tableName) {
          _others.push(`${item.setting.tableName}(表名)`)
        }
        if (item.setting.innerFunc) {
          _others.push(`${item.setting.innerFunc}(内部函数)`)
        }
        if (item.setting.outerFunc) {
          _others.push(`${item.setting.outerFunc}(外部函数)`)
        }
        cell.title = cell.title + _others.join('、')
        _item.sublist.push(cell)
      }
      if (item.action) {
        item.action.forEach(cell => {
          let _cell = this.getBtnCell(cell, item)
          _item.sublist.push(_cell)
        })
      }
      if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) {
        item.subcards.forEach(card => {
          card.elements && card.elements.forEach(cell => {
            if (cell.eleType === 'button') {
              let _cell = this.getBtnCell(cell, item)
              _item.sublist.push(_cell)
            }
          })
          card.backElements && card.backElements.forEach(cell => {
            if (cell.eleType === 'button') {
              let _cell = this.getBtnCell(cell, item)
              _item.sublist.push(_cell)
            }
          })
        })
      } else if (item.type === 'table' && item.subtype === 'normaltable') {
        item.cols.forEach(col => {
          if (col.type !== 'action') return
          col.elements && col.elements.forEach(cell => {
            let _cell = this.getBtnCell(cell, item)
            _item.sublist.push(_cell)
          })
        })
      }
      data.push(_item)
    })
    return data
  }
  getData = (config) => {
    let data = []
    let item = {uuid: Utils.getuuid(), title: '数据源:'}
    let _others = []
    if (config.Template === 'SubTable') {
      if (config.tabNo) {
        _others.push(`${config.tabNo}(菜单参数)`)
      }
    }
    if (config.setting.tableName) {
      _others.push(`${config.setting.tableName}(表名)`)
    }
    if (config.setting.innerFunc) {
      _others.push(`${config.setting.innerFunc}(内部函数)`)
    }
    if (config.setting.outerFunc) {
      _others.push(`${config.setting.outerFunc}(外部函数)`)
    }
    item.title = item.title + _others.join('、')
    data.push(item)
    // 按钮
    config.action && config.action.forEach(item => {
      let _item = {uuid: Utils.getuuid(), title: `按钮(${item.label}):`}
      let _others = []
      let tablename = item.OpenType === 'excelIn' ? (item.sheet || '') : (item.sql || '')
      if (item.OpenType === 'excelOut' && item.intertype === 'system') {
        tablename = config.setting.tableName || ''
      }
      if (item.OpenType === 'popview') {
        _item.sublist = []
        Api.getLocalCacheConfig({
          func: 'sPC_Get_LongParam',
          MenuID: item.linkTab
        }).then(res => {
          if (res.LongParam) {
            let _config
            try { // 配置信息解析
              _config = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
            } catch (e) {
              _config = ''
            }
            if (_config) {
              _item.sublist = this.getData(_config)
              this.setState({key: item.uuid})
            }
          }
        })
      } else if (['pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(item.OpenType)) {
        if (tablename) {
          _others.push(`${tablename}(表名)`)
        }
        if (item.innerFunc) {
          _others.push(`${item.innerFunc}(内部函数)`)
        }
        if (item.outerFunc) {
          _others.push(`${item.outerFunc}(外部函数)`)
        }
      }
      _item.title = _item.title + _others.join('、')
      data.push(_item)
    })
    // 标签页
    config.tabgroups && config.tabgroups.forEach(group => {
      group.sublist.forEach(tab => {
        let _item = {uuid: Utils.getuuid(), title: `标签(${tab.label}):`, sublist: []}
        Api.getLocalCacheConfig({
          func: 'sPC_Get_LongParam',
          MenuID: tab.linkTab
        }).then(res => {
          if (res.LongParam) {
            let _config
            try { // 配置信息解析
              _config = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
            } catch (e) {
              _config = ''
            }
            if (_config) {
              _item.sublist = this.getData(_config)
              this.setState({key: tab.uuid})
            }
          }
        })
        data.push(_item)
      })
    })
    if (config.Template === 'CalendarPage' && config.tab) {
      let _item = {uuid: Utils.getuuid(), title: `标签(${config.tab.label}):`, sublist: []}
      Api.getLocalCacheConfig({
        func: 'sPC_Get_LongParam',
        MenuID: config.tab.linkTab
      }).then(res => {
        if (res.LongParam) {
          let _config
          try { // 配置信息解析
            _config = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
          } catch (e) {
            _config = ''
          }
          if (_config) {
            _item.sublist = this.getData(_config)
            this.setState({key: config.tab.linkTab})
          }
        }
      })
      data.push(_item)
    }
    return data
  }
  getTreeNode = (data) => {
    return data.map(item => {
      if (item.sublist && item.sublist.length) {
        return (
          <TreeNode title={item.title} key={item.uuid} selectable={false}>
            {this.getTreeNode(item.sublist)}
          </TreeNode>
        )
      }
      return <TreeNode key={item.uuid} title={item.title} isLeaf selectable={false} />
    })
  }
  render() {
    const { menu, dict } = this.props
    const { debug, visible, data } = this.state
    return (
      <div className={'page-message-wrap ' + (debug && options.sysType !== 'cloud' ? 'exist' : '')}>
        {debug && options.sysType !== 'cloud' ? <Button
          icon="copy"
          shape="circle"
          className="page-message"
          onClick={this.handleviewconfig}
        /> : null}
        <Modal
          className="menu-tree-modal"
          title={'菜单信息'}
          width={'850px'}
          maskClosable={false}
          visible={visible}
          onCancel={() => this.setState({visible: false})}
          footer={[
            <Button key="close" onClick={() => this.setState({visible: false})}>{dict['main.close']}</Button>
          ]}
          destroyOnClose
        >
          <div className="menu-header">
            <span>菜单名称:{menu.MenuName}</span>
            {menu.MenuNo ? <span>菜单参数:<Paragraph copyable>{menu.MenuNo}</Paragraph></span> : null}
          </div>
          {visible ? <Tree defaultExpandAll showLine={true}>
            {this.getTreeNode(data)}
          </Tree> : null}
        </Modal>
      </div>
    )
  }
}
export default PageMessage
src/tabviews/zshare/pageMessage/index.scss
New file
@@ -0,0 +1,35 @@
.page-message-wrap {
  .page-message {
    position: fixed;
    z-index: 2;
    bottom: 65px;
    right: 30px;
    width: 40px;
    height: 40px;
  }
}
.custom-popview {
  .page-message-wrap {
    display: none;
  }
}
.ant-modal.menu-tree-modal {
  top: 60px;
  .ant-modal-body {
    min-height: 300px;
    .menu-header {
      text-align: center;
      span {
        font-weight: 600;
        margin-right: 20px;
      }
      .ant-typography {
        font-weight: 600;
        display: inline-block;
      }
    }
    .ant-tree li .ant-tree-node-content-wrapper {
      cursor: default;
    }
  }
}
src/tabviews/zshare/settingcomponent/editTable/index.jsx
New file
@@ -0,0 +1,322 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
// import { fromJS } from 'immutable'
import { Table, Form, Icon, Select, Cascader } from 'antd'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
let eTDict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
const EditableContext = React.createContext()
const shortkeycode = {
  65: 'A', 66: 'B', 67: 'C', 68: 'D', 69: 'E', 70: 'F', 71: 'G', 72: 'H', 73: 'I', 74: 'J', 75: 'K', 76: 'L', 77: 'M',
  78: 'N', 79: 'O', 80: 'P', 81: 'Q', 82: 'R', 83: 'S', 84: 'T', 85: 'U', 86: 'V', 87: 'W', 88: 'X', 89: 'Y', 90: 'Z'
}
class CustomEditableCell extends Component {
  getInput = () => {
    const { inputType, options, record } = this.props
    if (inputType === 'select') {
      let _options = []
      if (record.$port) {
        _options = window.GLOB.UserCacheMap.get(record.$port)
      }
      return (
        <Select allowClear>
          {_options.map((item, i) => (<Select.Option key={i} title={item.value} value={item.value}> {item.text} </Select.Option>))}
        </Select>
      )
    } else if (inputType === 'cascader') {
      return (
        <Cascader allowClear options={options} placeholder=""/>
      )
    }
  }
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const { editing, editable, dataIndex, record, children, className } = this.props
    return (
      <td className={className}>
        {editing && editable ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              initialValue: record[dataIndex] || '',
            })(this.getInput())}
          </Form.Item>
        ) : (
          children
        )}
      </td>
    )
  }
  render() {
    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
  }
}
class CustomEditTable extends Component {
  static propTpyes = {
    data: PropTypes.any,            // 数据列表
    onChange: PropTypes.func        // 数据变化
  }
  state = {
    data: [],
    editingKey: '',
    visible: false,
    columns: [{
      title: '名称',
      dataIndex: 'label',
      width: '25%'
    }, {
      title: '快捷键',
      dataIndex: 'shortcut',
      inputType: 'cascader',
      editable: true,
      options: [],
      width: '25%',
      render: (text, record) => {
        if (!text) return ''
        return text[0] + '+' + shortkeycode[text[1]]
      }
    }, {
      title: '打印机',
      dataIndex: 'printer',
      inputType: 'select',
      editable: true,
      options: [],
      width: '25%'
    }, {
      title: '操作',
      dataIndex: 'operation',
      width: '140px',
      render: (text, record) => {
        const { editingKey } = this.state
        const editable = this.isEditing(record)
        return editable ? (
          <div style={{textAlign: 'center', minWidth: '110px'}}>
            <EditableContext.Consumer>
              {form => (
                <span onClick={() => this.save(form, record.uuid)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                  {eTDict['model.save']}
                </span>
              )}
            </EditableContext.Consumer>
            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{eTDict['model.cancel']}</span>
          </div>
        ) : (
          <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px'}}>
            <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><Icon type="edit" /></span>
          </div>
        )
      }
    }],
    printTypeColumns: [
      {
        title: '打印类型',
        dataIndex: 'Text',
        width: '26.1%'
      },
      {
        title: '打印机',
        dataIndex: 'printer',
        inputType: 'select',
        editable: true,
        options: [],
      },
      {
        title: '操作',
        dataIndex: 'operation',
        width: '153px',
        render: (text, record) => {
          const { editingKey } = this.state
          const editable = this.isEditing(record)
          return editable ? (
            <div style={{textAlign: 'center', minWidth: '110px'}}>
              <EditableContext.Consumer>
                {form => (
                  <span onClick={() => this.save(form, record.uuid, record.parentId)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                    {eTDict['model.save']}
                  </span>
                )}
              </EditableContext.Consumer>
              <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{eTDict['model.cancel']}</span>
            </div>
          ) : (
            <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px'}}>
              <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><Icon type="edit" /></span>
            </div>
          )
        }
      }
    ]
  }
  UNSAFE_componentWillMount () {
    const { data } = this.props
    let keys = ['shift', 'ctrl', 'alt']
    let _options = []
    keys.forEach(item => {
      let _op = {
        value: item,
        label: item,
        children: []
      }
      Object.keys(shortkeycode).forEach(key => {
        if (item === 'ctrl' && ['65', '67', '68', '69', '70', '71', '72', '74', '75', '76', '78', '79', '80', '82', '83', '84', '85', '86', '87', '88', '90'].includes(key)) return
        if (item === 'alt' && ['65', '68', '69', '70'].includes(key)) return
        _op.children.push({
          value: +key,
          label: shortkeycode[key]
        })
      })
      _options.push(_op)
    })
    this.setState({
      data: data,
      columns: this.state.columns.map(item => {
        if (item.dataIndex === 'shortcut') {
          item.options = _options
        }
        return item
      })
    })
  }
  isEditing = record => record.uuid === this.state.editingKey
  cancel = () => {
    this.setState({ editingKey: '' })
  }
  handleDelete = (uuid) => {
    const { data } = this.state
    let _data = data.filter(item => uuid !== item.uuid)
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  save(form, uuid, parentId) {
    form.validateFields((error, row) => {
      if (error) {
        return;
      }
      let newData = null
      if (parentId) {
        newData = this.state.data.map(item => {
          if (parentId === item.uuid) {
            item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
              if (uuid === cell.uuid) {
                cell = {...cell, ...row}
              }
              return cell
            })
          }
          return item
        })
      } else {
        newData = this.state.data.map(item => {
          if (uuid === item.uuid) {
            item = {...item, ...row}
          }
          return item
        })
      }
      this.setState({ data: newData, editingKey: '' }, () => {
        this.props.onChange(newData)
      })
    })
  }
  edit(uuid) {
    this.setState({ editingKey: uuid })
  }
  render() {
    let components = {
      body: {
        cell: CustomEditableCell
      }
    }
    const columns = this.state.columns.map(col => {
      if (!col.editable) return col
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          options: col.options || [],
          title: col.title,
          editable: col.dataIndex === 'shortcut' || record.funcType === 'print',
          editing: this.isEditing(record),
        }),
      }
    })
    const printTypeColumns = this.state.printTypeColumns.map(col => {
      if (!col.editable) return col
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          options: [],
          title: col.title,
          editable: true,
          editing: this.isEditing(record),
        }),
      }
    })
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-custom-edit-table">
          <Table
            bordered
            rowKey="uuid"
            components={components}
            dataSource={this.state.data}
            columns={columns}
            rowClassName={(record) => 'editable-row' + (record.$expanded ? ' print' : '')}
            pagination={false}
            expandedRowRender={record => (
              record.$expanded ?
                <Table
                  bordered
                  rowKey="key"
                  size="small"
                  components={components}
                  rowClassName="editable-row"
                  dataSource={record.verify.printerTypeList}
                  columns={printTypeColumns}
                  pagination={false}
                /> : null
            )}
          />
        </div>
      </EditableContext.Provider>
    )
  }
}
export default Form.create()(CustomEditTable)
src/tabviews/zshare/settingcomponent/editTable/index.scss
New file
@@ -0,0 +1,66 @@
.modal-custom-edit-table {
  .editable-row {
    .ant-form-explain {
      position: absolute;
      font-size: 12px;
      margin-top: -4px;
    }
    .ant-select {
      width: 100%;
    }
    > td {
      padding: 14px 10px;
    }
    > td:last-child {
      padding: 0px;
    }
  }
  .ant-table-expanded-row {
    td[colspan="4"] {
      padding: 10px;
      .ant-table-wrapper {
        margin: 0;
        .ant-table-body {
          margin: 0;
        }
      }
    }
  }
  .editable-row:not(.print) {
    .ant-table-row-expand-icon-cell {
      div {
        display: none;
      }
    }
  }
  thead tr th:last-child {
    text-align: center;
  }
  .edit-operation-btn {
    display: block;
    text-align: center;
    span {
      margin-right: 10px;
      cursor: pointer;
      font-size: 16px;
      padding: 5px;
    }
    .primary {
      color: #1890ff;
    }
    span:last-child {
      margin-right: 0px;
    }
  }
  .edit-operation-btn.disabled {
    cursor: default;
    span {
      cursor: default;
    }
    .primary {
      color: rgba(0, 0, 0, .25);
    }
  }
}
src/tabviews/zshare/settingcomponent/index.jsx
@@ -1,23 +1,28 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Icon, Button, Modal, notification } from 'antd'
import { Button, Modal, notification, Spin, Empty } from 'antd'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import UtilsUpdate from '@/utils/utils-update.js'
import options from '@/store/options.js'
import asyncComponent from '@/utils/asyncSpinComponent'
import './index.scss'
const VerifyCard = asyncComponent(() => import('@/tabviews/zshare/verifycard'))
const EditTable = asyncComponent(() => import('./editTable'))
class CustomSetting extends Component {
  static propTpyes = {
    dict: PropTypes.any,              // 字典表
    reloadview: PropTypes.func,       // 页面刷新
    dict: PropTypes.object,           // 字典表
    config: PropTypes.object,         // 页面配置信息
    shortcuts: PropTypes.any,         // 自定义设置
    permAction: PropTypes.object,     // 按钮权限
  }
  state = {
    userParam: null,       // 保存用户编辑中的配置
    visible: false,        // 模态框控制
    components: null,      // 组件集合
    revertLoading: false,  // 恢复默认设置
    confirmLoading: false, // 自定义设置模态框加载中
  }
@@ -26,22 +31,357 @@
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  controlCustomSetting = () => {
  trigger = () => {
    const { config } = this.props
    this.setState({
      visible: true,
      confirmLoading: false,
      revertLoading: false
    })
    if (config.Template === 'CommonTable' || config.Template === 'TreePage') {
      this.getPageConfig()
    } else if (config.Template === 'CustomPage') {
      this.getCustomPageConfig()
    } else {
      notification.warning({
        top: 92,
        message: '配置信息格式错误!',
        duration: 5
      })
    }
  }
  changeMenuParam = (param) => {
    this.setState({userParam: param})
  getCustomPageConfig = () => {
    const { shortcuts } = this.props
    let config = fromJS(this.props.config).toJS()
    let userConfig = {}
    let printbtns = []
    let _components = []
    shortcuts.forEach(item => {
      userConfig[item.uuid] = item
    })
    let filterComponent = (components) => {
      components.forEach(item => {
        if (item.type === 'tabs') {
          item.subtabs.forEach(tab => {
            filterComponent(tab.components)
          })
          return
        } else if (item.type === 'group') {
          filterComponent(item.components)
          return
        }
        let _comp = {title: item.name, uuid: item.uuid, action: []}
        item.action && item.action.forEach(cell => {
          cell.$expanded = false
          if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
            cell.$port = cell.verify ? cell.verify.linkUrl : ''
            if (cell.verify && cell.verify.printerTypeList) {
              cell.verify.printerTypeList = cell.verify.printerTypeList.map(_cell => {
                _cell.parentId = cell.uuid
                _cell.$port = cell.$port
                return _cell
              })
              cell.$expanded = true
            }
            printbtns.push(cell)
          }
          _comp.action.push({...cell, ...(userConfig[cell.uuid] || {})})
        })
        if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) {
          item.subcards.forEach(card => {
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              cell.$expanded = false
              if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
                cell.$port = cell.verify ? cell.verify.linkUrl : ''
                if (cell.verify && cell.verify.printerTypeList) {
                  cell.verify.printerTypeList = cell.verify.printerTypeList.map(_cell => {
                    _cell.parentId = cell.uuid
                    _cell.$port = cell.$port
                    return _cell
                  })
                  cell.$expanded = true
                }
                printbtns.push(cell)
              }
              _comp.action.push({...cell, ...(userConfig[cell.uuid] || {})})
            })
            card.backElements && card.backElements.forEach(cell => {
              if (cell.eleType !== 'button') return
              cell.$expanded = false
              if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
                cell.$port = cell.verify ? cell.verify.linkUrl : ''
                if (cell.verify && cell.verify.printerTypeList) {
                  cell.verify.printerTypeList = cell.verify.printerTypeList.map(_cell => {
                    _cell.parentId = cell.uuid
                    _cell.$port = cell.$port
                    return _cell
                  })
                  cell.$expanded = true
                }
                printbtns.push(cell)
              }
              _comp.action.push({...cell, ...(userConfig[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 => {
              cell.$expanded = false
              if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
                cell.$port = cell.verify ? cell.verify.linkUrl : ''
                if (cell.verify && cell.verify.printerTypeList) {
                  cell.verify.printerTypeList = cell.verify.printerTypeList.map(_cell => {
                    _cell.parentId = cell.uuid
                    _cell.$port = cell.$port
                    return _cell
                  })
                  cell.$expanded = true
                }
                printbtns.push(cell)
              }
              _comp.action.push({...cell, ...(userConfig[cell.uuid] || {})})
            })
          })
        }
        if (_comp.action.length > 0) {
          _components.push(_comp)
        }
      })
    }
    filterComponent(config.components)
    this.setState({components: _components})
    this.getPrinter(printbtns)
  }
  getPageConfig = () => {
    const { shortcuts, permAction } = this.props
    let config = fromJS(this.props.config).toJS()
    let userConfig = {}
    let components = []
    let _component = { title: '主表', uuid: config.MenuID, action: [] }
    let printbtns = []
    shortcuts.forEach(item => {
      userConfig[item.uuid] = item
    })
    config.action && config.action.forEach(item => {
      item.$expanded = false
      if (item.OpenType === 'funcbutton' && item.funcType === 'print') {
        item.$port = item.verify ? item.verify.linkUrl : ''
        printbtns.push(item)
        if (item.verify && item.verify.printerTypeList && item.verify.printerTypeList.length > 0) {
          item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
            cell.parentId = item.uuid
            cell.$port = item.$port
            return cell
          })
          item.$expanded = true
        }
      }
      _component.action.push({...item, ...(userConfig[item.uuid] || {})})
    })
    if (_component.action.length > 0) {
      components.push(_component)
    }
    let deffers = []
    config.tabgroups && config.tabgroups.forEach(group => {
      group.sublist.forEach(tab => {
        deffers.push(new Promise(resolve => {
          let param = {
            func: 'sPC_Get_LongParam',
            MenuID: tab.linkTab
          }
          Api.getCacheConfig(param).then(res => {
            res.tab = tab
            resolve(res)
          })
        }))
      })
    })
    if (deffers.length > 0) {
      Promise.all(deffers).then(result => {
        let errors = result.filter(res => !res.status)
        if (errors.length > 0) {
          notification.warning({
            top: 92,
            message: errors[0].message,
            duration: 5
          })
          return
        }
        result.forEach(res => {
          if (!res.LongParam) return
          let subconfig = ''
          try {
            subconfig = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
          } catch (e) {
            console.warn('Parse Failure')
            subconfig = ''
          }
          if (!subconfig || !subconfig.enabled) return
          subconfig = UtilsUpdate.updateSubTable(subconfig)
          let _comp = {title: res.tab.label, uuid: res.tab.uuid, action: []}
          subconfig.action.forEach(item => {
            if (!permAction[item.uuid]) return
            item.$expanded = false
            if (item.OpenType === 'funcbutton' && item.funcType === 'print') {
              let _item = window.GLOB.UserCacheMap.get(res.tab.uuid + item.uuid)
              item.printer = _item ? (_item.printer || '') : ''
              item.$port = item.verify ? item.verify.linkUrl : ''
              if (item.verify && item.verify.printerTypeList) {
                item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                  cell.parentId = item.uuid
                  cell.$port = item.$port
                  cell.printer = _item && _item.printerList ? (_item.printerList[cell.Value] || '') : ''
                  return cell
                })
                item.$expanded = true
              }
              printbtns.push(item)
            }
            _comp.action.push({...item, ...(userConfig[item.uuid] || {})})
          })
          if (_comp.action.length > 0) {
            components.push(_comp)
          }
        })
        this.setState({components})
        this.getPrinter(printbtns)
      })
    } else {
      this.setState({components})
      this.getPrinter(printbtns)
    }
  }
  getPrinter = (printbtns) => {
    let links = []
    printbtns.forEach(item => {
      if (!item.verify || !item.verify.linkUrl) {
        notification.warning({
          top: 92,
          message: '按钮《' + item.label + '》设置错误!',
          duration: 5
        })
      } else if (!links.includes(item.verify.linkUrl)) {
        links.push(item.verify.linkUrl)
        let socket = null
        socket = new WebSocket('ws://' + item.verify.linkUrl)
        // 打开Socket
        socket.onopen = () =>{
          let request  = {
            requestID: '',
            version: '',
            cmd: 'getPrinters'
          }
          socket.send(JSON.stringify(request))
        }
        // 监听消息
        socket.onmessage = (event) => {
          let data = ''
          try {
            data = JSON.parse(event.data)
          } catch {
            data = ''
          }
          if (data && data.cmd === 'getPrinters' && (data.status === true || data.status === 'success')) {
            let _printers = []
            let _printer = data.printers[0]
            if (_printer && typeof(_printer) === 'string') {
              _printers = Array.from(new Set(data.printers))
              _printers = _printers.map(print => {
                return {
                  value: print,
                  text: print
                }
              })
            } else if (_printer && typeof(_printer) === 'object') {
              _printers = data.printers.map(p => p.name)
              _printers = Array.from(new Set(_printers))
              _printers = _printers.map(print => {
                return {
                  value: print,
                  text: print
                }
              })
            }
            window.GLOB.UserCacheMap.set(item.verify.linkUrl, _printers)
          } else if (data && data.cmd === 'getPrinters') {
            notification.warning({
              top: 92,
              message: data.message,
              duration: 5
            })
          }
        }
        socket.onerror = () => {
          let tool = item.verify.linkUrl
          if (item.verify.linkUrl === '127.0.0.1:13529') {
            tool = '明科通讯组件'
          } else if (item.verify.linkUrl === '127.0.0.1:13528') {
            tool = 'CAINIAO打印组件'
          }
          notification.warning({
            top: 92,
            message: '无法连接到: ' + tool,
            duration: 5
          })
        }
      }
    })
  }
  settingRevert = () => {
    const { config } = this.props
    let param = {
      func: 's_TrdMenu_UserParam_del',
      MenuID: this.props.MenuID
      MenuID: config.MenuID
    }
    this.setState({
      revertLoading: true
@@ -59,22 +399,50 @@
        })
        return
      }
      this.setState({
        visible: false,
        revertLoading: false
      }, () => {
        window.GLOB.CacheMap = new Map()
        this.props.reloadview()
      Api.deleteMenuStorage(config.MenuID).then(() => {
        this.setState({
          visible: false,
          revertLoading: false
        }, () => {
          window.GLOB.CacheMap = new Map()
          MKEmitter.emit('reloadMenuView', config.MenuID)
        })
      })
    })
  }
  settingSubmit = () => {
    const { userParam } = this.state
    let _LongParam = ''
    const { config } = this.props
    const { components } = this.state
    let _LongParam = {version: '1.0', action: [], printers: []}
    components.forEach(com => {
      com.action.forEach(item => {
        if (item.shortcut && item.shortcut.length > 0) {
          _LongParam.action.push({uuid: item.uuid, parentId: com.uuid, shortcut: item.shortcut, $shortcut: item.shortcut.join('+')})
        }
        if (item.funcType === 'print' && (item.printer || item.verify.printerTypeList)) {
          let printerList = {}
          if (item.verify.printerTypeList) {
            item.verify.printerTypeList.forEach(cell => {
              printerList[cell.Value] = cell.printer || ''
            })
          }
          _LongParam.printers.push({
            uuid: item.uuid,
            parentId: com.uuid,
            printer: item.printer || '',
            printerList
          })
        }
      })
    })
    try {
      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(userParam)))
      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam)))
    } catch (e) {
      notification.warning({
        top: 92,
@@ -84,12 +452,10 @@
      return
    }
    let easyCode = userParam[this.props.MenuID] ? userParam[this.props.MenuID].easyCode : ''
    let param = {
      func: 'sPC_TrdMenu_UserParam',
      MenuID: this.props.MenuID,
      EasyCode: easyCode || '',
      MenuID: config.MenuID,
      EasyCode: config.easyCode || '',
      LongParam: _LongParam
    }
@@ -110,29 +476,48 @@
        return
      }
      Api.deleteMenuStorage(this.props.MenuID).then(() => {
      Api.deleteMenuStorage(config.MenuID).then(() => {
        this.setState({
          visible: false,
          confirmLoading: false
        }, () => {
          window.GLOB.CacheMap = new Map()
          this.props.reloadview()
          MKEmitter.emit('reloadMenuView', config.MenuID)
        })
      })
    })
  }
  onChange = (list, parentId) => {
    const { components } = this.state
    this.setState({
      components: components.map(item => {
        if (item.uuid === parentId) {
          item.action = list
        }
        return item
      })
    })
  }
  render() {
    const { components, visible } = this.state
    
    return (
      <div>
        <Icon className="custom-control" type="setting" onClick={this.controlCustomSetting} />
      <div className="page-setting-wrap">
        {options.sysType === 'local' ? <Button
          icon="setting"
          shape="circle"
          className="page-setting"
          onClick={this.trigger}
        /> : null}
        <Modal
          wrapClassName="common-table-custom-modal"
          wrapClassName="custom-setting-modal"
          title={'自定义设置'}
          maskClosable={false}
          width={950}
          visible={this.state.visible}
          visible={visible}
          onCancel={() => { this.setState({ visible: false }) }}
          footer={[
            <Button key="revert" type="danger" loading={this.state.revertLoading} onClick={this.settingRevert}>{this.props.dict['main.revert.default']}</Button>,
@@ -141,17 +526,14 @@
          ]}
          destroyOnClose
        >
          {this.state.visible ?
            <VerifyCard
              MenuID={this.props.MenuID}
              MenuName={this.props.MenuName}
              permAction={this.props.permAction}
              config={this.props.config}
              userConfig={this.props.userConfig}
              columns={this.props.columns}
              handleParam={this.changeMenuParam}
            /> : null
          }
          {components && components.length > 0 ? components.map(item => (
            <div key={item.uuid}>
              <p className="component-title">{item.title}</p>
              <EditTable data={item.action} onChange={(list) => this.onChange(list, item.uuid)}/>
            </div>
          )) : null}
          {components && components.length === 0 ? <Empty /> : null}
          {!components ? <Spin size="large" /> : null}
        </Modal>
      </div>
    )
src/tabviews/zshare/settingcomponent/index.scss
@@ -1,4 +1,24 @@
.common-table-custom-modal {
.page-setting-wrap {
  .page-setting {
    position: fixed;
    z-index: 2;
    bottom: 65px;
    right: 30px;
    width: 40px;
    height: 40px;
  }
}
.custom-popview {
  .page-setting-wrap {
    display: none;
  }
}
.page-message-wrap.exist + .page-setting-wrap {
  .page-setting {
    bottom: 110px;
  }
}
.custom-setting-modal {
  .ant-modal {
    top: 50px;
    padding-bottom: 5px;
@@ -6,8 +26,24 @@
      max-height: calc(100vh - 190px);
      min-height: 250px;
      overflow-y: auto;
      padding-top: 0px;
      position: relative;
      .ant-spin {
        position: absolute;
        left: calc(50% - 22px);
        top: 100px;
      }
      .ant-empty {
        margin: 15vh 8px;
        margin-top: 30px;
      }
      .component-title {
        font-size: 16px;
        display: inline-block;
        margin: 20px 0px 10px 0px;
        padding: 0 10px;
        border-bottom: 2px solid #1890ff;
      }
    }
    .ant-modal-body::-webkit-scrollbar {
src/tabviews/zshare/verifycard/index.jsx
File was deleted
src/tabviews/zshare/verifycard/index.scss
File was deleted
src/tabviews/zshare/verifycard/tabcard/actionform/index.jsx
File was deleted
src/tabviews/zshare/verifycard/tabcard/columnform/index.jsx
File was deleted
src/tabviews/zshare/verifycard/tabcard/columnform/index.scss
src/tabviews/zshare/verifycard/tabcard/index.jsx
File was deleted
src/tabviews/zshare/verifycard/tabcard/index.scss
File was deleted
src/tabviews/zshare/verifycard/tabcard/printform/index.jsx
File was deleted
src/tabviews/zshare/verifycard/tabcard/printform/index.scss
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.jsx
File was deleted
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.scss
src/templates/comtableconfig/index.jsx
@@ -202,20 +202,37 @@
    })
  }
  getFuncNames = (data) => {
  getFuncNames = (config) => {
    let funcNames = []
    let tableNames = []
    data.forEach(item => {
      if (item.tableName) {
        tableNames.push(item.tableName)
      }
      if (item.innerFunc) {
        funcNames.push({func: item.innerFunc, label: item.label || ''})
    if (config.setting.tableName) {
      tableNames.push(config.setting.tableName)
    }
    if (config.setting.innerFunc) {
      funcNames.push({func: config.setting.innerFunc, label: config.MenuName || ''})
    }
    if (config.setting.outerFunc) {
      funcNames.push({func: config.setting.outerFunc, label: config.MenuName || ''})
    }
    config.action.forEach(item => {
      let tablename = item.OpenType === 'excelIn' ? (item.sheet || '') : (item.sql || '')
      if (item.OpenType === 'excelOut' && item.intertype === 'system') {
        tablename = config.setting.tableName || ''
      }
      if (item.callbackFunc) {
        funcNames.push({func: item.callbackFunc, label: item.label || ''})
      if (['pop', 'prompt', 'exec', 'excelIn', 'excelOut', 'funcbutton'].includes(item.OpenType)) {
        if (tablename) {
          tableNames.push(tablename)
        }
        if (item.innerFunc) {
          funcNames.push({func: item.innerFunc, label: item.label || ''})
        }
        if (item.callbackFunc) {
          funcNames.push({func: item.callbackFunc, label: item.label || ''})
        }
      }
    })
@@ -279,70 +296,6 @@
    if (vresult !== true) {
      _config.enabled = false
    }
    _config.funcs = [] // 页面及子页面存储过程集
    _config.funcs.push({
      type: 'view',
      subtype: 'view',
      uuid: menu.MenuID,
      intertype: _config.setting.interType || 'system',
      interface: _config.setting.interface || '',
      tableName: _config.setting.tableName || '',
      innerFunc: _config.setting.innerFunc || '',
      outerFunc: _config.setting.outerFunc || ''
    })
    _config.action.forEach(item => {
      let tablename = item.OpenType === 'excelIn' ? (item.sheet || '') : (item.sql || '')
      if (item.OpenType === 'excelOut' && item.intertype === 'system') {
        tablename = _config.setting.tableName || ''
      }
      if (item.OpenType === 'tab' || item.OpenType === 'blank') {
        _config.funcs.push({
          type: 'tab',
          subtype: 'btn',
          uuid: item.uuid,
          label: item.label,
          linkTab: item.uuid
        })
      } else if (item.OpenType === 'popview') {
        _config.funcs.push({
          type: 'tab',
          subtype: 'btn',
          uuid: item.uuid,
          label: item.label,
          linkTab: item.linkTab
        })
      } else if (['pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(item.OpenType)) {
        _config.funcs.push({
          type: 'button',
          subtype: 'btn',
          uuid: item.uuid,
          label: item.label,
          tableName: tablename,
          intertype: item.intertype,
          interface: item.interface || '',
          innerFunc: item.innerFunc || '',
          outerFunc: item.outerFunc || '',
          callbackFunc: item.callbackFunc || ''
        })
      }
    })
    _config.tabgroups.forEach(group => {
      group.sublist.forEach(tab => {
        _config.funcs.push({
          type: 'tab',
          subtype: 'tab',
          uuid: tab.uuid,
          label: tab.label,
          linkTab: tab.linkTab
        })
      })
    })
    if (this.state.closeVisible) { // 显示关闭对话框时,模态框中保存按钮,显示保存中状态
      this.setState({
@@ -436,7 +389,7 @@
    tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp)
    let _vals = this.getFuncNames(_config.funcs)
    let _vals = this.getFuncNames(_config)
    let param = {
      func: 'sPC_TrdMenu_AddUpt',
src/templates/formtabconfig/index.jsx
@@ -613,6 +613,7 @@
  
          let param = {
            func: 's_debug_sql',
            exec_type: 'y',
            LText: res.dataSource
          }
@@ -620,7 +621,7 @@
          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.secretkey = Utils.encrypt('', param.timestamp)
  
          if (window.GLOB.mainSystemApi && res.database === 'sso') {
            param.rduri = window.GLOB.mainSystemApi
@@ -1469,6 +1470,7 @@
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: res.dataresource
        }
@@ -1476,7 +1478,7 @@
        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.secretkey = Utils.encrypt('', param.timestamp)
        
        Api.getLocalConfig(param).then(result => {
          if (result.status) {
src/templates/menuconfig/editfirstmenu/index.jsx
@@ -363,6 +363,7 @@
            dict={dict}
            type="add"
            menu={null}
            inputSubmit={this.addMemuSubmit}
            wrappedComponentRef={(inst) => this.addMenuFormRef = inst}
          />
        </Modal>
@@ -392,6 +393,7 @@
            dict={dict}
            type="edit"
            menu={this.state.editMenu}
            inputSubmit={this.editMemuSubmit}
            wrappedComponentRef={(inst) => this.editMenuFormRef = inst}
          />
        </Modal>
src/templates/menuconfig/editfirstmenu/menuform/index.jsx
@@ -6,9 +6,10 @@
class MainSearch extends Component {
  static propTpyes = {
    menu: PropTypes.any, // 搜索条件列表
    dict: PropTypes.object, // 字典项
    type: PropTypes.string // 字典项
    menu: PropTypes.any,         // 菜单信息,新建时为null
    dict: PropTypes.object,      // 字典项
    type: PropTypes.string,      // 操作类型
    inputSubmit: PropTypes.func
  }
  state = {
@@ -115,7 +116,7 @@
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
              })(<Input placeholder="" autoFocus={item.key.toLowerCase() === 'menuname'} autoComplete="off" disabled={item.readonly} />)}
            </Form.Item>
          </Col>
        )
@@ -136,7 +137,7 @@
                  showSearch
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  onChange={(value) => {this.openTypeChange(item.key, value)}}
                  getPopupContainer={() => document.getElementById('form-box')}
                  getPopupContainer={() => document.getElementById('first-menu-form-box')}
                >
                  {item.options.map(option =>
                    <Select.Option key={option.id} value={option.id}>{option.text}</Select.Option>
@@ -209,6 +210,13 @@
    })
  }
  onEnterSubmit = (e) => {
    // 表单回车提交
    if (e.key !== 'Enter') return
    this.props.inputSubmit && this.props.inputSubmit()
  }
  render() {
    const formItemLayout = {
      labelCol: {
@@ -221,7 +229,7 @@
      }
    }
    return (
      <Form {...formItemLayout} className="ant-advanced-search-form" id="form-box">
      <Form {...formItemLayout} className="ant-advanced-search-form" id="first-menu-form-box" onKeyDown={this.onEnterSubmit}>
        <Row gutter={24}>{this.getFields()}</Row>
      </Form>
    )
src/templates/menuconfig/editsecmenu/index.jsx
@@ -444,6 +444,7 @@
          {this.state.formlist ?
            <MenuForm
              dict={dict}
              inputSubmit={this.memuHandleSubmit}
              formlist={this.state.formlist}
              wrappedComponentRef={(inst) => this.menuFormRef = inst}
            /> : null}
src/templates/menuconfig/editthdmenu/index.jsx
@@ -21,6 +21,7 @@
import MenuForm from './menuform'
import TransferForm from '@/templates/zshare/basetransferform'
import Utils from '@/utils/utils.js'
import MenuUtils from '@/menu/utils/menuUtils.js'
import DragElement from '../menuelement'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import './index.scss'
@@ -627,9 +628,7 @@
        OpenType: 'newtab'
      }
      if (sysMenu.OriginMenuId && sysMenu.Template === 'CustomPage') {
        PageParam.originMenuId = sysMenu.OriginMenuId
      } else if (sysMenu.Template === 'NewPage') {
      if (sysMenu.Template === 'NewPage') {
        PageParam.OpenType = 'NewPage'
        PageParam.url = res.url
      }
@@ -660,31 +659,95 @@
        confirmLoading: true
      })
      Api.getSystemConfig(param).then(response => {
        if (response.status) {
          this.setState({
            sysTemplates: sysTemplates,
            confirmLoading: false,
            handleMVisible: false,
            sysMenu: '',
            tabview: ''
          })
          this.props.reload()
        } else {
          this.setState({
            confirmLoading: false
          })
          notification.warning({
            top: 92,
            message: response.message,
            duration: 5
          })
        }
      })
      if (sysMenu.Template === 'CustomPage' && sysMenu.OriginMenuId) {
        this.copyMenu(param, sysMenu.OriginMenuId)
      } else {
        Api.getSystemConfig(param).then(response => {
          if (response.status) {
            this.setState({
              sysTemplates: sysTemplates,
              confirmLoading: false,
              handleMVisible: false,
              sysMenu: '',
              tabview: ''
            })
            this.props.reload()
          } else {
            this.setState({
              confirmLoading: false
            })
            notification.warning({
              top: 92,
              message: response.message,
              duration: 5
            })
          }
        })
      }
    })
  }
  copyMenu = (param, MenuId) => {
    Api.getSystemConfig({
      func: 'sPC_Get_LongParam',
      MenuID: MenuId
    }).then(result => {
      if (result.status) {
        let config = null
        try {
          config = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : null
        } catch (e) {
          console.warn('Parse Failure')
          config = null
        }
        if (config) {
          config.uuid = param.MenuID
          config.MenuID = param.MenuID
          config.parentId = param.ParentID
          config.MenuName = param.MenuName
          config.MenuNo = param.MenuNo
          config.easyCode = ''
          config.components = MenuUtils.resetConfig(config.components)
          param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
        }
        Api.getSystemConfig(param).then(response => {
          if (response.status) {
            this.setState({
              confirmLoading: false,
              handleMVisible: false,
              sysMenu: '',
              tabview: ''
            })
            this.props.reload()
          } else {
            this.setState({
              confirmLoading: false
            })
            notification.warning({
              top: 92,
              message: response.message,
              duration: 5
            })
          }
        })
      } else {
        this.setState({
          confirmLoading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
      }
    })
  }
  UNSAFE_componentWillMount () {
    this.getUsedTemplate()
@@ -883,6 +946,7 @@
          <MenuForm
            menu={this.state.sysMenu}
            dict={dict}
            inputSubmit={this.memuSubmit}
            wrappedComponentRef={(inst) => this.menuFormRef = inst}
          />
        </Modal>
src/templates/menuconfig/editthdmenu/menuform/index.jsx
@@ -6,9 +6,10 @@
class MainSearch extends Component {
  static propTpyes = {
    menu: PropTypes.object,     // 菜单信息
    dict: PropTypes.object,     // 字典项
    supMenuList: PropTypes.any  // 表格数据
    menu: PropTypes.object,      // 菜单信息
    dict: PropTypes.object,      // 字典项
    supMenuList: PropTypes.any,  // 表格数据
    inputSubmit: PropTypes.func  // 回车提交
  }
  state = {
@@ -48,6 +49,13 @@
    })
  }
  onEnterSubmit = (e) => {
    // 表单回车提交
    if (e.key !== 'Enter') return
    this.props.inputSubmit && this.props.inputSubmit()
  }
  render() {
    const { getFieldDecorator } = this.props.form
    const { menu } = this.state
@@ -63,7 +71,7 @@
    }
    return (
      <Form {...formItemLayout} style={{paddingRight: '20px'}}>
      <Form {...formItemLayout} style={{paddingRight: '20px'}} onKeyDown={this.onEnterSubmit}>
        <Row gutter={24}>
          <Col span={24}>
            <Form.Item label={'一级菜单'}>
@@ -120,7 +128,7 @@
                    message: this.props.dict['form.required.input'] + '菜单名称!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" />)}
              })(<Input placeholder="" autoFocus autoComplete="off" />)}
            </Form.Item>
          </Col>
          <Col span={24}>
src/templates/menuconfig/menuform/index.jsx
@@ -5,8 +5,9 @@
class MainSearch extends Component {
  static propTpyes = {
    dict: PropTypes.object, // 字典项
    formlist: PropTypes.array
    dict: PropTypes.object,     // 字典项
    formlist: PropTypes.array,
    inputSubmit: PropTypes.func
  }
  openTypeChange = (key, value) => {
@@ -46,7 +47,7 @@
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
              })(<Input placeholder="" autoFocus={item.key.toLowerCase() === 'menuname'} autoComplete="off" disabled={item.readonly} />)}
            </Form.Item>
          </Col>
        )
@@ -97,6 +98,13 @@
    })
  }
  onEnterSubmit = (e) => {
    // 表单回车提交
    if (e.key !== 'Enter') return
    this.props.inputSubmit && this.props.inputSubmit()
  }
  render() {
    const formItemLayout = {
      labelCol: {
@@ -109,7 +117,7 @@
      }
    }
    return (
      <Form {...formItemLayout} className="ant-advanced-search-form" id="form-box">
      <Form {...formItemLayout} className="ant-advanced-search-form" id="form-box" onKeyDown={this.onEnterSubmit}>
        <Row gutter={24}>{this.getFields()}</Row>
      </Form>
    )
src/templates/modalconfig/index.jsx
@@ -414,6 +414,7 @@
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: res.dataSource
        }
@@ -421,7 +422,7 @@
        
        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.secretkey = Utils.encrypt('', param.timestamp)
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          param.rduri = window.GLOB.mainSystemApi
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -122,19 +122,35 @@
          aaa:
        `
        let _initsql = ''
        this.props.scripts.forEach(script => {
          if (this.state.editItem && this.state.editItem.uuid === script.uuid) return
          if (script.status === 'false' || script.position !== 'init') return
        let _initCustomScript = '' // 初始化脚本
        let _prevCustomScript = '' // 默认sql前执行脚本
        let _backCustomScript = '' // 默认sql后执行脚本
          _initsql += `
            ${script.sql}
        this.props.scripts.forEach(item => {
          if (item.status === 'false') return
          if (item.position === 'init') {
            _initCustomScript += `
            /* 初始化脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else if (item.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          }
        })
        let param = {
          func: 's_debug_sql',
          LText: this.state.verifySql + _initsql + values.sql + tail
          exec_type: 'y',
          LText: this.state.verifySql + _initCustomScript + _prevCustomScript + _backCustomScript + tail
        }
        param.LText = param.LText.replace(/@\$|\$@/ig, '')
@@ -146,7 +162,7 @@
        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.secretkey = Utils.encrypt('', param.timestamp)
        
        this.setState({loading: true})
        Api.getLocalConfig(param).then(res => {
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -308,6 +308,7 @@
    
            let param = {
              func: 's_debug_sql',
              exec_type: 'y',
              LText: values.sql
            }
    
@@ -315,7 +316,7 @@
    
            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.secretkey = Utils.encrypt('', param.timestamp)
            
            Api.getLocalConfig(param).then(res => {
              if (res.status) {
src/templates/sharecomponent/searchcomponent/index.jsx
@@ -194,6 +194,7 @@
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: res.dataSource
        }
@@ -201,7 +202,7 @@
        
        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.secretkey = Utils.encrypt('', param.timestamp)
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          param.rduri = window.GLOB.mainSystemApi
src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
@@ -278,11 +278,12 @@
    } else if (setting.execute !== 'false' || _scripts.length > 0) {
      let param = {
        func: 's_debug_sql',
        exec_type: 'y',
        LText: SettingUtils.getDebugSql(setting, _scripts, columns, Utils.getRegOptions(searches), config.calendar)
      }
      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.secretkey = Utils.encrypt('', param.timestamp)
      
      Api.getLocalConfig(param).then(result => {
        if (result.status) {
src/templates/sharecomponent/settingcomponent/settingform/index.jsx
@@ -265,11 +265,12 @@
    } else { // type 为 submit 、 verify ,以及其他需要验证的场景
      let param = {
        func: 's_debug_sql',
        exec_type: 'y',
        LText: SettingUtils.getDebugSql(setting, _scripts, arr_field, regoptions, search)
      }
      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.secretkey = Utils.encrypt('', param.timestamp)
      
      Api.getLocalConfig(param).then(result => {
        if (result.status) {
src/templates/sharecomponent/settingcomponent/settingform/index.scss
@@ -59,4 +59,7 @@
    border: 0;
    box-shadow: unset;
  }
  .ant-tabs-nav-wrap {
    text-align: center;
  }
}
src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
@@ -124,11 +124,12 @@
    } else { // type 为 submit 、 verify ,以及其他需要验证的场景
      let param = {
        func: 's_debug_sql',
        exec_type: 'y',
        LText: SettingUtils.getDebugSql(setting, _scripts)
      }
      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.secretkey = Utils.encrypt('', param.timestamp)
      
      Api.getLocalConfig(param).then(result => {
        if (result.status) {
src/templates/treepageconfig/index.jsx
@@ -164,30 +164,6 @@
    })
  }
  getFuncNames = (data, funcNames, tableNames) => {
    data.forEach(item => {
      // if (item.subfuncs) {
      //   this.getFuncNames(item.subfuncs, funcNames, tableNames)
      //   return
      // }
      if (item.tableName) {
        tableNames.push(item.tableName)
      }
      if (item.innerFunc) {
        funcNames.push({func: item.innerFunc, label: item.label || ''})
      }
      if (item.callbackFunc) {
        funcNames.push({func: item.callbackFunc, label: item.label || ''})
      }
    })
    return {
      func: funcNames,
      table: tableNames
    }
  }
  /**
   * @description 三级菜单保存
   */
@@ -231,31 +207,6 @@
      _config.enabled = false
    }
    _config.funcs = [] // 页面及子页面存储过程集
    _config.funcs.push({
      type: 'view',
      subtype: 'view',
      uuid: menu.MenuID,
      intertype: _config.setting.interType || 'inner',
      interface: _config.setting.interface || '',
      tableName: _config.setting.tableName || '',
      innerFunc: _config.setting.innerFunc || '',
      outerFunc: _config.setting.outerFunc || ''
    })
    _config.tabgroups.forEach(group => {
      group.sublist.forEach(tab => {
        _config.funcs.push({
          type: 'tab',
          subtype: 'tab',
          uuid: tab.uuid,
          label: tab.label,
          linkTab: tab.linkTab
        })
      })
    })
    if (this.state.closeVisible) { // 显示关闭对话框时,模态框中保存按钮,显示保存中状态
      this.setState({
        menucloseloading: true
@@ -266,258 +217,224 @@
      })
    }
    new Promise(resolve => {
      // let deffers = []
      // _config.funcs.forEach(item => {
      //   if (item.type === 'tab') {
      //     let deffer = new Promise(resolve => {
      //       Api.getSystemConfig({
      //         func: 'sPC_Get_LongParam',
      //         MenuID: item.linkTab
      //       }).then(result => {
      //         if (result.status && result.LongParam) {
      //           let _LongParam = ''
      //           if (result.LongParam) {
      //             try {
      //               _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
      //             } catch (e) {
      //               console.warn('Parse Failure')
      //               _LongParam = ''
      //             }
      //           }
    // 保存时删除配置类型,system 、user
    delete _config.type
    delete _config.isAdd
    let _LongParam = ''
    try {
      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
    } catch (e) {
      notification.warning({
        top: 92,
        message: '编译错误',
        duration: 5
      })
      this.setState({
        menucloseloading: false,
        menuloading: false
      })
      return
    }
    let _sort = 0
    let btntabs = []
    
      //           if (_LongParam) {
      //             item.menuNo = _LongParam.tabNo || ''
      //             item.subfuncs = _LongParam.funcs || []
      //           }
      //         }
      //         resolve()
      //       })
      //     })
    let tabParam = { // 添加菜单tab页
      func: 'sPC_sMenusTab_AddUpt',
      MenuID: menu.MenuID
    }
      //     deffers.push(deffer)
      //   }
      // })
    let _LText = []
      // if (deffers.length === 0) {
      //   resolve()
      // } else {
      //   Promise.all(deffers).then(() => {
      //     resolve()
      //   })
      // }
      resolve()
    }).then(() => {
      // 保存时删除配置类型,system 、user
      delete _config.type
      delete _config.isAdd
      let _LongParam = ''
      try {
        _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
      } catch (e) {
        notification.warning({
          top: 92,
          message: '编译错误',
          duration: 5
        })
        this.setState({
          menucloseloading: false,
          menuloading: false
        })
        return
      }
      let _sort = 0
      let btntabs = []
      let tabParam = { // 添加菜单tab页
        func: 'sPC_sMenusTab_AddUpt',
        MenuID: menu.MenuID
      }
      let _LText = []
      btntabs.forEach(item => {
        _LText.push(`select '${item.uuid}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${item.sort * 10}' as Sort`)
    btntabs.forEach(item => {
      _LText.push(`select '${item.uuid}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${item.sort * 10}' as Sort`)
    })
    _config.tabgroups.forEach(group => {
      group.sublist.forEach(item => {
        _sort++
        _LText.push(`select '${menu.MenuID}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${_sort * 10}' as Sort`)
      })
      _config.tabgroups.forEach(group => {
        group.sublist.forEach(item => {
          _sort++
          _LText.push(`select '${menu.MenuID}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${_sort * 10}' as Sort`)
        })
      })
    })
      _LText = _LText.join(' union all ')
    _LText = _LText.join(' union all ')
      tabParam.LText = Utils.formatOptions(_LText)
      tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp)
    tabParam.LText = Utils.formatOptions(_LText)
    tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp)
      let _vals = this.getFuncNames(_config.funcs, [], [])
      let _tables = Array.from(new Set(_vals.table))
    let _funcs = []
    let _tables = []
      let param = {
        func: 'sPC_TrdMenu_AddUpt',
        FstID: _config.fstMenuId,
        SndID: _config.ParentId,
        ParentID: _config.ParentId,
        MenuID: menu.MenuID,
        MenuNo: _config.MenuNo,
        EasyCode: _config.easyCode,
        Template: _config.Template,
        MenuName: _config.MenuName,
        PageParam: JSON.stringify({...menu.PageParam, Template: _config.Template, OpenType: _config.OpenType}),
        LongParam: _LongParam,
        LText: _vals.func.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`),
        LTexttb: _tables.map(item => `select '${menu.MenuID}' as MenuID,'${item}' as tbName`)
      }
    if (_config.setting.tableName) {
      _tables.push(_config.setting.tableName)
    }
    if (_config.setting.innerFunc) {
      _funcs.push({func: _config.setting.innerFunc, label: _config.MenuName || ''})
    }
    if (_config.setting.outerFunc) {
      _funcs.push({func: _config.setting.outerFunc, label: _config.MenuName || ''})
    }
      if (menu.menuSort) { // 菜单新建时设置排序
        param.Sort = menu.menuSort
      }
    let param = {
      func: 'sPC_TrdMenu_AddUpt',
      FstID: _config.fstMenuId,
      SndID: _config.ParentId,
      ParentID: _config.ParentId,
      MenuID: menu.MenuID,
      MenuNo: _config.MenuNo,
      EasyCode: _config.easyCode,
      Template: _config.Template,
      MenuName: _config.MenuName,
      PageParam: JSON.stringify({...menu.PageParam, Template: _config.Template, OpenType: _config.OpenType}),
      LongParam: _LongParam,
      LText: _funcs.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`),
      LTexttb: _tables.map(item => `select '${menu.MenuID}' as MenuID,'${item}' as tbName`)
    }
      param.LText = param.LText.join(' union all ')
      param.LText = Utils.formatOptions(param.LText)
      param.LTexttb = param.LTexttb.join(' union all ')
      param.LTexttb = Utils.formatOptions(param.LTexttb)
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    if (menu.menuSort) { // 菜单新建时设置排序
      param.Sort = menu.menuSort
    }
      if (openEdition) { // 版本管理
        param.open_edition = openEdition
      }
    param.LText = param.LText.join(' union all ')
    param.LText = Utils.formatOptions(param.LText)
    param.LTexttb = param.LTexttb.join(' union all ')
    param.LTexttb = Utils.formatOptions(param.LTexttb)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
      // 有按钮或标签删除时,先进行删除操作
      // 删除成功后,保存页面配置
      new Promise(resolve => {
        if (delTabs.length > 0) {
          let deffers = delTabs.map(item => {
            let _param = {
              func: 'sPC_MainMenu_Del',
              MenuID: item.uuid
            }
    if (openEdition) { // 版本管理
      param.open_edition = openEdition
    }
            return new Promise(resolve => {
              Api.getSystemConfig(_param).then(response => {
                resolve(response)
              })
    // 有按钮或标签删除时,先进行删除操作
    // 删除成功后,保存页面配置
    new Promise(resolve => {
      if (delTabs.length > 0) {
        let deffers = delTabs.map(item => {
          let _param = {
            func: 'sPC_MainMenu_Del',
            MenuID: item.uuid
          }
          return new Promise(resolve => {
            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) {
              this.setState({
                menuloading: false,
                menucloseloading: false
              })
              notification.warning({
                top: 92,
                message: error.message,
                duration: 5
              })
              resolve(false)
            } else {
              this.setState({
                delTabs: []
              })
              resolve(true)
        })
        Promise.all(deffers).then(result => {
          let error = null
          result.forEach(response => {
            if (!response.status) {
              error = response
            }
          })
        } else if (delTabs.length === 0) {
          resolve(true)
        }
      }).then(resp => {
        if (resp === false) return
        let localParam = fromJS(param).toJS()
        localParam.func = 'sPC_TrdMenu_AddUpt_For_Local'
        delete localParam.LongParam
        delete localParam.PageParam
        delete localParam.Template
        delete localParam.Sort
        delete localParam.EasyCode
        delete localParam.open_edition
        Api.getSystemConfig(param).then(response => {
          if (response.status) {
            this.setState({
              config: _config,
              openEdition: response.open_edition || '',
              originMenu: fromJS(_config).toJS()
            })
            // 存在标签页时
            if (tabParam.LText) {
              Api.getSystemConfig(tabParam).then(result => {
                if (result.status) {
                  notification.success({
                    top: 92,
                    message: '保存成功',
                    duration: 2
                  })
                  this.props.reloadmenu()
                  Api.getLocalConfig(localParam)
                  if (this.state.closeVisible) {
                    this.props.handleView()
                  } else {
                    this.setState({
                      menuloading: false,
                      menucloseloading: false
                    })
                  }
                } else {
                  notification.warning({
                    top: 92,
                    message: result.message,
                    duration: 5
                  })
                  this.setState({
                    menuloading: false,
                    menucloseloading: false
                  })
                }
              })
            } else {
              notification.success({
                top: 92,
                message: '保存成功',
                duration: 2
              })
              this.props.reloadmenu()
              Api.getLocalConfig(localParam)
              if (this.state.closeVisible) {
                this.props.handleView()
              } else {
                this.setState({
                  menuloading: false,
                  menucloseloading: false
                })
              }
            }
          } else {
          if (error) {
            this.setState({
              menuloading: false,
              menucloseloading: false
            })
            notification.warning({
              top: 92,
              message: response.message,
              message: error.message,
              duration: 5
            })
            resolve(false)
          } else {
            this.setState({
              delTabs: []
            })
            resolve(true)
          }
        })
      } else if (delTabs.length === 0) {
        resolve(true)
      }
    }).then(resp => {
      if (resp === false) return
      let localParam = fromJS(param).toJS()
      localParam.func = 'sPC_TrdMenu_AddUpt_For_Local'
      delete localParam.LongParam
      delete localParam.PageParam
      delete localParam.Template
      delete localParam.Sort
      delete localParam.EasyCode
      delete localParam.open_edition
      Api.getSystemConfig(param).then(response => {
        if (response.status) {
          this.setState({
            config: _config,
            openEdition: response.open_edition || '',
            originMenu: fromJS(_config).toJS()
          })
          // 存在标签页时
          if (tabParam.LText) {
            Api.getSystemConfig(tabParam).then(result => {
              if (result.status) {
                notification.success({
                  top: 92,
                  message: '保存成功',
                  duration: 2
                })
                this.props.reloadmenu()
                Api.getLocalConfig(localParam)
                if (this.state.closeVisible) {
                  this.props.handleView()
                } else {
                  this.setState({
                    menuloading: false,
                    menucloseloading: false
                  })
                }
              } else {
                notification.warning({
                  top: 92,
                  message: result.message,
                  duration: 5
                })
                this.setState({
                  menuloading: false,
                  menucloseloading: false
                })
              }
            })
          } else {
            notification.success({
              top: 92,
              message: '保存成功',
              duration: 2
            })
            this.props.reloadmenu()
            Api.getLocalConfig(localParam)
            if (this.state.closeVisible) {
              this.props.handleView()
            } else {
              this.setState({
                menuloading: false,
                menucloseloading: false
              })
            }
          }
        } else {
          this.setState({
            menuloading: false,
            menucloseloading: false
          })
          notification.warning({
            top: 92,
            message: response.message,
            duration: 5
          })
        }
      })
    })
  }
src/templates/zshare/editTable/index.jsx
@@ -471,8 +471,12 @@
        cell: EditableCell
      }
    }
    let moveprops = {}
    if (actions.includes('move')) {
      components.body.row = DragableBodyRow
      moveprops.moveAble = !this.state.editingKey
      moveprops.moveRow = this.moveRow
    }
    
    const columns = this.state.columns.map(col => {
@@ -509,8 +513,7 @@
              pagination={false}
              onRow={(record, index) => ({
                index,
                moveAble: !this.state.editingKey,
                moveRow: this.moveRow,
                ...moveprops
              })}
            />
          </DndProvider>
src/templates/zshare/formconfig.jsx
@@ -385,7 +385,7 @@
      type: 'radio',
      key: 'setAll',
      label: Formdict['header.form.setAll'],
      initVal: card.setAll || 'false',
      initVal: card.setAll || 'true',
      options: [{
        value: 'true',
        text: Formdict['model.true']
@@ -2318,6 +2318,15 @@
      }]
    },
    {
      type: 'text',
      key: 'suffix',
      label: '后缀名',
      tooltip: '可以上传文件的后缀名,多个类型用逗号分隔,空值时不校验。',
      initVal: card.suffix || '',
      required: false,
      readonly: false
    },
    {
      type: 'radio',
      key: 'encryption',
      label: '加密传输',
src/templates/zshare/modalform/index.jsx
@@ -22,7 +22,7 @@
  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'fieldlength', 'display', 'tooltip', 'width', 'multiple'],
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'entireLine', 'tooltip'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'entireLine', 'tooltip', 'emptyText', 'enter'],
  fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'entireLine', 'tooltip'],
  fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'entireLine', 'tooltip', 'suffix'],
  switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'entireLine', 'tooltip'],
  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine', 'tooltip'],
  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'entireLine', 'tooltip'],
src/templates/zshare/verifycard/customform/index.jsx
@@ -97,6 +97,7 @@
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: this.props.initsql + values.sql
        }
@@ -110,7 +111,7 @@
        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.secretkey = Utils.encrypt('', param.timestamp)
        
        this.setState({loading: true})
        Api.getLocalConfig(param).then(res => {
src/templates/zshare/verifycard/customscript/index.jsx
@@ -37,10 +37,11 @@
  }
  handleConfirm = () => {
    const { editItem } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        values.uuid = editItem ? editItem.uuid : ''
        let _quot = values.sql.match(/'{1}/g)
        let _lparen = values.sql.match(/\({1}/g)
@@ -88,19 +89,35 @@
          aaa:
        `
        let _initsql = ''
        this.props.customScripts.forEach(script => {
          if (this.state.editItem && this.state.editItem.uuid === script.uuid) return
          if (script.status === 'false' || script.position !== 'init') return
        let _initCustomScript = '' // 初始化脚本
        let _prevCustomScript = '' // 默认sql前执行脚本
        let _backCustomScript = '' // 默认sql后执行脚本
          _initsql += `
            ${script.sql}
        this.props.customScripts.forEach(item => {
          if (item.status === 'false') return
          if (item.position === 'init') {
            _initCustomScript += `
            /* 初始化脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else if (item.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          }
        })
        let param = {
          func: 's_debug_sql',
          LText: this.props.initsql + _initsql + values.sql + tail
          exec_type: 'y',
          LText: this.props.initsql + _initCustomScript + _prevCustomScript + _backCustomScript + tail
        }
        // 数据权限
@@ -115,7 +132,7 @@
        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.secretkey = Utils.encrypt('', param.timestamp)
        
        this.setState({loading: true})
        Api.getLocalConfig(param).then(res => {
src/utils/utils-datamanage.js
@@ -135,7 +135,7 @@
        value: orderBy
      }, {
        reg: new RegExp('@pageSize@', 'ig'),
        value: pageSize
        value: setting.laypage ? pageSize : '9999'
      }, {
        reg: new RegExp('@pageIndex@', 'ig'),
        value: pageIndex
src/views/login/index.jsx
@@ -288,8 +288,12 @@
    Api.getTouristMsg().then(result => {
      if (result.status) {
        result.UserID && sessionStorage.setItem('UserID', result.UserID)
        result.LoginUID && sessionStorage.setItem('LoginUID', result.LoginUID)
        if (result.UserID && !sessionStorage.getItem('UserID')) {
          sessionStorage.setItem('UserID', result.UserID)
        }
        if (result.LoginUID && !sessionStorage.getItem('LoginUID')) {
          sessionStorage.setItem('LoginUID', result.LoginUID)
        }
        if (result.UserID && result.LoginUID) {
          this.setState({touristLogin: true})
src/views/login/index.scss
@@ -22,6 +22,7 @@
      font-weight: 600;
      padding-left: 20px;
      font-family: "黑体","宋体",sans-serif,"Arial","Microsoft YaHei";
      z-index: 1;
    }
  }
@@ -99,7 +100,7 @@
      min-width: 300px;
      border-radius: 5px;
      overflow: hidden;
      border: 1px solid #e8e8e8;
      border: 1px solid #bfbfbf;
      .form-item-wrap {
        padding: 0.6vw 1.6vw 1.6vw;
src/views/menudesign/index.jsx
@@ -14,6 +14,7 @@
import antdEnUS from 'antd/es/locale/en_US'
import antdZhCN from 'antd/es/locale/zh_CN'
import MKEmitter from '@/utils/events.js'
import MenuUtils from '@/menu/utils/menuUtils.js'
import asyncComponent from '@/utils/asyncComponent'
import { modifyCustomMenu } from '@/store/action'
@@ -33,12 +34,16 @@
const PasteController = asyncComponent(() => import('@/menu/pastecontroller'))
const PaddingController = asyncComponent(() => import('@/menu/padcontroller'))
const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
const StyleCombController = asyncComponent(() => import('@/menu/stylecombcontroller'))
const StyleCombControlButton = asyncComponent(() => import('@/menu/stylecombcontrolbutton'))
const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller'))
const PopviewController = asyncComponent(() => import('@/menu/popview'))
const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
sessionStorage.setItem('isEditState', 'true')
sessionStorage.setItem('editMenuType', 'menu') // 编辑菜单类型
document.body.className = ''
window.GLOB.UserComponentMap = new Map() // 缓存用户自定义组件
class MenuDesign extends Component {
  state = {
@@ -51,13 +56,15 @@
    tableFields: [],
    delButtons: [],
    copyButtons: [],
    thawButtons: [],
    activeKey: 'basedata',
    menuloading: false,
    oriConfig: null,
    openEdition: '',
    config: null,
    popBtn: null,             // 弹窗标签页
    visible: false
    visible: false,
    customComponents: []
  }
  UNSAFE_componentWillMount() {
@@ -88,8 +95,12 @@
  componentDidMount () {
    MKEmitter.addListener('delButtons', this.delButtons)
    MKEmitter.addListener('thawButtons', this.thawButtons)
    MKEmitter.addListener('copyButtons', this.copyButtons)
    MKEmitter.addListener('changePopview', this.initPopview)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
    MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent)
    this.updateCustomComponent()
  }
  /**
@@ -100,15 +111,85 @@
      return
    }
    MKEmitter.removeListener('delButtons', this.delButtons)
    MKEmitter.removeListener('thawButtons', this.thawButtons)
    MKEmitter.removeListener('copyButtons', this.copyButtons)
    MKEmitter.removeListener('changePopview', this.initPopview)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
    MKEmitter.removeListener('updateCustomComponent', this.updateCustomComponent)
  }
  updateCustomComponent = () => {
    Api.getSystemConfig({
      func: 's_get_custom_components',
      typecharone: ''
    }).then(res => {
      let coms = []
      if (res.cus_list && res.cus_list.length > 0) {
        res.cus_list.forEach(item => {
          let config = ''
          try {
            config = JSON.parse(window.decodeURIComponent(window.atob(item.long_param)))
          } catch (e) {
            console.warn('Parse Failure')
            config = ''
          }
          if (!config || !item.c_name) return
          window.GLOB.UserComponentMap.set(item.c_id, item.c_name)
          coms.push({
            uuid: item.c_id,
            type: 'menu',
            title: item.c_name,
            url: item.images,
            component: config.type,
            subtype: config.subtype,
            width: config.width || 24,
            config
          })
        })
      }
      this.setState({customComponents: coms})
    })
  }
  updateComponentStyle = (parentId, keys, style) => {
    const { config } = this.state
    if (config.uuid !== parentId) return
    let components = config.components.map(item => {
      if (keys.includes(item.uuid)) {
        item.style = {...item.style, ...style}
      }
      return item
    })
    this.setState({
      config: {...config, components: []}
    }, () => {
      this.setState({
        config: {...config, components: components}
      })
    })
  }
  delButtons = (items) => {
    this.setState({delButtons: [...this.state.delButtons, ...items]})
    const { copyButtons } = this.state
    this.setState({
      delButtons: [...this.state.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]})
  }
  initPopview = (card, btn) => {
@@ -129,11 +210,15 @@
    btn.config = _config
    btn.component = card
    sessionStorage.setItem('editMenuType', 'popview') // 编辑弹窗标签
    this.setState({popBtn: btn, visible: true})
  }
  handleBack = () => {
    this.setState({popBtn: null, delButtons: []}, () => {
    this.setState({popBtn: null, delButtons: [], copyButtons: []}, () => {
      sessionStorage.setItem('editMenuType', 'menu')
      this.props.modifyCustomMenu(this.state.config)
      this.setState({visible: false})
    })
  }
@@ -210,6 +295,7 @@
        } else {
          config.uuid = MenuId
          config.MenuID = MenuId
          config.Template = 'CustomPage'
        }
        if (MenuType === 'billPrint') {
@@ -228,6 +314,7 @@
          openEdition: result.open_edition || '',
        })
        this.props.modifyCustomMenu(config)
        this.getRoleFields()
      } else {
        notification.warning({
@@ -316,7 +403,7 @@
  }
  submitConfig = () => {
    const { openEdition, MenuType, delButtons } = this.state
    const { openEdition, MenuType, delButtons, copyButtons, thawButtons } = this.state
    let config = fromJS(this.state.config).toJS()
    if (MenuType === 'billPrint' && (!config.firstCount || !config.everyPCount)) {
@@ -386,9 +473,13 @@
      LText: []
    }
    let btnIds = '' // 用于复制按钮的过滤
    if (MenuType !== 'billPrint') {
      btnParam.LText = this.getMenuMessage()
      btnParam.LText = btnParam.LText.join(' union all ')
      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)
@@ -400,7 +491,7 @@
      menuloading: true
    }, () => {
      new Promise(resolve => {
        if (MenuType === 'billPrint') {
        if (MenuType === 'billPrint') { // 打印生成页面效果图
          html2canvas(document.getElementById('menu-shell-inner')).then(canvas => {
            let img = canvas.toDataURL('image/png') // 获取生成的图片
            Api.fileuploadbase64(img, 'cloud').then(result => {
@@ -420,9 +511,6 @@
                      message: response.message,
                      duration: 5
                    })
                    this.setState({
                      menuloading: false
                    })
                    resolve(false)
                  }
                })
@@ -432,9 +520,6 @@
                  message: result.ErrMesg,
                  duration: 5
                })
                this.setState({
                  menuloading: false
                })
                resolve(false)
              }
            })
@@ -442,7 +527,7 @@
        } else {
          resolve(true)
        }
      }).then(res => {
      }).then(res => { // 按钮删除
        if (!res) return
        if (delButtons.length === 0) {
@@ -456,18 +541,9 @@
          }
          return Api.getSystemConfig(_param)
        }
      }).then(res => {
      }).then(res => { // 按钮解除冻结
        if (!res) return
        if (res.status) {
          this.setState({
            delButtons: []
          })
          return Api.getSystemConfig(param)
        } else {
          this.setState({
            menuloading: false
          })
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
@@ -475,7 +551,32 @@
          })
          return false
        }
      }).then(res => {
        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 => { // 页面按钮关系保存
        if (!res) return
        if (res.status) {
@@ -492,9 +593,6 @@
            }
          }
        } else {
          this.setState({
            menuloading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
@@ -502,11 +600,105 @@
          })
          return false
        }
      }).then(res => {
      }).then(res => { // 按钮复制
        if (!res) return
        if (res.status) {
        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 = 'CustomPage'
                    } else {
                      resolve({
                        status: true
                      })
                      return
                    }
                    let _param = {
                      func: 'sPC_ButtonParam_AddUpt',
                      ParentID: _config.uuid,
                      MenuID: item.uuid,
                      MenuNo: '',
                      Template: 'CustomPage',
                      MenuName: item.label,
                      PageParam: JSON.stringify({Template: 'CustomPage'}),
                      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: []}
          }, () => {
@@ -522,11 +714,6 @@
        } else {
          this.setState({
            menuloading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
        }
      })
@@ -646,7 +833,7 @@
  }
  render () {
    const { activeKey, MenuType, popBtn, visible, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading } = this.state
    const { activeKey, MenuType, popBtn, visible, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading, customComponents } = this.state
    return (
      <ConfigProvider locale={_locale}>
@@ -685,6 +872,9 @@
                  <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>
@@ -698,6 +888,7 @@
                  <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>
@@ -711,6 +902,7 @@
          </DndProvider> : null}
          {popBtn && visible ? <PopviewController btn={popBtn} handleBack={this.handleBack}/> : null}
          <StyleController />
          <StyleCombController />
          <ModalController />
        </div>
      </ConfigProvider>
src/views/menudesign/index.scss
@@ -8,15 +8,7 @@
    position: relative;
    background: #ffffff;
    padding: 50px 0px 0px 0px;
    // .menu-setting::before {
    //   content: ' ';
    //   position: absolute;
    //   width: 300px;
    //   height: 100%;
    //   left: 0;
    //   top: 0;
    // }
    .menu-setting {
      position: fixed;
      left: 0;
@@ -27,6 +19,7 @@
      background: #ffffff;
      box-shadow: 0px 2px 5px #bcbcbc;
      overflow-y: auto;
      overflow-x: hidden;
      > .ant-collapse {
        background-color: #ffffff;
@@ -116,6 +109,7 @@
      > .ant-card {
        >.ant-card-head {
          margin-bottom: 0px;
          position: relative;
          .ant-card-head-title {
            color: #1890ff;
            padding: 5px 0;
src/views/printTemplate/index.jsx
@@ -2,7 +2,7 @@
import { DndProvider } from 'react-dnd'
import { is, fromJS } from 'immutable'
import HTML5Backend from 'react-dnd-html5-backend'
import { Card, notification, Row, Button, Modal } from 'antd'
import { Card, notification, Row, Button, Modal, Input, Icon } from 'antd'
import DragElement from './dragelement'
import MutilForm from './mutilform'
import SourceElement from './dragelement/source'
@@ -39,7 +39,11 @@
    editItemType: '',
    fields: [],
    formlist: null,
    saveloading: false
    saveloading: false,
    upPlus: 1,
    upMinus: 1,
    leftPlus: 1,
    leftMinus: 1
  }
  getclickpoint = (e) => {
@@ -814,17 +818,81 @@
    })
  }
  change = (e, type) => {
    let val = e.target.value
    val = parseInt(val)
    if (isNaN(val)) {
      val = ''
    }
    this.setState({[type]: val})
  }
  updatePosition = (type) => {
    let val = 0
    if (type === 'upPlus') {
      val = this.state.upPlus || 0
    } else if (type === 'upMinus') {
      val = this.state.upMinus || 0
    } else if (type === 'leftPlus') {
      val = this.state.leftPlus || 0
    } else if (type === 'leftMinus') {
      val = this.state.leftMinus || 0
    }
    if (!val) return
    let config = fromJS(this.state.config).toJS()
    if (type === 'upPlus') {
      config.elements = config.elements.map(item => {
        item.top = (item.top || 0) + val
        return item
      })
    } else if (type === 'upMinus') {
      config.elements = config.elements.map(item => {
        item.top = (item.top || 0) - val
        return item
      })
    } else if (type === 'leftPlus') {
      config.elements = config.elements.map(item => {
        item.left = (item.left || 0) + val
        return item
      })
    } else if (type === 'leftMinus') {
      config.elements = config.elements.map(item => {
        item.left = (item.left || 0) - val
        return item
      })
    }
    this.setState({
      config: config,
      editItemId: config.uuid,
      editItemType: config.type,
      formlist: getpageform(config)
    }, () => {
      this.resetview()
    })
  }
  render () {
    return (
      <div className="print-template">
        <DndProvider backend={HTML5Backend}>
          <header className="print-header-container ant-menu-dark">模板制作</header>
          <aside className="tools">
            <Card title="工具栏">
            <Card className="tool-bar" title="工具栏">
              {printItems.map((item, index) => {
                return (<SourceElement key={index} content={item}/>)
              })}
            </Card>
            <Card className="move-bar" title="整体移动">
              <Input addonBefore={<Icon title="距上" type="arrow-up" />} addonAfter={<Icon onClick={() => this.updatePosition('upPlus')} type="plus" />} onChange={(e) => this.change(e, 'upPlus')} value={this.state.upPlus} />
              <Input addonBefore={<Icon title="距上" type="arrow-up" />} addonAfter={<Icon onClick={() => this.updatePosition('upMinus')} type="minus" />} onChange={(e) => this.change(e, 'upMinus')} value={this.state.upMinus} />
              <Input addonBefore={<Icon title="距左" type="arrow-left" />} addonAfter={<Icon onClick={() => this.updatePosition('leftPlus')} type="plus" />} onChange={(e) => this.change(e, 'leftPlus')} value={this.state.leftPlus} />
              <Input addonBefore={<Icon title="距左" type="arrow-left" />} addonAfter={<Icon onClick={() => this.updatePosition('leftMinus')} type="minus" />} onChange={(e) => this.change(e, 'leftMinus')} value={this.state.leftMinus} />
            </Card>
          </aside>
          <div className="switchbox" onClick={this.switchbox}></div>
          <DragElement dropcard={this.dropcard} />
src/views/printTemplate/index.scss
@@ -4,6 +4,9 @@
  padding: 75px 250px 30px 240px;
  text-align: center;
  .ant-card-head {
    min-height: 45px;
  }
  .print-header-container {
    position: fixed;
    z-index: 1060;
@@ -27,7 +30,6 @@
    bottom: 0px;
    text-align: left;
    .ant-card {
      height: 100%;
      .ant-card-head {
        background: #1890ff;
        color: #ffffff;
@@ -36,7 +38,29 @@
        padding: 10px 0;
      }
      .ant-card-body {
        padding: 24px 12px;
        padding: 24px 12px 0px;
        .print-source-item:last-child {
          margin-bottom: 0;
        }
      }
    }
    .ant-card.tool-bar {
      height: 300px;
      border-bottom: 0;
    }
    .ant-card.move-bar {
      height: calc(100% - 300px);
      .ant-input-group-wrapper {
        margin-bottom: 15px;
        input + .ant-input-group-addon {
          padding: 0;
        }
        .anticon-plus, .anticon-minus {
          cursor: pointer;
          line-height: 25px;
          padding-left: 15px;
          padding-right: 15px;
        }
      }
    }
  }