king
2024-02-03 06a670976e2145a10ea05207041d3cf3164cd380
Merge branch 'positec' into dms
1 文件已重命名
176个文件已修改
1 文件已复制
6个文件已删除
2个文件已添加
7305 ■■■■■ 已修改文件
package-lock.json 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/README.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/manifest.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/editor/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mkPicture/index.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mkPicture/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/normalform/modalform/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/normalform/modalform/mkTable/index.jsx 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/calendar/options.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/card.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/options.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/double-data-card/index.jsx 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/double-data-card/options.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/data-card/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/prop-card/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.jsx 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx 179 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/index.jsx 195 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/index.scss 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx 280 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/index.jsx 200 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.jsx 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/chartcompile/index.jsx 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/chartcompile/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/chartcompile/formconfig.jsx 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/chartcompile/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/dragtitle/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/formaction/actionform/index.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/formaction/formconfig.jsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/formaction/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/normal-group/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/paste/index.jsx 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/colsControl/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/colsControl/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/colsControl/markform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/markcomponent/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/markcomponent/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/normalform/index.jsx 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/normalform/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/pastecomponent/index.jsx 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/pasteforms/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/options.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/index.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/tableIn/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/options.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/options.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.jsx 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/options.jsx 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/paste/index.jsx 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/paste/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tree/antd-tree/options.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/settingform/index.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/settingform/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/utils.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/debug/index.jsx 252 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulesource/option.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/pastecontroller/index.jsx 346 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/antv-tabs/index.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/antv-tabs/options.jsx 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/tabs/tabcomponents/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/topbar/normal-navbar/options.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/modulesource/option.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/options.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/modulesource/option.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/basetable/index.jsx 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/basetable/index.scss 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 239 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/double-data-card/index.jsx 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/prop-card/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-pie/index.jsx 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/simple-form/index.jsx 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/interfaces/interItem/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalheader/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/base-table/index.jsx 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/popview/index.jsx 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/popview/index.scss 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/rolemanage/index.jsx 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/excelInbutton/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/exportPdf/index.jsx 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/exportPdf/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funczip/index.jsx 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funczip/index.scss 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funczip/mock.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.jsx 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/newpagebutton/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/shareLink/index.jsx 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/shareLink/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkCheck/index.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkSwitch/index.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/index.jsx 179 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/mkDatePicker/index.jsx 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/mkSelect/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/actionform/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/formconfig.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/cardcomponent/formconfig.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/utils.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/formconfig.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/tabform/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/codemirror/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.jsx 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/baseform/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 807 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/option.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-datamanage.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basedesign/updateFormTab/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/billprint/index.jsx 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/index.scss 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/index.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/homeform/index.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/popview/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/printmenuform/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/popview/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/sidemenu/index.jsx 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -8409,6 +8409,11 @@
        "iconv-lite": "~0.4.13"
      }
    },
    "encryptlong": {
      "version": "3.1.4",
      "resolved": "https://registry.npmjs.org/encryptlong/-/encryptlong-3.1.4.tgz",
      "integrity": "sha512-nx+om7MXaSBSBPBNKKPrOWMot/C0L0Ru8dy9WTyjO5k8Wo+1hsnK0d8uX1UjctkgcgEWhkKhVScniYDjXvnKgw=="
    },
    "end-of-stream": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
@@ -12764,6 +12769,11 @@
        }
      }
    },
    "jsencrypt": {
      "version": "3.3.2",
      "resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.3.2.tgz",
      "integrity": "sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A=="
    },
    "jsesc": {
      "version": "2.5.2",
      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@@ -14930,6 +14940,14 @@
        }
      }
    },
    "node-rsa": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz",
      "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==",
      "requires": {
        "asn1": "^0.2.4"
      }
    },
    "node-sass": {
      "version": "4.12.0",
      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
package.json
@@ -47,6 +47,7 @@
    "dragact": "^0.2.12",
    "echarts": "^5.2.1",
    "echarts-for-react": "^2.0.15-beta.1",
    "encryptlong": "^3.1.4",
    "eslint": "^6.1.0",
    "eslint-config-react-app": "^5.0.1",
    "eslint-loader": "2.2.1",
@@ -73,12 +74,14 @@
    "jest-watch-typeahead": "0.3.1",
    "js-table2excel": "^1.0.3",
    "jsbarcode": "^3.11.3",
    "jsencrypt": "^3.3.2",
    "jspdf": "^2.5.1",
    "jssha": "^3.2.0",
    "jszip": "^3.10.0",
    "md5": "^2.2.1",
    "mini-css-extract-plugin": "0.5.0",
    "moment": "^2.24.0",
    "node-rsa": "^1.1.1",
    "node-sass": "^4.12.0",
    "optimize-css-assets-webpack-plugin": "5.0.3",
    "pnp-webpack-plugin": "1.5.0",
public/README.txt
@@ -18,4 +18,5 @@
transfer          -- 是否使用转接口,使用转接口时请设置为 true, 使用转接口时,外部接口调用前不会做登录验证
keepPassword      -- 记住密码,默认开启,当值为 false 时禁用
updateStatus      -- 是否更新开发状态,默认开启,当值为 false 时禁用
forcedUpdate      -- 传输号升级时,是否自动退出,格式为(YYYY-MM-DD),用于升级后刷新用户本地配置
platforms         -- 移动端可使用的平台类型,默认为 ["H5", "wechat", "android", "ios", "wxMiniProgram"] 分别代表H5页面、微信公众号、安卓APP、苹果APP、微信小程序
public/manifest.json
@@ -6,5 +6,5 @@
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "mk_version": "20231201"
  "mk_version": "20240203"
}
src/api/index.js
@@ -711,7 +711,7 @@
    param.sign = md5(values)
    param.t = new Date().getTime();
    ['arr_field', 'LText_field', 'custom_script', 'LText1', 'LText', 'LText2', 'DateCount'].forEach(key => {
    ['arr_field', 'custom_script', 'LText', 'DateCount'].forEach(key => {
      if (param[key]) {
        let val = param[key]
        delete param[key]
@@ -821,7 +821,7 @@
      param = this.encryptParam(param)
      axios({
        url: token.interface,
        url: `${token.interface}${param.func ? '/' + param.func : ''}`,
        method: 'post',
        data: JSON.stringify(param)
      }).then(res => {
@@ -870,7 +870,7 @@
          param = this.encryptParam(param)
          axios({
            url: token.interface,
            url: `${token.interface}${param.func ? '/' + param.func : ''}`,
            method: 'post',
            data: JSON.stringify(param)
          }).then(res => {
@@ -900,7 +900,7 @@
   * @description 获取业务通用接口
   * 访问 'https://sso.mk9h.cn/webapi/dostars'或云端时,传入userid、LoginUID
   */
  genericInterface (param) {
  genericInterface (param, script = '', position) {
    param.userid = param.userid || sessionStorage.getItem('UserID') || ''
    param.lang = param.lang || sessionStorage.getItem('lang') || ''
    param.SessionUid = localStorage.getItem('SessionUid') || ''
@@ -925,7 +925,25 @@
      }
    }
    if (param.$login) {
    if (script) {
      try {
        // eslint-disable-next-line
        let func = new Function('axios', 'Api', 'param', 'position', 'systemType', script)
        let promise = func(axios, this, param, position, window.GLOB.systemType)
        if (promise instanceof Promise) {
          return promise
        }
      } catch (e) {
        console.warn(e)
      }
      return Promise.resolve({
        status: false,
        message: '自定义脚本执行错误',
        ErrCode: 'E'
      })
    } else if (param.$login) {
      let rduri = param.rduri || ''
      delete param.$login
src/assets/css/main.scss
@@ -535,7 +535,7 @@
    background: var(--mk-sys-color5);
  }
  .ant-calendar-today:not(.ant-calendar-disabled-cell) {
  .ant-calendar-today:not(.ant-calendar-disabled-cell):not(.ant-calendar-selected-day) {
    .ant-calendar-date {
      color: var(--mk-sys-color);
      border-color: var(--mk-sys-color4);
src/components/editor/index.jsx
@@ -4,7 +4,6 @@
import BraftEditor from 'braft-editor'
import 'braft-editor/dist/index.css'
import 'braft-extensions/dist/table.css'
// import 'braft-editor/dist/output.css'
import Table from 'braft-extensions/dist/table'
import SparkMD5 from 'spark-md5'
import moment from 'moment'
src/components/header/index.jsx
@@ -31,7 +31,8 @@
    searchkey: '',
    thdMenuList: [],
    debug: sessionStorage.getItem('debug') === 'true' && window.GLOB.memberLevel > 0,
    collapse: sessionStorage.getItem('collapse') === 'true'
    collapse: sessionStorage.getItem('collapse') === 'true',
    lang: sessionStorage.getItem('lang') || ''
  }
  UNSAFE_componentWillMount () {
@@ -230,7 +231,13 @@
  getwork = () => {
    if (sessionStorage.getItem('work_grade')) return
    Api.genericInterface({func: 's_get_local_my_worker_v1'}).then(result => {
    let param = {func: 's_get_local_my_worker_v1'}
    if (window.GLOB.forcedUpdate) {
      param.s_version_up = 'true'
    }
    Api.genericInterface(param).then(result => {
      sessionStorage.setItem('work_grade', result.work_grade || 0)
      sessionStorage.setItem('work_group', result.work_group || '')
@@ -782,7 +789,7 @@
        </Dropdown>
        {/* 编辑状态登录 */}
        <Modal
          title="登录开发机"
          title={<span>登录开发机{this.state.lang === 'en-US' ? <span style={{color: 'red'}}>(英文)</span> : ''}</span>}
          visible={this.state.loginVisible}
          onOk={this.loginSubmit}
          width={'430px'}
src/components/mkPicture/index.jsx
@@ -9,6 +9,7 @@
class MkPicture extends Component {
  static propTpyes = {
    style: PropTypes.object,
    lostTip: PropTypes.bool,
    scale: PropTypes.bool,
    url: PropTypes.string,
    urls: PropTypes.array,
@@ -20,24 +21,26 @@
  }
  UNSAFE_componentWillMount() {
    const { url } = this.props
    const { url, lostTip } = this.props
    if (url) {
      this.setState({url: url, lost: false})
      this.checkUrl(url)
    } else {
      this.setState({url: LostPng, lost: true})
      this.setState({url: lostTip ? LostPng: '', lost: true})
    }
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { lostTip } = this.props
    if (nextProps.url) {
      if (nextProps.url !== this.state.url) {
        this.setState({url: nextProps.url, lost: false})
        this.checkUrl(nextProps.url)
      }
    } else {
      this.setState({url: LostPng, lost: true})
      this.setState({url: lostTip ? LostPng: '', lost: true})
    }
  }
@@ -63,9 +66,15 @@
  }
  render() {
    const { style, scale, urls } = this.props
    const { style, scale, urls, lostTip } = this.props
    const { url, lost } = this.state
    if (!lostTip && !url) {
      return (
        <div className="ant-mk-picture empty" style={style}></div>
      )
    }
    return (
      <div
        className={'ant-mk-picture' + (scale ? ' scale' : '') + (lost ? ' lost' : '')}
src/components/mkPicture/index.scss
@@ -6,6 +6,9 @@
.ant-mk-picture.lost {
  background-size: contain!important;
}
.ant-mk-picture.empty {
  background: transparent!important;
}
.ant-mk-picture.scale {
  cursor: zoom-in;
}
src/components/normalform/modalform/index.jsx
@@ -282,9 +282,9 @@
      let label = item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip> : item.label
    
      if (item.type === 'text') {
        content = (<MKEInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
        content = (<MKEInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val}, item)} onSubmit={this.props.inputSubmit} />)
      } else if (item.type === 'number') {
        content = (<MKNumberInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
        content = (<MKNumberInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val}, item)} onSubmit={this.props.inputSubmit} />)
      } else if (item.type === 'select' || item.type === 'multiselect') {
        content = (<MKSelect config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} />)
      } else if (item.type === 'color') {
@@ -306,7 +306,7 @@
      } else if (item.type === 'source') {
        content = (<SourceComponent type="" placement="right"/>)
      } else if (item.type === 'table') {
        content = (<MKTable tip={item.tip || ''} fixed={item.fixed === true} columns={item.columns || []} actions={item.actions || []}/>)
        content = (<MKTable tip={item.tip || ''} columns={item.columns || []} actions={item.actions || []}/>)
      } else if (item.type === 'hint') {
        fields.push(
          <Col span={24} key={index}>
src/components/normalform/modalform/mkTable/index.jsx
@@ -153,8 +153,9 @@
class EditTable extends Component {
  static propTpyes = {
    columns: PropTypes.array,       // 显示列
    onChange: PropTypes.func        // 数据变化
    actions: PropTypes.array,
    columns: PropTypes.array,
    onChange: PropTypes.func
  }
  state = {
@@ -166,7 +167,7 @@
  }
  UNSAFE_componentWillMount () {
    let actions = this.props.actions || []
    const { actions } = this.props
    let columns = fromJS(this.props.columns).toJS()
    let operation = {
@@ -189,16 +190,16 @@
          </div>
        ) : (
          <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px', whiteSpace: 'nowrap'}}>
            <span className="primary" onClick={() => {editingKey === '' && this.edit(record)}}><EditOutlined /></span>
            {editingKey === '' ? <Popconfirm
            {actions.includes('edit') ? <span className="primary" onClick={() => {editingKey === '' && this.edit(record)}}><EditOutlined /></span> : null}
            {actions.includes('del') && editingKey === '' ? <Popconfirm
              overlayClassName="popover-confirm"
              title="确定删除吗?"
              onConfirm={() => this.handleDelete(record.uuid)
            }>
              <span className="danger"><DeleteOutlined /></span>
            </Popconfirm> : null}
            {editingKey !== '' ? <span className="danger"><DeleteOutlined /></span> : null}
            {actions.includes('view') ? <span className="copy" onClick={() => {editingKey === '' && this.changeMenu(record.menu)}}><ArrowRightOutlined /></span> : null}
            {actions.includes('del') && editingKey !== '' ? <span className="danger"><DeleteOutlined /></span> : null}
            {actions.includes('view') ? <span className="copy" onClick={() => {editingKey === '' && this.changeMenu(record)}}><ArrowRightOutlined /></span> : null}
          </div>
        )
      }
@@ -217,7 +218,8 @@
  //   return !is(fromJS(this.state), fromJS(nextState))
  // }
  changeMenu = (MenuId) => {
  changeMenu = (record) => {
    let MenuId = record.menu
    if (MenuId === 'IM') {
      if (!sessionStorage.getItem('instantMessage')) return
@@ -231,7 +233,7 @@
  
      MKEmitter.emit('changeEditMenu', {routerUrl: '/imdesign/' + param})
    } else {
      MKEmitter.emit('changeEditMenu', {MenuID: MenuId})
      MKEmitter.emit('changeEditMenu', { ...record, MenuID: MenuId})
    }
  }
@@ -274,7 +276,18 @@
    columns.forEach(col => {
      if (col.unique !== true || !unique) return
      let _index = newData.findIndex(item => record.uuid !== item.uuid && record[col.dataIndex] === item[col.dataIndex])
      let _index = newData.findIndex(item => {
        if (record.uuid === item.uuid) return false
        if (col.inputType === 'cascader') {
          if (!Array.isArray(record[col.dataIndex]) || !Array.isArray(item[col.dataIndex])) {
            return false
          }
          return record[col.dataIndex].toString() === item[col.dataIndex].toString()
        }
        return record[col.dataIndex] === item[col.dataIndex]
      })
      if (_index > -1) {
        notification.warning({
@@ -392,7 +405,7 @@
  }
  render() {
    const { fixed } = this.props
    const { actions } = this.props
    let components = {
      body: {
        cell: EditableCell
@@ -401,8 +414,11 @@
    let moveprops = {}
    components.body.row = DragableBodyRow
    moveprops.moveAble = !this.state.editingKey
    moveprops.moveRow = this.moveRow
    if (actions.includes('move')) {
      moveprops.moveAble = !this.state.editingKey
      moveprops.moveRow = this.moveRow
    }
    
    let  columns = this.state.columns.map(col => {
      if (col.copy) {
@@ -437,7 +453,7 @@
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-editable-table">
          {!fixed ? <Button disabled={!!this.state.editingKey} type="link" onClick={this.addline}><PlusOutlined style={{}}/></Button> : null}
          {actions.includes('add') ? <Button disabled={!!this.state.editingKey} type="link" onClick={this.addline}><PlusOutlined style={{}}/></Button> : null}
          <DndProvider>
            <Table
              bordered
src/index.js
@@ -48,7 +48,7 @@
    if (!config) return
    if (config.defaultApp) {
      if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
      if (/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(navigator.userAgent)) {
        window.location.replace(window.location.href.split(/(index.html)+/ig)[0].replace('admin/', '') + 'mob/index.html#/index')
        return
      }
@@ -89,11 +89,6 @@
    // 只有业务系统才可以设置为正式系统
    if (GLOB.sysType === 'local' && (config.systemType === 'official' || config.systemType === 'production')) {
      GLOB.systemType = 'production'
      if (config.probation && /^20\d{2}-\d{2}-\d{2}$/.test(config.probation) && new Date(config.probation).getTime() > new Date().getTime()) {
        GLOB.probation = true
      }
      if (!config.mainSystemApi) {
        document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">系统未设置单点地址,请联系管理员!</div>'
        return
@@ -104,6 +99,14 @@
        document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">正式系统不可使用 http://cloud.mk9h.cn 做为单点地址,请联系管理员!</div>'
        return
      }
      GLOB.systemType = 'production'
      if (config.probation && /^20\d{2}-\d{2}-\d{2}$/.test(config.probation) && new Date(config.probation).getTime() > new Date().getTime()) {
        GLOB.probation = true
      }
      if (config.forcedUpdate && /^20\d{2}-\d{2}-\d{2}$/.test(config.forcedUpdate) && new Date(config.forcedUpdate).getTime() > new Date().getTime()) {
        GLOB.forcedUpdate = true
      }
    } else if (GLOB.sysType === 'local') {
      GLOB.probation = true
      GLOB.debugger = true
src/menu/components/calendar/options.jsx
@@ -195,6 +195,7 @@
      label: '颜色标识',
      initval: wrap.signs || [],
      required: false,
      actions: ['edit', 'del', 'add', 'move'],
      span: 24,
      columns: [
        {
@@ -224,7 +225,7 @@
      initval: wrap.menus || [],
      required: true,
      span: 24,
      actions: ['view'],
      actions: ['edit', 'del', 'add', 'move', 'view'],
      forbid: isprint,
      columns: [
        {
src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -65,8 +65,14 @@
  }
  if (card.eleType === 'picture' && card.maxWidth) {
    _style.maxWidth = card.maxWidth
    let left = _style.marginLeft && _style.marginLeft !== '0px' ? _style.marginLeft : 'auto'
    let right = _style.marginRight && _style.marginRight !== '0px' ? _style.marginRight : 'auto'
    let left = _style.marginLeft || 'auto'
    let right = _style.marginRight || 'auto'
    if (_style.marginLeft === '0px' && _style.marginRight === '0px') {
      left = 'auto'
      right = 'auto'
    }
    _style.margin = (_style.marginTop || 0) + ' ' + right + ' ' + (_style.marginBottom || 0) + ' ' + left
    delete _style.marginLeft
    delete _style.marginRight
src/menu/components/card/cardcellcomponent/elementform/index.jsx
@@ -164,7 +164,10 @@
      } else {
        _options.push('value')
      }
      if (this.record.eleType === 'video' && this.record.posterType) {
      if (this.record.eleType === 'picture' && this.record.noValue === 'show') {
        _options.push('lostTip')
      } else if (this.record.eleType === 'video' && this.record.posterType) {
        if (this.record.posterType === 'dynamic') {
          _options.push('posterField')
        } else {
@@ -341,7 +344,7 @@
          return item
        })
      })
    } else if (['datatype', 'showInfo', 'showType', 'fixStyle', 'posterType', 'eval', 'linkType', 'tipType'].includes(key)) {
    } else if (['datatype', 'showInfo', 'showType', 'fixStyle', 'posterType', 'eval', 'linkType', 'tipType', 'noValue'].includes(key)) {
      let _options = this.getOptions()
      this.setState({
src/menu/components/card/cardcellcomponent/elementform/index.scss
@@ -43,7 +43,7 @@
  .ant-popover-inner-content {
    div {
      max-width: 750px;
      word-break: break-all;
      word-break: normal;
    }
  }
}
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -675,6 +675,18 @@
    },
    {
      type: 'radio',
      key: 'lostTip',
      label: '图片缺失',
      initVal: card.lostTip || 'true',
      tooltip: '图片地址不存在时,是否提示图片丢失。',
      required: false,
      options: [
        { value: 'true', text: '提示' },
        { value: 'false', text: '不提示' }
      ]
    },
    {
      type: 'radio',
      key: 'alignItems',
      label: '垂直对齐',
      initVal: card.alignItems || '',
src/menu/components/card/cardcellcomponent/index.jsx
@@ -245,6 +245,10 @@
    } else if (_card.eleType === 'picture') {
      _card.style = style
      delete _card.style.backgroundImage
      delete _card.style.paddingTop
      delete _card.style.paddingBottom
      delete _card.style.paddingLeft
      delete _card.style.paddingRight
    } else {
      _card.style = style
    }
@@ -310,8 +314,9 @@
        supId = ''
      }
    }
    let menu = window.GLOB.customMenu
    let modules = MenuUtils.getSubModules(window.GLOB.customMenu.components, cards.uuid, supId, true)
    let modules = MenuUtils.getSubModules(menu.components, cards.uuid, supId, menu.interfaces || null)
    if (cards.subtype === 'basetable') {
      this.setState({
@@ -320,7 +325,7 @@
        formlist: getBaseTableActionForm(card, functip, cards, usefulFields, modules)
      })
    } else {
      let anchors = MenuUtils.getAnchors(window.GLOB.customMenu.components, cards.uuid) || []
      let anchors = MenuUtils.getAnchors(menu.components, cards.uuid) || []
      this.setState({
        actvisible: true,
@@ -414,6 +419,10 @@
            res.innerHeight = res.barHeight + (res.displayValue === 'true' ? fontSize + 2 : 0)
          } else if (res.eleType === 'picture') {
            delete res.style.backgroundImage
            delete res.style.paddingTop
            delete res.style.paddingBottom
            delete res.style.paddingLeft
            delete res.style.paddingRight
          }
          
          return res
src/menu/components/card/cardcomponent/options.jsx
@@ -67,7 +67,7 @@
      required: false,
      options: [
        {value: 'card', label: '属性卡'},
        {value: 'header', label: '表格头'},
        {value: 'header', label: '表格头(可排序)'},
      ],
      controlFields: [
        {field: 'type', values: ['card']},
@@ -286,7 +286,7 @@
      initval: menus,
      required: true,
      span: 24,
      actions: ['view'],
      actions: ['edit', 'del', 'add', 'move', 'view'],
      columns: [
        {
          title: '标识',
src/menu/components/card/data-card/index.jsx
@@ -341,8 +341,30 @@
  getWrapForms = () => {
    const { card } = this.state
    let buttons = []
    card.action && card.action.forEach(n => {
      buttons.push({
        value: n.uuid,
        label: n.label
      })
    })
    card.subcards.forEach(m => {
      if (m.$cardType !== 'extendCard') return
      m.elements.forEach(n => {
        if (n.eleType === 'button') {
          buttons.push({
            value: n.uuid,
            label: n.label
          })
        }
      })
    })
    
    return getWrapForm(card.wrap, card.subtype, card.columns, card.uuid, card.supNodes, card.setting)
    return getWrapForm(card.wrap, card.subtype, card.columns, card.uuid, card.supNodes, card.setting, buttons)
  }
  updateWrap = (res) => {
src/menu/components/card/data-card/options.jsx
@@ -187,6 +187,7 @@
      ],
      controlFields: [
        {field: 'slidetip', values: ['slide']},
        {field: 'maxPageSize', values: ['page']},
      ],
      forbid: subtype === 'propcard'
    },
@@ -413,10 +414,10 @@
      field: 'autoExec',
      label: '自动执行',
      initval: wrap.autoExec || '',
      tooltip: '数据更新时自动执行按钮。注:此按钮执行成功后谨慎选择刷新项,避免造成循环执行。',
      tooltip: subtype === 'propcard' ? '数据更新时自动执行按钮。注:此按钮执行成功后谨慎选择刷新项,避免造成循环执行。' : '初始化自动执行按钮。',
      required: false,
      options: buttons,
      forbid: subtype !== 'propcard',
      forbid: subtype !== 'propcard' && subtype !== 'datacard',
      controlFields: [
        {field: 'emptyExec', notNull: true},
      ]
@@ -621,6 +622,17 @@
      forbid: !!appType || subtype !== 'datacard' || isprint
    },
    {
      type: 'number',
      field: 'maxPageSize',
      label: '每页最大数',
      initval: wrap.maxPageSize || '',
      min: 10,
      max: 500,
      precision: 0,
      required: false,
      forbid: !laypage || appType === 'mob' || subtype !== 'datacard'
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
@@ -646,6 +658,7 @@
      required: true,
      forbid: subtype !== 'datacard' || appType === 'mob' || isprint,
      span: 24,
      actions: ['edit', 'del', 'add', 'move'],
      columns: [
        {
          title: '序号',
src/menu/components/card/double-data-card/index.jsx
@@ -331,8 +331,30 @@
  getWrapForms = () => {
    const { card } = this.state
    let buttons = []
    card.action && card.action.forEach(n => {
      buttons.push({
        value: n.uuid,
        label: n.label
      })
    })
    card.subcards.forEach(m => {
      if (m.$cardType !== 'extendCard') return
      m.elements.forEach(n => {
        if (n.eleType === 'button') {
          buttons.push({
            value: n.uuid,
            label: n.label
          })
        }
      })
    })
    
    return getWrapForm(card.wrap, card.columns, card.setting)
    return getWrapForm(card.wrap, card.columns, card.setting, buttons)
  }
  updateWrap = (res) => {
@@ -501,7 +523,7 @@
            <NormalForm title="双重数据卡设置" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="datacard" card={card}/>
            <CopyComponent type="doublecard" card={card}/>
            <PasteComponent options={['action', 'search', 'form', 'cardcell']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
src/menu/components/card/double-data-card/options.jsx
@@ -1,7 +1,7 @@
/**
 * @description Wrap表单配置信息
 */
export default function (wrap, columns = [], setting) {
export default function (wrap, columns = [], setting, buttons = []) {
  let appType = sessionStorage.getItem('appType')
  let laypage = setting && setting.laypage !== 'false'
  let roleList = sessionStorage.getItem('sysRoles')
@@ -75,6 +75,7 @@
      ],
      controlFields: [
        {field: 'slidetip', values: ['slide']},
        {field: 'maxPageSize', values: ['page']},
      ],
    },
    {
@@ -183,6 +184,15 @@
      required: false
    },
    {
      type: 'select',
      field: 'autoExec',
      label: '自动执行',
      initval: wrap.autoExec || '',
      tooltip: '初始化自动执行按钮。',
      required: false,
      options: buttons
    },
    {
      type: 'number',
      field: 'minWidth',
      label: '最小宽度',
@@ -264,6 +274,17 @@
      forbid: !!appType || isprint
    },
    {
      type: 'number',
      field: 'maxPageSize',
      label: '每页最大数',
      initval: wrap.maxPageSize || '',
      min: 10,
      max: 500,
      precision: 0,
      required: false,
      forbid: !laypage || appType === 'mob'
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
src/menu/components/carousel/data-card/index.jsx
@@ -207,7 +207,7 @@
            <NormalForm title="轮播-动态数据" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="datacard" card={card}/>
            <CopyComponent type="cardatacard" card={card}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)}/>
src/menu/components/carousel/prop-card/index.jsx
@@ -252,7 +252,7 @@
            <NormalForm title="轮播-静态数据" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="propcard" card={card}/>
            <CopyComponent type="carpropcard" card={card}/>
            <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
@@ -179,7 +179,7 @@
      initval: card.menus || [],
      required: true,
      span: 24,
      actions: appType === 'pc' ? ['view'] : [],
      actions: ['edit', 'del', 'add', 'move', 'view'],
      columns: [
        {
          title: '标识',
src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx
@@ -157,7 +157,7 @@
      initval: card.menus || [],
      required: true,
      span: 24,
      actions: appType === 'pc' ? ['view'] : [],
      actions: ['edit', 'del', 'add', 'move', 'view'],
      columns: [
        {
          title: '标识',
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -187,7 +187,7 @@
      initval: card.menus || [],
      required: true,
      span: 24,
      actions: ['view'],
      actions: ['edit', 'del', 'add', 'move', 'view'],
      forbid: appType === 'mob' || card.chartType !== 'bar',
      hidden: card.click !== 'menus',
      columns: [
@@ -224,28 +224,41 @@
export function getOptionForm (card, columns) {
  let appType = sessionStorage.getItem('appType')
  let shapes = []
  let shape = card.shape
  if (card.chartType === 'line') {
    shapes = [
      { field: 'smooth', label: 'smooth(平滑线)' },
      { field: 'line', label: 'line(直线)' },
      { field: 'dot', label: 'dot(点状线)' },
      { field: 'dash', label: 'dash(虚线)' },
      { field: 'hv', label: 'hv(水平-垂直线)' },
      { field: 'vh', label: 'vh(垂直-水平线)' },
      { field: 'hvh', label: 'hvh(水平-垂直-水平线)' },
      { field: 'vhv', label: 'vhv(垂直-水平-垂直线)' }
      { field: 'smooth', label: '平滑线' },
      { field: 'line', label: '直线' },
      { field: 'dot', label: '点状线' },
      { field: 'dash', label: '虚线' },
      { field: 'hv', label: '水平-垂直线' },
      { field: 'vh', label: '垂直-水平线' },
      { field: 'hvh', label: '水平-垂直-水平线' },
      { field: 'vhv', label: '垂直-水平-垂直线' }
    ]
  } else if (card.chartType === 'bar') {
    shapes = [
      { field: 'rect', label: 'rect(矩形)' },
      { field: 'hollow-rect', label: 'hollow-rect(空心矩形)' },
      { field: 'rect', label: '矩形' },
      { field: 'hollow-rect', label: '空心矩形' },
      // { field: 'hollow', label: 'hollow(空心矩形)' },
      // { field: 'line', label: 'line(线条)' },
      // { field: 'tick', label: 'tick(波动)' },
      // { field: 'funnel', label: 'funnel(漏斗图)' },
      { field: 'pyramid', label: 'pyramid(金字塔)' }
      { field: 'pyramid', label: '金字塔' },
      { field: 'barChart', label: '条形图' },
      { field: 'roseChart', label: '玫瑰图' },
    ]
    if (card.transpose === 'true') {
      shape = 'barChart'
    } else if (card.coordinate === 'polar') {
      shape = 'roseChart'
    }
  }
  if (!shape) {
    shape = shapes[0].field
  }
  let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype))
@@ -294,24 +307,36 @@
  if (card.y_label !== 'hidden') {
    tickVals.push('y_label')
  }
  let datatype = card.datatype || 'query'
  if (card.enabled === 'true') {
    datatype = 'custom'
  }
  return [
    {
      type: 'radio',
      field: 'datatype',
      label: '数据类型',
      initval: card.datatype || 'query',
      label: '图形类型',
      initval: datatype,
      tooltip: '统计图表适用于展示数据类型为动态值。',
      required: false,
      $trans: true,
      options: [
        { value: 'query', label: '查询' },
        { value: 'query', label: card.chartType !== 'line' ? '柱状图' : '折线图' },
        { value: 'custom', label: '自定义图形' },
        { value: 'statistics', label: '统计' }
      ],
      controlFields: [
        {field: 'InfoType', values: ['statistics']},
        {field: 'InfoValue', values: ['statistics']},
        {field: 'Yaxis', values: ['query']},
        {field: 'Yaxis', values: ['query', 'custom']},
        {field: 'adjust', values: ['query', 'statistics']},
        {field: 'area', values: ['query', 'statistics']},
        {field: 'show', values: ['query', 'statistics']},
        {field: 'selectColor', values: ['query']},
        {field: 'barSize', values: card.chartType !== 'line' ? ['query', 'custom', 'statistics'] : ['custom']},
        {field: 'mutilBar', values: ['custom']},
      ]
    }, {
      type: 'select',
@@ -336,6 +361,20 @@
      options: yfields
    }, {
      type: 'select',
      field: 'shape',
      label: '形状',
      initval: shape,
      required: false,
      options: shapes
    }, {
      type: 'multiselect',
      field: 'Yaxis',
      label: 'Y-轴',
      initval: card.Yaxis || [],
      required: true,
      options: yfields
    }, {
      type: 'select',
      field: 'legend',
      label: '图例位置',
      initval: card.legend || 'bottom',
@@ -356,20 +395,6 @@
        { field: 'hidden', label: '隐藏' }
      ]
    }, {
      type: 'multiselect',
      field: 'Yaxis',
      label: 'Y-轴',
      initval: card.Yaxis || [],
      required: true,
      options: yfields
    }, {
      type: 'select',
      field: 'shape',
      label: '形状',
      initval: card.shape || (shapes[0] && shapes[0].field),
      required: false,
      options: shapes
    }, {
      type: 'radio',
      field: 'tooltip',
      label: '悬浮提示',
@@ -384,39 +409,9 @@
      }]
    }, {
      type: 'radio',
      field: 'point',
      label: '点图',
      initval: card.point || 'false',
      required: false,
      forbid: !['line'].includes(card.chartType),
      options: [{
        value: 'true',
        label: '显示'
      }, {
        value: 'false',
        label: '隐藏'
      }]
    }, {
      type: 'radio',
      field: 'transpose',
      label: '变换',
      initval: card.transpose || 'false',
      tooltip: '横纵坐标轴交换',
      forbid: card.chartType === 'line',
      required: false,
      options: [{
        value: 'true',
        label: '是'
      }, {
        value: 'false',
        label: '否'
      }]
    }, {
      type: 'radio',
      field: 'show',
      label: '显示',
      initval: card.show || 'value',
      tooltip: '当使用自定义设置时,可在显示(值/%)处单独设置显示类型。注:自定义为空时使用此处设置。',
      required: false,
      options: [{
        value: 'value',
@@ -441,34 +436,6 @@
      ]
    }, {
      type: 'radio',
      field: 'labelColor',
      label: '标注颜色',
      initval: card.labelColor || 'system',
      tooltip: '使用系统色时,使用色系选项设置的系统颜色,使用自定义为颜色设置中定义的图形颜色。',
      required: false,
      options: [{
        value: 'system',
        label: '系统'
      }, {
        value: 'custom',
        label: '自定义'
      }]
    // }, {
    //   type: 'radio',
    //   field: 'labelValue',
    //   label: '标注值',
    //   initval: card.labelValue || 'default',
    //   tooltip: '标注值的显示规则。',
    //   required: false,
    //   options: [{
    //     value: 'default',
    //     label: '默认'
    //   }, {
    //     value: 'zero',
    //     label: '隐藏 0 值'
    //   }],
    }, {
      type: 'radio',
      field: 'adjust',
      label: '多柱排列',
      initval: card.adjust || 'dodge',
@@ -483,31 +450,44 @@
      }]
    }, {
      type: 'radio',
      field: 'mutilBar',
      label: '多柱排列',
      initval: card.mutilBar || 'dodge',
      required: false,
      options: [{
        value: 'dodge',
        label: '分组'
      }, {
        value: 'stack',
        label: '堆叠'
      }]
    }, {
      type: 'radio',
      field: 'point',
      label: '点图',
      initval: card.point || 'false',
      required: false,
      forbid: card.chartType === 'bar',
      options: [{
        value: 'true',
        label: '显示'
      }, {
        value: 'false',
        label: '隐藏'
      }]
    }, {
      type: 'radio',
      field: 'area',
      label: '面积图',
      initval: card.area || 'false',
      required: false,
      forbid: ['bar'].includes(card.chartType),
      forbid: card.chartType === 'bar',
      options: [{
        value: 'true',
        label: '显示'
      }, {
        value: 'false',
        label: '不显示'
      }]
    }, {
      type: 'radio',
      field: 'coordinate',
      label: '坐标',
      initval: card.coordinate || 'angle',
      required: false,
      forbid: card.chartType === 'line',
      options: [{
        value: 'angle',
        label: '二维坐标'
      }, {
        value: 'polar',
        label: '极坐标'
      }]
    }, {
      type: 'checkbox',
@@ -547,47 +527,6 @@
      controlFields: [
        {field: 'color', notNull: true},
      ]
    // }, {
    //   type: 'radio',
    //   field: 'grid',
    //   label: '网格线',
    //   initval: card.grid || 'show',
    //   required: false,
    //   options: [{
    //     value: 'show',
    //     label: '显示'
    //   }, {
    //     value: 'hidden',
    //     label: '隐藏'
    //   }]
    // }, {
    //   type: 'radio',
    //   field: 'y_line',
    //   label: 'y轴边线',
    //   initval: card.y_line || 'hidden',
    //   tooltip: '图形左侧或右侧的边线。',
    //   required: false,
    //   options: [{
    //     value: 'show',
    //     label: '显示'
    //   }, {
    //     value: 'hidden',
    //     label: '隐藏'
    //   }]
    }, {
      type: 'radio',
      field: 'download',
      label: '导出图片',
      initval: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        label: '禁用'
      }, {
        value: 'enable',
        label: '启用'
      }]
    }, {
      type: 'radio',
      field: 'empty',
@@ -608,7 +547,6 @@
      max: 200,
      precision: 0,
      initval: card.barSize,
      forbid: !['bar'].includes(card.chartType),
      required: false
    }, {
      type: 'number',
@@ -619,7 +557,7 @@
      max: 200,
      precision: 0,
      initval: card.barRadius || 0,
      forbid: !['bar'].includes(card.chartType),
      forbid: card.chartType === 'line',
      required: false
    }, {
      type: 'number',
@@ -670,37 +608,37 @@
      initval: card.rotate,
      forbid: appType !== 'mob',
      required: false
    }, {
      type: 'multiselect',
      field: 'interaction',
      label: '交互效果',
      initval: card.interaction || [],
      required: false,
      forbid: appType === 'mob',
      options: [
        { value: 'element-active', label: '元素聚焦' },
        { value: 'element-selected', label: '元素选中(多选)' },
        { value: 'element-single-selected', label: '元素选中(单选)' },
        { value: 'active-region', label: '背景框' },
        { value: 'view-zoom', label: '视图缩放' },
        { value: 'element-highlight', label: '元素高亮' },
        { value: 'element-highlight-by-color', label: '同色元素高亮' },
        { value: 'element-highlight-by-x', label: '同X轴元素高亮' },
        { value: 'legend-filter', label: '图例过滤' },
        { value: 'legend-active', label: '图例聚焦' },
        { value: 'legend-highlight', label: '图例高亮' },
        { value: 'brush', label: '选框过滤' },
      ],
      controlFields: [
        {field: 'selectColor', values: ['element-selected', 'element-single-selected']},
      ]
    // }, {
    //   type: 'multiselect',
    //   field: 'interaction',
    //   label: '交互效果',
    //   initval: card.interaction || [],
    //   required: false,
    //   forbid: appType === 'mob',
    //   options: [
    //     { value: 'element-active', label: '元素聚焦' },
    //     { value: 'element-selected', label: '元素选中(多选)' },
    //     { value: 'element-single-selected', label: '元素选中(单选)' },
    //     { value: 'active-region', label: '背景框' },
    //     { value: 'view-zoom', label: '视图缩放' },
    //     { value: 'element-highlight', label: '元素高亮' },
    //     { value: 'element-highlight-by-color', label: '同色元素高亮' },
    //     { value: 'element-highlight-by-x', label: '同X轴元素高亮' },
    //     { value: 'legend-filter', label: '图例过滤' },
    //     { value: 'legend-active', label: '图例聚焦' },
    //     { value: 'legend-highlight', label: '图例高亮' },
    //     { value: 'brush', label: '选框过滤' },
    //   ],
    //   controlFields: [
    //     {field: 'selectColor', values: ['element-selected', 'element-single-selected']},
    //   ]
    }, {
      type: 'color',
      field: 'selectColor',
      label: '选中颜色',
      initval: card.selectColor || '',
      tooltip: '选中柱形图的颜色,启用自定义设置时无效。',
      forbid: !['bar'].includes(card.chartType),
      tooltip: '选中柱形图的颜色。',
      forbid: card.chartType === 'line',
      allowClear: true,
      required: false
    }
src/menu/components/chart/antv-bar/chartcompile/index.jsx
@@ -181,10 +181,15 @@
    plot.zoomYaxis = plot.zoomYaxis || 'default'
    let datatype = plot.datatype || 'query'
    if (plot.enabled === 'true') {
      datatype = 'custom'
    }
    this.setState({
      visible: true,
      view: 'base',
      datatype: plot.datatype || 'query',
      datatype: datatype,
      fieldName: fieldName,
      plot: plot,
      baseFormlist: getBaseForm(plot, config.columns),
@@ -299,6 +304,7 @@
          { value: 'false', text: '隐藏'}
        ],
        render: (text, record) => {
          if (record.axis !== 'true') return ''
          let trans = {'true': '显示', 'false': '隐藏'}
          return trans[text] || ''
        }
@@ -317,7 +323,7 @@
        ],
        render: (text, record) => {
          let trans = {value: '数值', percent: '百分比', thdSeparator: '千分位'}
          return trans[text] || ''
          return trans[text] || '数值'
        }
      },
      {
@@ -359,9 +365,18 @@
      this.normalRef.handleConfirm().then(values => {
        let _plot = {...plot, ...values}
        if (_plot.datatype === 'custom') {
          _plot.datatype = 'query'
          _plot.enabled = 'true'
          _plot.show = 'value'
        } else {
          _plot.enabled = 'false'
        }
        if (_plot.datatype !== plot.datatype) {
          _plot.colors = null
        }
        this.resetPlot(_plot)
        this.setState({
@@ -398,6 +413,14 @@
    if (view === 'normal') {
      this.normalRef.handleConfirm().then(values => {
        let _plot = {...plot, ...values}
        if (_plot.datatype === 'custom') {
          _plot.datatype = 'query'
          _plot.enabled = 'true'
          _plot.show = 'value'
        } else {
          _plot.enabled = 'false'
        }
        if (_plot.datatype !== plot.datatype) {
          _plot.colors = null
@@ -482,6 +505,14 @@
  resetPlot = (_plot) => {
    const { config } = this.props
    if (_plot.chartType === 'bar') {
      _plot.transpose = _plot.shape === 'barChart' ? 'true' : 'false'
      _plot.coordinate = _plot.shape === 'roseChart' ? 'polar' : 'angle'
      if (_plot.shape === 'barChart' || _plot.shape === 'roseChart') {
        _plot.shape = 'rect'
      }
    }
    if (_plot.axis) {
      _plot.grid = _plot.axis.includes('grid') ? 'show' : 'hidden'
      _plot.x_line = _plot.axis.includes('x_line') ? 'show' : 'hidden'
@@ -531,7 +562,8 @@
            name: labels[item] || item,
            axis: i === 0 ? 'true' : 'false',
            label: _plot.label === 'false' ? 'false' : true,
            title: 'true',
            show: 'value',
            title: 'false',
            shape: _plot.chartType === 'bar' && i === 0 ? ['bar', 'rect'] : ['line', 'smooth']
          }
        })
@@ -668,15 +700,15 @@
                {datatype === 'statistics' ? <Button className="color-add mk-green" onClick={this.addColor}>添加</Button> : null}
                {datatype === 'statistics' ? <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={plot.ramp ==='true' ? rampStatColorColumns : statColorColumns} onChange={this.changeColor}/> : null}
                {datatype !== 'statistics' ? <EditTable actions={['edit']} data={plot.colors || []} columns={plot.ramp ==='true' ? rampColorColumns : colorColumns} onChange={this.changeColor}/> : null}
                {plot.chartType === 'bar' && plot.datatype === 'query' ? <div className="mk-bar-colors">
                  <p>柱形颜色:可根据柱图序号设置颜色。注:使用自定义图形设置或多根柱图时无效。</p>
                {plot.chartType === 'bar' && datatype === 'query' ? <div className="mk-bar-colors">
                  <p>柱形颜色:可根据柱图序号设置颜色。注:多根柱图时无效。</p>
                  <div className="bar-color-add"><PlusOutlined onClick={this.addbarColor}/></div>
                  <EditTable actions={['edit', 'move', 'del']} data={plot.barcolors || []} columns={barColorColumns} onChange={this.changebarColor}/>
                </div> : null}
              </div>
            </TabPane> : null}
            {plot ? <TabPane tab="自定义图形设置" disabled={datatype === 'statistics'} key="custom">
              <Col span={8}>
            {plot ? <TabPane tab="自定义图形设置" disabled={datatype !== 'custom'} key="custom">
              {/* <Col span={8}>
                <Form {...formItemLayout}>
                  <Form.Item label="是否启用" style={{marginBottom: 10}}>
                    <Radio.Group value={plot.enabled || 'false'} onChange={(e) => this.optionChange(e.target.value, 'enabled')}>
@@ -685,8 +717,8 @@
                    </Radio.Group>
                  </Form.Item>
                </Form>
              </Col>
              <Col span={8}>
              </Col> */}
              {/* <Col span={8}>
                <Form {...formItemLayout}>
                  <Form.Item label="多柱排列" style={{marginBottom: 10}}>
                    <Radio.Group value={plot.mutilBar || 'dodge'} onChange={(e) => this.optionChange(e.target.value, 'mutilBar')}>
@@ -696,7 +728,7 @@
                    </Radio.Group>
                  </Form.Item>
                </Form>
              </Col>
              </Col> */}
              <Col span={8}>
                <Form {...formItemLayout}>
                  <Form.Item label="Y轴区间" style={{marginBottom: 10}}>
src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
@@ -20,24 +20,24 @@
  return [
    {
      type: 'text',
      key: 'title',
      field: 'title',
      label: '标题',
      initVal: card.title,
      initval: card.title,
      required: false
    },
    {
      type: 'text',
      key: 'name',
      field: 'name',
      label: '组件名称',
      initVal: card.name,
      initval: card.name,
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      key: 'width',
      field: 'width',
      label: '宽度',
      initVal: card.width,
      initval: card.width,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
@@ -46,43 +46,42 @@
    },
    {
      type: 'styleInput',
      key: 'height',
      field: 'height',
      label: '图表高度',
      initVal: card.height,
      initval: card.height,
      tooltip: '图表绘图区域的高度,不包括标题及内外边距。',
      required: true,
      options: ['px', 'vh', 'vw']
    },
    {
      type: 'radio',
      key: 'permission',
      field: 'permission',
      label: '权限验证',
      initVal: card.permission || 'false',
      initval: card.permission || 'false',
      required: false,
      options: [
        {value: 'true', text: '启用'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || ispop || isprint
    },
    {
      type: 'radio',
      key: 'cacheLocal',
      field: 'cacheLocal',
      label: '本地缓存',
      initVal: card.cacheLocal || 'true',
      initval: card.cacheLocal || 'true',
      required: false,
      options: [
        {value: 'true', text: '继承菜单'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '继承菜单'},
        {value: 'false', label: '禁用'},
      ],
      forbid: ispop || isprint
    },
    {
      type: 'select',
      key: 'blacklist',
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initVal: card.blacklist || [],
      multi: true,
      initval: card.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType || isprint
@@ -95,30 +94,30 @@
 * @param {Array}  columns    // 显示列
 */
export function getOptionForm (card, columns) {
  let appType = sessionStorage.getItem('appType')
  // let appType = sessionStorage.getItem('appType')
  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
  return [
    {
      type: 'text',
      key: 'label',
      field: 'label',
      label: '指标名称',
      initVal: card.label || '',
      initval: card.label || '',
      required: false
    },
    {
      type: 'select',
      key: 'valueField',
      field: 'valueField',
      label: '显示值',
      initVal: card.valueField || '',
      initval: card.valueField || '',
      required: true,
      options: yfields
    },
    {
      type: 'number',
      key: 'maxValue',
      field: 'maxValue',
      label: '最大值',
      initVal: card.maxValue || 100,
      initval: card.maxValue || 100,
      tooltip: '仪表盘最大刻度值',
      min: 0,
      max: 999999,
@@ -127,9 +126,9 @@
    },
    {
      type: 'number',
      key: 'tickInterval',
      field: 'tickInterval',
      label: '间隔',
      initVal: card.tickInterval || 10,
      initval: card.tickInterval || 10,
      tooltip: '仪表盘刻度间隔值。',
      min: 0,
      max: 999999,
@@ -138,56 +137,58 @@
    },
    {
      type: 'radio',
      key: 'percent',
      field: 'percent',
      label: '百分率',
      initVal: card.percent || 'true',
      initval: card.percent || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '使用'
        label: '使用'
      }, {
        value: 'false',
        text: '不使用'
        label: '不使用'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
      }]
    // }, {
    //   type: 'radio',
    //   field: 'download',
    //   label: '导出图片',
    //   initval: card.download || 'forbid',
    //   required: false,
    //   forbid: appType === 'mob',
    //   options: [{
    //     value: 'forbid',
    //     label: '禁用'
    //   }, {
    //     value: 'enable',
    //     label: '启用'
    //   }]
    },
    // {
    //   type: 'radio',
    //   key: 'empty',
    //   field: 'empty',
    //   label: '空值隐藏',
    //   initVal: card.empty || 'show',
    //   initval: card.empty || 'show',
    //   tooltip: '当查询数据为空时,隐藏该组件。',
    //   required: false,
    //   options: [
    //     {value: 'show', text: '否'},
    //     {value: 'hidden', text: '是'},
    //     {value: 'show', label: '否'},
    //     {value: 'hidden', label: '是'},
    //   ],
    // },
    {
      type: 'color',
      key: 'tickColor',
      field: 'tickColor',
      label: '刻度线',
      initVal: card.tickColor || '#CBCBCB',
      initval: card.tickColor || '',
      allowClear: true,
      required: false
    },
    {
      type: 'color',
      key: 'labelColor',
      field: 'labelColor',
      label: '指标颜色',
      initVal: card.labelColor || '#545454',
      initval: card.labelColor || '',
      allowClear: true,
      required: false
    }
  ]
@@ -199,32 +200,32 @@
 * @param {Array}  columns    // 显示列
 */
export function getRadioOptionForm (card, columns) {
  let appType = sessionStorage.getItem('appType')
  // let appType = sessionStorage.getItem('appType')
  let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype))
  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
  return [
    {
      type: 'select',
      key: 'labelField',
      field: 'labelField',
      label: '指标',
      initVal: card.labelField || '',
      initval: card.labelField || '',
      required: true,
      options: xfields
    },
    {
      type: 'select',
      key: 'valueField',
      field: 'valueField',
      label: '值',
      initVal: card.valueField || '',
      initval: card.valueField || '',
      required: true,
      options: yfields
    },
    {
      type: 'number',
      key: 'maxValue',
      field: 'maxValue',
      label: '最大值',
      initVal: card.maxValue || 100,
      initval: card.maxValue || 100,
      min: 0,
      max: 999999,
      decimal: 1,
@@ -232,9 +233,9 @@
    },
    {
      type: 'number',
      key: 'radius',
      field: 'radius',
      label: '外环',
      initVal: card.radius || 75,
      initval: card.radius || 75,
      tooltip: '图形所占区域的百分率。',
      min: 30,
      max: 100,
@@ -243,9 +244,9 @@
    },
    {
      type: 'number',
      key: 'fontSize',
      field: 'fontSize',
      label: '字体大小',
      initVal: card.fontSize || 28,
      initval: card.fontSize || 28,
      min: 12,
      max: 300,
      decimal: 0,
@@ -253,44 +254,46 @@
    },
    {
      type: 'radio',
      key: 'percent',
      field: 'percent',
      label: '百分率',
      initVal: card.percent || 'true',
      initval: card.percent || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '使用'
        label: '使用'
      }, {
        value: 'false',
        text: '不使用'
        label: '不使用'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
      }]
    // }, {
    //   type: 'radio',
    //   field: 'download',
    //   label: '导出图片',
    //   initval: card.download || 'forbid',
    //   required: false,
    //   forbid: appType === 'mob',
    //   options: [{
    //     value: 'forbid',
    //     label: '禁用'
    //   }, {
    //     value: 'enable',
    //     label: '启用'
    //   }]
    },
    {
      type: 'color',
      key: 'backColor',
      field: 'backColor',
      label: '背景色',
      initVal: card.backColor || '#ebedf0',
      initval: card.backColor || '',
      allowClear: true,
      required: false
    },
    {
      type: 'color',
      key: 'labelColor',
      field: 'labelColor',
      label: '字体颜色',
      initVal: card.labelColor || '#8c8c8c',
      initval: card.labelColor || '',
      allowClear: true,
      required: false
    }
  ]
src/menu/components/chart/antv-dashboard/chartcompile/index.jsx
@@ -1,19 +1,18 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Form, Row, Col, Select, Radio, Tooltip, Input, InputNumber, notification, Tabs, Button } from 'antd'
import { QuestionCircleOutlined, EditOutlined } from '@ant-design/icons'
import { Modal, Form, notification, Tabs, Button } from 'antd'
import { EditOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import { getBaseForm, getOptionForm, getRadioOptionForm } from './formconfig'
import asyncComponent from '@/utils/asyncComponent'
import ColorSketch from '@/mob/colorsketch'
import './index.scss'
const { TabPane } = Tabs
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform'))
const ModalForm = asyncComponent(() => import('@/components/normalform/modalform'))
class LineChartDrawerForm extends Component {
  static propTpyes = {
@@ -61,156 +60,20 @@
    })
  }
  getFields() {
    const { formlist } = this.state
    const { getFieldDecorator } = this.props.form
    const fields = []
    if (!formlist) {
      return fields
    }
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      if (item.type === 'text') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请选择' + item.label + '!'
                  }
                ]
              })(
                <Select mode={item.multi ? 'multiple' : ''}>
                  {item.options.map((option, index) =>
                    <Select.Option key={index} value={option.field}>
                      {option.label}
                    </Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请选择' + item.label + '!'
                  }
                ]
              })(
                <Radio.Group disabled={item.readonly}>
                  {item.options.map(option => {
                    return (
                      <Radio key={option.value} value={option.value}>{option.text}</Radio>
                    )
                  })}
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'color') {
        fields.push(
          <Col span={12} key={index} className="color-col">
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(
                <ColorSketch />
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
  }
  onSubmit = () => {
    const { config } = this.props
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
          this.setState({
            plot: _plot,
            visible: false
          })
          this.props.plotchange({...config, plot: _plot})
        }
      this.normalRef.handleConfirm().then(values => {
        let _plot = {...plot, ...values}
        this.setState({
          plot: _plot,
          visible: false
        })
        this.props.plotchange({...config, plot: _plot})
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
@@ -236,15 +99,13 @@
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
      this.normalRef.handleConfirm().then(values => {
        let _plot = {...plot, ...values}
          this.setState({
            plot: _plot,
            view: tab
          })
        }
        this.setState({
          plot: _plot,
          view: tab
        })
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
@@ -295,20 +156,10 @@
  render() {
    const { config } = this.props
    const { visible, plot, colorColumns, view, baseFormlist } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 18 }
      }
    }
    const { visible, plot, colorColumns, view, baseFormlist, formlist } = this.state
    return (
      <div className="line-chart-drawer-form">
      <div className="dashboard-chart-drawer-form">
        <EditOutlined title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="mk-pop-modal"
@@ -322,12 +173,10 @@
          {config.name ? <div className="mk-com-name">{config.name} - 编辑</div> : null}
          <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}>
            <TabPane tab="组件设置" key="base">
              <NormalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
              <ModalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
            </TabPane>
            <TabPane tab="图表设置" key="normal">
              <Form {...formItemLayout}>
                <Row gutter={16}>{this.getFields()}</Row>
              </Form>
              <ModalForm formlist={formlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.normalRef = inst}/>
            </TabPane>
            {plot ? <TabPane tab="颜色设置" key="color">
              <div>
src/menu/components/chart/antv-dashboard/chartcompile/index.scss
@@ -1,15 +1,10 @@
.line-chart-drawer-form {
.dashboard-chart-drawer-form {
  display: inline-block;
  > .anticon-edit {
    color: #1890ff;
  }
}
.menu-chart-edit-box {
  .color-sketch-block {
    position: relative;
    top: 5px;
    width: 240px;
  }
  .color-add {
    float: right;
    margin-bottom: 10px;
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
@@ -46,24 +46,24 @@
  return [
    {
      type: 'text',
      key: 'title',
      field: 'title',
      label: '标题',
      initVal: card.title,
      initval: card.title,
      required: false
    },
    {
      type: 'text',
      key: 'name',
      field: 'name',
      label: '组件名称',
      initVal: card.name,
      initval: card.name,
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      key: 'width',
      field: 'width',
      label: '宽度',
      initVal: card.width,
      initval: card.width,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
@@ -72,75 +72,67 @@
    },
    {
      type: 'styleInput',
      key: 'height',
      field: 'height',
      label: '图表高度',
      initVal: card.height,
      initval: card.height,
      tooltip: '图表绘图区域的高度,不包括标题及内外边距。',
      required: true,
      options: ['px', 'vh', 'vw']
    },
    {
      type: 'cascader',
      key: 'linkmenu',
      type: isApp ? 'select' : 'cascader',
      field: 'linkmenu',
      label: '关联菜单',
      initVal: card.linkmenu || [],
      tooltip: '双击饼图,会打开关联的菜单。',
      initval: card.linkmenu || (isApp ? '' : []),
      tooltip: '点击饼图,会打开关联的菜单。',
      required: false,
      forbid: isApp,
      options: menulist
    },
    {
      type: 'select',
      key: 'linkmenu',
      label: '关联菜单',
      initVal: card.linkmenu || '',
      tooltip: '双击饼图,会打开关联的菜单。',
      required: false,
      forbid: !isApp,
      options: menulist
    },
    {
      type: 'radio',
      key: 'open',
      label: '打开方式',
      initVal: card.open || 'blank',
      required: false,
      forbid: !isApp,
      options: [
        { value: 'blank', text: '新窗口' },
        { value: 'self', text: '当前窗口' }
      forbid: appType === 'mob',
      options: menulist,
      controlFields: [
        {field: 'open', notNull: true },
      ]
    },
    {
      type: 'radio',
      key: 'permission',
      field: 'open',
      label: '打开方式',
      initval: card.open || 'blank',
      required: false,
      forbid: appType !== 'pc',
      options: [
        { value: 'blank', label: '新窗口' },
        { value: 'self', label: '当前窗口' }
      ]
    },
    {
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initVal: card.permission || 'false',
      initval: card.permission || 'false',
      required: false,
      options: [
        {value: 'true', text: '启用'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || ispop || isprint
    },
    {
      type: 'radio',
      key: 'cacheLocal',
      field: 'cacheLocal',
      label: '本地缓存',
      initVal: card.cacheLocal || 'true',
      initval: card.cacheLocal || 'true',
      required: false,
      options: [
        {value: 'true', text: '继承菜单'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '继承菜单'},
        {value: 'false', label: '禁用'},
      ],
      forbid: ispop || isprint
    },
    {
      type: 'select',
      key: 'blacklist',
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initVal: card.blacklist || [],
      multi: true,
      initval: card.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType || isprint
@@ -153,55 +145,61 @@
 * @param {Array}  columns    // 显示列
 */
export function getOptionForm (card, columns) {
  let appType = sessionStorage.getItem('appType')
  // let appType = sessionStorage.getItem('appType')
  let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype))
  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
  return [
    {
      type: 'radio',
      key: 'shape',
      field: 'shape',
      label: '形状',
      initVal: card.shape || 'pie',
      initval: card.shape || 'pie',
      required: false,
      options: [
        { value: 'pie', text: '饼图' },
        { value: 'ring', text: '环图' },
        { value: 'nest', text: '嵌套' },
        { value: 'nightingale', text: '南丁格尔图' }
        { value: 'pie', label: '饼图' },
        { value: 'ring', label: '环图' },
        { value: 'nest', label: '嵌套' }
      ],
      controlFields: [
        {field: 'type', values: ['nest']},
        {field: 'legend', values: ['pie', 'ring']},
        {field: 'show', values: ['pie', 'ring']},
        {field: 'splitLine', values: ['pie', 'ring']},
        {field: 'splitColor', values: ['pie', 'ring']},
        {field: 'innerRadius', values: ['nest', 'ring']},
      ]
    },
    {
      type: 'select',
      key: 'Xaxis',
      field: 'Xaxis',
      label: '名称',
      initVal: card.Xaxis || '',
      initval: card.Xaxis || '',
      required: true,
      options: xfields
    },
    {
      type: 'select',
      key: 'Yaxis',
      field: 'Yaxis',
      label: '值',
      initVal: card.Yaxis || '',
      initval: card.Yaxis || '',
      required: true,
      options: yfields
    },
    {
      type: 'select',
      key: 'type',
      field: 'type',
      label: '类型',
      initVal: card.type || '',
      initval: card.type || '',
      tooltip: '内环的分类字段。',
      required: true,
      options: xfields,
      hidden: card.shape !== 'nest',
    },
    {
      type: 'select',
      key: 'legend',
      field: 'legend',
      label: '图例位置',
      initVal: card.legend || 'bottom',
      initval: card.legend || 'bottom',
      required: false,
      options: [
        { field: 'bottom', label: '下' },
@@ -218,13 +216,12 @@
        { field: 'left-bottom', label: '左下' },
        { field: 'hidden', label: '隐藏' }
      ],
      hidden: card.shape === 'nest',
    },
    {
      type: 'number',
      key: 'radius',
      field: 'radius',
      label: '外环',
      initVal: card.radius || 75,
      initval: card.radius || 75,
      tooltip: '图形所占区域的百分率。',
      min: 30,
      max: 100,
@@ -233,134 +230,137 @@
    },
    {
      type: 'number',
      key: 'innerRadius',
      field: 'innerRadius',
      label: '内环',
      initVal: card.innerRadius || 0,
      initval: card.innerRadius || 0,
      tooltip: '内部空白区域占图形的百分率。',
      min: 0,
      max: 90,
      decimal: 0,
      hidden: !card.shape || card.shape === 'pie',
      required: true
    },
    {
      type: 'radio',
      key: 'tooltip',
      field: 'tooltip',
      label: '悬浮提示',
      initVal: card.tooltip || 'true',
      initval: card.tooltip || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '显示'
        label: '显示'
      }, {
        value: 'false',
        text: '隐藏'
        label: '隐藏'
      }]
    },
    {
      type: 'radio',
      key: 'show',
      field: 'show',
      label: '格式化',
      initVal: card.show || 'value',
      initval: card.show || 'value',
      required: false,
      options: [{
        value: 'value',
        text: '无'
        label: '无'
      }, {
        value: 'percent',
        text: '百分比'
        label: '百分比'
      }]
    },
    {
      type: 'radio',
      key: 'label',
      field: 'label',
      label: '标注',
      initVal: card.label || 'false',
      initval: card.label || 'false',
      required: false,
      options: [{
        value: 'false',
        text: '隐藏'
        label: '隐藏'
      }, {
        value: 'inner',
        text: '内侧'
      }, {
        value: 'outer',
        text: '蜘蛛'
        label: '内侧'
      }, {
        value: 'normal',
        text: '常规'
      }],
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
        label: '外侧'
      }, {
        value: 'enable',
        text: '启用'
      }]
        value: 'outer',
        label: '蜘蛛'
      }],
    // }, {
    //   type: 'radio',
    //   field: 'download',
    //   label: '导出图片',
    //   initval: card.download || 'forbid',
    //   required: false,
    //   forbid: appType === 'mob',
    //   options: [{
    //     value: 'forbid',
    //     label: '禁用'
    //   }, {
    //     value: 'enable',
    //     label: '启用'
    //   }]
    }, {
      type: 'radio',
      key: 'empty',
      field: 'empty',
      label: '空值隐藏',
      initVal: card.empty || 'show',
      initval: card.empty || 'show',
      tooltip: '当查询数据为空时,隐藏该组件。',
      required: false,
      options: [
        {value: 'show', text: '否'},
        {value: 'hidden', text: '是'},
        {value: 'show', label: '否'},
        {value: 'hidden', label: '是'},
      ],
    }, {
      type: 'number',
      key: 'splitLine',
      field: 'splitLine',
      label: '分隔线',
      initVal: card.splitLine || '',
      initval: card.splitLine || '',
      tooltip: '分隔线的宽度。',
      min: 0,
      max: 20,
      decimal: 0,
      required: false
    }, {
      type: 'color',
      key: 'splitColor',
      label: '分隔色',
      initVal: card.splitColor || '#ffffff',
      tooltip: '分隔线的颜色,存在分隔线时有效。',
      required: false
    }, {
      type: 'color',
      key: 'color',
      label: '色系',
      initVal: card.color || 'rgba(0, 0, 0, 0.85)',
      tooltip: '坐标轴及示例等提示文字使用的颜色。',
      required: false
    }, {
      type: 'select',
      key: 'interaction',
      label: '交互效果',
      initVal: card.interaction || [],
      multi: true,
      required: false,
      forbid: appType === 'mob',
      options: [
        { value: 'element-active', label: '元素聚焦' },
        { value: 'element-selected', label: '元素选中(多选)' },
        { value: 'element-single-selected', label: '元素选中(单选)' },
        // { value: 'active-region', label: '背景框' },
        // { value: 'view-zoom', label: '视图缩放' },
        { value: 'element-highlight', label: '元素高亮' },
        // { value: 'element-highlight-by-color', label: '同色元素高亮' },
        // { value: 'element-highlight-by-x', label: '同X轴元素高亮' },
        { value: 'legend-filter', label: '图例过滤' },
        { value: 'legend-active', label: '图例聚焦' },
        { value: 'legend-highlight', label: '图例高亮' },
        // { value: 'brush', label: '选框过滤' },
      controlFields: [
        {field: 'splitColor', notNull: true}
      ]
    }, {
      type: 'color',
      field: 'splitColor',
      label: '分隔色',
      initval: card.splitColor || '#ffffff',
      tooltip: '分隔线的颜色。',
      allowClear: true,
      required: false
    // }, {
    //   type: 'color',
    //   field: 'color',
    //   label: '色系',
    //   initval: card.color || 'rgba(0, 0, 0, 0.85)',
    //   tooltip: '示例等提示文字使用的颜色。',
    //   required: false
    // } , {
    //   type: 'select',
    //   field: 'interaction',
    //   label: '交互效果',
    //   initval: card.interaction || [],
    //   multi: true,
    //   required: false,
    //   forbid: appType === 'mob',
    //   options: [
    //     { value: 'element-active', label: '元素聚焦' },
    //     { value: 'element-selected', label: '元素选中(多选)' },
    //     { value: 'element-single-selected', label: '元素选中(单选)' },
    //     // { value: 'active-region', label: '背景框' },
    //     // { value: 'view-zoom', label: '视图缩放' },
    //     { value: 'element-highlight', label: '元素高亮' },
    //     // { value: 'element-highlight-by-color', label: '同色元素高亮' },
    //     // { value: 'element-highlight-by-x', label: '同X轴元素高亮' },
    //     { value: 'legend-filter', label: '图例过滤' },
    //     { value: 'legend-active', label: '图例聚焦' },
    //     { value: 'legend-highlight', label: '图例高亮' },
    //     // { value: 'brush', label: '选框过滤' },
    //   ]
    }
  ]
}
src/menu/components/chart/antv-pie/chartcompile/index.jsx
@@ -1,21 +1,20 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Form, Row, Col, Select, Radio, Tooltip, Input, notification, InputNumber, Tabs, Button } from 'antd'
import { QuestionCircleOutlined, EditOutlined } from '@ant-design/icons'
import { Modal, notification, Tabs, Button } from 'antd'
import { EditOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import { getBaseForm, getOptionForm } from './formconfig'
import asyncComponent from '@/utils/asyncComponent'
import ColorSketch from '@/mob/colorsketch'
import './index.scss'
const { TabPane } = Tabs
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform'))
const NormalForm = asyncComponent(() => import('@/components/normalform/modalform'))
class LineChartDrawerForm extends Component {
class PieChartDrawerForm extends Component {
  static propTpyes = {
    plot: PropTypes.object,
    config: PropTypes.object,
@@ -80,145 +79,9 @@
      }, () => {
        if (val === 'ring') {
          this.props.form.setFieldsValue({innerRadius: 50})
        } else if (val === 'nightingale') {
          this.props.form.setFieldsValue({innerRadius: 0})
        }
      })
    }
  }
  getFields() {
    const { formlist } = this.state
    const { getFieldDecorator } = this.props.form
    const fields = []
    if (!formlist) {
      return fields
    }
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      if (item.type === 'text') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请选择' + item.label + '!'
                  }
                ]
              })(
                <Select mode={item.multi ? 'multiple' : ''}>
                  {item.options.map((option, index) =>
                    <Select.Option key={index} value={option.field || option.value}>
                      {option.label}
                    </Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请选择' + item.label + '!'
                  }
                ]
              })(
                <Radio.Group style={{whiteSpace: 'nowrap'}} disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}>
                  {item.options.map(option => {
                    return (
                      <Radio key={option.value} value={option.value}>{option.text}</Radio>
                    )
                  })}
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'color') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(
                <ColorSketch />
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
  }
  onSubmit = () => {
@@ -226,17 +89,15 @@
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
          this.setState({
            plot: _plot,
            visible: false
          })
          this.props.plotchange({...config, plot: _plot})
        }
      this.normalRef.handleConfirm().then(values => {
        let _plot = {...plot, ...values}
        this.setState({
          plot: _plot,
          visible: false
        })
        this.props.plotchange({...config, plot: _plot})
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
@@ -262,15 +123,13 @@
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
      this.normalRef.handleConfirm().then(values => {
        let _plot = {...plot, ...values}
          this.setState({
            plot: _plot,
            view: tab
          })
        }
        this.setState({
          plot: _plot,
          view: tab
        })
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
@@ -321,17 +180,7 @@
  render() {
    const { config } = this.props
    const { visible, plot, colorColumns, view, baseFormlist } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 18 }
      }
    }
    const { visible, plot, colorColumns, formlist, view, baseFormlist } = this.state
    return (
      <div className="line-chart-drawer-form">
@@ -339,7 +188,7 @@
        <Modal
          wrapClassName="mk-pop-modal"
          visible={visible}
          width={850}
          width={900}
          maskClosable={false}
          onOk={this.onSubmit}
          onCancel={() => { this.setState({ visible: false }) }}
@@ -351,9 +200,7 @@
              <NormalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
            </TabPane>
            <TabPane tab="图表设置" key="normal">
              <Form {...formItemLayout}>
                <Row gutter={16}>{this.getFields()}</Row>
              </Form>
              <NormalForm formlist={formlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.normalRef = inst}/>
            </TabPane>
            {plot ? <TabPane tab="颜色设置" key="color">
              <div>
@@ -362,11 +209,10 @@
              </div>
            </TabPane> : null}
          </Tabs>
        </Modal>
      </div>
    );
  }
}
export default Form.create()(LineChartDrawerForm)
export default PieChartDrawerForm
src/menu/components/chart/antv-pie/chartcompile/index.scss
@@ -5,11 +5,6 @@
  }
}
.menu-chart-edit-box {
  .color-sketch-block {
    position: relative;
    top: 5px;
    width: 240px;
  }
  .color-add {
    float: right;
    margin-bottom: 10px;
src/menu/components/chart/antv-pie/index.jsx
@@ -417,7 +417,7 @@
      height: getHeight(plot.height)
    })
    if (plot.shape !== 'nightingale' && plot.show !== 'value') {
    if (plot.show !== 'value') {
      dv.transform({
        type: 'percent',
        field: Y_axis,
@@ -436,29 +436,13 @@
    }
    chart.data(dv.rows)
    if (plot.shape === 'nightingale') {
      chart.coordinate('polar', {
        innerRadius: plot.innerRadius ? (plot.innerRadius / 100) : 0,
        radius: plot.radius ? (plot.radius / 100) : 0.85,
      })
    } else {
      chart.coordinate('theta', {
        innerRadius: plot.shape !== 'pie' && plot.innerRadius ? (plot.innerRadius / 100) : 0,
        radius: plot.radius ? (plot.radius / 100) : 0.85,
      })
    }
    chart.coordinate('theta', {
      innerRadius: plot.shape !== 'pie' && plot.innerRadius ? (plot.innerRadius / 100) : 0,
      radius: plot.radius ? (plot.radius / 100) : 0.85,
    })
    if (!plot.legend || plot.legend === 'hidden') {
      chart.legend(false)
    } else if (plot.shape === 'nightingale') {
      chart.legend(X_axis, {
        position: plot.legend,
        itemName: {
          style: {
            fill: color,
          }
        }
      })
    } else {
      chart.legend({
        position: plot.legend,
@@ -480,100 +464,73 @@
    }
    // 饼图或环图
    if (plot.shape !== 'nightingale') {
      let _chart = chart
        .interval()
        .adjust('stack')
        .position(Y_axis)
        .color(X_axis)
        .tooltip(`${X_axis}*${Y_axis}`, (name, value) => {
          if (plot.show !== 'value') {
            value = (value * 100).toFixed(2) + '%'
          }
          return {
            name: name,
            value: value
    let _chart = chart
      .interval()
      .adjust('stack')
      .position(Y_axis)
      .color(X_axis)
      .tooltip(`${X_axis}*${Y_axis}`, (name, value) => {
        if (plot.show !== 'value') {
          value = (value * 100).toFixed(2) + '%'
        }
        return {
          name: name,
          value: value
        }
      })
    if (plot.splitLine) {
      _chart.style({
        lineWidth: plot.splitLine,
        stroke: plot.splitColor,
      })
    }
    if (plot.label !== 'false') {
      if (plot.label === 'inner') {
        _chart.label(Y_axis, {
          offset: -30,
          content: (data) => {
            let _val = ''
            if (plot.show !== 'value') {
              _val = `${(data[Y_axis] * 100).toFixed(2)}%`
            } else {
              _val = `${data[Y_axis]}`
            }
            return _val
          },
          style: {
            textAlign: 'center',
            fontSize: 16,
            shadowBlur: 2,
            shadowColor: 'rgba(0, 0, 0, .45)',
            fill: '#fff',
          }
        })
      } else {
        _chart.label(Y_axis, {
          layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' },
          labelHeight: 20,
          content: (data) => {
            let _val = ''
            if (plot.show !== 'value') {
              _val = `${(data[Y_axis] * 100).toFixed(2)}%`
            } else {
              _val = `${data[Y_axis]}`
            }
      if (plot.splitLine) {
        _chart.style({
          lineWidth: plot.splitLine,
          stroke: plot.splitColor,
            return `${data[X_axis]}: ${_val}`
          },
          labelLine: {
            style: {
              lineWidth: 0.5,
            },
          },
          style: {
            fill: color
          }
        })
      }
      if (plot.label !== 'false') {
        if (plot.label === 'inner') {
          _chart.label(Y_axis, {
            offset: -30,
            content: (data) => {
              let _val = ''
              if (plot.show !== 'value') {
                _val = `${(data[Y_axis] * 100).toFixed(2)}%`
              } else {
                _val = `${data[Y_axis]}`
              }
              return _val
            },
            style: {
              textAlign: 'center',
              fontSize: 16,
              shadowBlur: 2,
              shadowColor: 'rgba(0, 0, 0, .45)',
              fill: '#fff',
            }
          })
        } else {
          _chart.label(Y_axis, {
            layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' },
            labelHeight: 20,
            content: (data) => {
              let _val = ''
              if (plot.show !== 'value') {
                _val = `${(data[Y_axis] * 100).toFixed(2)}%`
              } else {
                _val = `${data[Y_axis]}`
              }
              return `${data[X_axis]}: ${_val}`
            },
            labelLine: {
              style: {
                lineWidth: 0.5,
              },
            },
            style: {
              fill: color
            }
          })
        }
      }
    } else {
      chart.axis(false)
      let _chart = chart
        .interval()
        .position(`${X_axis}*${Y_axis}`)
        .color(X_axis)
        if (plot.label !== 'false') {
          let _label = {}
          if (plot.label === 'inner') {
            _label.offset = -15
          } else {
            _label.style = {
              fill: color
            }
          }
          _chart.label(X_axis, _label)
        }
        if (plot.splitLine) {
          _chart.style({
            lineWidth: plot.splitLine,
            stroke: plot.splitColor,
          })
        }
    }
    if (plot.interaction && plot.interaction.length) {
src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx
@@ -20,24 +20,24 @@
  return [
    {
      type: 'text',
      key: 'title',
      field: 'title',
      label: '标题',
      initVal: card.title,
      initval: card.title,
      required: false
    },
    {
      type: 'text',
      key: 'name',
      field: 'name',
      label: '组件名称',
      initVal: card.name,
      initval: card.name,
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      key: 'width',
      field: 'width',
      label: '宽度',
      initVal: card.width,
      initval: card.width,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
@@ -46,43 +46,42 @@
    },
    {
      type: 'styleInput',
      key: 'height',
      field: 'height',
      label: '图表高度',
      initVal: card.height,
      initval: card.height,
      tooltip: '图表绘图区域的高度,不包括标题及内外边距。',
      required: true,
      options: ['px', 'vh', 'vw']
    },
    {
      type: 'radio',
      key: 'permission',
      field: 'permission',
      label: '权限验证',
      initVal: card.permission || 'false',
      initval: card.permission || 'false',
      required: false,
      options: [
        {value: 'true', text: '启用'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || ispop || isprint
    },
    {
      type: 'radio',
      key: 'cacheLocal',
      field: 'cacheLocal',
      label: '本地缓存',
      initVal: card.cacheLocal || 'true',
      initval: card.cacheLocal || 'true',
      required: false,
      options: [
        {value: 'true', text: '继承菜单'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '继承菜单'},
        {value: 'false', label: '禁用'},
      ],
      forbid: ispop || isprint
    },
    {
      type: 'select',
      key: 'blacklist',
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initVal: card.blacklist || [],
      multi: true,
      initval: card.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType || isprint
@@ -96,132 +95,97 @@
 * @param {Array}  columns    // 显示列
 */
export function getOptionForm (card, columns) {
  let appType = sessionStorage.getItem('appType')
  // let appType = sessionStorage.getItem('appType')
  let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype))
  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
  return [
    {
      type: 'select',
      key: 'gender',
      field: 'gender',
      label: '类型',
      initVal: card.gender || '',
      initval: card.gender || '',
      required: true,
      options: xfields
    },
    {
      type: 'select',
      key: 'Xaxis',
      field: 'Xaxis',
      label: 'X-轴',
      initVal: card.Xaxis || '',
      initval: card.Xaxis || '',
      required: true,
      options: columns
    },
    {
      type: 'select',
      key: 'Yaxis',
      field: 'Yaxis',
      label: 'Y-轴',
      initVal: card.Yaxis || '',
      initval: card.Yaxis || '',
      required: true,
      options: yfields
    },
    {
      type: 'radio',
      key: 'shape',
      field: 'shape',
      label: '形状',
      initVal: card.shape || 'circle',
      initval: card.shape || 'circle',
      required: false,
      options: [{
        value: 'circle',
        text: 'circle'
        label: '圆形'
      }, {
        value: 'square',
        text: 'square'
        label: '方形'
      }]
    },
    {
      type: 'radio',
      key: 'tooltip',
      field: 'tooltip',
      label: '悬浮提示',
      initVal: card.tooltip || 'true',
      initval: card.tooltip || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '显示'
        label: '显示'
      }, {
        value: 'false',
        text: '隐藏'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
        label: '隐藏'
      }]
    },
    {
      type: 'radio',
      key: 'empty',
      field: 'empty',
      label: '空值隐藏',
      initVal: card.empty || 'show',
      initval: card.empty || 'show',
      tooltip: '当查询数据为空时,隐藏该组件。',
      required: false,
      options: [
        {value: 'show', text: '否'},
        {value: 'hidden', text: '是'},
        {value: 'show', label: '否'},
        {value: 'hidden', label: '是'},
      ],
    },
    {
      type: 'text',
      key: 'Xunit',
      field: 'Xunit',
      label: 'X轴单位',
      initVal: card.Xunit || '',
      initval: card.Xunit || '',
      required: false
    },
    {
      type: 'text',
      key: 'Yunit',
      field: 'Yunit',
      label: 'Y轴单位',
      initVal: card.Yunit || '',
      initval: card.Yunit || '',
      required: false
    },
    {
      type: 'color',
      key: 'color',
      label: '色系',
      initVal: card.color || 'rgba(0, 0, 0, 0.65)',
      tooltip: '坐标轴提示文字及示例的颜色。',
      field: 'lineColor',
      label: '坐标轴颜色',
      initval: card.lineColor || '',
      tooltip: '坐标轴线的颜色。',
      allowClear: true,
      required: false
    }, {
      type: 'select',
      key: 'interaction',
      label: '交互效果',
      initVal: card.interaction || [],
      multi: true,
      required: false,
      forbid: appType === 'mob',
      options: [
        { value: 'element-active', label: '元素聚焦' },
        { value: 'element-selected', label: '元素选中(多选)' },
        { value: 'element-single-selected', label: '元素选中(单选)' },
        // { value: 'active-region', label: '背景框' },
        { value: 'view-zoom', label: '视图缩放' },
        { value: 'element-highlight', label: '元素高亮' },
        { value: 'element-highlight-by-color', label: '同色元素高亮' },
        { value: 'element-highlight-by-x', label: '同X轴元素高亮' },
        { value: 'legend-filter', label: '图例过滤' },
        { value: 'legend-active', label: '图例聚焦' },
        { value: 'legend-highlight', label: '图例高亮' },
        { value: 'brush', label: '选框过滤' },
      ]
    }
  ]
}
src/menu/components/chart/antv-scatter/chartcompile/index.jsx
@@ -1,16 +1,15 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Form, Row, Col, Select, Radio, Tooltip, Input, InputNumber, Tabs } from 'antd'
import { QuestionCircleOutlined, EditOutlined } from '@ant-design/icons'
import { Modal, Form, Tabs } from 'antd'
import { EditOutlined } from '@ant-design/icons'
import { getBaseForm, getOptionForm } from './formconfig'
import asyncComponent from '@/utils/asyncComponent'
import ColorSketch from '@/mob/colorsketch'
import './index.scss'
const { TabPane } = Tabs
const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform'))
const ModalForm = asyncComponent(() => import('@/components/normalform/modalform'))
class LineChartDrawerForm extends Component {
  static propTpyes = {
@@ -39,156 +38,20 @@
    })
  }
  getFields() {
    const { formlist } = this.state
    const { getFieldDecorator } = this.props.form
    const fields = []
    if (!formlist) {
      return fields
    }
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      if (item.type === 'text') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请选择' + item.label + '!'
                  }
                ]
              })(
                <Select mode={item.multi ? 'multiple' : ''}>
                  {item.options.map((option, index) =>
                    <Select.Option key={index} value={option.field || option.value}>
                      {option.label || option.text}
                    </Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: '请选择' + item.label + '!'
                  }
                ]
              })(
                <Radio.Group disabled={item.readonly}>
                  {item.options.map(option => {
                    return (
                      <Radio key={option.value} value={option.value}>{option.text}</Radio>
                    )
                  })}
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'color') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(
                <ColorSketch />
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
  }
  onSubmit = () => {
    const { config } = this.props
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
      this.normalRef.handleConfirm().then(values => {
        let _plot = {...plot, ...values}
          this.setState({
            plot: _plot,
            visible: false
          })
        this.setState({
          plot: _plot,
          visible: false
        })
          this.props.plotchange({...config, plot: _plot})
        }
        this.props.plotchange({...config, plot: _plot})
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
@@ -208,13 +71,11 @@
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          this.setState({
            plot: {...plot, ...values},
            view: tab
          })
        }
      this.normalRef.handleConfirm().then(values => {
        this.setState({
          plot: {...plot, ...values},
          view: tab
        })
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
@@ -228,17 +89,7 @@
  render() {
    const { config } = this.props
    const { view, visible, baseFormlist } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 18 }
      }
    }
    const { view, visible, baseFormlist, formlist } = this.state
    return (
      <div className="line-chart-drawer-form">
@@ -255,12 +106,10 @@
          {config.name ? <div className="mk-com-name">{config.name} - 编辑</div> : null}
          <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}>
            <TabPane tab="组件设置" key="base">
              <NormalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
              <ModalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
            </TabPane>
            <TabPane tab="图表设置" key="normal">
              <Form {...formItemLayout}>
                <Row gutter={16}>{this.getFields()}</Row>
              </Form>
              <ModalForm formlist={formlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.normalRef = inst}/>
            </TabPane>
          </Tabs>
        </Modal>
src/menu/components/chart/antv-scatter/chartcompile/index.scss
@@ -5,11 +5,6 @@
  }
}
.menu-chart-edit-box {
  .color-sketch-block {
    position: relative;
    top: 5px;
    width: 240px;
  }
  .color-add {
    float: right;
    margin-bottom: 10px;
src/menu/components/chart/antv-scatter/index.jsx
@@ -350,7 +350,7 @@
            {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="添加搜索" onClick={this.addSearch}/> : null}
            {appType !== 'mob' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={this.addButton}/> : null}
            <ChartCompileForm config={card} plotchange={this.updateComponent}/>
            <CopyComponent type="line" card={card}/>
            <CopyComponent type="scatter" card={card}/>
            <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
src/menu/components/chart/chart-custom/chartcompile/formconfig.jsx
@@ -20,35 +20,35 @@
  return [
    {
      type: 'text',
      key: 'title',
      field: 'title',
      label: '标题',
      initVal: card.title,
      initval: card.title,
      required: false
    },
    {
      type: 'text',
      key: 'name',
      field: 'name',
      label: '组件名称',
      initVal: card.name,
      initval: card.name,
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'radio',
      key: 'chartType',
      field: 'chartType',
      label: '图表类型',
      initVal: card.chartType || 'antv',
      initval: card.chartType || 'antv',
      required: true,
      options: [
        { value: 'antv', text: 'antv' },
        { value: 'echarts', text: 'echarts' }
        { value: 'antv', label: 'antv5.0' },
        { value: 'echarts', label: 'echarts' }
      ]
    },
    {
      type: 'number',
      key: 'width',
      field: 'width',
      label: '宽度',
      initVal: card.width,
      initval: card.width,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
@@ -57,67 +57,45 @@
    },
    {
      type: 'styleInput',
      key: 'height',
      field: 'height',
      label: '图表高度',
      initVal: card.height,
      initval: card.height,
      tooltip: '图表绘图区域的高度,不包括标题及内外边距。',
      required: true,
      options: ['px', 'vh', 'vw']
    },
    {
      type: 'radio',
      key: 'permission',
      field: 'permission',
      label: '权限验证',
      initVal: card.permission || 'false',
      initval: card.permission || 'false',
      required: false,
      options: [
        {value: 'true', text: '启用'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || ispop || isprint
    },
    {
      type: 'radio',
      key: 'cacheLocal',
      field: 'cacheLocal',
      label: '本地缓存',
      initVal: card.cacheLocal || 'true',
      initval: card.cacheLocal || 'true',
      required: false,
      options: [
        {value: 'true', text: '继承菜单'},
        {value: 'false', text: '禁用'},
        {value: 'true', label: '继承菜单'},
        {value: 'false', label: '禁用'},
      ],
      forbid: ispop || isprint
    },
    {
      type: 'select',
      key: 'blacklist',
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initVal: card.blacklist || [],
      multi: true,
      initval: card.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType || isprint
    },
    // {
    //   type: 'cascader',
    //   key: 'linkmenu',
    //   label: '关联菜单',
    //   initVal: card.linkmenu || [],
    //   tooltip: '在使用柱形图且未启用自定义设置时有效。',
    //   required: false,
    //   forbid: appType === 'pc' || appType === 'mob',
    //   options: menulist
    // },
    // {
    //   type: 'select',
    //   key: 'linkmenu',
    //   label: '关联菜单',
    //   initVal: card.linkmenu || '',
    //   tooltip: '双击柱状图,会打开关联的菜单。',
    //   required: false,
    //   forbid: appType !== 'pc',
    //   options: menulist
    // },
    }
  ]
}
src/menu/components/chart/chart-custom/chartcompile/index.jsx
@@ -9,7 +9,7 @@
// import './index.scss'
const { TabPane } = Tabs
const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform'))
const ModalForm = asyncComponent(() => import('@/components/normalform/modalform'))
const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror'))
class CustomChartDrawerForm extends Component {
@@ -104,10 +104,10 @@
          {config.name ? <div className="mk-com-name">{config.name} - 编辑</div> : null}
          <Tabs activeKey={view} onChange={this.changeTab}>
            <TabPane tab="组件设置" key="base">
              <NormalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
              <ModalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
            </TabPane>
            {plot ? <TabPane tab="JS" key="JS">
              {plot.chartType === 'antv' ? <div>入参:Chart、 DataSet、 wrap(dom节点)、data、 config</div> : <div>入参:echarts、 DataSet、 wrap(dom节点)、 data、 config</div>}
              {plot.chartType === 'antv' ? <div>入参:Chart、 chartId(dom节点id)、data、 config</div> : <div>入参:echarts、 chartId(dom节点id)、 data、 config</div>}
              <CodeMirror mode="text/javascript" theme="cobalt" value={plot.script} onChange={this.onChange} />
            </TabPane> : null}
          </Tabs>
src/menu/components/chart/chart-custom/index.jsx
@@ -251,7 +251,7 @@
          <div className="mk-popover-control">
            {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="添加搜索" onClick={this.addSearch}/> : null}
            <ChartCompileForm config={card} plotchange={this.updateComponent}/>
            <CopyComponent type="line" card={card}/>
            <CopyComponent type="chart" card={card}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
src/menu/components/form/dragtitle/card.jsx
@@ -90,7 +90,7 @@
          <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
        </NormalForm>
        <CopyComponent type="formgroup" card={card}/>
        <PasteForms config={card} updateConfig={(res) => pasteForm(res, id)} />
        <PasteForms config={card} update={(res) => pasteForm(res, id)} />
        <CloseOutlined className="close" type="close" onClick={close} />
      </div>
    } trigger="hover">
src/menu/components/form/formaction/actionform/index.jsx
@@ -57,10 +57,13 @@
    } else if (this.record.type === 'close' || this.record.type === 'reset') {
      shows = ['typeName', 'label']
    } else {
      shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload', 'preButton'] // 选项列表
      shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload', 'preButton', 'formCache'] // 选项列表
      if (this.record.execSuccess === 'never') {
        shows.push('resetForms')
      }
      if (this.record.syncComponent && this.record.syncComponent[0]) {
        shows.push('syncDelay')
      }
      if (this.record.intertype === 'custom') {
        shows.push('procMode', 'interface', 'callbackType', 'proInterface', 'method', 'cross', 'stringify', 'ContentType', 'outerBlacklist')
@@ -102,6 +105,9 @@
        shows.push('innerFunc')
      } else {
        shows.push('sql', 'sqlType')
        if (this.record.execSuccess === 'never' && this.record.resetForms && this.record.resetForms[0]) {
          shows.push('returnValue')
        }
      }
      
      if (this.record.linkmenu && this.record.linkmenu !== 'goback') {
@@ -260,7 +266,7 @@
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<InputNumber min={0} max={10000} precision={0} onPressEnter={this.handleSubmit}/>)}
              })(<InputNumber min={0} max={10000} placeholder={item.placeholder || ''} precision={0} onPressEnter={this.handleSubmit}/>)}
            </Form.Item>
          </Col>
        )
src/menu/components/form/formaction/formconfig.jsx
@@ -127,10 +127,17 @@
  fields.forEach(item => {
    if (item.type !== 'text' && item.type !== 'number') return
    resets.push({
      value: item.field,
      text: item.label
    })
    if (item.label !== item.field) {
      resets.push({
        value: item.field,
        text: item.label + ' (' + item.field + ')'
      })
    } else {
      resets.push({
        value: item.field,
        text: item.label
      })
    }
  })
  return [
@@ -467,6 +474,15 @@
      options: modules
    },
    {
      type: 'number',
      key: 'syncDelay',
      label: '刷新延迟',
      initVal: card.syncDelay,
      tooltip: '同步刷新组件的延迟时间,单位毫秒。',
      // placeholder: '单位毫秒',
      required: false
    },
    {
      type: 'cascader',
      key: 'anchors',
      label: '跳转锚点',
@@ -497,6 +513,20 @@
    },
    {
      type: 'radio',
      key: 'returnValue',
      label: '更新表单',
      initVal: card.returnValue || 'false',
      tooltip: '与重置表单配合使用,开启时,必须在自定义脚本中返回数据,用于替换字段集和填充表单。',
      options: [{
        value: 'false',
        text: '禁用'
      }, {
        value: 'true',
        text: '启用'
      }]
    },
    {
      type: 'radio',
      key: 'reload',
      label: '上一页',
      initVal: card.reload || 'false',
@@ -510,5 +540,20 @@
        text: '刷新'
      }]
    },
    // {
    //   type: 'radio',
    //   key: 'formCache',
    //   label: '表单缓存',
    //   initVal: card.formCache || 'false',
    //   tooltip: '主要用于数据修改后,更新相关表单的选项,清空缓存后表单再次打开时数据会重新加载。',
    //   required: false,
    //   options: [{
    //     value: 'false',
    //     text: '不清空'
    //   }, {
    //     value: 'clear',
    //     text: '清空'
    //   }]
    // },
  ]
}
src/menu/components/form/formaction/index.jsx
@@ -100,8 +100,10 @@
      supId = config.wrap.supModule[config.wrap.supModule.length - 1]
    }
    let modules = MenuUtils.getSubModules(window.GLOB.customMenu.components, config.uuid, supId)
    let anchors = MenuUtils.getAnchors(window.GLOB.customMenu.components, config.uuid) || []
    let menu = window.GLOB.customMenu
    let modules = MenuUtils.getSubModules(menu.components, config.uuid, supId, menu.interfaces || null)
    let anchors = MenuUtils.getAnchors(menu.components, config.uuid) || []
    if (card.type === 'submit' && !card.Ot) {
      card.Ot = config.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
src/menu/components/form/simple-form/index.jsx
@@ -140,6 +140,13 @@
        if (item.subButton.intertype === 'system' && !item.subButton.sqlType) {
          card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮请设置操作类型`})
        }
        if (item.subButton.verify && !item.subButton.output) {
          if (item.subButton.verify.noteEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值短信发送无效!`})
          } else if (item.subButton.verify.emailEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值邮件发送无效!`})
          }
        }
        item.fields.forEach(m => {
          if (m.dataSource && /@ID@/ig.test(m.dataSource)) {
            idCtrl = true
@@ -161,6 +168,13 @@
        if (item.subButton.intertype === 'system' && !item.subButton.sqlType) {
          card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮请设置操作类型`})
        }
        if (item.subButton.verify && !item.subButton.output) {
          if (item.subButton.verify.noteEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值短信发送无效!`})
          } else if (item.subButton.verify.emailEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值邮件发送无效!`})
          }
        }
        item.fields.forEach(m => {
          if (m.dataSource && /@ID@/ig.test(m.dataSource)) {
            idCtrl = true
src/menu/components/form/step-form/index.jsx
@@ -147,6 +147,13 @@
        if (item.subButton.intertype === 'system' && !item.subButton.sqlType) {
          card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮请设置操作类型`})
        }
        if (item.subButton.verify && !item.subButton.output) {
          if (item.subButton.verify.noteEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值短信发送无效!`})
          } else if (item.subButton.verify.emailEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值邮件发送无效!`})
          }
        }
        item.fields.forEach(m => {
          if (m.dataSource && /@ID@/ig.test(m.dataSource)) {
            idCtrl = true
@@ -168,6 +175,13 @@
        if (item.subButton.intertype === 'system' && !item.subButton.sqlType) {
          card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮请设置操作类型`})
        }
        if (item.subButton.verify && !item.subButton.output) {
          if (item.subButton.verify.noteEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值短信发送无效!`})
          } else if (item.subButton.verify.emailEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值邮件发送无效!`})
          }
        }
        item.fields.forEach(m => {
          if (m.dataSource && /@ID@/ig.test(m.dataSource)) {
            idCtrl = true
src/menu/components/form/tab-form/index.jsx
@@ -159,6 +159,13 @@
        if (item.subButton.intertype === 'system' && !item.subButton.sqlType) {
          card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮请设置操作类型`})
        }
        if (item.subButton.verify && !item.subButton.output) {
          if (item.subButton.verify.noteEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值短信发送无效!`})
          } else if (item.subButton.verify.emailEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值邮件发送无效!`})
          }
        }
        item.fields.forEach(m => {
          if (m.dataSource && /@ID@/ig.test(m.dataSource)) {
            idCtrl = true
@@ -180,6 +187,13 @@
        if (item.subButton.intertype === 'system' && !item.subButton.sqlType) {
          card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮请设置操作类型`})
        }
        if (item.subButton.verify && !item.subButton.output) {
          if (item.subButton.verify.noteEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值短信发送无效!`})
          } else if (item.subButton.verify.emailEnable === 'true') {
            card.errors.push({ level: 0, detail: `${item.subButton.label} 按钮未设置返回值邮件发送无效!`})
          }
        }
        item.fields.forEach(m => {
          if (m.dataSource && /@ID@/ig.test(m.dataSource)) {
            idCtrl = true
src/menu/components/group/groupcomponents/index.jsx
@@ -51,7 +51,7 @@
    drop(item) {
      if (item.hasOwnProperty('originalIndex') || item.added) {
        return
      } else if (['login', 'navbar', 'topbar', 'tabs', 'search', 'group', 'menubar'].includes(item.component)) {
      } else if (['login', 'navbar', 'topbar', 'tabs', 'search', 'group', 'menubar', 'iframe', 'sharecode', 'officialAccount'].includes(item.component)) {
        return
      }
src/menu/components/group/normal-group/index.jsx
@@ -15,7 +15,7 @@
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const PasteComponent = asyncIconComponent(() => import('../paste'))
const PasteController = asyncIconComponent(() => import('@/menu/pastecontroller'))
const GroupComponents = asyncComponent(() => import('../groupcomponents'))
class NormalGroup extends Component {
@@ -178,9 +178,9 @@
            <NormalForm title="分组设置" width={700} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="tabs" card={group}/>
            <CopyComponent type="group" card={group}/>
            <UngroupOutlined title="释放" style={group.components.length > 0 ? {color: '#32c5d2'} : {color: '#eeeeee', cursor: 'not-allowed'}} onClick={this.unGroup}/>
            <PasteComponent insert={this.insert} />
            <PasteController type="group" tab={group} insert={this.insert} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(group.uuid)} />
          </div>
src/menu/components/group/paste/index.jsx
File was deleted
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -14,9 +14,9 @@
const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
const MKTable = asyncComponent(() => import('@/components/normalform/modalform/mkTable'))
const acTyOptions = {
  pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hidden', 'preButton'],
  prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hidden', 'preButton'],
  exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'hidden', 'preButton'],
  pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hidden', 'preButton', 'formCache'],
  prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hidden', 'preButton', 'formCache'],
  exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'hidden', 'preButton', 'formCache'],
  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'color', 'sheet', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'width', 'hidden'],
  excelOut: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'pagination', 'search', 'width', 'hidden'],
  popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'color', 'popClose', 'width', 'display', 'ratio', 'syncComponent', 'clickouter', 'maskStyle', 'closeButton', 'hidden'],
@@ -505,6 +505,10 @@
      } else if (_funcType === 'refund') {
        shows.push('Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu')
        reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
      } else if (_funcType === 'shareLink') {
        shows.push('shortUrl', 'shareUrl', 'shareProUrl', 'shareTip')
      // } else if (_funcType === 'expPdf') {
      //   shows.push('exportType')
      }
    }
    
@@ -523,7 +527,7 @@
          shows.push('reason')
        }
      }
    } else {
    } else if (openType !== 'funcbutton' || !['expPdf', 'shareLink'].includes(this.record.funcType)) {
      if (openType !== 'excelOut') {
        reOptions.control = [
          { value: '', text: '无' },
@@ -780,6 +784,7 @@
      let className = ''
      let content = null
      let initVal = item.initVal || ''
      let help = item.help || ''
      if (item.type === 'splitLine') {
        fields.push(
@@ -857,6 +862,7 @@
            filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
              option.props.extend.toLowerCase().indexOf(input.toLowerCase()) >= 0}
            onChange={(value) => {this.optionChange(item.key, value)}}
            on
            getPopupContainer={() => document.getElementById('winter')}
          >
            {item.options.map((option, index) =>
@@ -909,7 +915,7 @@
        rules = [
          { required: item.required, message: '请添加' + item.label + '!' }
        ]
        content = (<MKTable tip={''} columns={item.columns || []} actions={[]}/>)
        content = (<MKTable columns={item.columns || []} actions={item.actions}/>)
      } else if (item.type === 'icon') {
        rules = [
          { required: item.required, message: '请选择' + item.label + '!' }
@@ -936,7 +942,7 @@
          { required: item.required, message: '请选择' + item.label + '!' }
        ]
        content = <MkPrintTemps />
        content = <MkPrintTemps onChange={(value) => {this.optionChange(item.key, value)}}/>
      } else if (item.type === 'keyinterface') {
        span = 24
        className = 'textarea'
@@ -947,9 +953,13 @@
        content = <KeyInterface type={item.key === 'exInterface' ? 'develop' : 'product'}/>
      }
      if (help && typeof(help) === 'function') {
        help = help(this.record)
      }
      fields.push(
        <Col span={span} key={index}>
          <Form.Item className={className} help={item.help} label={item.tooltip ?
          <Form.Item className={className} help={help} label={item.tooltip ?
            <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.tooltip.length > 25 ? 350 : 250 }} title={<span onClick={(e) => e.stopPropagation()}>{item.tooltip}</span>}>
              <QuestionCircleOutlined className="mk-form-tip" />
              {item.label}
@@ -1077,6 +1087,8 @@
                }
              })
            }
          } else if (values.OpenType === 'funcbutton' && values.funcType === 'expPdf') {
            values.Ot = 'notRequired'
          }
          
          if (values.outerBlacklist) {
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -1,5 +1,5 @@
import React from 'react'
import { btnClasses } from '@/utils/option.js'
/**
 * @description 获取按钮表单配置信息
@@ -161,6 +161,8 @@
    { value: 'print', text: '标签打印' },
    { value: 'refund', text: '退款' },
    { value: 'closetab', text: '标签关闭' },
    { value: 'expPdf', text: '导出PDF' },
    { value: 'shareLink', text: '分享链接' },
    { value: 'megvii', text: '旷视面板机' },
    { value: 'filezip', text: '文件压缩包' },
  ]
@@ -203,6 +205,8 @@
      { value: 'reAuth', text: '切换系统(清空缓存-小程序)' },
      { value: 'clearCache', text: '清空本地配置' },
      { value: 'copyurl', text: '复制链接地址' },
      { value: 'expPdf', text: '导出PDF' },
      { value: 'shareLink', text: '分享链接' },
      { value: 'logout', text: '退出' },
      { value: 'goBack', text: '返回' },
    ]
@@ -468,6 +472,19 @@
      key: 'printTemp',
      label: '打印模板',
      initVal: card.printTemp || '',
      help: (record) => {
        if (record.printTemp) {
          return <span onClick={() => {
            sessionStorage.setItem('mk-print-temp', record.printTemp)
            window.open('#/hs')
            setTimeout(() => {
              sessionStorage.removeItem('mk-print-temp')
            }, 50)
          }} style={{color: '#1890ff', cursor: 'pointer', fontSize: '13px'}}>#查看模板</span>
        }
        return ''
      },
      required: true
    },
    {
@@ -751,6 +768,43 @@
      }]
    },
    {
      type: 'radio',
      key: 'shortUrl',
      label: '短链接',
      initVal: card.shortUrl || 'false',
      options: [{
        value: 'false',
        text: '禁用'
      }, {
        value: 'true',
        text: '启用'
      }]
    },
    {
      type: 'textarea',
      key: 'shareUrl',
      label: '链接地址',
      initVal: card.shareUrl || '',
      tooltip: '链接中如果存在@BID@或@ID@将自动替换。',
      required: true
    },
    {
      type: 'textarea',
      key: 'shareProUrl',
      label: '正式链接',
      initVal: card.shareProUrl || '',
      tooltip: '链接中如果存在@BID@或@ID@将自动替换。',
      required: false
    },
    {
      type: 'text',
      key: 'shareTip',
      label: '分享提示',
      initVal: card.shareTip || '',
      tooltip: '分享时对用户的提示信息。',
      required: false
    },
    {
      type: 'number',
      key: 'width',
      min: 0,
@@ -762,6 +816,21 @@
      forbid: type !== 'card',
      required: true
    },
    // {
    //   type: 'radio',
    //   key: 'exportType',
    //   label: '导出方式',
    //   initVal: card.exportType || 'download',
    //   tooltip: '',
    //   required: true,
    //   options: [{
    //     value: 'download',
    //     text: '下载本地'
    //   }, {
    //     value: 'link',
    //     text: '生成链接'
    //   }]
    // },
    {
      type: 'radio',
      key: 'show',
@@ -1206,6 +1275,21 @@
    },
    {
      type: 'radio',
      key: 'formCache',
      label: '表单缓存',
      initVal: card.formCache || 'false',
      tooltip: '主要用于数据修改后,更新相关表单的选项,清空缓存后表单再次打开时数据会重新加载。',
      required: false,
      options: [{
        value: 'false',
        text: '不清空'
      }, {
        value: 'clear',
        text: '清空'
      }]
    },
    {
      type: 'radio',
      key: 'hidden',
      label: '隐藏',
      initVal: card.hidden || 'false',
@@ -1349,13 +1433,14 @@
      label: '组件列表',
      initVal: card.syncComponents || [],
      required: true,
      actions: [],
      actions: ['edit', 'del', 'add', 'move'],
      columns: [
        {
          title: '组件',
          dataIndex: 'syncComId',
          inputType: 'cascader',
          editable: true,
          unique: true,
          required: true,
          extends: [{key: 'label', value: 'label'}],
          width: '70%',
@@ -1430,6 +1515,8 @@
    { value: 'print', text: '标签打印' },
    { value: 'refund', text: '退款' },
    { value: 'closetab', text: '标签关闭' },
    { value: 'expPdf', text: '导出PDF' },
    { value: 'shareLink', text: '分享链接' },
    { value: 'megvii', text: '旷视面板机' },
    { value: 'filezip', text: '文件压缩包' },
  ]
@@ -1603,6 +1690,19 @@
      key: 'printTemp',
      label: '打印模板',
      initVal: card.printTemp || '',
      help: (record) => {
        if (record.printTemp) {
          return <span onClick={() => {
            sessionStorage.setItem('mk-print-temp', record.printTemp)
            window.open('#/hs')
            setTimeout(() => {
              sessionStorage.removeItem('mk-print-temp')
            }, 50)
          }} style={{color: '#1890ff', cursor: 'pointer', fontSize: '13px'}}>#查看模板</span>
        }
        return ''
      },
      required: true
    },
    {
@@ -1872,18 +1972,70 @@
        text: '不重置'
      }]
    },
    // {
    //   type: 'radio',
    //   key: 'exportType',
    //   label: '导出方式',
    //   initVal: card.exportType || 'download',
    //   tooltip: '',
    //   required: true,
    //   options: [{
    //     value: 'download',
    //     text: '下载本地'
    //   }, {
    //     value: 'link',
    //     text: '生成链接'
    //   }]
    // },
    {
      type: 'number',
      key: 'width',
      min: 1,
      max: 24,
      precision: 0,
      label: '宽度',
      initVal: card.width || 12,
      tooltip: '栅格布局,每行等分为24列。',
      forbid: card.eleType !== 'button',
      type: 'radio',
      key: 'shortUrl',
      label: '短链接',
      initVal: card.shortUrl || 'false',
      options: [{
        value: 'false',
        text: '禁用'
      }, {
        value: 'true',
        text: '启用'
      }]
    },
    {
      type: 'textarea',
      key: 'shareUrl',
      label: '链接地址',
      initVal: card.shareUrl || '',
      tooltip: '链接中如果存在@BID@或@ID@将自动替换。',
      required: true
    },
    {
      type: 'textarea',
      key: 'shareProUrl',
      label: '正式链接',
      initVal: card.shareProUrl || '',
      tooltip: '链接中如果存在@BID@或@ID@将自动替换。',
      required: false
    },
    {
      type: 'text',
      key: 'shareTip',
      label: '分享提示',
      initVal: card.shareTip || '',
      tooltip: '分享时对用户的提示信息。',
      required: false
    },
    // {
    //   type: 'number',
    //   key: 'width',
    //   min: 1,
    //   max: 24,
    //   precision: 0,
    //   label: '宽度',
    //   initVal: card.width || 12,
    //   tooltip: '栅格布局,每行等分为24列。',
    //   forbid: card.eleType !== 'button',
    //   required: true
    // },
    {
      type: 'radio',
      key: 'show',
@@ -2173,6 +2325,21 @@
    },
    {
      type: 'radio',
      key: 'formCache',
      label: '表单缓存',
      initVal: card.formCache || 'false',
      tooltip: '主要用于数据修改后,更新相关表单的选项,清空缓存后表单再次打开时数据会重新加载。',
      required: false,
      options: [{
        value: 'false',
        text: '不清空'
      }, {
        value: 'clear',
        text: '清空'
      }]
    },
    {
      type: 'radio',
      key: 'hidden',
      label: '隐藏',
      initVal: card.hidden || 'false',
@@ -2221,12 +2388,13 @@
      label: '组件列表',
      initVal: card.syncComponents || [],
      required: true,
      actions: [],
      actions: ['edit', 'del', 'add', 'move'],
      columns: [
        {
          title: '组件',
          dataIndex: 'syncComId',
          inputType: 'cascader',
          unique: true,
          editable: true,
          required: true,
          extends: [{key: 'label', value: 'label'}],
src/menu/components/share/actioncomponent/index.jsx
@@ -206,8 +206,10 @@
        supId = ''
      }
    }
    let menu = window.GLOB.customMenu
    
    let modules = MenuUtils.getSubModules(window.GLOB.customMenu.components, config.uuid, supId, config.subtype !== 'basetable')
    let modules = MenuUtils.getSubModules(menu.components, config.uuid, supId, menu.interfaces || null)
    if (config.subtype === 'basetable') {
      delete card.eleType // 区分按钮位置
@@ -218,7 +220,7 @@
        formlist: getBaseTableActionForm(card, functip, config, usefulFields, modules)
      })
    } else {
      let anchors = MenuUtils.getAnchors(window.GLOB.customMenu.components, config.uuid) || []
      let anchors = MenuUtils.getAnchors(menu.components, config.uuid) || []
  
      this.setState({
        visible: true,
src/menu/components/share/colsControl/index.jsx
@@ -272,10 +272,16 @@
  }
  render() {
    const { config } = this.props
    const { colsCtrls, columns, visible, cols, searches } = this.state
    let className = ''
    if (config.colsCtrls && config.colsCtrls.length) {
      className = 'cols-ctrls'
    }
    return (
      <div style={{display: 'inline-block'}}>
      <div style={{display: 'inline-block'}} className={className}>
        <ApartmentOutlined style={{color: '#13c2c2'}} title="显示列控制" onClick={this.resetMark} />
        <Modal
          wrapClassName="column-control-modal-wrap"
src/menu/components/share/colsControl/index.scss
@@ -27,4 +27,18 @@
      background: rgba(0, 0, 0, 0);
    }
  }
}
.cols-ctrls {
  position: relative;
}
.cols-ctrls::after {
  content: ' ';
  display: block;
  position: absolute;
  top: 0;
  right: 7px;
  width: 4px;
  height: 4px;
  border-radius: 4px;
  background-color: red;
}
src/menu/components/share/colsControl/markform/index.jsx
@@ -115,7 +115,7 @@
              取消
            </Button> : null}
          </Col>
          {targetKeys ? <Col span={18}>
          {targetKeys ? <Col span={18} style={{clear: 'left'}}>
            <Form.Item label="显示列">
              {getFieldDecorator('cols', {
                initialValue: [],
src/menu/components/share/markcomponent/index.jsx
@@ -414,8 +414,13 @@
  render() {
    const { marks, markColumns, visible, options, signs } = this.state
    let className = ''
    if (this.props.type === 'line' && this.props.marks.length) {
      className = 'mk-line-marks'
    }
    return (
      <div style={{display: 'inline-block'}}>
      <div style={{display: 'inline-block'}} className={className}>
        <AntDesignOutlined className="profile" title="标记" onClick={this.resetMark} />
        <Modal
          wrapClassName="mark-modal-wrap"
src/menu/components/share/markcomponent/index.scss
@@ -22,4 +22,18 @@
      background: rgba(0, 0, 0, 0);
    }
  }
}
.mk-line-marks {
  position: relative;
}
.mk-line-marks::after {
  content: ' ';
  display: block;
  position: absolute;
  top: 0;
  right: 7px;
  width: 4px;
  height: 4px;
  border-radius: 4px;
  background-color: red;
}
src/menu/components/share/normalform/index.jsx
File was deleted
src/menu/components/share/normalform/index.scss
File was deleted
src/menu/components/share/pastecomponent/index.jsx
@@ -114,6 +114,10 @@
        return
      }
      if (res.copyType === 'editcols') {
        res.copyType = 'cols'
      }
      let type = res.copyType
      let config = fromJS(this.props.config).toJS()
@@ -168,24 +172,28 @@
      } else if (type === 'cols') {
        config.cols = config.cols.filter(col => !col.origin)
        let keys = config.cols.map(col => (col.field || '$empty'))
        let cols = []
        res.cols.forEach(col => {
          if (!col.field || !keys.includes(col.field)) {
            cols.push(col)
          }
        })
        if (cols.length === 0) {
          notification.warning({
            top: 92,
            message: '显示列已存在!',
            duration: 5
          })
          return
        if ((config.subtype === 'normaltable' || config.subtype === 'editable') && res.cols.length === 1) {
          config.cols.push(...res.cols)
        } else {
          config.cols.push(...cols)
          let keys = config.cols.map(col => (col.field || '$empty'))
          let cols = []
          res.cols.forEach(col => {
            if (!col.field || !keys.includes(col.field)) {
              cols.push(col)
            }
          })
          if (cols.length === 0) {
            notification.warning({
              top: 92,
              message: '显示列已存在!',
              duration: 5
            })
            return
          } else {
            config.cols.push(...cols)
          }
        }
      }
src/menu/components/share/pasteforms/index.jsx
@@ -38,6 +38,8 @@
      if (res.copyType === 'form') {
        delete res.copyType
        res = {fields: [res]}
      } else if (res.copyType === 'simpleform') {
        res = {fields: res.subcards[0].fields}
      }
      res.fields = res.fields || []
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -401,6 +401,18 @@
    },
    {
      type: 'radio',
      key: 'lostTip',
      label: '图片缺失',
      initVal: card.lostTip || 'true',
      tooltip: '图片地址不存在时,是否提示图片丢失。',
      required: false,
      options: [
        { value: 'true', text: '提示' },
        { value: 'false', text: '不提示' }
      ]
    },
    {
      type: 'radio',
      key: 'perspective',
      label: '字段透视',
      initVal: card.perspective || '',
src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -13,7 +13,7 @@
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'],
  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist', 'nameField'],
  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'prefix', 'postfix', 'blacklist'],
  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span'],
  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span', 'lostTip'],
  video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'fieldlength', 'blacklist', 'aspectRatio'],
  colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
  custom: ['label', 'type', 'Align', 'Width', 'blacklist', 'IsSort'],
src/menu/components/table/base-table/columns/editColumn/index.scss
@@ -34,7 +34,7 @@
  .ant-popover-inner-content {
    div {
      max-width: 750px;
      word-break: break-all;
      word-break: normal;
    }
  }
}
src/menu/components/table/base-table/index.jsx
@@ -219,7 +219,7 @@
  getWrapForms = () => {
    const { wrap, action, columns, cols } = this.state.card
    let _actions = [...action]
    let _actions = []
    cols.forEach(col => {
      if (col.type === 'custom') {
@@ -231,7 +231,7 @@
      }
    })
    return getWrapForm(wrap, _actions, columns)
    return getWrapForm(wrap, _actions, columns, action)
  }
  updateWrap = (res) => {
src/menu/components/table/base-table/options.jsx
@@ -1,7 +1,7 @@
/**
 * @description Wrap表单配置信息
 */
export default function (wrap, action = [], columns = []) {
export default function (wrap, action = [], columns = [], toolBtns = []) {
  const wrapForm = [
    {
      type: 'radio',
@@ -167,7 +167,16 @@
      tooltip: '双击表格中行,触发的按钮。',
      required: false,
      allowClear: true,
      options: action.map(item => ({value: item.uuid, label: item.label})),
      options: [...toolBtns, ...action].map(item => ({value: item.uuid, label: item.label})),
    },
    {
      type: 'select',
      field: 'autoExec',
      label: '自动执行',
      initval: wrap.autoExec || '',
      tooltip: '初始化自动执行按钮。',
      required: false,
      options: toolBtns.map(item => ({value: item.uuid, label: item.label}))
    },
    {
      type: 'select',
@@ -201,6 +210,16 @@
      required: false
    },
    {
      type: 'number',
      field: 'maxPageSize',
      label: '每页最大数',
      initval: wrap.maxPageSize || '',
      min: 10,
      max: 500,
      precision: 0,
      required: false
    },
    {
      type: 'radio',
      field: 'cacheSearch',
      label: '搜索缓存',
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -93,6 +93,16 @@
    label: card.label + '(下一行)'
  })
  if (wrap.commit === 'change') {
    editCols.push({
      field: '$noActX',
      label: '无动作',
      disabled: card.editType !== 'select'
    })
  } else if (card.enter === '$noActX') {
    card.enter = '$noAct'
  }
  return [
    {
      type: 'text',
src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -217,6 +217,21 @@
      }
    } else if (key === 'format' && value === 'percent') {
      this.props.form.setFieldsValue({postfix: '%'})
    } else if (key === 'editType') {
      let _options = this.getOptions()
      this.setState({
        formlist: this.state.formlist.map(item => {
          if (item.key === 'enter' && item.options && item.options[item.options.length - 1].field === '$noActX') {
            item.options[item.options.length - 1].disabled = value !== 'select'
          }
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          return item
        })
      })
    } else if (['editable', 'editType', 'resourceType', 'ctrlField', 'eval', 'Hide', 'IsSort'].includes(key)) {
      let _options = this.getOptions()
@@ -331,7 +346,7 @@
          getPopupContainer={() => document.getElementById('edit-table-column-winter')}
        >
          {options.map((option, i) =>
            <Select.Option key={i} datatype={option.datatype || ''} label={option.label || ''} value={(option.value || option.field || option.MenuID)}>
            <Select.Option key={i} disabled={option.disabled === true} datatype={option.datatype || ''} label={option.label || ''} value={(option.value || option.field || option.MenuID)}>
              {(option.text || option.label || option.MenuName)}
            </Select.Option>
          )}
@@ -521,6 +536,12 @@
          }
        }
        if (values.type === 'text' && values.editable === 'true') {
          if (values.editType !== 'select' && values.enter === '$noActX') {
            values.enter = '$noAct'
          }
        }
        if (values.dataSource) {
          let pass = checkSQL(values.dataSource)
src/menu/components/table/edit-table/columns/editColumn/index.scss
@@ -57,7 +57,7 @@
  .ant-popover-inner-content {
    div {
      max-width: 750px;
      word-break: break-all;
      word-break: normal;
    }
  }
}
src/menu/components/table/edit-table/columns/index.jsx
@@ -38,6 +38,32 @@
    this.props.updateCol({...column, marks: vals})
  }
  copycolumn = () => {
    const { column } = this.props
    let oInput = document.createElement('input')
    let val = {
      copyType: 'editcols',
      cols: [column]
    }
    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
    if (srcid) {
      val.$srcId = srcid
    }
    oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
    document.body.appendChild(oInput)
    oInput.select()
    document.execCommand('Copy')
    oInput.className = 'oInput'
    oInput.style.display = 'none'
    message.success('复制成功。')
    document.body.removeChild(oInput)
  }
  shouldComponentUpdate (nextProps, nextState) {
    if (this.props.rowSpan !== nextProps.rowSpan || this.props.colSpan !== nextProps.colSpan) {
@@ -77,6 +103,7 @@
            {column.type === 'custom' ? <PlusOutlined className="plus" title="添加元素" onClick={() => this.props.addElement(column)} /> : null}
            {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="添加按钮" onClick={() => this.props.addElement(column, 'button')} /> : null}
            <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
            <CopyOutlined title="复制显示列" style={{color: '#26C281'}} onClick={this.copycolumn} />
            {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
            {column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
            <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
@@ -520,7 +547,7 @@
    let oInput = document.createElement('input')
    let val = {
      copyType: 'cols',
      copyType: 'editcols',
      cols: columns.filter(col => !col.origin)
    }
src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -196,8 +196,10 @@
        supId = ''
      }
    }
    let menu = window.GLOB.customMenu
    
    let modules = MenuUtils.getSubModules(window.GLOB.customMenu.components, uuid, supId)
    let modules = MenuUtils.getSubModules(menu.components, uuid, supId, menu.interfaces || null)
    this.setState({
      fields: fromJS(columns).toJS().filter(item => item.field !== setting.primaryKey),
src/menu/components/table/edit-table/index.jsx
@@ -361,7 +361,7 @@
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="editable" card={card}/>
            <PasteComponent config={card} options={['action', 'search', 'form', 'cols']} updateConfig={this.updateComponent} />
            <PasteComponent config={card} options={['action', 'search', 'form', 'editcols']} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
src/menu/components/table/edit-table/options.jsx
@@ -221,6 +221,16 @@
      options: columns
    },
    {
      type: 'number',
      field: 'maxPageSize',
      label: '每页最大数',
      initval: wrap.maxPageSize || '',
      min: 10,
      max: 500,
      precision: 0,
      required: false
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -361,6 +361,18 @@
    },
    {
      type: 'radio',
      key: 'lostTip',
      label: '图片缺失',
      initVal: card.lostTip || 'true',
      tooltip: '图片地址不存在时,是否提示图片丢失。',
      required: false,
      options: [
        { value: 'true', text: '提示' },
        { value: 'false', text: '不提示' }
      ]
    },
    {
      type: 'radio',
      key: 'perspective',
      label: '字段透视',
      initVal: card.perspective || '',
src/menu/components/table/normal-table/columns/editColumn/index.jsx
@@ -14,7 +14,7 @@
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'],
  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'blacklist', 'nameField'],
  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'blacklist'],
  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span'],
  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span', 'lostTip'],
  video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'blacklist', 'aspectRatio'],
  colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
  custom: ['label', 'type', 'Align', 'Width', 'blacklist', 'IsSort'],
src/menu/components/table/normal-table/columns/editColumn/index.scss
@@ -34,7 +34,7 @@
  .ant-popover-inner-content {
    div {
      max-width: 750px;
      word-break: break-all;
      word-break: normal;
    }
  }
}
src/menu/components/table/normal-table/index.jsx
@@ -280,7 +280,7 @@
  getWrapForms = () => {
    const { wrap, action, columns, cols } = this.state.card
    let _actions = [...action]
    let _actions = []
    cols.forEach(col => {
      if (col.type === 'custom') {
@@ -292,7 +292,7 @@
      }
    })
    return getWrapForm(wrap, _actions, columns)
    return getWrapForm(wrap, _actions, columns, action)
  }
  updateWrap = (res) => {
@@ -374,7 +374,7 @@
            <PlusOutlined className="plus" title="添加列" onClick={() => this.addColumns()}/>
            {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="添加搜索" onClick={this.addSearch}/> : null}
            <PlusSquareOutlined className="plus" title="添加按钮" onClick={this.addButton}/>
            <NormalForm title="表格设置" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
            <NormalForm title="表格设置" width={850} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="normaltable" card={card}/>
src/menu/components/table/normal-table/options.jsx
@@ -1,7 +1,7 @@
/**
 * @description Wrap表单配置信息
 */
export default function (wrap, action = [], columns = []) {
export default function (wrap, action = [], columns = [], toolBtns) {
  let roleList = sessionStorage.getItem('sysRoles')
  let appType = sessionStorage.getItem('appType')
  let isprint = sessionStorage.getItem('MenuType') === 'billPrint'
@@ -209,8 +209,17 @@
      tooltip: '双击表格中行,触发的按钮。',
      required: false,
      allowClear: true,
      options: action.map(item => ({value: item.uuid, label: item.label})),
      options: [...toolBtns, ...action].map(item => ({value: item.uuid, label: item.label})),
      forbid: appType === 'mob'
    },
    {
      type: 'select',
      field: 'autoExec',
      label: '自动执行',
      initval: wrap.autoExec || '',
      tooltip: '初始化自动执行按钮。',
      required: false,
      options: toolBtns.map(item => ({value: item.uuid, label: item.label}))
    },
    {
      type: 'select',
@@ -244,6 +253,17 @@
      required: false
    },
    {
      type: 'number',
      field: 'maxPageSize',
      label: '每页最大数',
      initval: wrap.maxPageSize || '',
      min: 10,
      max: 500,
      precision: 0,
      required: false,
      forbid: appType === 'mob'
    },
    {
      type: 'radio',
      field: 'empty',
      label: '空值隐藏',
src/menu/components/tabs/antv-tabs/index.jsx
@@ -16,7 +16,7 @@
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('../paste'))
const PasteController = asyncIconComponent(() => import('@/menu/pastecontroller'))
const TabComponents = asyncComponent(() => import('../tabcomponents'))
const { TabPane } = Tabs
@@ -181,11 +181,11 @@
    this.props.updateConfig(tabs)
  }
  insert = (item, tab) => {
  insert = (item, tabId) => {
    let tabs = fromJS(this.state.tabs).toJS()
    tabs.subtabs.forEach(stab => {
      if (stab.uuid === tab.uuid) {
      if (stab.uuid === tabId) {
        stab.components.push(item)
      }
    })
@@ -220,7 +220,7 @@
    editab.hide = res.hide || 'false'
    editab.backgroundColor = res.backgroundColor
    // editab.controlVal = res.controlVal || ''
    editab.selectVal = res.selectVal || ''
    // editab.selectVal = res.selectVal || ''
    editab.blacklist = res.blacklist
    if (editab.uuid) {
@@ -264,6 +264,17 @@
      delete res.controlVals
    }
    if (res.selectVals) {
      let values = {}
      res.selectVals.forEach(item => {
        values[item.uuid] = item.value
      })
      tabs.subtabs.forEach(tab => {
        tab.selectVal = values[tab.uuid]
      })
      delete res.selectVals
    }
    res.tabStyle = res.tabStyle || 'line'
    res.cusClass = ''
@@ -297,7 +308,7 @@
                  <NormalForm title="标签编辑" width={800} update={this.updateTab} getForms={() => this.getTabForms(tab)}>
                    <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
                  </NormalForm>
                  <PasteComponent Tab={tab} insert={this.insert} />
                  <PasteController type="tabs" tab={tab} insert={(item) => this.insert(item, tab.uuid)} />
                  <CloseOutlined className="close" onClick={() => this.delTab(tab)} />
                </div>
              } trigger="hover">
src/menu/components/tabs/antv-tabs/options.jsx
@@ -42,14 +42,14 @@
    //   tooltip: '当禁用字段值与隐藏标记相等时,标签页会隐藏。注:1、多个值请用逗号分隔,2、@pass@值表示忽略此设置(始终显示),2、@pass_empty@值表示忽略空值,即未获取上级组件信息时显示(可与其他值拼接)。',
    //   required: false,
    // },
    {
      type: 'text',
      field: 'selectVal',
      label: '选中标记',
      initval: tab.selectVal || '',
      tooltip: '当选中字段值与选中标记相等时,标签页默认选中。',
      required: false
    },
    // {
    //   type: 'text',
    //   field: 'selectVal',
    //   label: '选中标记',
    //   initval: tab.selectVal || '',
    //   tooltip: '当选中字段值与选中标记相等时,标签页默认选中。',
    //   required: false
    // },
    {
      type: 'color',
      field: 'backgroundColor',
@@ -105,7 +105,8 @@
    roleList = []
  }
  let controlVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.controlVal}))
  let controlVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.controlVal || ''}))
  let selectVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.selectVal || ''}))
  let tabStyle = setting.cusClass || setting.tabStyle
@@ -238,7 +239,10 @@
      label: '选中字段',
      initval: setting.selectField || '',
      tooltip: '用于控制标签页初始化选中,在标签中填入选中标记,注:数据来源于url参数。',
      required: false
      required: false,
      controlFields: [
        {field: 'selectVals', notNull: true},
      ]
    },
    {
      type: 'color',
@@ -271,11 +275,11 @@
    {
      type: 'table',
      field: 'controlVals',
      label: '标签组',
      label: '标签组(禁用)',
      initval: controlVals,
      tooltip: '当禁用字段值与隐藏标记相等时,标签页会隐藏。注:1、多个值请用逗号分隔,2、@pass@值表示忽略此设置(始终显示),2、@pass_empty@值表示忽略空值,即未获取上级组件信息时显示(可与其他值拼接)。',
      required: false,
      fixed: true,
      actions: ['edit'],
      span: 24,
      columns: [
        {
@@ -294,6 +298,33 @@
          width: '50%'
        }
      ]
    },
    {
      type: 'table',
      field: 'selectVals',
      label: '标签组(选中)',
      initval: selectVals,
      tooltip: '当选中字段值与选中标记相等时,标签页默认选中。',
      required: false,
      actions: ['edit'],
      span: 24,
      columns: [
        {
          title: '标签名称',
          dataIndex: 'label',
          editable: false,
          required: false,
          width: '30%'
        },
        {
          title: '选中标记',
          dataIndex: 'value',
          inputType: 'input',
          editable: true,
          required: false,
          width: '50%'
        }
      ]
    }
  ]
src/menu/components/tabs/paste/index.jsx
File was deleted
src/menu/components/tabs/paste/index.scss
src/menu/components/tabs/tabcomponents/index.jsx
@@ -80,7 +80,7 @@
    drop(item) {
      if (item.hasOwnProperty('originalIndex') || item.added) {
        return
      } else if (['login', 'navbar', 'topbar'].includes(item.component)) {
      } else if (['login', 'navbar', 'topbar', 'iframe'].includes(item.component)) {
        return
      }
      
src/menu/components/tree/antd-tree/options.jsx
@@ -129,10 +129,10 @@
      initval: wrap.permission || 'false',
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'true', label: !appType ? '继承菜单' : '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType || ispop
      forbid: ispop
    },
    {
      type: 'radio',
src/menu/datasource/verifycard/index.jsx
@@ -564,6 +564,23 @@
        })
        return Promise.reject()
      }
    } else if (config.subtype === 'editable') {
      let _arr = []
      columns.forEach(col => {
        let key = col.field.toLowerCase()
        if (['jskey', 'data_type', 'bid'].includes(key)) {
          _arr.push(col.field)
        }
      })
      if (_arr.length > 0) {
        notification.warning({
          top: 92,
          message: '字段集中不可使用' + _arr.join('、') + '!注:此字段为提交时的系统字段。',
          duration: 5
        })
        return Promise.reject()
      }
    }
    return new Promise((resolve, reject) => {
src/menu/datasource/verifycard/settingform/index.jsx
@@ -264,7 +264,7 @@
                </Radio.Group>)}
              </Form.Item>
            </Col>
            {setting.interType === 'outer' ? <Col span={8}>
            {setting.interType === 'outer' ? <Col span={8} className="compact">
              <Form.Item label={
                <Tooltip placement="topLeft" title="业务系统指同一sso下的其他业务系统,外部系统指不同sso下的其他业务系统。">
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -284,6 +284,7 @@
                  <Radio value="false">业务</Radio>
                  <Radio value="true">单点</Radio>
                  <Radio value="external">外部</Radio>
                  <Radio value="custom">自定义</Radio>
                </Radio.Group>)}
              </Form.Item>
            </Col> : null}
@@ -332,7 +333,7 @@
                })(<KeyInterface type="develop"/>)}
              </Form.Item>
            </Col> : null}
            {setting.interType === 'outer' && setting.sysInterface === 'false' ? <Col className="outer-interface" span={24}>
            {setting.interType === 'outer' && (setting.sysInterface === 'false' || setting.sysInterface === 'custom') ? <Col className="outer-interface" span={24}>
              <Form.Item label={<Tooltip placement="topLeft" title="正式系统接口地址,为空时使用接口地址。">
                  <QuestionCircleOutlined className="mk-form-tip" />
                  正式地址
@@ -354,6 +355,18 @@
                })(<KeyInterface type="product"/>)}
              </Form.Item>
            </Col> : null}
            {setting.interType === 'outer' && setting.sysInterface === 'custom' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
              <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={
                <Tooltip placement="topLeft" title="外部接口入参及出参的自定义处理。">
                  <QuestionCircleOutlined className="mk-form-tip" />
                  自定义脚本
                </Tooltip>
              }>
                {getFieldDecorator('js_script', {
                  initialValue: setting.js_script || ''
                })(<CodeMirror mode="text/javascript" theme="cobalt" />)}
              </Form.Item>
            </Col> : null}
            {setting.interType === 'outer' ? <Col span={8}>
              <Form.Item label="外部函数">
                {getFieldDecorator('outerFunc', {
src/menu/datasource/verifycard/settingform/index.scss
@@ -17,6 +17,15 @@
  .ant-radio-group {
    white-space: nowrap;
  }
  .compact {
    padding-left: 0px!important;
    .ant-radio-group {
      span.ant-radio + * {
        padding-left: 6px;
        padding-right: 6px;
      }
    }
  }
  .outer-interface {
    .ant-form-item-label {
      width: 10.5%;
src/menu/datasource/verifycard/utils.jsx
@@ -75,7 +75,8 @@
    }
    if (_customScript) {
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_customScript}
      `
    }
@@ -151,7 +152,8 @@
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'1949-10-01 15:00:00'
      `
    } else if (_tailScript) {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_dataresource}
        ${_tailScript}
        aaa:
@@ -159,7 +161,8 @@
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'1949-10-01 15:00:00' 
      `
    } else {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_dataresource}`
    }
src/menu/debug/index.jsx
@@ -254,13 +254,16 @@
        item.action && item.action.forEach(cell => {
          if (cell.hidden === 'true') return false
          let sql = this.resetButton(item, cell, process)
          let res = this.resetButton(item, cell, process)
          if (sql) {
            if (typeof(sql) === 'string') {
              children.push({label: cell.label, sql: sql})
          if (res) {
            if (typeof(res) === 'string') {
              children.push({label: cell.label, sql: res})
            } else if (res.backSql) {
              children.push({label: cell.label, sql: res.sql})
              children.push({label: cell.label + '(回调)', sql: res.backSql})
            } else {
              children.push({label: cell.label, tabName: cell.label, sql: '', children: sql})
              children.push({label: cell.label, tabName: cell.label, sql: '', children: res})
            }
          }
        })
@@ -276,13 +279,16 @@
              } else if (col.type === 'custom') {
                col.elements.forEach(cell => {
                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
                  let sql = this.resetButton(item, cell, process)
                  let res = this.resetButton(item, cell, process)
                  if (sql) {
                    if (typeof(sql) === 'string') {
                      children.push({label: cell.label, sql: sql})
                  if (res) {
                    if (typeof(res) === 'string') {
                      children.push({label: cell.label, sql: res})
                    } else if (res.backSql) {
                      children.push({label: cell.label, sql: res.sql})
                      children.push({label: cell.label + '(回调)', sql: res.backSql})
                    } else {
                      children.push({label: cell.label, tabName: cell.label, sql: '', children: sql})
                      children.push({label: cell.label, tabName: cell.label, sql: '', children: res})
                    }
                  }
                })
@@ -300,13 +306,16 @@
          item.subcards && item.subcards.forEach(card => {
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button' || cell.hidden === 'true') return
              let sql = this.resetButton(item, cell, process)
              let res = this.resetButton(item, cell, process)
              if (sql) {
                if (typeof(sql) === 'string') {
                  children.push({label: cell.label, sql: sql})
              if (res) {
                if (typeof(res) === 'string') {
                  children.push({label: cell.label, sql: res})
                } else if (res.backSql) {
                  children.push({label: cell.label, sql: res.sql})
                  children.push({label: cell.label + '(回调)', sql: res.backSql})
                } else {
                  children.push({label: cell.label, tabName: cell.label, sql: '', children: sql})
                  children.push({label: cell.label, tabName: cell.label, sql: '', children: res})
                }
              }
            })
@@ -315,13 +324,16 @@
  
            card.backElements.forEach(cell => {
              if (cell.eleType !== 'button' || cell.hidden === 'true') return
              let sql = this.resetButton(item, cell, process, null, true)
              let res = this.resetButton(item, cell, process, null, true)
              if (sql) {
                if (typeof(sql) === 'string') {
                  children.push({label: cell.label, sql: sql})
              if (res) {
                if (typeof(res) === 'string') {
                  children.push({label: cell.label, sql: res})
                } else if (res.backSql) {
                  children.push({label: cell.label, sql: res.sql})
                  children.push({label: cell.label + '(回调)', sql: res.backSql})
                } else {
                  children.push({label: cell.label, tabName: cell.label, sql: '', children: sql})
                  children.push({label: cell.label, tabName: cell.label, sql: '', children: res})
                }
              }
            })
@@ -329,13 +341,16 @@
        } else if (item.type === 'balcony') {
          item.elements.forEach(cell => {
            if (cell.eleType !== 'button' || cell.hidden === 'true') return
            let sql = this.resetButton(item, cell, process)
            let res = this.resetButton(item, cell, process)
            if (sql) {
              if (typeof(sql) === 'string') {
                children.push({label: cell.label, sql: sql})
            if (res) {
              if (typeof(res) === 'string') {
                children.push({label: cell.label, sql: res})
              } else if (res.backSql) {
                children.push({label: cell.label, sql: res.sql})
                children.push({label: cell.label + '(回调)', sql: res.backSql})
              } else {
                children.push({label: cell.label, tabName: cell.label, sql: '', children: sql})
                children.push({label: cell.label, tabName: cell.label, sql: '', children: res})
              }
            }
          })
@@ -345,10 +360,15 @@
            if (!group.subButton.Ot) {
              group.subButton.Ot = item.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
            }
            let sql = this.resetButton(item, group.subButton, process, group)
            let res = this.resetButton(item, group.subButton, process, group)
            if (sql) {
              children.push({label: group.subButton.label, sql: sql})
            if (res) {
              if (typeof(res) === 'string') {
                children.push({label: group.subButton.label, sql: res})
              } else if (res.backSql) {
                children.push({label: group.subButton.label, sql: res.sql})
                children.push({label: group.subButton.label + '(回调)', sql: res.backSql})
              }
            }
          })
        }
@@ -372,9 +392,52 @@
          let _item = fromJS(item).toJS()
          _item.columns = _item.subColumns || []
          _item.setting.primaryKey = _item.setting.subKey
          sql = this.getSysDefaultSql(cell, _item, process, group)
          sql = this.getSysDefaultSql(cell, _item, process, group, false)
        } else {
          sql = this.getSysDefaultSql(cell, item, process, group)
          sql = this.getSysDefaultSql(cell, item, process, group, false)
        }
      }
      if (cell.callbackType === 'script' && cell.verify && cell.verify.cbScripts) {
        let defSql = ''
        if (item.subtype === 'dualdatacard' && isback) {
          let _item = fromJS(item).toJS()
          _item.columns = _item.subColumns || []
          _item.setting.primaryKey = _item.setting.subKey
          defSql = this.getSysDefaultSql(cell, _item, process, group, true)
        } else {
          defSql = this.getSysDefaultSql(cell, item, process, group, true)
        }
        let backSql = this.getSysBackSql(cell.verify.cbScripts, cell.cbTable)
        if (backSql) {
          backSql = `${defSql}
            ${backSql}
          `
          if (cell.output) {
            backSql += `
              aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${cell.output} as mk_b_id`
          } else {
            backSql += `
              aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
          }
          backSql = backSql.replace(/@ID@/ig, `'id'`)
          backSql = backSql.replace(/@BID@/ig, `'bid'`)
          backSql = backSql.replace(/@LoginUID@/ig, `'LoginUID'`)
          backSql = backSql.replace(/@SessionUid@/ig, `'SessionUid'`)
          backSql = backSql.replace(/@UserID@/ig, `'UserID'`)
          backSql = backSql.replace(/@Appkey@/ig, `'appkey'`)
          backSql = backSql.replace(/@typename@/ig, `'typename'`)
          backSql = backSql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
        }
        if (backSql) {
          return {
            backSql,
            sql
          }
        }
      }
    } else if (cell.OpenType === 'excelIn') {
@@ -421,7 +484,88 @@
    return sql
  }
  getSysDefaultSql = (btn, component, process, group) => {
  getSysBackSql = (scripts, cbTable) => {
    let _prev = ''
    let _back = ''
    scripts.forEach(script => {
      if (script.status === 'false') return
      if (script.position === 'front') {
        _prev += `
      /* 自定义脚本 */
      ${script.sql}
      `
      } else {
        _back += `
      /* 自定义脚本 */
      ${script.sql}
      `
      }
    })
    if (!_prev) return ''
    let tbs = []
    _prev.replace(/\n|\r/g, ' ').split(/\sdeclare\s/ig).forEach(line => {
      if (!/^\s*(@|#)[a-zA-Z0-9_]+\s+table\s+\(/ig.test(line)) return
      let tb = line.match(/(@|#)[a-zA-Z0-9_]+\s+table\s+\(.+(\)|date|datetime)\s*\)/ig)
      if (tb && tb.length === 1) {
        tbs.push(tb[0])
      }
    })
    tbs.forEach(tb => {
      let tbName = tb.match(/(@|#)[a-zA-Z0-9_]+/ig)[0]
      if (!tbName) return
      let content = tb.replace(/(@|#)[a-zA-Z0-9_]+\s+table\s+\(\s*/, '').replace(/\s*\)$/, '')
      content = content.replace(/decimal\(\s*\d+\s*,\s*\d+\s*\)/ig, 'decimal')
      let keys = []
      let vals = []
      let error = false
      let istop = new RegExp(cbTable + '$', 'ig').test(tbName)
      let id = tbName.replace(/@|#/, '')
      content.split(/\s*,\s*/).forEach(m => {
        let ms = m.split(/\s+/)
        if (ms.length > 1) {
          keys.push(ms[0])
          if (/^mk_level$/i.test(ms[0])) {
            vals.push(istop ? `'1'` : `'2'`)
          } else if (/^mk_id$/i.test(ms[0])) {
            vals.push(istop ? `'${cbTable}'` : `'${id}'`)
          } else if (/^mk_bid$/i.test(ms[0])) {
            vals.push(istop ? `''` : `'${cbTable}'`)
          } else if (/nvarchar/i.test(ms[1])) {
            vals.push(`'mk'`)
          } else if (/date/i.test(ms[1])) {
            vals.push(`'1949-10-01'`)
          } else if (/int|decimal/i.test(ms[1])) {
            vals.push('0')
          } else {
            error = true
          }
        } else {
          error = true
        }
      })
      if (error || vals.length === 0) return
      _prev += `
      Insert into ${tbName} (${keys.join(',')})
      Select ${vals.join(',')}
      `
    })
    return _prev + _back
  }
  getSysDefaultSql = (btn, component, process, group, retmsg) => {
    let primaryId = 'id'
    let BID = 'bid'
    let verify = btn.verify || {}
@@ -492,6 +636,9 @@
            _item.fieldlen = item.decimal || 0
          } else  if (_item.type === 'date') {
            _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
          } else if (item.declare === 'decimal') {
            _item.type = 'number'
            _item.fieldlen = item.decimal || 0
          }
    
          formdata.push(_item)
@@ -536,6 +683,9 @@
            _item.fieldlen = item.decimal || 0
          } else  if (_item.type === 'date') {
            _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
          } else if (item.declare === 'decimal') {
            _item.type = 'number'
            _item.fieldlen = item.decimal || 0
          }
    
          formdata.push(_item)
@@ -671,6 +821,10 @@
        /* 显示列变量赋值 */
        select ${_initColfields.join(',')}
        `
    }
    if (retmsg) {
      return _sql
    }
  
    // 去除禁用的验证
@@ -879,15 +1033,13 @@
        item.field.split(',').forEach((_field, index) => {
          let _key = _field.toLowerCase()
          let _val = ''
          let _fval = `'${_val}'`
  
          arr.push(_key)
          if (_key === 'bid') { // 表单中没有bid则使用系统bid变量
            _fval = '@BID@'
            _val = BID
          }
          arr.push(_key)
          _fieldValue.push(`${_key}=${_fval}`)
          _fieldValue.push(`${_key}='${_val}'`)
          _value.push(`${_labels[index] || ''}:${_val || ''}`)
        })
  
@@ -1624,10 +1776,14 @@
    item.setting.interType = 'system'
    item.setting.execute = btn.verify.defaultSql || 'true'
    item.setting.dataresource = btn.verify.dataresource || ''
    item.setting.primaryKey = btn.verify.primaryKey || component.setting.primaryKey || 'ID'
    item.setting.primaryKey = btn.verify.primaryKey || ''
    item.setting.queryType = btn.verify.queryType
    item.setting.laypage = btn.pagination
    item.setting.order = btn.verify.order || ''
    if (btn.Ot === 'requiredOnce') {
      item.setting.primaryKey = btn.verify.primaryKey || component.setting.primaryKey || 'ID'
    }
    item.scripts = btn.verify.scripts || []
@@ -1659,9 +1815,20 @@
    item.$searches = fromJS(searches).toJS()
    searches = formatSearch(searches)
    let _columns = item.columns || []
    let _columns = []
    if (item.subtype === 'dualdatacard') {
      _columns = [...item.columns, ...item.subColumns]
    } else if (item.columns) {
      _columns = [...item.columns]
    }
    if (item.setting.primaryKey) {
      let key = item.setting.primaryKey.toLowerCase()
      if (_columns.findIndex(cell => cell.field.toLowerCase() === key) === -1) {
        _columns.push({
          field: item.setting.primaryKey
        })
      }
    }
    let arr_field = _columns.map(col => col.field).join(',')
@@ -1714,7 +1881,8 @@
    let sql = ''
    if (_customScript) {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_customScript}
        ${_dataresource}
        ${_tailScript}
@@ -1723,7 +1891,8 @@
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'1949-10-01 15:00:00'
      `
    } else if (_tailScript) {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_dataresource}
        ${_tailScript}
        aaa:
@@ -1731,7 +1900,8 @@
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'1949-10-01 15:00:00' 
      `
    } else {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_dataresource}`
    }
    
src/menu/modulesource/option.jsx
@@ -12,7 +12,6 @@
import SandBox from '@/assets/mobimg/sandbox.png'
import Pie1 from '@/assets/mobimg/ring.png'
import Pie3 from '@/assets/mobimg/nest.png'
import Pie2 from '@/assets/mobimg/nightingale.png'
import Mainsearch from '@/assets/mobimg/mainsearch.png'
import Carousel from '@/assets/mobimg/carousel.png'
import Carousel1 from '@/assets/mobimg/carousel1.png'
@@ -59,7 +58,6 @@
  { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '饼图', width: 12 },
  { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '环图', width: 12 },
  { type: 'menu', url: Pie3, component: 'pie', subtype: 'nest', title: '嵌套饼图', width: 12 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 },
  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 },
  { type: 'menu', url: ratioboard, component: 'dashboard', subtype: 'ratioboard', title: '占比图', width: 12 },
  { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '散点图', width: 24 },
src/menu/pastecontroller/index.jsx
@@ -1,7 +1,9 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Button, notification } from 'antd'
import { SnippetsOutlined } from '@ant-design/icons'
import md5 from 'md5'
import MenuUtils from '@/utils/utils-custom.js'
import asyncComponent from '@/utils/asyncComponent'
@@ -18,60 +20,264 @@
    visible: false
  }
  resetconfig = (item, appType) => {
  resetconfig = (item, appType, commonId) => {
    if (item.type === 'tabs') {
      item.uuid = MenuUtils.getuuid()
      item.uuid = md5(commonId + item.uuid)
      item.setting.name = (item.setting.name || '') + MenuUtils.getSignName()
      item.name = item.setting.name
      item.subtabs.forEach(tab => {
        tab.uuid = MenuUtils.getuuid()
        tab.uuid = md5(commonId + tab.uuid)
        if (appType !== 'mob') {
          tab.components = tab.components.filter(cell => cell.type !== 'menubar')
        }
        tab.components = tab.components.map(cell => {
          cell = this.resetconfig(cell, appType)
          cell = this.resetconfig(cell, appType, commonId)
          return cell
        })
      })
    } else if (item.type === 'group') {
      item.uuid = MenuUtils.getuuid()
      item.uuid = md5(commonId + item.uuid)
      item.setting.name = (item.setting.name || '') + MenuUtils.getSignName()
      item.name = item.setting.name
      item.components = item.components.map(cell => {
        cell = MenuUtils.resetComponentConfig(cell, appType)
        cell.uuid = md5(commonId + cell.uuid)
        cell = MenuUtils.resetComponentConfig(cell, appType, commonId)
        return cell
      })
    } else {
      item = MenuUtils.resetComponentConfig(item, appType)
      item.uuid = md5(commonId + item.uuid)
      item = MenuUtils.resetComponentConfig(item, appType, commonId)
    }
    return item
  }
  pasteSubmit = () => {
    let appType = sessionStorage.getItem('appType')
    let options = ['tabs', 'timeline', 'datacard', 'propcard', 'simpleform', 'stepform', 'tabform', 'balcony', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'editor', 'pie', 'scatter', 'iframe', 'sandbox']
  resetlink = (item, commonId) => {
    if (item.type === 'tabs') {
      item.subtabs.forEach(tab => {
        tab.components.forEach(cell => {
          this.resetlink(cell, commonId)
        })
      })
    } else if (item.type === 'group') {
      item.components.forEach(cell => {
        this.resetlink(cell, commonId)
      })
    } else {
      if (['card', 'carousel', 'timeline'].includes(item.type)) {
        item.subcards.forEach(card => {
          card.elements && card.elements.forEach(cell => {
            if (cell.eleType === 'button') {
              this.resetBtn(cell, commonId)
            }
          })
          card.backElements && card.backElements.forEach(cell => {
            if (cell.eleType === 'button') {
              this.resetBtn(cell, commonId)
            }
          })
        })
      } else if (item.type === 'balcony') {
        item.elements && item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            this.resetBtn(cell, commonId)
          }
        })
      } else if (item.type === 'table' && item.cols) {
        let loopCol = (cols) => {
          cols.forEach(col => {
            if (col.type === 'colspan' && col.subcols) {
              loopCol(col.subcols)
            } else if (col.type === 'custom' && col.elements) {
              col.elements.forEach(cell => {
                if (cell.eleType === 'button') {
                  this.resetBtn(cell, commonId)
                }
              })
            }
          })
        }
        loopCol(item.cols)
      } else if (item.type === 'form') {
        item.subcards.forEach(cell => {
          if (cell.subButton) {
            this.resetBtn(cell.subButton, commonId)
          }
        })
      }
      item.action && item.action.forEach(cell => {
        this.resetBtn(cell, commonId)
      })
    if (appType === 'mob') {
      if (sessionStorage.getItem('editMenuType') !== 'popview') {
        options.push('menubar', 'topbar', 'singleSearch')
      } else {
      if (item.wrap && item.wrap.supType === 'multi') {
        if (item.setting && item.setting.supModule) {
          item.setting.supModule = ''
        }
        if (item.supNodes) {
          item.supNodes = item.supNodes.map(cell => {
            let id = cell.nodes[cell.nodes.length - 1]
            let _id = md5(commonId + id)
            if (this.modules[id] || this.modules[_id]) {
              cell.nodes = this.modules[id] || this.modules[_id]
              cell.componentId = cell.nodes[cell.nodes.length - 1]
              return cell
            }
            return null
          })
          item.supNodes = item.supNodes.filter(Boolean)
        }
        if (!item.supNodes || item.supNodes.length === 0) {
          item.wrap.supType = 'single'
          delete item.supNodes
        }
      }
      if (item.setting && item.setting.supModule && item.setting.supModule[0] !== 'empty') {
        let id = item.setting.supModule[item.setting.supModule.length - 1]
        let _id = md5(commonId + id)
        item.setting.supModule = this.modules[id] || this.modules[_id] || ''
      }
      if (item.wrap && item.wrap.supModule && item.wrap.supModule[0]) {
        let id = item.wrap.supModule[item.wrap.supModule.length - 1]
        let _id = md5(commonId + id)
        item.wrap.supModule = this.modules[id] || this.modules[_id] || ''
      }
    }
  }
  resetBtn (btn, commonId) {
    if (btn.switchTab && btn.switchTab.length > 0) {
      let id = btn.switchTab[btn.switchTab.length - 1]
      let _id = md5(commonId + id)
      btn.switchTab = this.modules[id] || this.modules[_id] || null
    }
    if (btn.anchors && btn.anchors.length > 0) {
      let id = btn.anchors[btn.anchors.length - 1]
      let _id = md5(commonId + id)
      btn.anchors = this.modules[id] || this.modules[_id] || null
    }
    if (btn.syncComponent && btn.syncComponent[0] === 'multiComponent' && btn.syncComponents) {
      btn.syncComponents = btn.syncComponents.map(m => {
        let id = m.syncComId[m.syncComId.length - 1]
        let _id = md5(commonId + id)
        return this.modules[id] || this.modules[_id] || null
      })
      btn.syncComponents = btn.syncComponents.filter(Boolean)
      if (btn.syncComponents.length === 0) {
        btn.syncComponent = null
        btn.syncComponents = null
      }
    } else if (btn.syncComponent && btn.syncComponent.length > 0) {
      let id = btn.syncComponent[btn.syncComponent.length - 1]
      let _id = md5(commonId + id)
      btn.syncComponent = this.modules[id] || this.modules[_id] || null
    }
  }
  resetmenu = (components, componentId, res) => {
    components.forEach(item => {
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          if (tab.uuid === componentId) {
            tab.components.push(res)
          } else {
            this.resetmenu(tab.components, componentId, res)
          }
        })
      } else if (item.type === 'group' && item.uuid === componentId) {
        item.components.push(res)
      }
    })
  }
  getModules = (components, interfaces, sups = []) => {
    components.forEach(item => {
      this.modules[item.uuid] = [...sups, item.uuid]
      if (item.type === 'tabs') {
        item.subtabs.forEach(f_tab => {
          this.getModules(f_tab.components, null, [...sups, item.uuid, f_tab.uuid])
        })
      } else if (item.type === 'group') {
        item.components.forEach(cell => {
          this.modules[cell.uuid] = [...sups, item.uuid, cell.uuid]
        })
      }
    })
    if (interfaces && interfaces.length > 0) {
      interfaces.forEach(item => {
        this.modules[item.uuid] = [item.uuid]
      })
    }
  }
  pasteSubmit = () => {
    const { type, tab } = this.props
    let appType = sessionStorage.getItem('appType')
    // ['calendar', 'balcony', 'datacard', 'doublecard', 'propcard', 'tablecard', 'cardatacard', 'carpropcard', 'line', 'dashboard', 'antvG6', 'pie', 'scatter', 'antvX6', 'chart', 'sandbox', 'editor', 'simpleform', 'stepform', 'tabform', 'group', 'iframe', 'mainsearch', 'basetable', 'editable', 'normaltable', 'tabs', 'timeline', 'tree', 'menubar', 'singleSearch', 'topbar']
    let options = []
    let types = {
      topbar: '导航栏',
      singleSearch: '搜索',
      iframe: 'iframe',
      tabs: '标签页',
      group: '分组',
      menubar: '菜单栏',
      mainsearch: '搜索'
    }
    if (!type) {
      options = ['tabs', 'timeline', 'datacard', 'doublecard', 'propcard', 'cardatacard', 'carpropcard', 'simpleform', 'stepform', 'tabform', 'balcony', 'group', 'normaltable', 'tablecard', 'line', 'editor', 'pie', 'scatter', 'iframe', 'sandbox']
      if (appType === 'mob') {
        options.push('menubar', 'singleSearch')
        if (sessionStorage.getItem('editMenuType') !== 'popview') {
          options.push('topbar')
        }
      } else {
        options.push('editable', 'mainsearch', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
      }
    } else {
      options.push('editable', 'mainsearch', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
      if (appType === 'mob') {
        options = ['balcony', 'datacard', 'doublecard', 'propcard', 'tablecard', 'cardatacard', 'carpropcard', 'line', 'pie', 'scatter', 'sandbox', 'editor', 'simpleform', 'stepform', 'tabform', 'normaltable', 'timeline']
        if (type === 'tabs') {
          options.push('tabs', 'group', 'menubar')
        }
      } else {
        options = ['calendar', 'balcony', 'datacard', 'doublecard', 'propcard', 'tablecard', 'cardatacard', 'carpropcard', 'line', 'dashboard', 'antvG6', 'pie', 'scatter', 'antvX6', 'chart', 'sandbox', 'editor', 'simpleform', 'stepform', 'tabform', 'editable', 'normaltable', 'timeline', 'tree']
        if (type === 'tabs') {
          options.push('tabs', 'group', 'mainsearch')
        }
      }
    }
    this.pasteFormRef.handleConfirm().then(res => {
      if (res.copyType === 'basetable') {
        res.copyType = 'normaltable'
        res.subtype = 'normaltable'
      }
      if (!options.includes(res.copyType)) {
      if (!res.copyType) {
        notification.warning({
          top: 92,
          message: '配置信息格式错误!',
@@ -80,22 +286,116 @@
        return
      }
      res = this.resetconfig(res, appType)
      if (res.copyType === 'basetable') {
        res.copyType = 'normaltable'
        res.subtype = 'normaltable'
      }
      // delete res.copyType
      let menu = fromJS(window.GLOB.customMenu).toJS()
      if (!options.includes(res.copyType)) {
        if (type && types[res.copyType]) {
          notification.warning({
            top: 92,
            message: (type === 'group' ? '分组中' : '标签页中') + '不可添加《' + types[res.copyType] + '》组件!',
            duration: 5
          })
          return
        } else {
          notification.warning({
            top: 92,
            message: '配置信息格式错误!',
            duration: 5
          })
        }
        return
      } else if (appType === 'mob') {
        if (res.type === 'search') {
          if (menu.components.filter(card => card.type === 'topbar' && card.wrap.type !== 'navbar').length > 0) {
            notification.warning({
              top: 92,
              message: '导航栏使用了搜索,不可添加搜索组件!',
              duration: 5
            })
            return
          }
          if (menu.components.filter(card => card.type === 'search').length > 0) {
            notification.warning({
              top: 92,
              message: '搜索条件不可重复添加!',
              duration: 5
            })
            return
          }
        } else if (res.type === 'topbar') {
          if (menu.components.findIndex(m => m.type === 'topbar') > -1) {
            notification.warning({
              top: 92,
              message: '导航栏不可重复添加!',
              duration: 5
            })
            return
          }
        }
      } else if (res.type === 'search') {
        if (tab) {
          if (tab.components.findIndex(card => card.type === 'search') > -1) {
            notification.warning({
              top: 92,
              message: '搜索条件不可重复添加!',
              duration: 5
            })
            return
          }
        } else {
          if (menu.components.findIndex(m => m.type === 'search') > -1) {
            notification.warning({
              top: 92,
              message: '搜索条件不可重复添加!',
              duration: 5
            })
            return
          }
        }
      }
      delete res.copyType
      let commonId = MenuUtils.getuuid()
      res = this.resetconfig(res, appType, commonId)
      if (tab) {
        this.resetmenu(menu.components, tab.uuid, res)
      } else {
        menu.components.push(res)
      }
      this.modules = {}
      this.getModules(menu.components, menu.interfaces)
      this.resetlink(res, commonId)
      
      this.props.insert(res)
      this.setState({visible: false})
      notification.success({
        top: 92,
        message: '粘贴成功!',
        duration: 2
      })
    })
  }
  render() {
    const { type } = this.props
    const { visible } = this.state
    return (
      <>
        <Button style={{borderColor: '#40a9ff', color: '#40a9ff'}} onClick={() => {this.setState({visible: true})}}><SnippetsOutlined />粘贴</Button>
        {type ? <SnippetsOutlined style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} /> :
        <Button style={{borderColor: '#40a9ff', color: '#40a9ff'}} onClick={() => {this.setState({visible: true})}}><SnippetsOutlined />粘贴</Button>}
        <Modal
          title="粘贴"
          visible={visible}
src/mob/components/tabs/antv-tabs/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Tabs, Popover, Modal, notification } from 'antd'
import { Tabs, Popover, Modal } from 'antd'
import { ToolOutlined, PlusOutlined, EditOutlined, FontColorsOutlined, DeleteOutlined, CloseOutlined } from '@ant-design/icons'
import MKEmitter from '@/utils/events.js'
@@ -16,7 +16,7 @@
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/tabs/paste'))
const PasteController = asyncIconComponent(() => import('@/menu/pastecontroller'))
const TabComponents = asyncComponent(() => import('../tabcomponents'))
const { TabPane } = Tabs
@@ -203,20 +203,11 @@
    this.props.updateConfig(tabs)
  }
  insert = (item, tab) => {
  insert = (item, tabId) => {
    let tabs = fromJS(this.state.tabs).toJS()
    if (item.type === 'search') {
      notification.warning({
        top: 92,
        message: '移动端搜索组件不可粘贴!',
        duration: 5
      })
      return
    }
    tabs.subtabs.forEach(stab => {
      if (stab.uuid === tab.uuid) {
      if (stab.uuid === tabId) {
        stab.components.push(item)
      }
    })
@@ -251,7 +242,7 @@
    editab.hide = res.hide || 'false'
    editab.backgroundColor = res.backgroundColor
    // editab.controlVal = res.controlVal || ''
    editab.selectVal = res.selectVal || ''
    // editab.selectVal = res.selectVal || ''
    editab.blacklist = res.blacklist
    if (editab.uuid) {
@@ -295,6 +286,17 @@
      delete res.controlVals
    }
    if (res.selectVals) {
      let values = {}
      res.selectVals.forEach(item => {
        values[item.uuid] = item.value
      })
      tabs.subtabs.forEach(tab => {
        tab.selectVal = values[tab.uuid]
      })
      delete res.selectVals
    }
    tabs.setting = res
@@ -321,7 +323,7 @@
                  <NormalForm title="标签编辑" width={800} update={this.updateTab} getForms={() => this.getTabForms(tab)}>
                    <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
                  </NormalForm>
                  <PasteComponent Tab={tab} insert={this.insert} />
                  <PasteController type="tabs" tab={tab} insert={(item) => this.insert(item, tab.uuid)} />
                  <FontColorsOutlined className="style" title="调整样式" onClick={this.changeTabStyle}/>
                  <CloseOutlined className="close" onClick={() => this.delTab(tab)} />
                </div>
src/mob/components/tabs/antv-tabs/options.jsx
@@ -41,14 +41,14 @@
    //   tooltip: '当禁用字段值与隐藏标记相等时,标签页会隐藏。注:多个值请用逗号分隔。',
    //   required: false
    // },
    {
      type: 'text',
      field: 'selectVal',
      label: '选中标记',
      initval: tab.selectVal || '',
      tooltip: '当选中字段值与选中标记相等时,标签页默认选中。',
      required: false
    },
    // {
    //   type: 'text',
    //   field: 'selectVal',
    //   label: '选中标记',
    //   initval: tab.selectVal || '',
    //   tooltip: '当选中字段值与选中标记相等时,标签页默认选中。',
    //   required: false
    // },
    {
      type: 'color',
      field: 'backgroundColor',
@@ -82,7 +82,8 @@
    label: '上一页(url参数)'
  })
  let controlVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.controlVal}))
  let controlVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.controlVal || ''}))
  let selectVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.selectVal || ''}))
  const tabForm = [
    {
@@ -156,7 +157,10 @@
      label: '选中字段',
      initval: setting.selectField || '',
      tooltip: '用于控制标签页初始化选中,在标签中填入选中标记,注:数据源于url参数。',
      required: false
      required: false,
      controlFields: [
        {field: 'selectVals', notNull: true},
      ]
    },
    {
      type: 'color',
@@ -180,11 +184,11 @@
    {
      type: 'table',
      field: 'controlVals',
      label: '标签组',
      label: '标签组(禁用)',
      initval: controlVals,
      tooltip: '当禁用字段值与隐藏标记相等时,标签页会隐藏。注:1、多个值请用逗号分隔,2、@pass@值表示忽略此设置(始终显示),2、@pass_empty@值表示忽略空值,即未获取上级组件信息时显示(可与其他值拼接)。',
      required: false,
      fixed: true,
      actions: ['edit'],
      span: 24,
      columns: [
        {
@@ -203,6 +207,33 @@
          width: '50%'
        }
      ]
    },
    {
      type: 'table',
      field: 'selectVals',
      label: '标签组(选中)',
      initval: selectVals,
      tooltip: '当选中字段值与选中标记相等时,标签页默认选中。',
      required: false,
      actions: ['edit'],
      span: 24,
      columns: [
        {
          title: '标签名称',
          dataIndex: 'label',
          editable: false,
          required: false,
          width: '30%'
        },
        {
          title: '选中标记',
          dataIndex: 'value',
          inputType: 'input',
          editable: true,
          required: false,
          width: '50%'
        }
      ]
    }
  ]
src/mob/components/tabs/tabcomponents/index.jsx
@@ -80,7 +80,7 @@
    drop(item) {
      if (item.hasOwnProperty('originalIndex') || item.added) {
        return
      } else if (['login', 'navbar', 'topbar'].includes(item.component)) {
      } else if (['login', 'navbar', 'topbar', 'iframe', 'sharecode', 'officialAccount'].includes(item.component)) {
        return
      }
      
src/mob/components/topbar/normal-navbar/options.jsx
@@ -219,7 +219,7 @@
      initval: wrap.menus || [],
      required: false,
      span: 24,
      actions: ['view'],
      actions: ['edit', 'del', 'add', 'move', 'view'],
      tip: <span style={{fontSize: '12px', color: '#959595', position: 'relative', top: '-8px'}}>当使用图标<MkIcon type="user"/>,且右侧只有一个菜单时,会显示用户头像。</span>,
      columns: [
        {
src/mob/modulesource/option.jsx
@@ -12,7 +12,6 @@
import Editor from '@/assets/mobimg/editor.png'
import SandBox from '@/assets/mobimg/sandbox.png'
import Pie1 from '@/assets/mobimg/ring.png'
import Pie2 from '@/assets/mobimg/nightingale.png'
import singlesearch from '@/assets/mobimg/singlesearch.png'
import Navbar from '@/assets/mobimg/navbar-mob.png'
import Carousel from '@/assets/mobimg/carousel.png'
@@ -56,7 +55,6 @@
  { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '条形图', width: 24 },
  { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '饼图', width: 24 },
  { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '环图', width: 24 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 24 },
  // { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 },
  { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '散点图', width: 24 },
  { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '富文本', width: 24 },
src/pc/components/login/normal-login/options.jsx
@@ -232,6 +232,7 @@
      label: '协议组',
      initval: wrap.groups || [],
      required: true,
      actions: ['edit', 'del', 'add', 'move'],
      span: 24,
      columns: [
        {
src/pc/modulesource/option.jsx
@@ -13,7 +13,6 @@
import SandBox from '@/assets/mobimg/sandbox.png'
import Pie1 from '@/assets/mobimg/ring.png'
import Pie3 from '@/assets/mobimg/nest.png'
import Pie2 from '@/assets/mobimg/nightingale.png'
import Mainsearch from '@/assets/mobimg/mainsearch.png'
import Navbar from '@/assets/mobimg/navbar.png'
import Carousel from '@/assets/mobimg/carousel.png'
@@ -54,7 +53,6 @@
  { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '饼图', width: 12 },
  { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '环图', width: 12 },
  { type: 'menu', url: Pie3, component: 'pie', subtype: 'nest', title: '嵌套饼图', width: 12 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 },
  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 },
  { type: 'menu', url: ratioboard, component: 'dashboard', subtype: 'ratioboard', title: '占比图', width: 12 },
  { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '散点图', width: 24 },
src/tabviews/basetable/index.jsx
@@ -208,7 +208,7 @@
          }
        })
      }
      // 获取主搜索条件
      config.components.forEach(component => {
        if (component.type === 'tabs') return
@@ -346,11 +346,6 @@
        item.name = (MenuName || '')
      }
      // 搜索条件初始化
      Utils.initSearchVal(item)
      item.$searches = Utils.initMainSearch(item.search)
      if (item.setting.supModule) {
        let pid = item.setting.supModule.pop()
        if (pid && pid !== 'empty') {
@@ -359,6 +354,11 @@
          item.setting.supModule = ''
        }
      }
      // 搜索条件初始化
      Utils.initSearchVal(item)
      item.$searches = Utils.initMainSearch(item.search)
      let statFields = []
      let getCols = (cols) => {
@@ -484,7 +484,7 @@
    }
    if (cell.OpenType === 'excelOut') { // 导出
      cell.$menuName = item.name
      cell.$menuName = item.$menuname
      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
        cell.errorType = 'error1'
@@ -506,12 +506,24 @@
    }
    if (cell.verify && cell.verify.preHandle === 'true') {
      try {
        // eslint-disable-next-line
        let func = new Function('btn', 'systemType', cell.verify.pre_func)
        func(cell, window.GLOB.systemType)
      } catch (e) {
        console.warn(e)
      let script = cell.verify.pre_func
      if (!/#position-/.test(script) || /#position-init/.test(script)) {
        try {
          // eslint-disable-next-line
          let func = new Function('btn', 'position', 'systemType', script)
          func(cell, 'init', window.GLOB.systemType)
        } catch (e) {
          console.warn(e)
        }
      }
      if (/#position-inner/.test(script)) {
        cell.$innerScript = script
      }
      if (/#position-outer/.test(script)) {
        cell.$outerScript = script
      }
      if (/#position-callback/.test(script)) {
        cell.$callbackScript = script
      }
    }
src/tabviews/basetable/index.scss
@@ -31,15 +31,7 @@
    left: calc(50% - 16px);
    top: calc(50vh - 70px);
  }
  .common-table-copy {
    position: fixed;
    z-index: 2;
    bottom: 65px;
    right: 30px;
    width: 40px;
    height: 40px;
  }
  .ant-btn-link:hover {
    opacity: 0.8;
  }
src/tabviews/custom/components/card/balcony/index.jsx
@@ -360,7 +360,7 @@
    
    if (config.wrap.datatype === 'static') {
      this.setState({
        data: {$$BID: BID || '', $$BData: BData, $$empty: true},
        data: {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()},
      })
      return
    } else if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -23,6 +23,8 @@
const PrintButton = asyncComponent(() => import('@/tabviews/zshare/actionList/printbutton'))
const FuncMegvii = asyncComponent(() => import('@/tabviews/zshare/actionList/funcMegvii'))
const FuncZip = asyncComponent(() => import('@/tabviews/zshare/actionList/funczip'))
const ExportPdf = asyncComponent(() => import('@/tabviews/zshare/actionList/exportPdf'))
const ShareLink = asyncComponent(() => import('@/tabviews/zshare/actionList/shareLink'))
const EditLine = asyncComponent(() => import('@/tabviews/zshare/actionList/editLine'))
const BarCode = asyncComponent(() => import('@/components/barcode'))
const QrCode = asyncComponent(() => import('@/components/qrcode'))
@@ -655,10 +657,8 @@
        let url = ''
        if (card.maxWidth) {
          _style.maxWidth = card.maxWidth
          if (_style.marginLeft === '0px') {
          if (_style.marginLeft === '0px' && _style.marginRight === '0px') {
            delete _style.marginLeft
          }
          if (_style.marginRight === '0px') {
            delete _style.marginRight
          }
        }
@@ -701,7 +701,7 @@
        urls.forEach((u, i) => {
          contents.push(<div className={'ant-col ant-col-' + card.width} key={card.uuid + i} style={_style_} span={card.width}>
            <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
              <MkPicture style={_imagestyle} scale={scale} url={u} urls={urls}/>
              <MkPicture style={_imagestyle} lostTip={card.lostTip !== 'false'} scale={scale} url={u} urls={urls}/>
            </div>
          </div>)
        })
@@ -1010,148 +1010,125 @@
        if (card.wrapStyle) {
          _style_ = {..._style_, ...card.wrapStyle}
        }
        let MkButton = null
  
        if (['exec', 'prompt', 'pop', 'form'].includes(card.OpenType)) {
          contents.push(
            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <NormalButton
                btn={card}
                BID={data.$$BID}
                BData={data.$$BData || ''}
                disabled={_disabled}
                setting={cards.setting}
                columns={cards.columns}
                selectedData={_data}
              />
            </div>
          )
          MkButton = <NormalButton
            btn={card}
            BID={data.$$BID}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
            columns={cards.columns}
            selectedData={_data}
          />
        } else if (card.OpenType === 'excelIn') {
          contents.push(
            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <ExcelInButton
                btn={card}
                BID={data.$$BID}
                BData={data.$$BData || ''}
                disabled={_disabled}
                setting={cards.setting}
                selectedData={_data}
              />
            </div>
          )
          MkButton = <ExcelInButton
            btn={card}
            BID={data.$$BID}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
            selectedData={_data}
          />
        } else if (card.OpenType === 'excelOut') {
          contents.push(
            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <ExcelOutButton
                btn={card}
                BID={data.$$BID}
                BData={data.$$BData || ''}
                disabled={_disabled}
                setting={cards.setting}
                selectedData={_data}
              />
            </div>
          )
          MkButton = <ExcelOutButton
            btn={card}
            BID={data.$$BID}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
            selectedData={_data}
          />
        } else if (card.OpenType === 'popview') {
          contents.push(
            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <PopupButton
                btn={card}
                BID={data.$$BID}
                BData={data.$$BData || ''}
                disabled={_disabled}
                setting={cards.setting}
                selectedData={_data}
              />
            </div>
          )
          MkButton = <PopupButton
            btn={card}
            BID={data.$$BID}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
            selectedData={_data}
          />
        } else if (card.OpenType === 'tab') {
          contents.push(
            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <TabButton
                btn={card}
                BID={data.$$BID}
                BData={data.$$BData || ''}
                disabled={_disabled}
                selectedData={_data}
              />
            </div>
          )
          MkButton = <TabButton
            btn={card}
            BID={data.$$BID}
            BData={data.$$BData || ''}
            disabled={_disabled}
            selectedData={_data}
          />
        } else if (card.OpenType === 'innerpage') {
          contents.push(
            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <NewPageButton
                btn={card}
                BID={data.$$BID}
                BData={data.$$BData || ''}
                disabled={_disabled}
                selectedData={_data}
              />
            </div>
          )
          MkButton = <NewPageButton
            btn={card}
            BID={data.$$BID}
            BData={data.$$BData || ''}
            disabled={_disabled}
            selectedData={_data}
          />
        } else if (card.OpenType === 'funcbutton') {
          if (card.funcType === 'changeuser' || card.funcType === 'closetab') {
            contents.push(
              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                <ChangeUserButton
                  btn={card}
                  BID={data.$$BID}
                  BData={data.$$BData || ''}
                  disabled={_disabled}
                  setting={cards.setting}
                  selectedData={_data}
                />
              </div>
            )
            MkButton = <ChangeUserButton
              btn={card}
              BID={data.$$BID}
              BData={data.$$BData || ''}
              disabled={_disabled}
              setting={cards.setting}
              selectedData={_data}
            />
          } else if (card.funcType === 'print') {
            contents.push(
              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                <PrintButton
                  btn={card}
                  BID={data.$$BID}
                  BData={data.$$BData || ''}
                  disabled={_disabled}
                  setting={cards.setting}
                  columns={cards.columns}
                  selectedData={_data}
                />
              </div>
            )
            MkButton = <PrintButton
              btn={card}
              BID={data.$$BID}
              BData={data.$$BData || ''}
              disabled={_disabled}
              setting={cards.setting}
              columns={cards.columns}
              selectedData={_data}
            />
          } else if (card.funcType === 'megvii') {
            contents.push(
              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                <FuncMegvii
                  btn={card}
                  BID={data.$$BID}
                  disabled={_disabled}
                  setting={cards.setting}
                  selectedData={_data}
                />
              </div>
            )
            MkButton = <FuncMegvii
              btn={card}
              BID={data.$$BID}
              disabled={_disabled}
              setting={cards.setting}
              selectedData={_data}
            />
          } else if (card.funcType === 'filezip') {
            contents.push(
              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                <FuncZip
                  btn={card}
                  BID={data.$$BID}
                  disabled={_disabled}
                  setting={cards.setting}
                  selectedData={_data}
                />
              </div>
            )
            MkButton = <FuncZip
              btn={card}
              BID={data.$$BID}
              BData={data.$$BData || ''}
              disabled={_disabled}
              setting={cards.setting}
              selectedData={_data}
            />
          } else if (card.funcType === 'expPdf') {
            MkButton = <ExportPdf
              btn={card}
            />
          } else if (card.funcType === 'shareLink') {
            MkButton = <ShareLink
              BID={data.$$BID}
              btn={card}
              selectedData={_data}
            />
          } else if (card.funcType === 'addline' || card.funcType === 'delline') {
            contents.push(
              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                <EditLine
                  btn={card}
                  disabled={_disabled}
                  selectedData={_data}
                />
              </div>
            )
            MkButton = <EditLine
              btn={card}
              disabled={_disabled}
              selectedData={_data}
            />
          }
        }
        if (MkButton) {
          contents.push(
            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              {MkButton}
            </div>
          )
        }
      }
    })
src/tabviews/custom/components/card/data-card/index.jsx
@@ -154,6 +154,10 @@
        pageOptions.push(size)
        pageOptions = pageOptions.sort((a, b) => a - b)
      }
      if (_config.wrap.maxPageSize) {
        pageOptions = pageOptions.filter(item => item <= _config.wrap.maxPageSize)
      }
    }
    let _data = []
@@ -236,6 +240,8 @@
    }
    this.initExec()
    this.autoExec()
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -327,6 +333,25 @@
      setTimeout(() => {
        this.loadData()
      }, config.setting.delay || 0)
    }
  }
  autoExec = (times) => {
    const { config } = this.state
    if (!config.wrap.autoExec) return
    let btn = document.getElementById('button' + config.wrap.autoExec)
    this.autoTimer && clearTimeout(this.autoTimer)
    if (btn) {
      MKEmitter.emit('triggerBtnId', config.wrap.autoExec, [])
    } else if (!times || times < 20) {
      times = times ? times + 1 : 1
      this.autoTimer = setTimeout(() => {
        this.autoExec(times)
      }, 1000)
    }
  }
@@ -680,7 +705,9 @@
      if (!config.setting.supModule || config.setting.supModule !== MenuID) return
      if (id !== this.state.BID || id !== '') {
        this.setState({ BID: id, BData: data, pageIndex: 1 }, () => {
          this.loadData()
          if (!config.checkBid) {
            this.loadData()
          }
        })
      }
    }
src/tabviews/custom/components/card/double-data-card/index.jsx
@@ -170,6 +170,9 @@
        pageOptions.push(size)
        pageOptions = pageOptions.sort((a, b) => a - b)
      }
      if (_config.wrap.maxPageSize) {
        pageOptions = pageOptions.filter(item => item <= _config.wrap.maxPageSize)
      }
    }
    if (_config.wrap.zHeight) {
@@ -229,6 +232,8 @@
    if (config.setting.onload === 'true') {
      this.initExec()
    }
    this.autoExec()
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -319,6 +324,25 @@
      setTimeout(() => {
        this.loadData()
      }, config.setting.delay || 0)
    }
  }
  autoExec = (times) => {
    const { config } = this.state
    if (!config.wrap.autoExec) return
    let btn = document.getElementById('button' + config.wrap.autoExec)
    this.autoTimer && clearTimeout(this.autoTimer)
    if (btn) {
      MKEmitter.emit('triggerBtnId', config.wrap.autoExec, [])
    } else if (!times || times < 20) {
      times = times ? times + 1 : 1
      this.autoTimer = setTimeout(() => {
        this.autoExec(times)
      }, 1000)
    }
  }
@@ -522,7 +546,9 @@
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data, pageIndex: 1 }, () => {
        this.loadData()
        if (!config.checkBid) {
          this.loadData()
        }
      })
    }
  }
@@ -1193,6 +1219,20 @@
                    subClass = opens.indexOf(item.key) > -1 ? 'mk-unfold' : 'mk-collapse'
                    unfold = opens.indexOf(item.key) > -1
                  }
                  if (!unfold && item.children.length > 5) {
                    return (
                      <Col key={index} span={card.setting.width} style={card.wStyle}>
                        <div className={className} style={wrapStyle}>
                          <CardItem card={card} cards={config} data={item} onDoubleClick={() => this.onDoubleClick(item.key, subClass)} onClick={() => {this.changeCard(item.key, item, subClass)}}>
                            <span className="circle-select"></span>
                            {card.setting.controlIcon === 'left' ? <PlusSquareOutlined className={subClass} onClick={(e) => this.changeUnfold(e, item.key, subClass)}/> : null}
                            {card.setting.controlIcon === 'right' ? <UpOutlined className={subClass} onClick={(e) => this.changeUnfold(e, item.key, subClass)}/> : null}
                          </CardItem>
                        </div>
                      </Col>
                    )
                  }
                }
                return (
src/tabviews/custom/components/card/prop-card/index.jsx
@@ -377,7 +377,7 @@
    let btn = document.getElementById('button' + config.wrap.autoExec)
    clearTimeout(this.autoTimer)
    this.autoTimer && clearTimeout(this.autoTimer)
    if (btn) {
      MKEmitter.emit('triggerBtnId', config.wrap.autoExec, data.$$empty ? [] : [data])
@@ -495,7 +495,7 @@
    
    if (config.wrap.datatype === 'static') {
      this.setState({
        data: {$$BID: BID || '', $$BData: BData, $$empty: true},
        data: {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()},
      })
      if (!btn) {
src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
@@ -205,20 +205,6 @@
              )}
            </Form.Item>
          </Col> : null}
          {nodetype === 'node' ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="标记将作为节点ID">
                <QuestionCircleOutlined className="mk-form-tip" />
                标记
              </Tooltip>
            }>
              {getFieldDecorator('sign', {
                initialValue: data.sign || ''
              })(
                <Input placeholder="" autoComplete="off"/>
              )}
            </Form.Item>
          </Col> : null}
          <Col span={24}>
            <Form.Item label="备注">
              {getFieldDecorator('remark', {
src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -676,7 +676,7 @@
      height: plot.height
    })
    if (plot.shape !== 'nightingale' && plot.show !== 'value') {
    if (plot.show !== 'value') {
      dv.transform({
        type: 'percent',
        field: Y_axis,
@@ -696,27 +696,13 @@
    chart.data(dv.rows)
    if (plot.shape === 'nightingale') {
      chart.coordinate('polar', {
        innerRadius: plot.innerRadius ? (plot.innerRadius / 100) : 0,
        radius: plot.radius ? (plot.radius / 100) : 0.75,
      })
    } else {
      chart.coordinate('theta', {
        innerRadius: plot.shape !== 'pie' && plot.innerRadius ? (plot.innerRadius / 100) : 0,
        radius: plot.radius ? (plot.radius / 100) : 0.75,
      })
    }
    chart.coordinate('theta', {
      innerRadius: plot.shape !== 'pie' && plot.innerRadius ? (plot.innerRadius / 100) : 0,
      radius: plot.radius ? (plot.radius / 100) : 0.75,
    })
    if (!plot.legend || plot.legend === 'hidden') {
      chart.legend(false)
    } else if (plot.shape === 'nightingale') {
      chart.legend(X_axis, {
        position: plot.legend,
        itemName: {
          style: { fill: color }
        }
      })
    } else {
      chart.legend({
        position: plot.legend,
@@ -746,125 +732,84 @@
      })
    }
    if (plot.shape !== 'nightingale') {
      let _chart = chart
        .interval()
        .adjust('stack')
        .position(Y_axis)
        .tooltip(`${X_axis}*${Y_axis}`, (name, value) => {
          if (plot.show !== 'value') {
            value = (value * 100).toFixed(2) + '%'
          }
          return {
            name: name,
            value: value
          }
        })
      if (plot.splitLine) {
        _chart.style({
          lineWidth: plot.splitLine,
          stroke: plot.splitColor,
        })
      }
      if (plot.colors && plot.colors.length > 0) {
        let limit = chartColors.length
        _chart.color(X_axis, (type) => {
          if (colors.has(type)) {
            return colors.get(type)
          } else {
            let _c = chartColors[colorIndex % limit]
            colors.set(type, _c)
            colorIndex++
            return _c
          }
        })
      } else {
        _chart.color(X_axis)
      }
      if (plot.label !== 'false') {
        if (plot.label === 'inner') {
          _chart.label(Y_axis, {
            offset: -30,
            content: (data) => {
              let _val = ''
              if (plot.show !== 'value') {
                _val = `${(data[Y_axis] * 100).toFixed(2)}%`
              } else {
                _val = `${data[Y_axis]}`
              }
              return _val
            },
            style: {
              textAlign: 'center',
              fontSize: 16,
              shadowBlur: 2,
              shadowColor: 'rgba(0, 0, 0, .45)',
              fill: '#fff',
            }
          })
        } else {
          _chart.label(Y_axis, {
            layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' },
            labelHeight: 20,
            content: (data) => {
              let _val = ''
              if (plot.show !== 'value') {
                _val = `${(data[Y_axis] * 100).toFixed(2)}%`
              } else {
                _val = `${data[Y_axis]}`
              }
              return `${data[X_axis]}: ${_val}`
            },
            labelLine: {
              style: {
                lineWidth: 0.5,
              },
            },
            style: {
              fill: color
            }
          })
    let _chart = chart
      .interval()
      .adjust('stack')
      .position(Y_axis)
      .tooltip(`${X_axis}*${Y_axis}`, (name, value) => {
        if (plot.show !== 'value') {
          value = (value * 100).toFixed(2) + '%'
        }
      }
    } else {
      chart.axis(false)
      let _chart = chart
        .interval()
        .position(`${X_axis}*${Y_axis}`)
        return {
          name: name,
          value: value
        }
      })
      if (plot.colors && plot.colors.length > 0) {
        let limit = chartColors.length
        _chart.color(X_axis, (type) => {
          if (colors.has(type)) {
            return colors.get(type)
          } else {
            let _c = chartColors[colorIndex % limit]
            colors.set(type, _c)
            colorIndex++
            return _c
    if (plot.splitLine) {
      _chart.style({
        lineWidth: plot.splitLine,
        stroke: plot.splitColor,
      })
    }
    if (plot.colors && plot.colors.length > 0) {
      let limit = chartColors.length
      _chart.color(X_axis, (type) => {
        if (colors.has(type)) {
          return colors.get(type)
        } else {
          let _c = chartColors[colorIndex % limit]
          colors.set(type, _c)
          colorIndex++
          return _c
        }
      })
    } else {
      _chart.color(X_axis)
    }
    if (plot.label !== 'false') {
      if (plot.label === 'inner') {
        _chart.label(Y_axis, {
          offset: -30,
          content: (data) => {
            let _val = ''
            if (plot.show !== 'value') {
              _val = `${(data[Y_axis] * 100).toFixed(2)}%`
            } else {
              _val = `${data[Y_axis]}`
            }
            return _val
          },
          style: {
            textAlign: 'center',
            fontSize: 16,
            shadowBlur: 2,
            shadowColor: 'rgba(0, 0, 0, .45)',
            fill: '#fff',
          }
        })
      } else {
        _chart.color(X_axis)
      }
      if (plot.label !== 'false') {
        let _label = {}
        if (plot.label === 'inner') {
          _label.offset = -15
        } else {
          _label.style = {
        _chart.label(Y_axis, {
          layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' },
          labelHeight: 20,
          content: (data) => {
            let _val = ''
            if (plot.show !== 'value') {
              _val = `${(data[Y_axis] * 100).toFixed(2)}%`
            } else {
              _val = `${data[Y_axis]}`
            }
            return `${data[X_axis]}: ${_val}`
          },
          labelLine: {
            style: {
              lineWidth: 0.5,
            },
          },
          style: {
            fill: color
          }
        }
        _chart.label(X_axis, _label)
      }
      if (plot.splitLine) {
        _chart.style({
          lineWidth: plot.splitLine,
          stroke: plot.splitColor,
        })
      }
    }
src/tabviews/custom/components/form/simple-form/index.jsx
@@ -70,6 +70,10 @@
    let _group = _config.subcards[0]
    if (_config.wrap.refocus) {
      _group.setting.refocus = _config.wrap.refocus
    }
    if (_group.subButton.enable === 'false' && (!_group.closeButton || _group.closeButton.enable !== 'true') && (!_group.resetButton || _group.resetButton.enable !== 'true')) {
      _group.subButton.style.display = 'none'
      _group.$button = 'no-button'
@@ -213,15 +217,27 @@
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn, id) => {
  refreshByButtonResult = (menuId, position, btn, id, lines, res) => {
    const { config, group, BID } = this.state
    if (config.uuid !== menuId) return
    if (position === 'resetData') {
      let _data = fromJS(this.state.data || {}).toJS()
      Object.keys(_data).forEach(key => {
        let _key = key.toLowerCase()
        if (typeof(res[_key]) !== 'undefined') {
          _data[key] = res[_key]
        }
      })
      this.setState({
        data: _data
      })
      return
    }
    if (position === 'grid' && config.wrap.refocus) {
      let _group = fromJS(group).toJS()
      _group.setting.focus = config.wrap.refocus
src/tabviews/custom/components/interfaces/interItem/index.jsx
@@ -124,6 +124,10 @@
    let searches = []
    if (config.setting.useMSearch) {
      searches = window.GLOB.SearchBox.get(config.$searchId) || []
      if (window.GLOB.SearchBox.has(config.$searchId + 'required') && searches.filter(item => item.required && item.value === '').length > 0) {
        return
      }
    }
    this.loading = true
src/tabviews/custom/components/module/voucher/index.jsx
@@ -1166,7 +1166,7 @@
            <div className="voucher-code">
              <Select value={charType} dropdownClassName="mk-vcode-dropdown" onChange={(val, option) => this.setState({status: 'change', charType: val, charName: option.props.charName, charInt: option.props.charint})}>
                {typeOptions.map(option =>
                  <Select.Option key={option.voucher_char_int} value={option.voucher_class} charName={option.voucher_char} charint={option.voucher_char_int}>{option.voucher_char}</Select.Option>
                  <Select.Option key={option.id} value={option.voucher_class} charName={option.voucher_char} charint={option.voucher_char_int}>{option.voucher_char}</Select.Option>
                )}
              </Select>
              <InputNumber precision={0} min={1} value={charInt} autoComplete="off" onChange={(val) => this.setState({status: 'change', charInt: val})}/> 号
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -268,7 +268,7 @@
        <div>
          {photos.map((url, i) => (
            <Col key={i} span={col.span || 24}>
              <MkPicture style={{paddingTop, backgroundSize: col.backgroundSize || 'cover'}} scale={scale} url={url} urls={photos}/>
              <MkPicture lostTip={col.lostTip !== 'false'} style={{paddingTop, backgroundSize: col.backgroundSize || 'cover'}} scale={scale} url={url} urls={photos}/>
            </Col>
          ))}
        </div>
@@ -566,6 +566,10 @@
      pageOptions = pageOptions.sort((a, b) => a - b)
    }
    if (setting.maxPageSize) {
      pageOptions = pageOptions.filter(item => item <= setting.maxPageSize)
    }
    let allColumns = null
    if (colsCtrls) {
      rowspans = null
src/tabviews/custom/components/share/normalheader/index.jsx
@@ -27,7 +27,14 @@
    })
  }
  shouldComponentUpdate (nextProps, nextState) { return false }
  shouldComponentUpdate (nextProps, nextState) {
    const { config } = this.props
    if (config.checkBid && this.props.BID !== nextProps.BID) {
      return true
    }
    return false
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
src/tabviews/custom/components/table/base-table/index.jsx
@@ -137,7 +137,7 @@
    let _orderBy = orderBy || setting.order
    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
    let result = await Api.genericInterface(param)
    let result = await Api.genericInterface(param, setting.js_script)
    if (result.status) {
      if (repage === 'false' && result.data && result.data.length === 0 && result.total > 0 && pageIndex > 1) {
        let _pageIndex = Math.ceil(result.total / pageSize)
@@ -566,8 +566,10 @@
        BID: id,
        BData: data
      }, () => {
        this.loadmaindata(true, 'true')
        this.getStatFieldsValue()
        if (!setting.checkBid) {
          this.loadmaindata(true, 'true')
          this.getStatFieldsValue()
        }
      })
    }
  }
@@ -606,6 +608,25 @@
    })
  }
  autoExec = (times) => {
    const { config } = this.state
    if (!config.wrap.autoExec) return
    let btn = document.getElementById('button' + config.wrap.autoExec)
    this.autoTimer && clearTimeout(this.autoTimer)
    if (btn) {
      MKEmitter.emit('triggerBtnId', config.wrap.autoExec, [])
    } else if (!times || times < 20) {
      times = times ? times + 1 : 1
      this.autoTimer = setTimeout(() => {
        this.autoExec(times)
      }, 1000)
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
@@ -621,6 +642,8 @@
    if (config.setting.useMSearch) {
      MKEmitter.addListener('searchRefresh', this.searchRefresh)
    }
    this.autoExec()
  }
  /**
src/tabviews/custom/components/table/edit-table/index.jsx
@@ -584,9 +584,11 @@
        BID: id,
        BData: data
      }, () => {
        setTimeout(() => {
          this.loadmaindata(true, 'true')
        }, setting.delay || 0)
        if (!setting.checkBid) {
          setTimeout(() => {
            this.loadmaindata(true, 'true')
          }, setting.delay || 0)
        }
      })
    }
  }
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -55,7 +55,7 @@
    this.node.blur()
    
    if (config.enter === '$noAct') return
    if (/\$noAct/.test(config.enter)) return
    if (/\$next/.test(config.enter)) {
      MKEmitter.emit('nextLine' + config.tableId, lineId, config.enter.replace('$next_', ''))
@@ -191,7 +191,7 @@
    this.props.onChange(values)
    if (config.enter === '$noAct') return
    if (/\$noAct/.test(config.enter)) return
    if (/\$next/.test(config.enter)) {
      MKEmitter.emit('nextLine' + config.tableId, lineId, config.enter.replace('$next_', ''))
@@ -283,9 +283,11 @@
    this.props.onChange(values, val)
    if (config.enter === '$noActX') return
    this.node.blur()
    
    if (config.enter === '$noAct') return
    if (/\$noAct/.test(config.enter)) return
    setTimeout(() => {
      if (/\$next/.test(config.enter)) {
@@ -308,7 +310,7 @@
    const { config, lineId } = this.props
    if (config.$ctrl) {
      MKEmitter.emit('colBlur' + config.tableId, lineId, config.uuid)
      MKEmitter.emit('colBlur' + config.tableId, lineId, config.uuid, true)
    }
    setTimeout(() => {
@@ -408,7 +410,7 @@
    this.node.blur()
    
    if (config.enter === '$noAct') return
    if (/\$noAct/.test(config.enter)) return
    if (/\$next/.test(config.enter)) {
      MKEmitter.emit('nextLine' + config.tableId, lineId, config.enter.replace('$next_', ''))
@@ -536,7 +538,7 @@
    this.node.blur()
    
    if (config.enter === '$noAct') return
    if (/\$noAct/.test(config.enter)) return
    setTimeout(() => {
      if (/\$next/.test(config.enter)) {
@@ -1471,6 +1473,10 @@
      pageOptions = pageOptions.sort((a, b) => a - b)
    }
    if (setting.maxPageSize) {
      pageOptions = pageOptions.filter(item => item <= setting.maxPageSize)
    }
    let allColumns = null
    if (colsCtrls) {
      allColumns = [..._columns]
@@ -1550,7 +1556,11 @@
    MKEmitter.removeListener('changeRecord' + tableId, this.changeRecord)
  }
  colBlur = (lineId) => {
  colBlur = (lineId, colId, defer) => {
    if (defer && this.focusId === lineId && this.colId !== colId) {
      return
    }
    this.blurId = lineId
    this.focusId = ''
src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx
@@ -292,7 +292,7 @@
    this.props.onBlur && this.props.onBlur()
    if (config.enter === '$noAct') return
    if (/\$noAct/.test(config.enter)) return
    setTimeout(() => {
      if (/\$next/.test(config.enter)) {
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -199,6 +199,8 @@
    }
    this.initExec()
    this.autoExec()
  }
  /**
@@ -298,6 +300,25 @@
      setTimeout(() => {
        this.loadmaindata()
      }, config.setting.delay || 0)
    }
  }
  autoExec = (times) => {
    const { config } = this.state
    if (!config.wrap.autoExec) return
    let btn = document.getElementById('button' + config.wrap.autoExec)
    this.autoTimer && clearTimeout(this.autoTimer)
    if (btn) {
      MKEmitter.emit('triggerBtnId', config.wrap.autoExec, [])
    } else if (!times || times < 20) {
      times = times ? times + 1 : 1
      this.autoTimer = setTimeout(() => {
        this.autoExec(times)
      }, 1000)
    }
  }
@@ -763,7 +784,9 @@
        BID: id,
        BData: data
      }, () => {
        this.loadmaindata(true, 'true')
        if (!setting.checkBid) {
          this.loadmaindata(true, 'true')
        }
      })
    }
  }
src/tabviews/custom/index.jsx
@@ -249,7 +249,7 @@
      let initInters = []
      config.interfaces = this.formatInterSetting(config.interfaces, regs, MenuID, initInters)
      config.interfaces = this.formatInterSetting(config.interfaces, regs, MenuID, initInters, config.MenuName)
      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, param, MenuID, config.interfaces, config.$cache, config.$time, config.MenuName, MenuID, MenuID, config.process === 'true')
      let params = []
@@ -563,13 +563,6 @@
        item.type = 'card'
      }
      // 搜索条件初始化
      if (item.search) {
        Utils.initSearchVal(item)
        item.$searches = Utils.initMainSearch(item.search)
      }
      if (item.wrap && item.wrap.supType === 'multi') { // 数据卡多上级组件
        item.setting.supModule = item.supNodes[0].componentId
      } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
@@ -579,6 +572,13 @@
        } else {
          item.setting.supModule = ''
        }
      }
      // 搜索条件初始化
      if (item.search) {
        Utils.initSearchVal(item)
        item.$searches = Utils.initMainSearch(item.search)
      }
      let pass = skip
@@ -887,7 +887,7 @@
    }
    if (cell.OpenType === 'excelOut') { // 导出
      cell.$menuName = item.name
      cell.$menuName = item.$menuname
      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
        cell.errorType = 'error1'
@@ -919,12 +919,24 @@
    }
    if (cell.verify && cell.verify.preHandle === 'true') {
      try {
        // eslint-disable-next-line
        let func = new Function('btn', 'systemType', cell.verify.pre_func)
        func(cell, window.GLOB.systemType)
      } catch (e) {
        console.warn(e)
      let script = cell.verify.pre_func
      if (!/#position-/.test(script) || /#position-init/.test(script)) {
        try {
          // eslint-disable-next-line
          let func = new Function('btn', 'position', 'systemType', script)
          func(cell, 'init', window.GLOB.systemType)
        } catch (e) {
          console.warn(e)
        }
      }
      if (/#position-inner/.test(script)) {
        cell.$innerScript = script
      }
      if (/#position-outer/.test(script)) {
        cell.$outerScript = script
      }
      if (/#position-callback/.test(script)) {
        cell.$callbackScript = script
      }
    }
@@ -1175,7 +1187,7 @@
  }
  // 格式化默认设置
  formatInterSetting = (inters, regs, MenuID, initInters) => {
  formatInterSetting = (inters, regs, MenuID, initInters, MenuName) => {
    if (!inters) return []
    let initlimit = false
@@ -1233,7 +1245,7 @@
      })
      delete inter.scripts
      inter.setting.$name = '公共数据源-' + inter.setting.name
      inter.setting.$name = (MenuName || '') + '-公共数据源-' + inter.setting.name
      inter.setting.execute = inter.setting.execute !== 'false'
      if (!inter.setting.execute) {
src/tabviews/custom/index.scss
@@ -32,14 +32,6 @@
    top: calc(50vh - 70px);
  }
  
  .common-table-copy {
    position: fixed;
    z-index: 2;
    bottom: 65px;
    right: 30px;
    width: 40px;
    height: 40px;
  }
  .ant-btn-link:hover {
    opacity: 0.8;
  }
src/tabviews/custom/popview/index.jsx
@@ -323,13 +323,6 @@
        }
      }
      // 搜索条件初始化
      if (item.search) {
        Utils.initSearchVal(item)
        item.$searches = Utils.initMainSearch(item.search)
      }
      if (item.wrap && item.wrap.supType === 'multi') { // 数据卡多上级组件
        item.setting.supModule = item.supNodes[0].componentId
      } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
@@ -339,6 +332,13 @@
        } else {
          item.setting.supModule = ''
        }
      }
      // 搜索条件初始化
      if (item.search) {
        Utils.initSearchVal(item)
        item.$searches = Utils.initMainSearch(item.search)
      }
      // 权限过滤
@@ -608,7 +608,7 @@
    }
    if (cell.OpenType === 'excelOut') { // 导出
      cell.$menuName = item.name
      cell.$menuName = item.$menuname
      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
        cell.errorType = 'error1'
@@ -636,12 +636,24 @@
    }
    if (cell.verify && cell.verify.preHandle === 'true') {
      try {
        // eslint-disable-next-line
        let func = new Function('btn', 'systemType', cell.verify.pre_func)
        func(cell, window.GLOB.systemType)
      } catch (e) {
        console.warn(e)
      let script = cell.verify.pre_func
      if (!/#position-/.test(script) || /#position-init/.test(script)) {
        try {
          // eslint-disable-next-line
          let func = new Function('btn', 'position', 'systemType', script)
          func(cell, 'init', window.GLOB.systemType)
        } catch (e) {
          console.warn(e)
        }
      }
      if (/#position-inner/.test(script)) {
        cell.$innerScript = script
      }
      if (/#position-outer/.test(script)) {
        cell.$outerScript = script
      }
      if (/#position-callback/.test(script)) {
        cell.$callbackScript = script
      }
    }
src/tabviews/custom/popview/index.scss
@@ -31,15 +31,7 @@
    left: calc(50% - 16px);
    top: calc(50vh - 70px);
  }
  .common-table-copy {
    position: fixed;
    z-index: 2;
    bottom: 65px;
    right: 30px;
    width: 40px;
    height: 40px;
  }
  .ant-btn-link:hover {
    opacity: 0.8;
  }
src/tabviews/rolemanage/index.jsx
@@ -356,7 +356,7 @@
  /**
   * @description 获取权限分配树
   */
  getTree = (parents, options) => {
  getTree = (parents, options, addSelf) => {
    parents.forEach(parent => {
      parent.children = []
@@ -367,7 +367,7 @@
            title: option.MenuName,
            key: option.MenuID,
            addSelf: option.OnlySelf === 'true',
            tabs: option.Tabs
            // tabs: option.Tabs
          })
        }
      })
@@ -375,13 +375,13 @@
      if (parent.children.length === 0) {
        parent.children = null
        // 针对标签,生成新的id,并保存关联关系(标签不唯一)
        if (parent.tabs) {
          let _uuid = Utils.getuuid()
          linkMap.set(_uuid, parent.key)
        // if (parent.tabs) {
        //   let _uuid = Utils.getuuid()
        //   linkMap.set(_uuid, parent.key)
          parent.originKey = parent.key
          parent.key = _uuid
        }
        //   parent.originKey = parent.key
        //   parent.key = _uuid
        // }
      } else {
        // 三级菜单创建子项
        if (parent.addSelf) {
@@ -392,20 +392,29 @@
          parent.children.unshift({
            title: parent.title + '(仅页面)',
            key: _uuid,
            isSubView: true
            // isSubView: true
          })
        } else if (addSelf) {
          let _uuid = Utils.getuuid()
          linkMap.set(_uuid, parent.key)
          parent.subKey = _uuid
          parent.children.unshift({
            title: parent.title + '(表格)',
            key: _uuid,
          })
        }
        // 针对标签,生成新的id,并保存关联关系(标签不唯一)
        if (parent.tabs) {
          let _uuid = Utils.getuuid()
          linkMap.set(_uuid, parent.key)
        // if (parent.tabs) {
        //   let _uuid = Utils.getuuid()
        //   linkMap.set(_uuid, parent.key)
          
          parent.originKey = parent.key
          parent.key = _uuid
        }
        //   parent.originKey = parent.key
        //   parent.key = _uuid
        // }
        parent.children = this.getTree(parent.children, options)
        parent.children = this.getTree(parent.children, options, parent.addSelf)
      }
    })
    return parents
@@ -442,8 +451,8 @@
          }
        }
        return true
      } else if (parent.isSubView) {
        return true
      // } else if (parent.isSubView) {
      //   return true
      }
      return false
    })
src/tabviews/subtable/index.jsx
@@ -88,7 +88,6 @@
        config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
        config.setting.MenuName = Tab.label
        config.setting.$name = Tab.label
        config.setting.foreignKey = Tab.foreignKey || ''
        config.setting.supModule = Tab.supMenu || ''
        config.setting.ContainerId = Tab.ContainerId || ''
      } catch (e) {
src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -582,6 +582,7 @@
    return <>
      <Button
        type={type}
        id={'button' + btn.uuid}
        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
        loading={loading}
        disabled={disabled}
src/tabviews/zshare/actionList/exportPdf/index.jsx
New file
@@ -0,0 +1,154 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button } from 'antd'
import html2Canvas from 'html2canvas'
import moment from 'moment'
import JsPDF from 'jspdf'
import MKEmitter from '@/utils/events.js'
import MkIcon from '@/components/mk-icon'
// import './index.scss'
class ExportPDF extends Component {
  static propTpyes = {
    btn: PropTypes.object
  }
  state = {
    loading: false,
  }
  componentDidMount () {
    MKEmitter.addListener('triggerBtnId', this.actionTrigger)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
  }
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId) => {
    const { btn } = this.props
    const { loading } = this.state
    if (loading) return
    if (triggerId && btn.uuid !== triggerId) return
    this.setState({
      loading: true
    }, () => {
      this.getCanvas()
    })
  }
  getCanvas = () => {
    const { btn } = this.props
    let wrap = document.getElementById('menu' + btn.$MenuID)
    const opts = {
      scale: 1.5,        // 缩放比例,提高生成图片清晰度
      useCORS: false,    // 允许加载跨域的图片
      allowTaint: false, // 允许图片跨域,和 useCORS 二者不可共同使用
      tainttest: false,  // 检测每张图片已经加载完成
      logging: false     // 日志开关,发布的时候记得改成 false
    }
    // eslint-disable-next-line
    html2Canvas(wrap, opts).then(canvas => {
      // const contentWidth = parseInt(canvas.style.width) * 2
      // const contentHeight = parseInt(canvas.style.height) * 2
      const contentWidth = canvas.width
      const contentHeight = canvas.height
      const pageHeight = (contentWidth / 592.28) * 841.89
      let leftHeight = contentHeight
      const imgWidth = 595.28
      const imgHeight = (592.28 / contentWidth) * contentHeight
      const pageData = canvas.toDataURL('image/jpeg', 1.0)
      let position = 0
      let title = btn.logLabel + moment().format('YYYYMMDDHHmmss')
      const PDF = new JsPDF('', 'pt', 'a4')
      if (leftHeight < pageHeight) {
        PDF.addImage(pageData, 'JPEG', 10, 0, imgWidth - 20, imgHeight)
      } else {
        while (leftHeight > 0) {
          PDF.addImage(pageData, 'JPEG', 10, position, imgWidth - 20, imgHeight)
          leftHeight -= pageHeight
          position -= 841.89
          if (leftHeight > 0) {
            PDF.addPage()
          }
        }
      }
      PDF.save(title + '.pdf')
      this.setState({
        loading: false
      })
    })
  }
  render() {
    const { btn } = this.props
    const { loading } = this.state
    let label = ''
    let icon = ''
    let type = 'link'
    let className = ''
    let style = {...btn.style}
    if (loading) {
      style.opacity = 0
    }
    if (btn.show === 'button') {
      label = btn.label
      icon = btn.icon || ''
    } else if (btn.show === 'link') {
      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
      icon = ''
    } else if (btn.show === 'icon') {
      icon = btn.icon || ''
    } else if (!btn.$toolbtn) {
      icon = btn.icon || ''
      label = btn.label
      className = 'mk-btn mk-' + btn.class
    } else {
      type = ''
      icon = btn.icon || ''
      label = btn.label
      className = 'mk-btn mk-' + btn.class
    }
    return (
      <Button
        type={type}
        title={btn.show === 'icon' ? btn.label : ''}
        style={style}
        icon={icon}
        className={className}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
  }
}
export default ExportPDF
src/tabviews/zshare/actionList/exportPdf/index.scss
src/tabviews/zshare/actionList/funczip/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button, Modal, notification, message, Progress } from 'antd'
import { Button, Modal, notification, message } from 'antd'
import JSZip from 'jszip'
import { saveAs } from 'file-saver'
@@ -10,7 +10,7 @@
import MKEmitter from '@/utils/events.js'
import MkIcon from '@/components/mk-icon'
import './index.scss'
// import './index.scss'
class FuncZip extends Component {
  static propTpyes = {
@@ -21,10 +21,7 @@
  state = {
    loading: false,
    disabled: false,
    loadingNumber: '',
    loadingTotal: '',
    hidden: false,
    visible: false
  }
  UNSAFE_componentWillMount () {
@@ -340,9 +337,7 @@
    const { btn } = this.props
    this.setState({
      loading: false,
      loadingNumber: '',
      loadingTotal: ''
      loading: false
    })
    
    if (btn.execSuccess !== 'never') {
@@ -361,9 +356,7 @@
    const { btn } = this.props
    this.setState({
      loading: false,
      loadingNumber: '',
      loadingTotal: ''
      loading: false
    })
    if (res.ErrCode === '01') {
@@ -411,7 +404,7 @@
  render() {
    const { btn } = this.props
    const { loading, disabled, hidden, loadingNumber, loadingTotal } = this.state
    const { loading, disabled, hidden } = this.state
    if (hidden) return null
@@ -439,10 +432,6 @@
      className = 'mk-btn mk-' + btn.class
    }
    
    if (loadingNumber && !loadingTotal && btn.$toolbtn && (!btn.show || btn.show === 'button')) {
      label = (loadingNumber && !loadingTotal ? `(${loadingNumber})` : '') + btn.label
    }
    return (
      <>
        <Button
@@ -455,7 +444,6 @@
          className={className}
          onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
        >{label}</Button>
        {loadingTotal ? <Progress className="mk-button-progress" percent={(loadingTotal - loadingNumber) / loadingTotal * 100} size="small" showInfo={false} /> : null}
      </>
    )
  }
src/tabviews/zshare/actionList/funczip/index.scss
@@ -1,26 +0,0 @@
.ip-list-modal {
  .ip-item {
    display: inline-block;
    border: 1px solid #d9d9d9;
    padding: 10px;
    height: 100px;
    width: calc(33% - 20px);
    margin: 10px;
    cursor: pointer;
    .ip {
      color: #000000;
    }
    .remark {
      word-break: break-all;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }
  }
  .ip-item.active {
    border-color: var(--mk-sys-color);
    box-shadow: 0 0 2px var(--mk-sys-color);
  }
}
src/tabviews/zshare/actionList/funczip/mock.js
File was deleted
src/tabviews/zshare/actionList/index.jsx
@@ -18,6 +18,8 @@
const FuncMegvii = asyncComponent(() => import('./funcMegvii'))
const FuncZip = asyncComponent(() => import('./funczip'))
const EditLine = asyncComponent(() => import('./editLine'))
const ExportPdf = asyncComponent(() => import('./exportPdf'))
const ShareLink = asyncComponent(() => import('./shareLink'))
class ActionList extends Component {
  static propTpyes = {
@@ -180,14 +182,30 @@
          return (
            <FuncZip
              key={item.uuid}
              show={item.show || 'actionList'}
              disabled={false}
              BID={BID}
              btn={item}
              BData={BData}
              setting={setting}
              selectedData={selectedData}
            />
          )
        } else if (item.funcType === 'expPdf') {
          return (
            <ExportPdf
              key={item.uuid}
              btn={item}
            />
          )
        } else if (item.funcType === 'shareLink') {
          return (
            <ShareLink
              key={item.uuid}
              BID={BID}
              btn={item}
              selectedData={selectedData}
            />
          )
        } else if (item.funcType === 'addline' || item.funcType === 'delline') {
          return (
            <EditLine
src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -128,6 +128,13 @@
        duration: 5
      })
      return
    } else if (btn.pageTemplate === 'custom' && window.GLOB.systemType === 'production' && !btn.proUrl) {
      notification.warning({
        top: 92,
        message: '尚未设置正式系统链接地址!',
        duration: 5
      })
      return
    } else if (!btn.pageTemplate) {
      notification.warning({
        top: 92,
@@ -195,7 +202,7 @@
      window.open(url)
    } else if (btn.pageTemplate === 'custom') {
      let url = btn.url
      if (window.GLOB.systemType === 'production' && btn.proUrl) {
      if (window.GLOB.systemType === 'production') {
        url = btn.proUrl
      }
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -1124,6 +1124,12 @@
      if (btn.intertype === 'system') {
        params = this.getSystemParam(data, formdata)
        if (btn.returnValue === 'true') {
          params = params.map(item => {
            item.script_type = 'Y'
            return item
          })
        }
      } else {
        params = this.getInnerParam(data, formdata)
      }
@@ -1295,7 +1301,7 @@
      return
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$innerScript, 'inner').then(res => {
      record.mk_api_key = res.mk_api_key || ''
      if (res.status) {
@@ -1535,7 +1541,7 @@
      param.menuname = param.menuname + '(回调)'
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$callbackScript, 'callback').then(res => {
      if (res.status) {
        this.triggerNote(res, param.ID) // 消息
@@ -1892,7 +1898,7 @@
      return
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$innerScript, 'inner').then(res => {
      if (res.status) {
        if ((res.mk_ex_invoke === 'false' || res.mk_ex_invoke === false) && params.length === 0) {
          this.execSuccess(res)
@@ -1990,7 +1996,7 @@
      }
    }
    Api.genericInterface(result).then(res => {
    Api.genericInterface(result, btn.$outerScript, 'outer').then(res => {
      if (!res) return // LoginError时中断请求
      if (ver_token && res.ErrCode === 'token_error') {
        res.ErrCode = 'E'
@@ -2053,11 +2059,14 @@
        func: btn.callbackFunc
      }
      // special 函数 s_sDataDictb_TBBack 云端验证
      if (window.GLOB.mkHS && param.func === 's_sDataDictb_TBBack' && param.LTextOut) {
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.secretkey = Utils.encrypt(param.LTextOut, param.timestamp)
        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
      if (window.GLOB.mkHS) {
        if (btn.callbackFunc === 's_sVersion_Local_add' && window.GLOB.forcedUpdate) { // special 传输号添加回调处理
          param.local_userid = sessionStorage.getItem('LocalUserID') || ''
        } else if (btn.callbackFunc === 's_sDataDictb_TBBack' && param.LTextOut) { // special 函数 s_sDataDictb_TBBack 云端验证
          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
          param.secretkey = Utils.encrypt(param.LTextOut, param.timestamp)
          param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
        }
      }
    } else {
      if (result.status) {
@@ -2079,7 +2088,7 @@
      param.menuname = param.menuname + '(回调)'
    }
    Api.genericInterface(param).then(res => {
    Api.genericInterface(param, btn.$callbackScript, 'callback').then(res => {
      if (res.status) {
        this.triggerNote(res, param.ID) // 消息
@@ -2223,7 +2232,19 @@
    const { autoMatic } = this.state
    if (btn.resetForms) {
      MKEmitter.emit('resetForms', btn.uuid)
      let data = {}
      Object.keys(res).forEach(key => {
        data[key.toLowerCase()] = res[key]
      })
      delete data.errcode
      delete data.errmesg
      delete data.message
      delete data.status
      MKEmitter.emit('resetForms', btn.uuid, data)
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'resetData', btn, null, null, data)
    }
    if (this.preCallback) {
@@ -2323,6 +2344,10 @@
      tabId = btn.refreshTab[btn.refreshTab.length - 1]
    }
    if (btn.formCache === 'clear') { // 清除表单缓存
      window.GLOB.CacheMap = new Map()
    }
    if (tabId && btn.$MenuID === tabId) { // 刷新当前菜单时,停止其他操作
      MKEmitter.emit('reloadMenuView', tabId, 'table')
      return
@@ -2354,7 +2379,14 @@
      } else if (/\$focus/.test(btn.syncComponentId)) {
        MKEmitter.emit('reloadData', btn.syncComponentId.split('$')[0], btn.syncComponentId.split('$')[1])
      } else {
        MKEmitter.emit('reloadData', btn.syncComponentId)
        if (btn.syncDelay) {
          this.delayTimer && clearTimeout(this.delayTimer)
          this.delayTimer = setTimeout(() => {
            MKEmitter.emit('reloadData', btn.syncComponentId)
          }, btn.syncDelay)
        } else {
          MKEmitter.emit('reloadData', btn.syncComponentId)
        }
      }
    }
src/tabviews/zshare/actionList/shareLink/index.jsx
New file
@@ -0,0 +1,193 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button, notification, message, Modal } from 'antd'
import md5 from 'md5'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import MkIcon from '@/components/mk-icon'
// import './index.scss'
class ShareLink extends Component {
  static propTpyes = {
    BID: PropTypes.string,
    btn: PropTypes.object,
    selectedData: PropTypes.any
  }
  state = {
    loading: false
  }
  componentDidMount () {
    MKEmitter.addListener('triggerBtnId', this.actionTrigger)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
  }
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId) => {
    const { btn, BID, selectedData } = this.props
    const { loading } = this.state
    if (loading) return
    if (triggerId && btn.uuid !== triggerId) return
    if (window.GLOB.systemType === 'production' && !btn.shareProUrl) {
      notification.warning({
        top: 92,
        message: '尚未设置正式系统链接地址!',
        duration: 5
      })
      return
    }
    let bid = BID || ''
    let id = ''
    if (selectedData && selectedData[0]) {
      id = selectedData[0].$$uuid || ''
    }
    let url = btn.shareUrl
    if (window.GLOB.systemType === 'production') {
      url = btn.shareProUrl
    }
    url = url.replace(/@BID@/ig, bid).replace(/@ID@/ig, id)
    if (btn.shortUrl === 'true') {
      this.setState({
        loading: true
      }, () => {
        this.getShortUrl(url)
      })
    } else {
      this.copyUrl(url)
    }
  }
  getShortUrl = (url) => {
    let _rduri = window.atob('aHR0cHM6Ly9lcGMubWs5aC5$mkjbi93ZWJhcGkvZG9zdGFycw=='.replace(/\$mk/ig, ''))
    let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
    let param = {
      func: 's_url_db_adduptdel',
      appkey: window.GLOB.appkey,
      userid: _id,
      LoginUID: _id,
      type: 'add_only',
      validity: 15,
      linkurl: url,
      nonc: '' + new Date().getTime(),
      id: md5(url + window.GLOB.appkey)
    }
    let keys = Object.keys(param).sort()
    let values = ''
    keys.forEach(key => {
      values += key + param[key]
    })
    param.sign = md5(values)
    param.t = new Date().getTime()
    Api.directRequest({
      url: _rduri + '/s_url_db_adduptdel',
      method: 'post',
      data: JSON.stringify(param)
    }).then(res => {
      this.setState({
        loading: false
      })
      if (res.status && res.id) {
        this.copyUrl('https://mk9h.cn/m.asp?m=' + res.id)
      } else {
        notification.warning({
          top: 92,
          message: res.message || '链接生成失败!',
          duration: 5
        })
      }
    }, () => {
      this.setState({
        loading: false
      })
    })
  }
  copyUrl = (url) => {
    const { btn } = this.props
    let oInput = document.createElement('input')
    oInput.value = url
    document.body.appendChild(oInput)
    oInput.select()
    document.execCommand('Copy')
    document.body.removeChild(oInput)
    if (btn.shareTip) {
      Modal.success({
        title: btn.shareTip
      })
    } else {
      message.success('已复制到剪切板。')
    }
  }
  render() {
    const { btn } = this.props
    const { loading } = this.state
    let label = ''
    let icon = ''
    let type = 'link'
    let className = ''
    let style = {...btn.style}
    if (btn.show === 'button') {
      label = btn.label
      icon = btn.icon || ''
    } else if (btn.show === 'link') {
      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
      icon = ''
    } else if (btn.show === 'icon') {
      icon = btn.icon || ''
    } else if (!btn.$toolbtn) {
      icon = btn.icon || ''
      label = btn.label
      className = 'mk-btn mk-' + btn.class
    } else {
      type = ''
      icon = btn.icon || ''
      label = btn.label
      className = 'mk-btn mk-' + btn.class
    }
    return (
      <Button
        type={type}
        title={btn.show === 'icon' ? btn.label : ''}
        style={style}
        loading={loading}
        icon={icon}
        className={className}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
  }
}
export default ShareLink
src/tabviews/zshare/actionList/shareLink/index.scss
copy from src/menu/components/group/paste/index.scss copy to src/tabviews/zshare/actionList/shareLink/index.scss
src/tabviews/zshare/mutilform/index.jsx
@@ -47,7 +47,8 @@
    send_type: '',
    timestamp: '',
    n_id: '',
    focusId: ''
    focusId: '',
    reFocusId: ''
  }
  record = {}
@@ -691,14 +692,24 @@
      focusItem = fieldMap.get(action.setting.focus)
    }
    this.setState({ formlist, ID, focusId: focusItem ? focusItem.uuid : '' }, () => {
    let reFocusItem = null
    if (action.setting.refocus && fieldMap.has(action.setting.refocus)) {
      reFocusItem = fieldMap.get(action.setting.refocus)
    }
    this.setState({
      formlist,
      ID,
      focusId: focusItem ? focusItem.uuid : '',
      reFocusId: reFocusItem ? reFocusItem.uuid : ''
    }, () => {
      if (unload) return
      
      if (focusItem) {
        if (focusItem.type === 'text' || focusItem.type === 'number') {
          setTimeout(() => {
            MKEmitter.emit('mkFC', 'focus', focusItem.uuid)
          }, 50)
          }, 20)
        } else {
          setTimeout(() => {
            MKEmitter.emit('mkFC', 'focus', focusItem.uuid)
@@ -733,9 +744,9 @@
    MKEmitter.removeListener('resetForms', this.resetForms)
  }
  resetForms = (id) => {
  resetForms = (id, data) => {
    const { action } = this.props
    const { focusId } = this.state
    const { focusId, reFocusId } = this.state
    if (id !== action.uuid) return
@@ -746,8 +757,14 @@
      if (item.type !== 'text' && item.type !== 'number') return item
      if (resetForms.includes(item.field)) {
        item.initval = item.orgval
        this.record[item.field] = item.orgval
        let key = item.field.toLowerCase()
        if (typeof(data[key]) !== 'undefined') {
          item.initval = data[key]
          this.record[item.field] = data[key]
        } else {
          item.initval = item.orgval
          this.record[item.field] = item.orgval
        }
      }
      return item
@@ -771,10 +788,10 @@
      })
    })
    if (focusId || this.submitId) {
    if (reFocusId || focusId || this.submitId) {
      setTimeout(() => {
        MKEmitter.emit('mkFC', 'focus', this.submitId || focusId)
      }, 50)
        MKEmitter.emit('mkFC', 'focus', this.submitId || reFocusId || focusId)
      }, 20)
    }
  }
@@ -1243,9 +1260,9 @@
          className = 'checkcard'
          content = (<MKCheckCard config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
        } else if (item.type === 'switch') {
          content = (<MKSwitch config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
          content = (<MKSwitch config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} onSubmit={this.props.inputSubmit}/>)
        } else if (item.type === 'check') {
          content = (<MKCheck config={item} onChange={(val) => this.recordChange({[item.field]: val}, item)}/>)
          content = (<MKCheck config={item} onChange={(val) => this.recordChange({[item.field]: val}, item)} onSubmit={this.props.inputSubmit}/>)
        } else if (item.type === 'checkbox') {
          content = (<MKCheckbox config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
        } else if (item.type === 'radio') {
src/tabviews/zshare/mutilform/mkCheck/index.jsx
@@ -2,6 +2,8 @@
import PropTypes from 'prop-types'
import { Checkbox } from 'antd'
import MKEmitter from '@/utils/events.js'
class MKCheck extends Component {
  static propTpyes = {
    config: PropTypes.object,
@@ -20,6 +22,21 @@
    } else {
      this.props.onChange(config.closeVal)
    }
    this.setState({}, () => {
      if (config.enter === 'tab') {
        MKEmitter.emit('mkFC', 'focus', config.tabUuid)
      } else if (config.enter === 'sub') {
        config.tabUuid && MKEmitter.emit('mkFC', 'focus', config.tabUuid)
        if (config.linkFields || config.subFields || config.controlFields) {
          setTimeout(() => {
            this.props.onSubmit(config.tabUuid)
          }, 1000)
        } else {
          this.props.onSubmit(config.tabUuid)
        }
      }
    })
  }
  componentWillUnmount () {
src/tabviews/zshare/mutilform/mkSwitch/index.jsx
@@ -33,6 +33,21 @@
    } else {
      this.props.onChange(config.closeVal, other)
    }
    this.setState({}, () => {
      if (config.enter === 'tab') {
        MKEmitter.emit('mkFC', 'focus', config.tabUuid)
      } else if (config.enter === 'sub') {
        config.tabUuid && MKEmitter.emit('mkFC', 'focus', config.tabUuid)
        if (config.linkFields || config.subFields || config.controlFields) {
          setTimeout(() => {
            this.props.onSubmit(config.tabUuid)
          }, 1000)
        } else {
          this.props.onSubmit(config.tabUuid)
        }
      }
    })
  }
  componentWillUnmount () {
src/tabviews/zshare/normalTable/index.jsx
@@ -655,7 +655,7 @@
      return (
        <div className="picture-col">
          {photos.map((url, i) => (<Col key={i} span={item.span || 24}>
            <MkPicture style={style} scale={scale} url={url} urls={photos}/>
            <MkPicture lostTip={item.lostTip !== 'false'} style={style} scale={scale} url={url} urls={photos}/>
          </Col>))}
        </div>
      )
src/tabviews/zshare/topSearch/index.jsx
@@ -25,8 +25,8 @@
class MainSearch extends Component {
  static propTpyes = {
    BID: PropTypes.any,          // 父级Id,用于查询下拉选择项
    config: PropTypes.object,    // 组件配置信息
    BID: PropTypes.any,
    config: PropTypes.object
  }
  state = {
@@ -121,6 +121,40 @@
        item.advanced = false
      }
      if (item.checkShift && !item.initval) {
        let d = ''
        if (window.GLOB.CacheData.has(item.$supId)) {
          d = window.GLOB.CacheData.get(item.$supId)
          d = d[item.dateShift] || ''
          if (d) {
            d = moment(d).format('YYYY-MM-DD')
            d = d === 'Invalid date' ? '' : d
          }
        }
        if (d) {
          if (item.type === 'daterange') {
            if (item.$initval === 'week') {
              item.initval = [moment(d).startOf('week').format(item.format), moment(d).endOf('week').format(item.format)].join(',')
            } else if (item.$initval === 'month') {
              item.initval = [moment(d).startOf('month').format(item.format), moment(d).endOf('month').format(item.format)].join(',')
            } else if (item.$initval === 'lastMonth') {
              item.initval = [moment(d).subtract(1, 'months').startOf('month').format(item.format), moment(d).subtract(1, 'months').endOf('month').format(item.format)].join(',')
            } else {
              try {
                let _initval = JSON.parse(item.$initval)
                let _vals = [moment(d).subtract(_initval[0], 'days').format(item.format), moment(d).subtract(_initval[1], 'days').format(item.format)]
                item.initval = _vals.join(',')
              } catch (e) {
                item.initval = ''
              }
            }
          } else {
            item.initval = moment(d).subtract(item.$initval, 'month').format('YYYY-MM')
          }
        }
      }
      if (item.type === 'group') {
        record[item.field] = item.initType
        record[item.datefield] = item.initval
@@ -144,24 +178,34 @@
        if (item.resourceType === '1' && item.dataSource) {
          let _option = Utils.getSelectQueryOptions(item)
          _option.sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
          let exec = true
          if (item.checkBid) {
            item.sql = _option.sql
            item.arr_field = _option.field
          if (window.GLOB.debugger === true) {
            console.info(_option.sql)
            exec = !!BID
          }
          // 测试系统单个请求
          if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && !window.GLOB.systemType) {
            deForms.push({
              ...item,
              arr_field: _option.field,
              data_sql: Utils.formatOptions(_option.sql)
            })
          } else { // 合并请求,区分本地及系统
            if (item.database === 'sso') {
              mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
            } else {
              localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
          if (exec) {
            _option.sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
            if (window.GLOB.debugger === true) {
              console.info(_option.sql)
            }
            // 测试系统单个请求
            if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && !window.GLOB.systemType) {
              deForms.push({
                ...item,
                arr_field: _option.field,
                data_sql: Utils.formatOptions(_option.sql)
              })
            } else { // 合并请求,区分本地及系统
              if (item.database === 'sso') {
                mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
              } else {
                localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
              }
            }
          }
        }
@@ -233,11 +277,84 @@
      searchlist: _list
    }, () => {
      if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
        this.improveSimpleSearch(deForms)
        this.improveSimpleSearch(deForms, false)
      } else if (mainItems.length > 0 || localItems.length > 0) {
        this.improveSearch(mainItems, localItems)
      }
    })
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { config, BID } = this.props
    if (config.checkBid && nextProps.BID !== BID) {
      this.resetOptions(nextProps.BID)
    }
  }
  resetOptions = (BID) => {
    let deForms = []
    let searchlist = fromJS(this.state.searchlist).toJS().map(item => {
      if (item.checkBid) {
        let sql = item.sql.replace(/@BID@/ig, `'${BID || ''}'`)
        if (window.GLOB.debugger === true) {
          console.info(sql)
        }
        deForms.push({
          ...item,
          arr_field: item.arr_field,
          data_sql: Utils.formatOptions(sql)
        })
      } else if (item.checkShift) {
        let d = ''
        if (window.GLOB.CacheData.has(item.$supId)) {
          d = window.GLOB.CacheData.get(item.$supId)
          d = d[item.dateShift] || ''
          if (d) {
            d = moment(d).format('YYYY-MM-DD')
            d = d === 'Invalid date' ? '' : d
          }
        }
        if (d) {
          if (item.type === 'daterange') {
            if (item.$initval === 'week') {
              item.initval = [moment(d).startOf('week').format(item.format), moment(d).endOf('week').format(item.format)].join(',')
            } else if (item.$initval === 'month') {
              item.initval = [moment(d).startOf('month').format(item.format), moment(d).endOf('month').format(item.format)].join(',')
            } else if (item.$initval === 'lastMonth') {
              item.initval = [moment(d).subtract(1, 'months').startOf('month').format(item.format), moment(d).subtract(1, 'months').endOf('month').format(item.format)].join(',')
            } else {
              try {
                let _initval = JSON.parse(item.$initval)
                let _vals = [moment(d).subtract(_initval[0], 'days').format(item.format), moment(d).subtract(_initval[1], 'days').format(item.format)]
                item.initval = _vals.join(',')
              } catch (e) {
                item.initval = ''
              }
            }
          } else {
            item.initval = moment(d).subtract(item.$initval, 'month').format('YYYY-MM')
          }
        }
      }
      return item
    })
    if (deForms.length > 0) {
      this.improveSimpleSearch(deForms, true, searchlist)
    } else {
      this.setState({
        searchlist: searchlist
      })
      setTimeout(() => {
        this.handleSubmit()
      }, 20)
    }
  }
  resetCheckcard = (item) => {
@@ -364,12 +481,12 @@
      delete result.message
      delete result.status
      this.resetSearch(result)
      this.resetSearch(result, false)
    })
  }
  // 测试系统单个请求下拉选项
  improveSimpleSearch = (deForms) => {
  improveSimpleSearch = (deForms, trigger, searchlist) => {
    if (deForms.length === 0) return
    let deffers = deForms.map((item, index) => {
@@ -421,13 +538,13 @@
      delete result.message
      delete result.status
      this.resetSearch(result)
      this.resetSearch(result, trigger, searchlist)
    })
  }
  resetSearch = (result) => {
    let trigger = false
    let _searchlist = fromJS(this.state.searchlist).toJS().map(item => {
  resetSearch = (result, submit, searchlist) => {
    let trigger = submit
    let _searchlist = fromJS(searchlist || this.state.searchlist).toJS().map(item => {
      if (['select', 'link', 'multiselect', 'checkcard', 'radio'].includes(item.type) && result[item.field] && result[item.field].length > 0) {
        let options = []
        let map = new Map()
@@ -492,9 +609,13 @@
        item.options = item.oriOptions
      }
      if (item.$first && item.options.length > 0) {
        item.initval = item.options[0].Value
        trigger = true
      if (item.$first) {
        if (item.options.length > 0) {
          item.initval = item.options[0].Value
          trigger = true
        } else {
          item.initval = ''
        }
      }
      return item
@@ -507,7 +628,7 @@
    if (trigger) {
      setTimeout(() => {
        this.handleSubmit()
      }, 10)
      }, 20)
    }
  }
@@ -567,7 +688,7 @@
      } else if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') {
        content = (<MKSelect config={item} onChange={(val, defer) => this.recordChange(val, defer, item)} />)
      } else if (item.type === 'date' || item.type === 'datemonth' || item.type === 'dateweek' || item.type === 'daterange') {
        content = (<MKDatePicker config={item} onChange={(val) => this.recordChange(val, false, item)} />)
        content = (<MKDatePicker config={item} onChange={(val, defer) => this.recordChange(val, defer, item)} />)
      } else if (item.type === 'group') {
        field = item.datefield
        content = <DateGroup position={index} config={item} onChange={(val, type) => this.dateGroupChange(val, type, item)} />
src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
@@ -15,28 +15,16 @@
    const config = props.config
    let mode = 'date'
    let format = 'YYYY-MM-DD'
    let format = config.format || 'YYYY-MM-DD'
    if (config.type === 'datemonth') {
      mode = 'month'
      format = 'YYYY-MM'
    } else if (config.type === 'week') {
      mode = 'week'
      format = 'YYYY-MM-DD'
    } else {
      if (config.type === 'daterange') {
        mode = 'daterange'
      }
      if (config.precision === 'day') {
        format = 'YYYY-MM-DD'
      } else if (config.precision === 'hour') {
        format = 'YYYY-MM-DD HH'
      } else if (config.precision === 'minute') {
        format = 'YYYY-MM-DD HH:mm'
      } else if (config.precision === 'second') {
        format = 'YYYY-MM-DD HH:mm:ss'
      }
    } else if (config.type === 'daterange') {
      mode = 'daterange'
    }
    let value = config.initval || null
    if (mode === 'daterange') {
@@ -62,6 +50,20 @@
    return !is(fromJS(this.state), fromJS(nextState))
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { config } = this.props
    if (config.checkShift && nextProps.config.initval && nextProps.config.initval !== config.initval) {
      let val = nextProps.config.initval.split(',')
      this.setState({
        value: [moment(val[0], config.format), moment(val[1], config.format)]
      })
      this.props.onChange(nextProps.config.initval, true)
    }
  }
  componentWillUnmount () {
    this.setState = () => {
      return
@@ -78,9 +80,9 @@
      if (_val && !_val[0]) {
        _val = ''
      }
      this.props.onChange(_val ? `${moment(_val[0]).format(format)},${moment(_val[1]).format(format)}` : '')
      this.props.onChange(_val ? `${moment(_val[0]).format(format)},${moment(_val[1]).format(format)}` : '', false)
    } else {
      this.props.onChange(val ? moment(val).format(format) : '')
      this.props.onChange(val ? moment(val).format(format) : '', false)
    }
  }
src/tabviews/zshare/topSearch/mkSelect/index.jsx
@@ -47,10 +47,12 @@
        options: fromJS(nextProps.config.options).toJS()
      })
      if (config.$first && nextProps.config.initval) {
      if (config.type !== 'multiselect') {
        this.setState({
          value: nextProps.config.initval
        })
        this.props.onChange(nextProps.config.initval, true)
      }
    }
  }
src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -302,17 +302,10 @@
        }
      } else if (_funcType === 'closetab') {
        shows.push('refreshTab')
      } else if (_funcType === 'megvii') {
        shows.push('subFunc', 'progress')
      } else if (_funcType === 'refund') {
        shows.push('Ot', 'execSuccess', 'execError')
        reOptions.Ot = requireOptions.filter(op => op.value === 'requiredSgl')
      } else if (_funcType === 'filezip') {
        reOptions.Ot = requireOptions
        reRequired.innerFunc = false
        shows.push('innerFunc', 'Ot', 'execSuccess', 'execError', 'urlkey')
      }
    }
src/templates/sharecomponent/actioncomponent/formconfig.jsx
@@ -119,12 +119,6 @@
      }, {
        value: 'closetab',
        text: '标签关闭'
      }, {
        value: 'megvii',
        text: '旷视面板机'
      }, {
        value: 'filezip',
        text: '文件压缩包'
      }]
    },
    { // 旷视面板机接口 待扩展
src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx
@@ -78,6 +78,10 @@
                  {
                    required: true,
                    message: '请输入字段!'
                  },
                  {
                    pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
                    message: '只允许包含数字、字母、汉字以及_'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleConfirm}/>)}
@@ -135,7 +139,7 @@
              )}
            </Form.Item>
          </Col>
          <Col span={6}>
          <Col span={6} style={{clear: 'left'}}>
            <Form.Item style={{marginBottom: 0}} label="导入">
              {getFieldDecorator('import', {
                initialValue: 'true'
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -59,6 +59,7 @@
        width: '15%',
        editable: true,
        inputType: 'select',
        keyCol: true,
        options: [
          { value: 'Nvarchar(10)', text: 'Nvarchar(10)' },
          { value: 'Nvarchar(20)', text: 'Nvarchar(20)' },
@@ -114,7 +115,10 @@
        required: false,
        inputType: 'number',
        unlimit: true,
        editable: true
        editable: true,
        keyVals: ['Int', 'Decimal(18,0)', 'Decimal(18,2)', 'Decimal(18,4)', 'Decimal(18,6)'],
        render: (text, record) => /^Decimal/ig.test(record.type) || /^int/ig.test(record.type) ? text : ''
      },
      {
        title: '最大值',
@@ -123,7 +127,9 @@
        required: false,
        inputType: 'number',
        unlimit: true,
        editable: true
        editable: true,
        keyVals: ['Int', 'Decimal(18,0)', 'Decimal(18,2)', 'Decimal(18,4)', 'Decimal(18,6)'],
        render: (text, record) => /^Decimal/ig.test(record.type) || /^int/ig.test(record.type) ? text : ''
      }
    ],
    uniqueColumns: [
@@ -447,6 +453,8 @@
      confirm({
        content: '部分字段名称与显示列不一致,是否更新?',
        okText: '更新',
        cancelText: '不更新',
        onOk() {
          _columns = _columns.map(item => {
            let key = item.Column.toLowerCase()
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
@@ -76,6 +76,9 @@
        width: 89.5%;
      }
    }
    .ant-form-explain {
      white-space: nowrap;
    }
  }
  .custom-table .ant-empty {
    margin: 20px 8px!important;
src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx
@@ -46,6 +46,10 @@
                  {
                    required: true,
                    message: '请输入字段!'
                  },
                  {
                    pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
                    message: '只允许包含数字、字母、汉字以及_'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleConfirm}/>)}
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -67,6 +67,7 @@
        inputType: 'select',
        editable: true,
        required: false,
        keyCol: true,
        width: '12%',
        render: (text) => {
          if (text === 'image') {
@@ -82,38 +83,6 @@
          {value: 'number', text: '数值'},
          {value: 'image', text: '图片'}
        ]
      },
      {
        title: '取绝对值',
        dataIndex: 'abs',
        inputType: 'radio',
        editable: true,
        required: false,
        width: '12%',
        render: (text, record) => {
          if (record.type !== 'number') return ''
          if (text === 'true') {
            return '是'
          } else {
            return '否'
          }
        },
        options: [
          {value: 'true', text: '是'},
          {value: 'false', text: '否'}
        ]
      },
      {
        title: '小数位',
        dataIndex: 'decimal',
        inputType: 'number',
        min: 0,
        max: 18,
        editable: true,
        required: false,
        width: '12%',
        render: (text, record) => record.type === 'number' ? text : ''
      },
      {
        title: '导出',
@@ -146,6 +115,40 @@
          {value: 'false', text: '否'}
        ]
      },
      {
        title: '取绝对值',
        dataIndex: 'abs',
        inputType: 'radio',
        editable: true,
        required: false,
        keyVals: ['number'],
        width: '12%',
        render: (text, record) => {
          if (record.type !== 'number') return ''
          if (text === 'true') {
            return '是'
          } else {
            return '否'
          }
        },
        options: [
          {value: 'true', text: '是'},
          {value: 'false', text: '否'}
        ]
      },
      {
        title: '小数位',
        dataIndex: 'decimal',
        inputType: 'number',
        min: 0,
        max: 18,
        editable: true,
        required: false,
        keyVals: ['number'],
        width: '12%',
        render: (text, record) => record.type === 'number' ? text : ''
      }
    ],
    scriptsColumns: [
      {
@@ -528,6 +531,13 @@
      if (card.intertype === 'system' && verify.dataType !== 'custom' && verify.columns.length > 0 && config.$c_ds && config.setting.interType === 'system' && config.columns && config.columns.length > 0) {
        let cols = []
        let columns = config.columns.map(c => c.field)
        if (config.subtype === 'dualdatacard' && config.subColumns) {
          config.subColumns.forEach(item => {
            columns.push(item.field)
          })
        }
        verify.columns.forEach(col => {
          if (col.output === 'false' || col.Column === '$Index') return
          if (!columns.includes(col.Column)) {
@@ -710,6 +720,8 @@
      confirm({
        content: '部分字段名称与显示列不一致,是否更新?',
        okText: '更新',
        cancelText: '不更新',
        onOk() {
          columns = columns.map(item => {
            let key = item.Column.toLowerCase()
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss
@@ -79,6 +79,9 @@
    .add {
      padding-top: 4px;
    }
    .ant-form-explain {
      white-space: nowrap;
    }
  }
  .custom-table .ant-empty {
    margin: 20px 8px!important;
src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
@@ -40,7 +40,7 @@
      }
    })
    let declare = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''`
    let declare = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''`
    if (verify.defaultSql === 'false') {
      _dataresource = ''
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -26,7 +26,6 @@
class VerifyCard extends Component {
  static propTpyes = {
    floor: PropTypes.any,      // 是否为子表
    btnTab: PropTypes.any,     // 表单标签页(按钮)参数
    config: PropTypes.any,     // 表单标签页参数
    card: PropTypes.object,
    columns: PropTypes.array
@@ -399,12 +398,16 @@
  }
  changeTemplate = (val) => {
    const { templates } = this.state
    const { templates, verify } = this.state
    let temp = templates.filter(temp => temp.value === val)[0]
    this.setState({
      selectimg: temp.img
      selectimg: temp.img,
      verify: {
        ...verify,
        Template: val
      }
    })
  }
@@ -854,7 +857,19 @@
                  </Form.Item>
                </Col> : null}
                {printMode !== 'custom' ? <Col span={8}>
                  <Form.Item label="打印模板">
                  <Form.Item label="打印模板" help={(() => {
                      if (verify.Template) {
                        return <span onClick={() => {
                          sessionStorage.setItem('mk-print-tab-temp', verify.Template)
                          window.open('#/hs')
                          setTimeout(() => {
                            sessionStorage.removeItem('mk-print-tab-temp')
                          }, 50)
                        }} style={{color: '#1890ff', cursor: 'pointer', fontSize: '13px'}}>#查看模板</span>
                      }
                      return null
                    })()}>
                    {getFieldDecorator('Template', {
                      initialValue: verify.Template || '',
                      rules: [
src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
@@ -20,7 +20,8 @@
    })
    if (_customScript) {
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${declareSql}
        ${_customScript}
      `
@@ -72,7 +73,8 @@
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'1949-10-01 15:00:00'
      `
    } else if (_tailScript) {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${declareSql}
        ${_dataresource}
        ${_tailScript}
@@ -81,7 +83,8 @@
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'1949-10-01 15:00:00' 
      `
    } else {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${declareSql}
        ${_dataresource}`
    }
src/templates/sharecomponent/cardcomponent/formconfig.jsx
@@ -48,14 +48,14 @@
      required: false,
      options: equalTabs
    },
    {
      type: 'text',
      key: 'foreignKey',
      label: '外键',
      tooltip: '外键旨在标签页中执行默认函数(添加)时,替换BID字段',
      initVal: card.foreignKey || '',
      required: false
    },
    // {
    //   type: 'text',
    //   key: 'foreignKey',
    //   label: '外键',
    //   tooltip: '外键旨在标签页中执行默认函数(添加)时,替换BID字段',
    //   initVal: card.foreignKey || '',
    //   required: false
    // },
    {
      type: 'number',
      key: 'level',
src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -240,6 +240,10 @@
      }
      shows.push('linkField')
      reRequired.linkField = false
    } else if (type === 'daterange' || type === 'datemonth') {
      if (this.record.initval) {
        shows.push('dateShift')
      }
    }
    if (dateOptions.hasOwnProperty(type)) { // 根据搜索条件类型,选择初始值的类型及数据
@@ -509,7 +513,7 @@
        rules = [
          { required: item.required, message: '请输入' + item.label + '!' }
        ]
        if (item.key === 'field' || item.key === 'datefield') {
        if (item.key === 'field' || item.key === 'datefield' || item.key === 'dateShift') {
          rules.push({
            pattern: (type === 'text' || type === 'select' || type === 'daterange') ? formRule.field.multipattern : formRule.field.pattern,
            message: formRule.field.message
src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
@@ -16,7 +16,8 @@
    })
    if (_customScript) {
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_customScript}
      `
    }
@@ -108,7 +109,8 @@
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'1949-10-01 15:00:00'
      `
    } else {
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
      sql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
        select @ErrorCode='',@retmsg ='',@UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
        ${_dataresource}`
    }
src/templates/sharecomponent/tabscomponent/formconfig.jsx
@@ -48,14 +48,14 @@
      required: false,
      options: equalTabs
    },
    {
      type: 'text',
      key: 'foreignKey',
      label: '外键',
      tooltip: '外键旨在标签页中执行默认函数(添加)时,替换BID字段',
      initVal: card.foreignKey || '',
      required: false
    },
    // {
    //   type: 'text',
    //   key: 'foreignKey',
    //   label: '外键',
    //   tooltip: '外键旨在标签页中执行默认函数(添加)时,替换BID字段',
    //   initVal: card.foreignKey || '',
    //   required: false
    // },
    {
      type: 'number',
      key: 'level',
src/templates/sharecomponent/tabscomponent/tabform/index.jsx
@@ -117,12 +117,6 @@
      if (item.type === 'text') {
        let rules = []
        if (item.key === 'foreignKey') {
          rules.push({
            pattern: /^[a-zA-Z_]*$/ig,
            message: item.label + '字段只允许包含字母及下划线!'
          })
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={
src/templates/zshare/codemirror/index.jsx
@@ -144,6 +144,8 @@
      _sql = _sql.replace(item.id, item.value)
    })
    _sql = _sql.replace(/,\n\s*/g, ',')
    this.setState({display: false, defaultVal: _sql}, () => {
      this.setState({display: true})
    })
src/templates/zshare/editTable/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Input, InputNumber, Popconfirm, Switch, Form, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd'
import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined, PlusOutlined } from '@ant-design/icons'
import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined, PlusOutlined, ConsoleSqlOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import ColorSketch from '@/mob/colorsketch'
@@ -123,7 +123,7 @@
class EditableCell extends Component {
  getInput = (form) => {
    const { inputType, options, min, max, unlimit, allowClear } = this.props
    const { inputType, options, min, max, unlimit, allowClear, typeChange } = this.props
    if (inputType === 'number' && unlimit) {
      return <InputNumber onPressEnter={() => this.getValue(form)} />
@@ -137,7 +137,7 @@
      return <CusSwitch />
    } else if (inputType === 'select') {
      return (
        <Select>
        <Select onChange={typeChange}>
          {options.map((item, i) => (<Select.Option key={i} value={item.field || item.value}> {item.label || item.text} </Select.Option>))}
        </Select>
      )
@@ -176,11 +176,18 @@
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const { editing, dataIndex, title, record, children, className, required, inputType, rules } = this.props
    const { editing, pass, dataIndex, title, record, children, className, required, inputType, rules } = this.props
    if (!editing) {
      return (
        <td className={className}>
          {children}
        </td>
      )
    }
    return (
      <td className={className}>
        {editing ? (
        {pass ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              rules: [
@@ -194,7 +201,7 @@
            })(this.getInput(form))}
          </Form.Item>
        ) : (
          children
          null
        )}
      </td>
    )
@@ -218,7 +225,9 @@
    data: [],
    editingKey: '',
    editLineId: '',
    columns: []
    columns: [],
    keyCol: null,
    keyVal: ''
  }
  UNSAFE_componentWillMount () {
@@ -226,6 +235,7 @@
    let columns = fromJS(this.props.columns).toJS()
    let operation = null
    let extra = null
    let keyCol = null
    
    if (actions) {
      actions.forEach(item => {
@@ -237,9 +247,17 @@
    if (actions && (actions.includes('edit') || actions.includes('copy') || actions.includes('del'))) {
      let _operation = null
      let render = null
      columns = columns.filter(item => {
        if (item.dataIndex === 'operation') {
          _operation = item
        }
        if (item.keyCol) {
          keyCol = item.dataIndex
        }
        if (item.dataIndex === 'sqlRender') {
          render = item.render
          return false
        }
        return item.dataIndex !== 'operation'
      })
@@ -271,7 +289,7 @@
            </div>
          ) : (
            <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px', whiteSpace: 'nowrap'}}>
              {actions.includes('edit') ? <span className="primary" title="编辑" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><EditOutlined /></span> : null}
              {actions.includes('edit') ? <span className="primary" title="编辑" onClick={() => {editingKey === '' && this.edit(record)}}><EditOutlined /></span> : null}
              {extra ? <span className="status" title={extra[2]} onClick={() => {editingKey === '' && this.handleStatus(record, extra[1])}}><SwapOutlined /></span> : null}
              {actions.includes('status') ? <span className="status" title="是否启用" onClick={() => {editingKey === '' && this.handleStatus(record, 'status')}}><SwapOutlined /></span> : null}
              {actions.includes('copy') ? <span className="copy" title="复制" onClick={() => {editingKey === '' && this.copy(record)}}><CopyOutlined /></span> : null}
@@ -279,10 +297,11 @@
                overlayClassName="popover-confirm"
                title="确定删除吗?"
                onConfirm={() => this.handleDelete(record.uuid)
              }>
                }>
                <span className="danger"><DeleteOutlined /></span>
              </Popconfirm> : null}
              {actions.includes('del') && editingKey !== '' ? <span className="danger"><DeleteOutlined /></span> : null}
              {actions.includes('sql') ? <span className="primary" title="SQL" onClick={() => {editingKey === '' && this.showSql(record, render)}}><ConsoleSqlOutlined /></span> : null}
            </div>
          )
        }
@@ -298,7 +317,8 @@
    this.setState({
      data: data || [],
      operation,
      columns
      columns,
      keyCol
    })
  }
@@ -338,6 +358,20 @@
      return
    }
    MKEmitter.removeListener('editLineId', this.getEditLineId)
  }
  showSql = (record, render) => {
    let list = render(record)
    if (list) {
      Modal.info({
        title: '',
        width: 500,
        className: 'sql-example',
        icon: null,
        content: list.map((n, index) => <div key={index} dangerouslySetInnerHTML={{ __html: n }}></div>)
      })
    }
  }
  getEditLineId = (id) => {
@@ -719,8 +753,14 @@
    })
  }
  edit(uuid) {
    this.setState({ editingKey: uuid })
  edit(record) {
    const { keyCol } = this.state
    this.setState({ editingKey: record.uuid, keyVal: keyCol ? record[keyCol] : '' })
  }
  typeChange = (val) => {
    this.setState({ keyVal: val })
  }
  moveRow = (dragIndex, hoverIndex) => {
@@ -771,7 +811,7 @@
  render() {
    const { actions, indexShow, searchKey } = this.props
    const { editLineId } = this.state
    const { editLineId, keyVal } = this.state
    let components = {
      body: {
@@ -790,7 +830,9 @@
      if (col.copy) {
        col.render = (text) => (<Paragraph copyable>{text}</Paragraph>)
      }
      if (!col.editable) return col
      return {
        ...col,
        onCell: record => ({
@@ -804,9 +846,12 @@
          unlimit: col.unlimit,
          required: col.required !== false ? true : false,
          allowClear: col.allowClear === true,
          keyCol: col.keyCol === true,
          title: col.title,
          editing: this.isEditing(record),
          pass: col.keyVals ? col.keyVals.includes(keyVal) : true,
          onSave: this.onSave,
          typeChange: this.typeChange,
        }),
      }
    })
src/templates/zshare/editTable/index.scss
@@ -127,3 +127,10 @@
  }
}
.ant-modal.ant-modal-confirm.ant-modal-confirm-info.sql-example {
  top: 100px;
  .ant-modal-body {
    padding: 24px;
  }
}
src/templates/zshare/formconfig.jsx
@@ -467,6 +467,15 @@
      forbid: appType === 'mob'
    },
    {
      type: 'text',
      key: 'dateShift',
      label: '日期偏移',
      initVal: card.dateShift || '',
      tooltip: '可以填入上级字段,用于控制初始值,例如:上级字段值为2023-12-10,初始值为本月,则初始区间为 2023-12-01 ~ 2023-12-31。',
      required: false,
      forbid: appType === 'mob'
    },
    {
      type: 'radio',
      key: 'precision',
      label: '精确度',
@@ -2331,6 +2340,23 @@
    },
    {
      type: 'radio',
      key: 'mkfocus',
      label: '聚焦时',
      initVal: card.mkfocus || 'def',
      options: [{
        value: 'def',
        text: '默认'
      }, {
        value: 'check',
        text: '全选'
      }, {
        value: 'clear',
        text: '清空'
      }],
      forbid: appType !== 'mob'
    },
    {
      type: 'radio',
      key: 'sendType',
      label: '发送方式',
      initVal: card.sendType || 'local',
@@ -2535,7 +2561,7 @@
      key: 'enter',
      label: '回车事件',
      initVal: (card.type === 'text' || card.type === 'number') ? (card.enter || 'sub') : (card.enter || 'false'),
      tooltip: '点击Enter键,或文本类表单输入回车符。',
      tooltip: '1、点击Enter键或文本类表单输入回车符;2、下拉选择或开关的选项切换。',
      options: [{
        value: 'sub',
        text: '提交'
src/templates/zshare/modalform/index.jsx
@@ -20,8 +20,8 @@
const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
const modalTypeOptions = {
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom'],
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant', 'mkfocus'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom', 'mkfocus'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
@@ -29,8 +29,8 @@
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'marginTop', 'marginBottom', 'dropdown'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkField', 'linkSubField', 'span', 'place', 'labelwidth', 'tooltip', 'extra', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  fileupload: ['readonly', 'required', 'hidden', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'compress', 'miniSet', 'splitline', 'marginTop', 'marginBottom', 'maxSize'],
  switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom'],
  check: ['initval', 'openVal', 'closeVal', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom', 'checkTip'],
  switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'enter', 'splitline', 'marginTop', 'marginBottom'],
  check: ['initval', 'openVal', 'closeVal', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'splitline', 'marginTop', 'marginBottom', 'checkTip'],
  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline', 'place', 'marginTop', 'marginBottom', 'minDate', 'maxDate', 'precision'],
  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'place', 'marginTop', 'marginBottom'],
  // datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline', 'marginTop', 'marginBottom', 'minDate', 'maxDate'],
@@ -254,6 +254,9 @@
        }
      }
    } else if (type === 'switch' || type === 'check') {
      if (this.record.enter === 'tab' || this.record.enter === 'sub') {
        shows.push('tabField')
      }
      reOptions.initval = [
        {value: true, text: '开'},
        {value: false, text: '关'}
src/templates/zshare/verifycard/baseform/index.jsx
@@ -137,7 +137,7 @@
    } else if (verify.accountdate === 'true' && !verify.accountfield) {
      error = '开启账期时,需要选择验证公司!'
    } else if (verify.preHandle === 'true' && !verify.pre_func) {
      error = '开启按钮预处理时,需要填写处理函数!'
      error = '开启自定义脚本时,需要填写处理函数!'
    } else if (verify.wxNote === 'true') {
      if (!verify.wxTemplateId) {
        error = '开启公众号消息推送时,需要选择消息模板!'
@@ -697,9 +697,9 @@
          <Col span={24}></Col>
          <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topRight" title="运行时修改按钮参数,入参为(btn, systemType)。注:systemType为系统类型,正式系统为production">
              <Tooltip placement="topRight" title="运行时修改按钮参数,入参为(btn, position, systemType),标记#position-(init,inner,outer,callback)">
                <QuestionCircleOutlined className="mk-form-tip" />
                按钮预处理
                自定义脚本
              </Tooltip>
            }>
              <Radio.Group value={verify.preHandle || 'false'} onChange={(e) => {this.onOptionChange(e.target.value, 'preHandle')}}>
src/templates/zshare/verifycard/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Tabs, Row, Col, Button, Popconfirm, notification, Modal, message, InputNumber, Typography } from 'antd'
import { CheckCircleOutlined, StopOutlined, EditOutlined, SwapOutlined, DeleteOutlined, ExclamationOutlined } from '@ant-design/icons'
import { CheckCircleOutlined, StopOutlined, EditOutlined, SwapOutlined, DeleteOutlined, ExclamationOutlined, ConsoleSqlOutlined } from '@ant-design/icons'
import Toast from 'antd-mobile/es/components/toast'
import Dialog from 'antd-mobile/es/components/dialog'
import moment from 'moment'
@@ -18,7 +18,7 @@
import BillcodeForm from './billcodeform'
import VoucherForm from './voucherform'
import asyncComponent from '@/utils/asyncComponent'
import { updateForm } from '@/utils/utils-update.js'
// import { updateForm } from '@/utils/utils-update.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
@@ -30,7 +30,6 @@
class VerifyCard extends Component {
  static propTpyes = {
    btnTab: PropTypes.any,     // 表单标签页(按钮)参数
    config: PropTypes.any,     // 表单标签页参数
    card: PropTypes.object,    // 按钮信息
    columns: PropTypes.array
@@ -114,6 +113,34 @@
              <CheckCircleOutlined style={{marginLeft: '5px'}}/>
            </div>
          )
      },
      {
        dataIndex: 'sqlRender',
        render: (record) => {
          let _fieldValue = []
          let _value = []
          let _labels = record.fieldlabel.split(',')
          record.field.split(',').forEach((_field, index) => {
            let _key = _field.toLowerCase()
            _fieldValue.push(`${_key}=${_key === 'bid' ? '@BID@' : ''}`)
            _value.push(`${_labels[index] || ''}:xxx`)
          })
          let _verifyType = ''
          if (record.verifyType === 'logic') {
            _verifyType = ' and deleted=0'
          }
          let sql = `select @tbid='', @ErrorCode='',@retmsg=''
          select @tbid='X' from ${this.props.card.sql} where ${_fieldValue.join(' and ')}${_verifyType}
          If @tbid!=''
          Begin
            select @ErrorCode='${record.errorCode}',@retmsg='${_value.join(', ')} 已存在'
            goto aaa
          end`
          return sql.split(/\n\s{10}/ig).map(n => n.replace(/^\s{2}/ig, '&nbsp;&nbsp;'))
        }
      }
    ],
    onceUniqueColumns: [
@@ -151,6 +178,27 @@
            </div>
          )
      },
      {
        dataIndex: 'sqlRender',
        render: (record) => {
          let primaryKey = 'id'
          if (this.props.config && this.props.config.setting && this.props.config.setting.primaryKey) {
            primaryKey = this.props.config.setting.primaryKey
          }
          let sql = `Set @tbid=''
          Select top 1 @tbid='X' from (select distinct ${record.field},1 as n from (数据源) tb inner join (select ID from  dbo.SplitComma(@ID@)) sp on tb.${primaryKey}=sp.ID ) a having sum(n)>1
          If @tbid!=''
          Begin
            Set @ErrorCode='E' Set @retmsg='${record.fieldlabel} 值不唯一'
            goto aaa
          end`
          return sql.split(/\n\s{10}/ig).map(n => n.replace(/^\s{2}/ig, '&nbsp;&nbsp;'))
        }
      }
    ],
    contrastColumns: [
      {
@@ -163,7 +211,7 @@
      {
        title: '运算符',
        dataIndex: 'operator',
        width: '14%',
        width: '13%',
        editable: true,
        inputType: 'select',
        options: [
@@ -187,14 +235,14 @@
      {
        title: '提示信息',
        dataIndex: 'errmsg',
        width: '14%',
        width: '13%',
        inputType: 'input',
        editable: true
      },
      {
        title: '报错编码',
        dataIndex: 'errorCode',
        width: '14%',
        width: '13%',
        editable: true,
        inputType: 'select',
        options: [
@@ -224,6 +272,18 @@
              <CheckCircleOutlined style={{marginLeft: '5px'}}/>
            </div>
          )
      },
      {
        dataIndex: 'sqlRender',
        render: (record) => {
          let sql = `If ${record.frontfield} ${record.operator} ${record.backfield}
          Begin
            select @ErrorCode='${record.errorCode}',@retmsg='${record.errmsg}'
            goto aaa
          end`
          return sql.split(/\n\s{10}/ig).map(n => n.replace(/^\s{2}/ig, '&nbsp;&nbsp;'))
        }
      }
    ],
    customColumns: [
@@ -530,13 +590,14 @@
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
            </Popconfirm>
            <span className="operation-btn" title="SQL" onClick={() => this.orderSql(record)} style={{color: '#1890ff'}}><ConsoleSqlOutlined /></span>
          </div>)
      }
    ]
  }
  UNSAFE_componentWillMount() {
    const { columns, config, card, btnTab } = this.props
    const { columns, config, card } = this.props
    const { appType } = this.state
    let _verify = fromJS(card.verify || {}).toJS()
@@ -641,105 +702,131 @@
      oriVerify: fromJS(_verify).toJS()
    })
    if (card.intertype === 'inner') {
      return
    if (card.intertype === 'inner') return
    let _fields = []
    if (card.OpenType === 'form') {
      _fields.push({
        field: card.field,
        label: card.label,
        type: 'text'
      })
    } else if (card.modal && (card.OpenType === 'pop' || !card.OpenType)) {
      _fields = card.modal.fields || []
    }
    new Promise(resolve => {
      let _fields = []
      if (card.OpenType === 'form') {
        _fields.push({
          field: card.field,
          label: card.label,
          type: 'text'
        })
        resolve(_fields)
      } else if (card.modal && (card.OpenType === 'pop' || !card.OpenType)) {
        _fields = card.modal.fields || []
        resolve(_fields)
      } else if (card.OpenType === 'pop') {
        Api.getCloudConfig({
          func: 'sPC_Get_LongParam',
          MenuID: card.uuid
        }).then(res => {
          if (res.status) {
            let _LongParam = ''
            if (res.LongParam) {
              try {
                _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
              } catch (e) {
                console.warn('Parse Failure')
                _LongParam = ''
              }
            }
            if (!_LongParam) {
              message.warning('未获取到表单信息,部分验证将无法设置!')
            } else {
              _LongParam = updateForm(_LongParam)
              _fields = _LongParam.fields || []
            }
          } else {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 5
            })
          }
          resolve(_fields)
        })
    let _usefulfields = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode', 'tbid', 'mk_deleted']
    let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@RoleID nvarchar(512)', '@mk_departmentcode nvarchar(512)', '@mk_organization nvarchar(512)', '@mk_user_type nvarchar(20)', '@mk_nation nvarchar(50)', '@mk_province nvarchar(50)', '@mk_city nvarchar(50)', '@mk_district nvarchar(50)', '@mk_address nvarchar(100)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)', '@bid nvarchar(50)', '@tbid nvarchar(50)', '@mk_deleted int']
    let _select = ['@UserName=\'\'', '@FullName=\'\'', '@RoleID=\'\'', '@mk_departmentcode=\'\'', '@mk_organization=\'\'', '@mk_user_type=\'\'', '@mk_nation=\'\'', '@mk_province=\'\'', '@mk_city=\'\'', '@mk_district=\'\'', '@mk_address=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'', '@bid=\'\'', '@mk_deleted=1']
    let fieldArr = _usefulfields.map(_f => _f.toLowerCase())
    let hasBid = false
    _usefulfields = []
    fieldArr.push('bid')
    let verIndex = _fields.findIndex(item => item.type === 'vercode')
    if (verIndex > -1) {
      _fields = fromJS(_fields).toJS()
      _fields.splice(verIndex, 0, {
        type: 'text',
        fieldlength: 50,
        writein: 'false',
        field: 'mk_timestamp'
      }, {
        type: 'text',
        fieldlength: 50,
        writein: 'false',
        field: 'mk_send_type'
      }, {
        type: 'text',
        fieldlength: 50,
        writein: 'false',
        field: 'mk_n_id'
      })
    }
    _fields = _fields.filter(_f => _f.field)
    _fields.forEach(_f => {
      if (_f.field.toLowerCase() === 'bid') {
        hasBid = true
      }
      if (fieldArr.includes(_f.field.toLowerCase())) return
      fieldArr.push(_f.field.toLowerCase())
      _usefulfields.push(_f.field)
      let _fieldlen = _f.fieldlength || 50
      if (_f.type === 'number') {
        _fieldlen = _f.decimal ? _f.decimal : 0
      }
      if (_fieldlen > 4000) {
        _fieldlen = 'max'
      }
      let _type = `nvarchar(${_fieldlen})`
      if (_f.type.match(/date/ig)) {
        _type = 'datetime'
        _select.push(`@${_f.field}='1949-10-01'`)
      } else if (_f.type === 'number') {
        _type = `decimal(18,${_fieldlen})`
        _select.push(`@${_f.field}=0`)
      } else if (_f.declare === 'decimal') {
        _type = `decimal(18,${_f.decimal || 0})`
        _select.push(`@${_f.field}=0`)
      } else if (_f.type === 'rate') {
        _type = `decimal(18,2)`
        _select.push(`@${_f.field}=0`)
      } else {
        resolve(_fields)
      }
    }).then(_fields => {
      let _usefulfields = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode', 'tbid', 'mk_deleted']
      let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@RoleID nvarchar(512)', '@mk_departmentcode nvarchar(512)', '@mk_organization nvarchar(512)', '@mk_user_type nvarchar(20)', '@mk_nation nvarchar(50)', '@mk_province nvarchar(50)', '@mk_city nvarchar(50)', '@mk_district nvarchar(50)', '@mk_address nvarchar(100)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)', '@bid nvarchar(50)', '@tbid nvarchar(50)', '@mk_deleted int']
      let _select = ['@UserName=\'\'', '@FullName=\'\'', '@RoleID=\'\'', '@mk_departmentcode=\'\'', '@mk_organization=\'\'', '@mk_user_type=\'\'', '@mk_nation=\'\'', '@mk_province=\'\'', '@mk_city=\'\'', '@mk_district=\'\'', '@mk_address=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'', '@bid=\'\'', '@mk_deleted=1']
      let fieldArr = _usefulfields.map(_f => _f.toLowerCase())
      let hasBid = false
      _usefulfields = []
      fieldArr.push('bid')
      let verIndex = _fields.findIndex(item => item.type === 'vercode')
      if (verIndex > -1) {
        _fields = fromJS(_fields).toJS()
        _fields.splice(verIndex, 0, {
          type: 'text',
          fieldlength: 50,
          writein: 'false',
          field: 'mk_timestamp'
        }, {
          type: 'text',
          fieldlength: 50,
          writein: 'false',
          field: 'mk_send_type'
        }, {
          type: 'text',
          fieldlength: 50,
          writein: 'false',
          field: 'mk_n_id'
        })
        _select.push(`@${_f.field}=''`)
      }
      _fields = _fields.filter(_f => _f.field)
      _fields.forEach(_f => {
        if (_f.field.toLowerCase() === 'bid') {
          hasBid = true
      _declare.push(`@${_f.field} ${_type}`)
    })
    let uniqueFields = fromJS(_fields).toJS()
    if (!hasBid) { // 唯一性验证添加BID
      uniqueFields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
      _fields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
    }
    let unionFields = fromJS(_fields).toJS()
    let formArr = _fields.map(_f => _f.field.toLowerCase())
    if (card.Ot !== 'notRequired' && columns) {
      columns.forEach(_f => {
        if (!_f.field) return
        let key = _f.field.toLowerCase()
        if (!formArr.includes(key)) {
          formArr.push(key)
          unionFields.push(_f)
        }
        if (fieldArr.includes(_f.field.toLowerCase())) return
        if (fieldArr.includes(key)) return
        fieldArr.push(_f.field.toLowerCase())
        fieldArr.push(key)
        _usefulfields.push(_f.field)
        let _fieldlen = _f.fieldlength || 50
        if (_f.datatype) { // 自定义字段
          if (/decimal/ig.test(_f.datatype)) {
            _select.push(`@${_f.field}=0`)
          } else {
            _select.push(`@${_f.field}=''`)
          }
        if (_f.type === 'number') {
          _fieldlen = _f.decimal ? _f.decimal : 0
          _declare.push(`@${_f.field} ${_f.datatype}`)
          return
        }
        let _fieldlen = _f.fieldlength || 50
        if (_fieldlen > 4000) {
          _fieldlen = 'max'
@@ -747,14 +834,13 @@
        let _type = `nvarchar(${_fieldlen})`
        if (_f.type.match(/date/ig)) {
          _type = 'datetime'
          _select.push(`@${_f.field}='1949-10-01'`)
        } else if (_f.type === 'number') {
          _type = `decimal(18,${_fieldlen})`
          _select.push(`@${_f.field}=0`)
        } else if (_f.type === 'rate') {
          _type = `decimal(18,2)`
        if (_f.type === 'number') {
          _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
        } else if (_f.type === 'picture' || _f.type === 'textarea') {
          _type = `nvarchar(${_fieldlen})`
        }
        if (_f.type === 'number') {
          _select.push(`@${_f.field}=0`)
        } else {
          _select.push(`@${_f.field}=''`)
@@ -762,271 +848,206 @@
        _declare.push(`@${_f.field} ${_type}`)
      })
    }
      let uniqueFields = fromJS(_fields).toJS()
    let _sql = `Declare ${_declare.join(', ')}
      Select ${_select.join(', ')}
    `
      if (!hasBid) { // 唯一性验证添加BID
        uniqueFields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
        _fields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
      }
    // 默认sql
    let _defaultsql = ''
    let _insertsql = ''
    let _updatesql = ''
    let _primaryKey = config.setting.primaryKey || 'id'
      let hasColumn = false
      if (columns && columns.length > 0) {
        if (btnTab) { // 表单标签
          hasColumn = btnTab.Ot !== 'notRequired'
        } else if (card.Ot !== 'notRequired') {
          hasColumn = true
        }
      }
    if (this.props.side === 'sub') {
      _primaryKey = config.setting.subKey || 'id'
    }
      let unionFields = fromJS(_fields).toJS()
      let formArr = _fields.map(_f => _f.field.toLowerCase())
    if (card.sqlType === 'insert' || card.sqlType === 'insertOrUpdate') {
      let keys = []
      let values = []
      if (hasColumn) {
        columns.forEach(_f => {
          if (_f.field && !formArr.includes(_f.field.toLowerCase())) {
            formArr.push(_f.field.toLowerCase())
            unionFields.push(_f)
          }
          if (!_f.field || fieldArr.includes(_f.field.toLowerCase())) return
      _fields.forEach(item => {
        if (!item.field || item.writein === 'false') return
          fieldArr.push(_f.field.toLowerCase())
          _usefulfields.push(_f.field)
        keys.push(item.field.toLowerCase())
          if (_f.datatype) { // 自定义字段
            if (/decimal/ig.test(_f.datatype)) {
              _select.push(`@${_f.field}=0`)
            } else {
              _select.push(`@${_f.field}=''`)
            }
            _declare.push(`@${_f.field} ${_f.datatype}`)
            return
          }
          let _fieldlen = _f.fieldlength || 50
          if (_fieldlen > 4000) {
            _fieldlen = 'max'
          }
          let _type = `nvarchar(${_fieldlen})`
          if (_f.type === 'number') {
            _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
          } else if (_f.type === 'picture' || _f.type === 'textarea') {
            _type = `nvarchar(${_fieldlen})`
          }
          if (_f.type === 'number') {
            _select.push(`@${_f.field}=0`)
          } else {
            _select.push(`@${_f.field}=''`)
          }
          _declare.push(`@${_f.field} ${_type}`)
        })
      }
      let _sql = `Declare ${_declare.join(', ')}
        Select ${_select.join(', ')}
      `
      // 默认sql
      let _defaultsql = ''
      let _insertsql = ''
      let _updatesql = ''
      let _primaryKey = config.setting.primaryKey || 'id'
      if (this.props.side === 'sub') {
        _primaryKey = config.setting.subKey || 'id'
      }
      if (card.sqlType === 'insert' || card.sqlType === 'insertOrUpdate') {
        let keys = []
        let values = []
        _fields.forEach(item => {
          if (!item.field || item.writein === 'false') return
          keys.push(item.field.toLowerCase())
          if (item.field.toLowerCase() === 'bid' && item.uuid === 'BID') {
            values.push('@BID@')
          } else {
            values.push('@' + item.field)
          }
        })
        if (!keys.includes(_primaryKey.toLowerCase())) {
          keys.push(_primaryKey.toLowerCase())
          values.push('@ID@')
        }
        if (!keys.includes('createuserid')) {
          keys.push('createuserid')
          values.push('@userid@')
        }
        if (!keys.includes('createuser')) {
          keys.push('createuser')
          values.push('@username')
        }
        if (!keys.includes('createstaff')) {
          keys.push('createstaff')
          values.push('@fullname')
        }
        if (!keys.includes('bid')) {
          keys.push('bid')
        if (item.field.toLowerCase() === 'bid' && item.uuid === 'BID') {
          values.push('@BID@')
        }
        if (!keys.includes('typename')) {
          keys.push('typename')
          values.push('@typename@')
        }
        keys = keys.join(', ')
        values = values.join(', ')
        _insertsql = `insert into ${card.sql} (${keys}) select ${values};`
      }
      if (card.sqlType === 'update' || card.sqlType === 'audit' || card.sqlType === 'insertOrUpdate') {
        let _form = []
        let _arr = []
        _fields.forEach(item => {
          if (!item.field || item.writein === 'false' || item.uuid === 'BID') return
          _arr.push(item.field.toLowerCase())
          if (item.field.toLowerCase() === 'bid') {
            _form.push(item.field + '=@BID@')
          } else {
            _form.push(item.field + '=@' + item.field)
          }
        })
        if (this.props.card.sqlType === 'audit') {
          if (!_arr.includes('submitdate')) {
            _form.push('submitdate=getdate()')
          }
          if (!_arr.includes('submituser')) {
            _form.push('submituser=@username')
          }
          if (!_arr.includes('submitstaff')) {
            _form.push('submitstaff=@fullname')
          }
          if (!_arr.includes('submituserid')) {
            _form.push('submituserid=@userid@')
          }
          if (!_arr.includes('typename')) {
            _form.push(`typename=@typename@`)
          }
        } else {
          if (!_arr.includes('modifydate')) {
            _form.push('modifydate=getdate()')
          }
          if (!_arr.includes('modifyuser')) {
            _form.push('modifyuser=@username')
          }
          if (!_arr.includes('modifystaff')) {
            _form.push('modifystaff=@fullname')
          }
          if (!_arr.includes('modifyuserid')) {
            _form.push('modifyuserid=@userid@')
          }
          if (!_arr.includes('typename')) {
            _form.push(`typename=@typename@`)
          }
          values.push('@' + item.field)
        }
        if (_verify.voucher && _verify.voucher.enabled) {
          if (!_arr.includes('bvoucher')) {
            _form.push('BVoucher=@BVoucher')
          }
          if (!_arr.includes('fibvoucherdate')) {
            _form.push('FIBVoucherDate=@FIBVoucherDate')
          }
          if (!_arr.includes('fiyear')) {
            _form.push('FiYear=@FiYear')
          }
        }
        _form = _form.join(', ')
        _updatesql = `update ${card.sql} set ${_form} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
      }
      if (card.sqlType === 'insert') {
        _defaultsql = _insertsql
      } else if (card.sqlType === 'update' || card.sqlType === 'audit') {
        _defaultsql = _updatesql
      } else if (card.sqlType === 'insertOrUpdate') {
        _defaultsql += `select @tbid=''
          select @tbid='X' from ${card.sql} where ${_primaryKey}=@ID@
          if @tbid=''
            begin
            ${_insertsql}
            end
          else
            begin
            ${_updatesql}
            end
        `
      } else if (card.sqlType === 'LogicDelete' || card.sqlType === 'custom') {
        let _voucher = ''
        if (_verify.voucher && _verify.voucher.enabled) {
          _voucher = ',BVoucher=@BVoucher,FIBVoucherDate=@FIBVoucherDate,FiYear=@FiYear'
        }
        _defaultsql = `update ${card.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@${_voucher} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
      } else if (card.sqlType === 'delete') {
        let _msg = ''
        if (columns && columns.length > 0 && card.Ot !== 'notRequired') {
          let _index = 0
          columns.forEach(col => {
            if (!col.field || col.Hide === 'true' || _index >= 4) return
            _msg += col.label + '=\'\','
            _index++
          })
        }
        _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff,typename) select left('删除表:${card.sql} 数据: ${_msg}${_primaryKey}='+@ID@,200),@userid@,@username,@fullname,@typename@ delete ${card.sql} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
      }
      let _columns = []
      if (columns) {
        _columns = fromJS(columns).toJS()
        let hasbid = false
        _columns = _columns.filter(col => {
          if (col.field && col.field.toLowerCase() === 'bid') {
            hasbid = true
          }
          return !!col.field
        })
        if (!hasbid) {
          _columns.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
        }
      }
      this.setState({
        fields: _fields,
        columnsFields: _columns,
        initsql: _sql,
        defaultsql: _defaultsql,
        usefulfields: _usefulfields.join(', '),
        uniqueColumns: this.state.uniqueColumns.map(col => {
          if (col.dataIndex === 'field') {
            col.options = uniqueFields
          }
          return col
        }),
        onceUniqueColumns: this.state.onceUniqueColumns.map(col => {
          if (col.dataIndex === 'field') {
            col.options = _columns
          }
          return col
        }),
        unionFields,
        uniqueFields
      })
      if (!keys.includes(_primaryKey.toLowerCase())) {
        keys.push(_primaryKey.toLowerCase())
        values.push('@ID@')
      }
      if (!keys.includes('createuserid')) {
        keys.push('createuserid')
        values.push('@userid@')
      }
      if (!keys.includes('createuser')) {
        keys.push('createuser')
        values.push('@username')
      }
      if (!keys.includes('createstaff')) {
        keys.push('createstaff')
        values.push('@fullname')
      }
      if (!keys.includes('bid')) {
        keys.push('bid')
        values.push('@BID@')
      }
      if (!keys.includes('typename')) {
        keys.push('typename')
        values.push('@typename@')
      }
      keys = keys.join(', ')
      values = values.join(', ')
      _insertsql = `insert into ${card.sql} (${keys}) select ${values};`
    }
    if (card.sqlType === 'update' || card.sqlType === 'audit' || card.sqlType === 'insertOrUpdate') {
      let _form = []
      let _arr = []
      _fields.forEach(item => {
        if (!item.field || item.writein === 'false' || item.uuid === 'BID') return
        _arr.push(item.field.toLowerCase())
        if (item.field.toLowerCase() === 'bid') {
          _form.push(item.field + '=@BID@')
        } else {
          _form.push(item.field + '=@' + item.field)
        }
      })
      if (this.props.card.sqlType === 'audit') {
        if (!_arr.includes('submitdate')) {
          _form.push('submitdate=getdate()')
        }
        if (!_arr.includes('submituser')) {
          _form.push('submituser=@username')
        }
        if (!_arr.includes('submitstaff')) {
          _form.push('submitstaff=@fullname')
        }
        if (!_arr.includes('submituserid')) {
          _form.push('submituserid=@userid@')
        }
        if (!_arr.includes('typename')) {
          _form.push(`typename=@typename@`)
        }
      } else {
        if (!_arr.includes('modifydate')) {
          _form.push('modifydate=getdate()')
        }
        if (!_arr.includes('modifyuser')) {
          _form.push('modifyuser=@username')
        }
        if (!_arr.includes('modifystaff')) {
          _form.push('modifystaff=@fullname')
        }
        if (!_arr.includes('modifyuserid')) {
          _form.push('modifyuserid=@userid@')
        }
        if (!_arr.includes('typename')) {
          _form.push(`typename=@typename@`)
        }
      }
      if (_verify.voucher && _verify.voucher.enabled) {
        if (!_arr.includes('bvoucher')) {
          _form.push('BVoucher=@BVoucher')
        }
        if (!_arr.includes('fibvoucherdate')) {
          _form.push('FIBVoucherDate=@FIBVoucherDate')
        }
        if (!_arr.includes('fiyear')) {
          _form.push('FiYear=@FiYear')
        }
      }
      _form = _form.join(', ')
      _updatesql = `update ${card.sql} set ${_form} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
    }
    if (card.sqlType === 'insert') {
      _defaultsql = _insertsql
    } else if (card.sqlType === 'update' || card.sqlType === 'audit') {
      _defaultsql = _updatesql
    } else if (card.sqlType === 'insertOrUpdate') {
      _defaultsql += `select @tbid=''
        select @tbid='X' from ${card.sql} where ${_primaryKey}=@ID@
        if @tbid=''
          begin
          ${_insertsql}
          end
        else
          begin
          ${_updatesql}
          end
      `
    } else if (card.sqlType === 'LogicDelete' || card.sqlType === 'custom') {
      let _voucher = ''
      if (_verify.voucher && _verify.voucher.enabled) {
        _voucher = ',BVoucher=@BVoucher,FIBVoucherDate=@FIBVoucherDate,FiYear=@FiYear'
      }
      _defaultsql = `update ${card.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@${_voucher} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
    } else if (card.sqlType === 'delete') {
      let _msg = ''
      if (columns && columns.length > 0 && card.Ot !== 'notRequired') {
        let _index = 0
        columns.forEach(col => {
          if (!col.field || col.Hide === 'true' || _index >= 4) return
          _msg += col.label + '=\'\','
          _index++
        })
      }
      _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff,typename) select left('删除表:${card.sql} 数据: ${_msg}${_primaryKey}='+@ID@,200),@userid@,@username,@fullname,@typename@ delete ${card.sql} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
    }
    let _columns = []
    if (columns) {
      _columns = fromJS(columns).toJS()
      let hasbid = false
      _columns = _columns.filter(col => {
        if (col.field && col.field.toLowerCase() === 'bid') {
          hasbid = true
        }
        return !!col.field
      })
      if (!hasbid) {
        _columns.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
      }
    }
    this.setState({
      fields: _fields,
      columnsFields: _columns,
      initsql: _sql,
      defaultsql: _defaultsql,
      usefulfields: _usefulfields.join(', '),
      uniqueColumns: this.state.uniqueColumns.map(col => {
        if (col.dataIndex === 'field') {
          col.options = uniqueFields
        }
        return col
      }),
      onceUniqueColumns: this.state.onceUniqueColumns.map(col => {
        if (col.dataIndex === 'field') {
          col.options = _columns
        }
        return col
      }),
      unionFields,
      uniqueFields
    })
  }
@@ -1134,6 +1155,45 @@
    })
  }
  orderSql = (record) => {
    let _ModularDetailCode = ''
    let _lpline = ''
    if (record.TypeCharOne === 'Lp') {
      if (record.linkField.toLowerCase() === 'bid') {
        _lpline = `set @ModularDetailCode= 'Lp'+ right('${record.mark || this.props.card.uuid}'+@BID@,48)`
      } else {
        _lpline = `set @ModularDetailCode= 'Lp'+ right('${record.mark || this.props.card.uuid}'+@${record.linkField.toLowerCase()},48)`
      }
      _ModularDetailCode = '@ModularDetailCode'
    } else if (record.TypeCharOne === 'BN') {
      _ModularDetailCode = `'${record.TypeCharOne}'`
    } else {
      _ModularDetailCode = `'${record.ModularDetailCode}'`
    }
    let sql = `select @BillCode='', @${record.field}='', @ModularDetailCode=''
    ${_lpline}
    exec s_get_BillCode
      @ModularDetailCode=${_ModularDetailCode},
      @Type=${record.Type},
      @TypeCharOne='${record.TypeCharOne}',
      @TypeCharTwo ='${record.TypeCharTwo}',
      @BillCode =@BillCode output,
      @ErrorCode =@ErrorCode output,
      @retmsg=@retmsg output
    if @ErrorCode!=''
      goto aaa
    set @${record.field}=@BillCode`
    Modal.info({
      title: '',
      width: 500,
      className: 'sql-example',
      icon: null,
      content: sql.split(/\n\s{4}/ig).map((n, index) => <div key={index} dangerouslySetInnerHTML={{ __html: n.replace(/\s/ig, '&nbsp;') }} style={{whiteSpace: 'nowrap'}}></div>)
    })
  }
  uniqueChange = (values) => {
    let verify = fromJS(this.state.verify).toJS()
@@ -1183,6 +1243,8 @@
  }
  scriptsChange = (values) => {
    const { columns, card } = this.props
    let verify = fromJS(this.state.verify).toJS()
    if (values.uuid) {
@@ -1196,6 +1258,35 @@
    } else {
      values.uuid = Utils.getuuid()
      verify.scripts.push(values)
    }
    if (/@bvoucher(\s|\))/ig.test(values.sql)) {
      if (verify.voucher && verify.voucher.enabled) {
      } else if (card.Ot !== 'notRequired' && columns) {
        let hasvoucher = false
        columns.forEach(_f => {
          if (!_f.field) return
          if (_f.field.toLowerCase() === 'bvoucher') {
            hasvoucher = true
          }
        })
        if (!hasvoucher) {
          notification.warning({
            top: 92,
            message: '未启用创建凭证,且字段集中不存在凭证字段(bvoucher)。',
            duration: 5
          })
        }
      } else {
        notification.warning({
          top: 92,
          message: '未启用创建凭证,且字段集中不存在凭证字段(bvoucher)。',
          duration: 5
        })
      }
    }
    MKEmitter.emit('editLineId', values.uuid)
@@ -1603,7 +1694,7 @@
            </span>
          } key="contrasts">
            <ContrastForm contrastChange={this.contrastChange}/>
            <EditTable actions={['edit', 'move', 'copy', 'del', 'status']} type="contrastverify" data={verify.contrasts} columns={contrastColumns} onChange={(contrasts) => this.setState({verify: {...verify, contrasts}})}/>
            <EditTable actions={['edit', 'move', 'copy', 'del', 'status', 'sql']} type="contrastverify" data={verify.contrasts} columns={contrastColumns} onChange={(contrasts) => this.setState({verify: {...verify, contrasts}})}/>
          </TabPane> : null}
          {verifyInter === 'system' ? <TabPane tab={
            <span>
@@ -1649,7 +1740,7 @@
              fields={card.Ot !== 'requiredOnce' ? uniqueFields : columnsFields}
              uniqueChange={this.uniqueChange}
            />
            <EditTable actions={['edit', 'move', 'del', 'status']} data={verify.uniques} columns={card.Ot !== 'requiredOnce' ? uniqueColumns : onceUniqueColumns} onChange={this.changeUniques}/>
            <EditTable actions={['edit', 'move', 'del', 'status', 'sql']} data={verify.uniques} columns={card.Ot !== 'requiredOnce' ? uniqueColumns : onceUniqueColumns} onChange={this.changeUniques}/>
          </TabPane> : null}
          {verifyInter === 'system' ? <TabPane tab={
            <span>
src/templates/zshare/verifycard/index.scss
@@ -106,6 +106,14 @@
  }
}
.ant-modal.ant-modal-confirm.ant-modal-confirm-info.sql-example {
  top: 100px;
  .ant-modal-body {
    padding: 24px;
  }
}
@media screen and (max-width: 1500px) {
  .mk-verify-tabs {
    .ant-tabs-nav .ant-tabs-tab {
src/utils/option.js
@@ -1,6 +1,4 @@
import nortable from '@/assets/img/normaltable.jpg'
// import mainsubtable from '@/assets/img/mainsubtable.jpg'
// import treepage from '@/assets/img/treepage.jpg'
import customImg from '@/assets/img/custom.jpg'
import newpage from '@/assets/img/newpage.jpg'
import rolemanage from '@/assets/img/rolemanage.jpg'
src/utils/utils-custom.js
@@ -6,7 +6,7 @@
   * @description 获取下级模块
   * @return {String}  selfId  当前组件id
   */
  static getSubModules (components, selfId, supId, has) {
  static getSubModules (components, selfId, supId, interfaces) {
    let modules = []
    components.forEach(item => {
      if (item.uuid === selfId || item.type === 'navbar') {
@@ -49,7 +49,7 @@
                type: 'tab',
                value: f_tab.uuid,
                label: f_tab.label,
                children: this.getSubModules(f_tab.components, selfId, supId, has)
                children: this.getSubModules(f_tab.components, selfId, supId)
              }
  
              if (subItem.children.length === 0) {
@@ -94,6 +94,15 @@
        }
      }
    })
    if (interfaces && interfaces.length > 0) {
      interfaces.forEach(item => {
        modules.push({
          value: item.uuid,
          label: item.name
        })
      })
    }
    return modules
  }
@@ -719,7 +728,7 @@
  * @description 重置组件配置
  * @return {String}  item 组件信息
  */
  static resetComponentConfig = (item, appType) => {
  static resetComponentConfig = (item, appType, commonId) => {
    if (item.type === 'navbar') {
      return item
    }
@@ -727,9 +736,6 @@
    if (item.subtype === 'tablecard') { // 兼容
      item.type = 'card'
    }
    item.uuid = this.getuuid()
    let commonId = this.getuuid()
    // 重置组件名称
    let sign = this.getSignName()
@@ -952,20 +958,6 @@
        cell.uuid = this.getuuid()
        return cell
      })
    }
    if (item.setting && item.setting.supModule && item.setting.supModule[0] !== 'empty') {
      item.setting.supModule = ''
    }
    if (item.wrap && item.wrap.supType === 'multi') {
      item.wrap.supType = 'single'
      delete item.supNodes
    }
    if (item.wrap && item.wrap.supModule) {
      item.wrap.supModule = ''
    }
    if (item.wrap && item.wrap.doubleClick) {
@@ -1656,6 +1648,14 @@
        }
      }
    }
    if (['pop', 'prompt', 'exec'].includes(cell.OpenType) && cell.verify && !cell.output) {
      if (cell.verify.noteEnable === 'true') {
        errors.push({ level: 0, detail: `按钮“${cell.label}”未设置返回值短信发送无效!`})
      } else if (cell.verify.emailEnable === 'true') {
        errors.push({ level: 0, detail: `按钮“${cell.label}”未设置返回值邮件发送无效!`})
      }
    }
  }
  if (card.$c_ac) {
src/utils/utils-datamanage.js
@@ -69,6 +69,12 @@
        } else {
          param.$token = setting.exInterface || ''
        }
      } else if (setting.sysInterface === 'custom') {
        if (window.GLOB.systemType === 'production') {
          param.rduri = setting.proInterface
        } else {
          param.rduri = setting.interface
        }
      } else {
        if (window.GLOB.systemType === 'production' && setting.proInterface) {
          param.rduri = setting.proInterface
@@ -278,9 +284,9 @@
      param.menuname = setting.$name
    }
    param.custom_script = Utils.formatOptions(_customScript)
    param.LText = Utils.formatOptions(LText)
    param.DateCount = Utils.formatOptions(DateCount)
    param.custom_script = Utils.formatOptions(_customScript, param.exec_type)
    param.LText = Utils.formatOptions(LText, param.exec_type)
    param.DateCount = Utils.formatOptions(DateCount, param.exec_type)
    if (setting.sub_field) {
      param.sub_name = setting.subdata
@@ -308,6 +314,8 @@
      if (setting.tableName === 's_custom_script' && window.GLOB.mainSystemApi) {
        param.rduri = window.GLOB.mainSystemApi
      }
    } else if (window.GLOB.forcedUpdate) {
      param.s_version_up = 'true'
    }
    return param
@@ -512,7 +520,6 @@
/**
 * @description 生成sPC_Get_structured_data请求参数
 * 1、把大接口sPC_Get_structured_data的ltext拆成三份,第一段:@LText1,第二段@LText,第三段@LText2
 */
export function getStructuredParams (params, config, BID) {
  let LText_field = []
@@ -560,8 +567,6 @@
  let param = {
    func: 'sPC_Get_structured_data',
    LText: _LText.join(' union all '),
    LText_field: LText_field.join(' union all '),
    BID: BID,
    username: sessionStorage.getItem('User_Name') || '',
    fullName: sessionStorage.getItem('Full_Name') || ''
@@ -571,12 +576,13 @@
    param.menuname = config.MenuName
  }
  let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
  param.LText1 = LText1
  param.LText = LText
  param.LText2 = LText2
  param.LText_field = Utils.formatOptions(param.LText_field)
  param.exec_type = 'y'
  param.LText = Utils.formatOptions(_LText.join(' union all '))
  param.custom_script = Utils.formatOptions(LText_field.join(' union all '))
  // param.LText1 = LText1
  // param.LText = LText
  // param.LText2 = LText2
  // param.LText_field = Utils.formatOptions(param.LText_field)
  if (config.cacheUseful === 'true') {
    param.time_type = config.timeUnit
@@ -588,7 +594,7 @@
  }
  param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
  param.secretkey = Utils.encrypt(param.LText, param.timestamp)
  param.secretkey = Utils.encrypt('', param.timestamp)
  return param
}
src/utils/utils.js
@@ -1,6 +1,7 @@
import React from 'react'
import moment from 'moment'
import md5 from 'md5'
// import NodeRSA from 'node-rsa'
const formatKeys = [
  { key: 'select', value: ' msltk ' },
@@ -119,10 +120,8 @@
   * @description sql加密
   * @return {String}   value
   */
  static formatOptions (value) {
  static formatOptions (value, exec_type = '') {
    if (!value) return ''
    let salt = 'minKe' // 盐值
    value = value.replace(/\n/ig, ' \n ')
    // 替换关键字
@@ -136,13 +135,43 @@
    if (window.GLOB.externalDatabase !== null) {
      value = value.replace(/@db@/ig, window.GLOB.externalDatabase)
    }
    // encode编码(中文字符超出base64加密范围)
    value = window.btoa(window.encodeURIComponent(value))
    // 插入字符
    let index = Math.floor(value.length / 2)
    value = value.slice(0, index) + salt + value.slice(index)
    // base64加密
    value = window.btoa(value)
    // if (exec_type === 'x') {
    //   // let publicKey = `-----BEGIN PUBLIC KEY-----
    //   //   MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwGxFURiCrk5a2xfWuM3W
    //   //   2lkS3ioZhUFXpkK1inMivItsA/J8MTaBB3EAVxC29xdVCU+xOzs512PuD2b1sjzX
    //   //   jwO6kx433NtB2okqGiP4RkzhEJHwdyc9dPUKdjirDznUWI9R7WayAf5Z4COhMsj2
    //   //   IbkyJgkb6Ivn0UgU0GSWc92HqJJmnb3Ti2gk6A2+oybz2RE3+xB/yOaNu3xav4yi
    //   //   xxo6harVLNBiaU+D7aDed1W3kE20gLOnEAvcLMjpe3n/QvF5RtELsm3T+vH3TIT2
    //   //   GI9+8cT20NZ2d7i41+j/AQZiPJNS3MVmc3aIhuyCOsNPLmvbZZi1KPSJIqkCwdEg
    //   //   mQIDAQAB
    //   //   -----END PUBLIC KEY-----`
    //   // let pubKey = new NodeRSA(publicKey, 'pkcs8-public')
    //   // value = window.encodeURIComponent(value)
    //   // value = pubKey.encrypt(value, 'base64')
    //   // const priKey = new NodeRSA(privateKey, 'pkcs8-private')
    //   // const res = priKey.decrypt(value, 'utf8')
    // } else {
      // encode编码(中文字符超出base64加密范围)
      // let str = window.encodeURIComponent(value)
      // if (str.length % 3 === 1) {
      //   str += '%2F*123*%2F'
      // } else if (str.length % 3 === 2) {
      //   str += '%2F*12*%2F'
      // }
      value = window.btoa(window.encodeURIComponent(value))
      // 插入字符
      let salt = 'minKe' // 盐值
      let index = Math.floor(value.length / 2)
      value = value.slice(0, index) + salt + value.slice(index)
      // base64加密
      value = window.btoa(value)
    // }
    return value
  }
@@ -169,59 +198,6 @@
  //   return value
  // }
  /**
   * @description sPC_TableData_InUpDe sql加密
   * @return {String}  value
   */
  static sPCInUpDeFormatOptions (value) {
    if (!value) return {LText: '', LText1: '', LText2: ''}
    let salt = 'minKe' // 盐值
    value = value.replace(/\n/ig, ' \n ')
    // 替换关键字
    formatKeys.forEach(item => {
      let reg = new RegExp('(^|\\s)' + item.key + '(\\s|$)', 'ig')
      value = value.replace(reg, item.value)
    })
    // 1、替换%符(数据库中解析后sql报错)
    value = value.replace(/%/ig, ' mpercent ')
    // 外联数据库替换
    if (window.GLOB.externalDatabase !== null) {
      value = value.replace(/@db@/ig, window.GLOB.externalDatabase)
    }
    let encodesql = (val) => {
      if (!val) return ''
      let _value = window.btoa(window.encodeURIComponent(val))
      // 插入字符
      let index = Math.floor(_value.length / 2)
      _value = _value.slice(0, index) + salt + _value.slice(index)
      // base64加密
      return window.btoa(_value)
    }
    let len = value.length
    // 注:LText 与 LText1 顺序颠倒
    if (len > 1000) {
      let limit = Math.floor(len / 3)
      return {
        LText1: encodesql(value.substring(0, limit)),
        LText: encodesql(value.substring(limit, limit * 2)),
        LText2: encodesql(value.substring(limit * 2))
      }
    } else {
      return {
        LText1: '',
        LText: encodesql(value),
        LText2: ''
      }
    }
  }
  /**
   * @description 初始化搜索条件初始值
@@ -260,10 +236,44 @@
          format = 'YYYY-MM-DD HH:mm:ss'
        }
        item.format = format
        item.initval = item.initval ? moment().subtract(item.initval, 'days').format(format) : ''
      } else if (item.type === 'datemonth') {
        item.initval = item.initval ? moment().subtract(item.initval, 'month').format('YYYY-MM') : ''
        item.format = 'YYYY-MM'
        if (item.initval) {
          if (!item.dateShift) {
            item.initval = moment().subtract(item.initval, 'month').format('YYYY-MM')
          } else {
            item.$initval = item.initval
            item.$supId = config.$pageId
            if (config.setting && config.setting.supModule) {
              item.$supId = config.setting.supModule
              config.checkBid = true
              config.setting.checkBid = true
              item.checkShift = true
            }
            item.initval = ''
            let d = ''
            if (window.GLOB.CacheData.has(item.$supId)) {
              d = window.GLOB.CacheData.get(item.$supId)
              d = d[item.dateShift] || ''
              if (d) {
                d = moment(d).format('YYYY-MM-DD')
                d = d === 'Invalid date' ? '' : d
              }
            }
            if (d) {
              item.initval = moment(d).subtract(item.initval, 'month').format('YYYY-MM')
            }
          }
        }
      } else if (item.type === 'dateweek') {
        item.format = 'YYYY-MM-DD'
        item.initval = item.initval ? moment().subtract(item.initval * 7, 'days').format('YYYY-MM-DD') : ''
      } else if (item.type === 'daterange') {
        let format = 'YYYY-MM-DD'
@@ -276,19 +286,66 @@
        } else if (item.precision === 'second') {
          format = 'YYYY-MM-DD HH:mm:ss'
        }
        if (item.initval === 'week') {
          item.initval = [moment().startOf('week').format(format), moment().endOf('week').format(format)].join(',')
        } else if (item.initval === 'month') {
          item.initval = [moment().startOf('month').format(format), moment().endOf('month').format(format)].join(',')
        } else if (item.initval === 'lastMonth') {
          item.initval = [moment().subtract(1, 'months').startOf('month').format(format), moment().subtract(1, 'months').endOf('month').format(format)].join(',')
        } else if (item.initval) {
          try {
            let _initval = JSON.parse(item.initval)
            let _vals = [moment().subtract(_initval[0], 'days').format(format), moment().subtract(_initval[1], 'days').format(format)]
            item.initval = _vals.join(',')
          } catch (e) {
        item.format = format
        if (item.initval) {
          if (!item.dateShift) {
            if (item.initval === 'week') {
              item.initval = [moment().startOf('week').format(format), moment().endOf('week').format(format)].join(',')
            } else if (item.initval === 'month') {
              item.initval = [moment().startOf('month').format(format), moment().endOf('month').format(format)].join(',')
            } else if (item.initval === 'lastMonth') {
              item.initval = [moment().subtract(1, 'months').startOf('month').format(format), moment().subtract(1, 'months').endOf('month').format(format)].join(',')
            } else if (item.initval) {
              try {
                let _initval = JSON.parse(item.initval)
                let _vals = [moment().subtract(_initval[0], 'days').format(format), moment().subtract(_initval[1], 'days').format(format)]
                item.initval = _vals.join(',')
              } catch (e) {
                item.initval = ''
              }
            }
          } else {
            item.$initval = item.initval
            item.$supId = config.$pageId
            if (config.setting && config.setting.supModule) {
              item.$supId = config.setting.supModule
              config.checkBid = true
              config.setting.checkBid = true
              item.checkShift = true
            }
            item.initval = ''
            let d = ''
            if (window.GLOB.CacheData.has(item.$supId)) {
              d = window.GLOB.CacheData.get(item.$supId)
              d = d[item.dateShift] || ''
              if (d) {
                d = moment(d).format('YYYY-MM-DD')
                d = d === 'Invalid date' ? '' : d
              }
            }
            if (d) {
              if (item.$initval === 'week') {
                item.initval = [moment(d).startOf('week').format(format), moment(d).endOf('week').format(format)].join(',')
              } else if (item.$initval === 'month') {
                item.initval = [moment(d).startOf('month').format(format), moment(d).endOf('month').format(format)].join(',')
              } else if (item.$initval === 'lastMonth') {
                item.initval = [moment(d).subtract(1, 'months').startOf('month').format(format), moment(d).subtract(1, 'months').endOf('month').format(format)].join(',')
              } else {
                try {
                  let _initval = JSON.parse(item.$initval)
                  let _vals = [moment(d).subtract(_initval[0], 'days').format(format), moment(d).subtract(_initval[1], 'days').format(format)]
                  item.initval = _vals.join(',')
                } catch (e) {
                  item.initval = ''
                }
              }
            }
          }
        }
      } else if (item.type === 'group') {
@@ -348,9 +405,16 @@
          item.initval = ''
          item.initType = ''
        }
      } else if ((item.type === 'select' || item.type === 'link') && item.initval === '$first' && item.resourceType === '1') {
        item.initval = ''
        item.$first = true
      } else if ((item.type === 'select' || item.type === 'link') && item.resourceType === '1') {
        if (/@BID@/ig.test(item.dataSource) && config.setting && config.setting.supModule) {
          config.checkBid = true
          config.setting.checkBid = true
          item.checkBid = true
        }
        if (item.initval === '$first') {
          item.initval = ''
          item.$first = true
        }
      }
      
      item.oriInitval = item.initval
@@ -1403,7 +1467,6 @@
  let datavars = {}                 // 声明的变量,表单及显示列
  let _actionType = null
  let _callbacksql = ''
  let foreignKey = setting.foreignKey ? setting.foreignKey.toLowerCase() : ''
  if (verify.default !== 'false') { // 判断是否使用默认sql
    _actionType = btn.sqlType
@@ -1786,19 +1849,13 @@
      item.field.split(',').forEach((_field, index) => {
        let _key = _field.toLowerCase()
        let _val = datavars[_key] !== undefined ? datavars[_key] : ''
        let _fval = `'${_val}'`
        if (_key === 'bid' && !datavars.bid) { // 表单中没有bid则使用系统bid变量
          _fval = '@BID@'
        }
        if (_key === 'bid' && foreignKey) {
          arr.push(foreignKey)
          _fieldValue.push(`${foreignKey}=${_fval}`)
        } else {
          arr.push(_key)
          _fieldValue.push(`${_key}=${_fval}`)
        arr.push(_key)
        if (_key === 'bid' && !_val) { // 表单中没有bid则使用系统bid变量
          _val = BID
        }
        
        _fieldValue.push(`${_key}='${_val}'`)
        _value.push(`${_labels[index] || ''}:${_val || ''}`)
      })
@@ -1914,14 +1971,7 @@
      values.push('@fullname')
    }
    if (!keys.includes('bid')) {
      if (foreignKey && !keys.includes(foreignKey)) {
        keys.push(foreignKey)
      } else {
        keys.push('bid')
      }
      values.push('@BID@')
    } else if (foreignKey && !keys.includes(foreignKey)) {
      keys.push(foreignKey)
      keys.push('bid')
      values.push('@BID@')
    }
@@ -2300,7 +2350,7 @@
      z_debug_end: select @ErrorCode='E',@retmsg='debug_end' goto aaa`
  }
  if (retmsg) {
  if (retmsg || btn.returnValue === 'true') {
    _sql += `
      aaa: if @ErrorCode!=''
      insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@`
src/views/basedesign/updateFormTab/index.jsx
@@ -915,7 +915,7 @@
    let _card = {
      uuid: newCon.uuid,
      type: 'table',
      name: newCon.name,
      name: newCon.name || '',
      format: 'array',
      pageable: true,
      switchable: true,
@@ -923,7 +923,7 @@
      action: [],
      subtype: 'normaltable',
      setting: { useMSearch: 'false', sync: 'false', onload: 'true' },
      wrap: {name: newCon.name},
      wrap: {name: newCon.name || ''},
      style: {},
      headerStyle: {},
      columns: [],
src/views/billprint/index.jsx
@@ -44,7 +44,8 @@
    visible: false,
    rePos: false,
    loading: false,
    auto: true
    auto: true,
    ismob: /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(navigator.userAgent)
  }
  UNSAFE_componentWillMount() {
@@ -166,8 +167,6 @@
        sessionStorage.setItem('LoginUID', result.LoginUID || '')
        sessionStorage.setItem('dataM', 'false')
        this.getMenuParam()
        // 获取系统信息
        let _param = {
          func: 's_Get_style',
@@ -198,6 +197,8 @@
              document.getElementsByTagName('head')[0].appendChild(link)
            }
          }
          this.getMenuParam()
        })
      } else {
        notification.warning({
@@ -249,6 +250,10 @@
            lostmsg: '抱歉,您访问的页面未启用,请联系管理员。'
          })
          return
        }
        if (config.webTitle) {
          document.title = config.webTitle
        }
        config.style = config.style || {}
@@ -325,7 +330,7 @@
        let initInters = []
        this.formatInterSetting(config.interfaces, regs, initInters, params, BID)
        this.formatInterSetting(config.interfaces, regs, initInters, params, BID, config.MenuName)
        config.components = config.components.map(component => {
          if (component.action) {
@@ -341,6 +346,8 @@
            component.$searches = []
          }
          component.data = [] // 初始化数据为空
          component.$menuname = (config.MenuName || '') + '-' + (component.name || '')
          if (component.subtype === 'tablecard') { // 兼容
            component.type = 'card'
@@ -466,6 +473,7 @@
          component.setting.arr_field = component.columns ? component.columns.map(col => col.field).join(',') : ''
          component.setting.laypage = false   // 是否分页,转为boolean 统一格式
          component.setting.$name = component.$menuname
          if (component.format === 'object') {
            component.setting.$top = true
@@ -539,7 +547,7 @@
          return component
        })
        _pars = this.getFormatParam(_pars)
        _pars = this.getFormatParam(_pars, config.MenuName)
        if (_pars) {
          _pars.componentId = 'union'
@@ -640,7 +648,7 @@
    return cell
  }
  formatInterSetting = (inters, regs, initInters, params, BID) => {
  formatInterSetting = (inters, regs, initInters, params, BID, MenuName) => {
    if (!inters) return []
    let delay = 15
@@ -652,6 +660,7 @@
      inter.setting.supModule = ''
      inter.setting.arr_field = inter.columns.map(col => col.field).join(',')
      inter.setting.$name = (MenuName || '') + '-公共数据源-' + inter.setting.name
      if (inter.setting.interType !== 'system') {
        let param = UtilsDM.getQueryDataParams(inter.setting, [], inter.setting.order || '', 1, 1000, BID)
@@ -683,7 +692,6 @@
      })
      delete inter.scripts
      inter.setting.$name = '公共数据源-' + inter.setting.name
      inter.setting.execute = inter.setting.execute !== 'false'
      inter.setting.laypage = false
      inter.setting.$top = true
@@ -771,7 +779,7 @@
    }
  }
  getFormatParam = (params) => {
  getFormatParam = (params, MenuName) => {
    const { BID } = this.state
    if (!params || params.length === 0) return ''
@@ -834,17 +842,21 @@
    let param = {
      func: 'sPC_Get_structured_data',
      LText: LText.join(' union all '),
      LText_field: LText_field.join(' union all '),
      BID: BID || '',
      username: userName,
      fullName: fullName
    }
    param.LText = Utils.formatOptions(param.LText)
    param.LText_field = Utils.formatOptions(param.LText_field)
    if (MenuName) {
      param.menuname = MenuName
    }
    param.exec_type = 'y'
    param.LText = Utils.formatOptions(LText.join(' union all '))
    param.custom_script = Utils.formatOptions(LText_field.join(' union all '))
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    param.secretkey = Utils.encrypt('', param.timestamp)
    return param
  }
@@ -1312,7 +1324,7 @@
  }
  render() {
    const { loadingview, viewlost, config, pages, auto, rePos, loading } = this.state
    const { loadingview, viewlost, config, pages, auto, rePos, loading, ismob } = this.state
    return (
      <div className="bill-print-wrap" >
@@ -1322,8 +1334,8 @@
        </div> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
        {config && window.GLOB.breakpoint ? <DebugTable /> : null}
        {pages && !loadingview && !viewlost ? <div className="print-button"><Button icon="printer" size="large" shape="circle" onClick={this.print}></Button></div> : null}
        {!loadingview && !viewlost ? <div className="refresh-button"><Button icon="reload" size="large" shape="circle" onClick={this.reload}></Button></div> : null}
        {pages && !loadingview && !viewlost && !ismob ? <div className="print-button"><Button icon="printer" size="large" shape="circle" onClick={this.print}></Button></div> : null}
        {!loadingview && !viewlost && !ismob ? <div className="refresh-button"><Button icon="reload" size="large" shape="circle" onClick={this.reload}></Button></div> : null}
      </div>
    )
  }
src/views/design/header/index.scss
@@ -65,24 +65,24 @@
    }
  }
  .header-menu.level4 {
    li {
      cursor: default;
      &:hover {
        span {
          cursor: default;
          color: rgba(255, 255, 255, 0.65);
          border-bottom: none;
        }
      }
      &.active {
        span {
          color: #ffffff;
          border-bottom: 4px solid #1890ff;
        }
      }
    }
  }
  // .header-menu.level4 {
  //   li {
  //     cursor: default;
  //     &:hover {
  //       span {
  //         cursor: default;
  //         color: rgba(255, 255, 255, 0.65);
  //         border-bottom: none;
  //       }
  //     }
  //     &.active {
  //       span {
  //         color: #ffffff;
  //         border-bottom: 4px solid #1890ff;
  //       }
  //     }
  //   }
  // }
  .header-setting {
    float: right;
src/views/design/sidemenu/index.jsx
@@ -119,16 +119,16 @@
      }
      _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
      window.open(`#/menudesign/${_param}`)
    } else if (cell.type === 'BaseTable') {
      sessionStorage.setItem('menuTree', JSON.stringify(this.props.menuTree))
      let _param = window.btoa(window.encodeURIComponent(JSON.stringify(cell)))
      window.open(`#/tabledesign/${_param}`)
    } else if (['CommonTable', 'TreePage'].includes(cell.type)) {
      sessionStorage.setItem('menuTree', JSON.stringify(this.props.menuTree))
      let _param = window.btoa(window.encodeURIComponent(JSON.stringify(cell)))
      window.open(`#/basedesign/${_param}`)
    } else if (cell.type === 'BaseTable') {
      sessionStorage.setItem('menuTree', JSON.stringify(this.props.menuTree))
      let _param = window.btoa(window.encodeURIComponent(JSON.stringify(cell)))
      window.open(`#/tabledesign/${_param}`)
    } else if (['RolePermission', 'NewPage'].includes(cell.type)) {
      let _cell = fromJS(cell).toJS()
      _cell.Template = _cell.PageParam.Template
src/views/menudesign/homeform/index.jsx
@@ -126,6 +126,19 @@
        <Row>
          <Col span={24}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="首页不进行权限控制。">
                <QuestionCircleOutlined className="mk-form-tip" />
                权限验证
              </Tooltip>
            }>
              <Radio.Group value={'false'} disabled={true}>
                <Radio value="true">使用</Radio>
                <Radio value="false">不使用</Radio>
              </Radio.Group>
            </Form.Item>
          </Col>
          <Col span={24}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="数据会缓存到用户本地,方便页面快速呈现。">
                <QuestionCircleOutlined className="mk-form-tip" />
                本地缓存
src/views/menudesign/index.jsx
@@ -125,6 +125,7 @@
    
    MKEmitter.addListener('changePopview', this.initPopview)
    MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
    MKEmitter.addListener('changeEditMenu', this.changeEditMenu)
    setTimeout(() => {
      this.getRoleFields()
      setGLOBFuncs()
@@ -196,6 +197,49 @@
    }
    MKEmitter.removeListener('changePopview', this.initPopview)
    MKEmitter.removeListener('triggerMenuSave', this.triggerMenuSave)
    MKEmitter.removeListener('changeEditMenu', this.changeEditMenu)
  }
  changeEditMenu = (menu) => {
    if (menu.MenuID && menu.MenuID.length === 3 && menu.MenuNo && !this.menuLoading) {
      this.menuLoading = true
      let param = {
        func: 'sPC_Get_LongParam',
        MenuID: menu.MenuID[2]
      }
      Api.getCloudConfig(param).then(result => {
        this.menuLoading = false
        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) {
            let _param = {
              MenuId: menu.MenuID[2],
              MenuID: menu.MenuID[2],
              ParentId: menu.MenuID[1],
              MenuName: menu.MenuName,
              MenuNo: menu.MenuNo
            }
            if (config.Template === 'BaseTable') {
              _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
              window.open(`#/tabledesign/${_param}`)
            } else if (config.Template === 'CustomPage') {
              _param.MenuType = 'custom'
              _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
              window.open(`#/menudesign/${_param}`)
            }
          }
        }
      })
    }
  }
  triggerMenuSave = () => {
@@ -1091,12 +1135,6 @@
    this.setState({config})
    window.GLOB.customMenu = config
    notification.success({
      top: 92,
      message: '粘贴成功!',
      duration: 2
    })
  }
  changeSetting = () => {
src/views/menudesign/popview/index.jsx
@@ -246,12 +246,6 @@
    this.setState({config})
    window.GLOB.customMenu = config
    notification.success({
      top: 92,
      message: '粘贴成功!',
      duration: 2
    })
  }
  render () {
src/views/menudesign/printmenuform/index.jsx
@@ -257,6 +257,18 @@
              })(<Input onChange={(e) => this.selectChange('callNo', e.target.value)}/>)}
            </Form.Item>
          </Col> : null}
          <Col span={24}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="可自定义在浏览器标题栏中显示的网页标题。">
                <QuestionCircleOutlined className="mk-form-tip" />
                网页标题
              </Tooltip>
            }>
              {getFieldDecorator('webTitle', {
                initialValue: config.webTitle || ''
              })(<Input onChange={(e) => this.selectChange('webTitle', e.target.value)}/>)}
            </Form.Item>
          </Col>
        </Row>
      </Form>
    )
src/views/mobdesign/index.jsx
@@ -1858,49 +1858,14 @@
  insert = (item) => {
    let config = fromJS(this.state.config).toJS()
    if (item.type === 'search') {
      if (config.components.filter(card => card.type === 'topbar' && card.wrap.type !== 'navbar').length > 0) {
        notification.warning({
          top: 92,
          message: '导航栏使用了搜索,不可添加搜索组件!',
          duration: 5
        })
        return
      }
      if (config.components.filter(card => card.type === 'search').length > 0) {
        notification.warning({
          top: 92,
          message: '搜索条件不可重复添加!',
          duration: 5
        })
        return
      }
    }
    if (item.type === 'topbar') {
      if (config.components.findIndex(m => m.type === 'topbar') > -1) {
        notification.warning({
          top: 92,
          message: '导航栏不可重复添加!',
          duration: 5
        })
        return
      }
      if (!config.style.paddingTop) {
        config.style.paddingTop = '50px'
      }
    if (item.type === 'topbar' && !config.style.paddingTop) {
      config.style.paddingTop = '50px'
    }
    config.components.push(item)
    this.setState({config})
    window.GLOB.customMenu = config
    notification.success({
      top: 92,
      message: '粘贴成功!',
      duration: 2
    })
  }
  setHomeView = () => {
src/views/mobdesign/popview/index.jsx
@@ -248,12 +248,6 @@
    this.setState({config})
    window.GLOB.customMenu = config
    notification.success({
      top: 92,
      message: '粘贴成功!',
      duration: 2
    })
  }
  render () {
src/views/pcdesign/index.jsx
@@ -1550,12 +1550,6 @@
    this.setState({config})
    window.GLOB.customMenu = config
    notification.success({
      top: 92,
      message: '粘贴成功!',
      duration: 2
    })
  }
  setHomeView = () => {
src/views/systemfunc/sidemenu/index.jsx
@@ -40,18 +40,50 @@
    }
    let tb =  sessionStorage.getItem('mk-table-node')
    let temp = sessionStorage.getItem('mk-print-temp')
    let tabTemp = sessionStorage.getItem('mk-print-tab-temp')
    sessionStorage.removeItem('mk-table-node')
    sessionStorage.removeItem('mk-print-temp')
    sessionStorage.removeItem('mk-print-tab-temp')
    this.setState({
      subMenulist: menulist,
      rootSubmenuKeys: menulist.map(item => item.MenuID),
      openKeys: [menulist[0].MenuID]
    }, () => {
      if (tb && menulist[0] && menulist[0].children[0] && menulist[0].children[0].MenuNo === 'sDatasM') {
        setTimeout(() => {
          MKEmitter.emit('modifyTabs', fromJS(menulist[0].children[0]).toJS())
        }, 500)
      if (!menulist[0] || menulist[0].children.length === 0) return
      if (tb) {
        let menu = menulist[0].children.filter(item => item.MenuNo === 'sDatasM')[0]
        if (menu) {
          setTimeout(() => {
            MKEmitter.emit('modifyTabs', fromJS(menu).toJS())
          }, 500)
        }
      } else if (temp) {
        let menu = menulist[0].children.filter(item => item.MenuNo === 'sPrintTemplate_webM')[0]
        if (menu) {
          menu = fromJS(menu).toJS()
          menu.param = {}
          menu.param.$searchkey = 'PrintTempNO'
          menu.param.$searchval = temp
          setTimeout(() => {
            MKEmitter.emit('modifyTabs', menu)
          }, 500)
        }
      } else if (tabTemp) {
        let menu = menulist[0].children.filter(item => item.MenuNo === 'sPrintTemplateM')[0]
        if (menu) {
          menu = fromJS(menu).toJS()
          menu.param = {}
          menu.param.$searchkey = 'PrintTempNO'
          menu.param.$searchval = tabTemp
          setTimeout(() => {
            MKEmitter.emit('modifyTabs', menu)
          }, 500)
        }
      }
      sessionStorage.removeItem('mk-table-node')
    })
  }