From da64ab0923bf8817fc8599a6e37b953ce38f64c8 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期日, 27 八月 2023 18:37:36 +0800
Subject: [PATCH] 2023-08-27

---
 src/templates/zshare/modalform/index.jsx                                           |   28 
 src/menu/components/form/formaction/index.scss                                     |    1 
 src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx                     |   12 
 src/menu/components/timeline/normal-timeline/index.jsx                             |   23 
 src/tabviews/custom/components/editor/braft-editor/index.jsx                       |  151 
 src/menu/components/card/balcony/options.jsx                                       |  123 
 src/menu/components/chart/antv-X6/index.scss                                       |  177 
 src/tabviews/zshare/settingcomponent/index.jsx                                     |    3 
 src/templates/zshare/verifycard/customscript/index.jsx                             |   80 
 src/views/menudesign/printmenuform/index.jsx                                       |  134 
 src/tabviews/custom/popview/index.jsx                                              |  409 
 src/menu/components/chart/antv-scatter/index.jsx                                   |   24 
 src/tabviews/home/index.jsx                                                        |  103 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx  |   96 
 src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx               |   12 
 src/tabviews/zshare/topSearch/mkCheckCard/index.scss                               |  188 
 src/menu/components/table/edit-table/columns/editColumn/index.jsx                  |    3 
 src/tabviews/zshare/actionList/changeuserbutton/index.jsx                          |   17 
 src/menu/datasource/verifycard/index.jsx                                           |   34 
 src/assets/css/main.scss                                                           |  196 
 src/components/header/index.scss                                                   |    4 
 src/tabviews/custom/components/module/voucher/resetAttach/index.scss               |    1 
 src/tabviews/zshare/mutilform/mkCheckCard/index.scss                               |    8 
 src/views/mkiframe/index.scss                                                      |   10 
 src/menu/components/card/cardcellcomponent/index.jsx                               |   90 
 src/menu/components/form/tab-form/index.jsx                                        |   62 
 src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx     |   23 
 src/pc/menushell/card.jsx                                                          |    2 
 src/templates/zshare/unattended/settingform/index.jsx                              |    1 
 src/menu/components/carousel/prop-card/index.jsx                                   |   23 
 src/mob/searchconfig/searchdragelement/card.jsx                                    |   21 
 src/templates/zshare/verifycard/uniqueform/index.jsx                               |    2 
 src/menu/components/search/main-search/dragsearch/card.jsx                         |   12 
 src/menu/components/card/cardcomponent/index.jsx                                   |   12 
 src/menu/components/chart/antv-pie/index.jsx                                       |   22 
 src/tabviews/custom/components/chart/antv-X6/index.jsx                             | 2071 +++
 src/views/systemproc/proc/index.scss                                               |    9 
 src/views/systemproc/index.jsx                                                     |   16 
 src/menu/components/card/prop-card/index.jsx                                       |   27 
 src/templates/zshare/customscript/index.jsx                                        |    2 
 src/menu/components/tabs/tabcomponents/card.jsx                                    |    8 
 src/templates/zshare/modalform/modaleditable/index.jsx                             |   95 
 src/menu/components/tabs/paste/index.jsx                                           |    2 
 src/menu/components/table/edit-table/columns/index.jsx                             |    2 
 src/menu/datasource/verifycard/utils.jsx                                           |  143 
 src/tabviews/custom/components/chart/antv-bar-line/index.jsx                       |  246 
 package-lock.json                                                                  |   11 
 src/assets/css/viewstyle.scss                                                      |  124 
 src/tabviews/custom/components/chart/antv-dashboard/index.jsx                      |  256 
 src/views/login/loginform.jsx                                                      |  303 
 src/views/menudesign/popview/index.jsx                                             |    3 
 src/menu/components/share/actioncomponent/dragaction/card.jsx                      |    6 
 src/tabviews/zshare/topSearch/index.jsx                                            |  102 
 src/menu/components/card/doublecardcomponent/index.scss                            |    1 
 src/templates/comtableconfig/index.jsx                                             |   32 
 src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx                   |    2 
 src/menu/components/form/simple-form/index.jsx                                     |   64 
 src/views/basedesign/index.jsx                                                     |   89 
 src/tabviews/custom/components/table/edit-table/index.jsx                          |  136 
 src/menu/modulesource/dragsource/index.jsx                                         |    5 
 src/api/index.js                                                                   |  217 
 src/mob/components/formdragelement/index.scss                                      |    4 
 config/webpack.config.js                                                           |   20 
 src/tabviews/zshare/topSearch/index.scss                                           |   14 
 src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx                 |   38 
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx             |  198 
 src/tabviews/custom/components/iframe/index.jsx                                    |  142 
 src/mob/mobshell/card.jsx                                                          |    2 
 src/menu/components/table/base-table/columns/editColumn/index.jsx                  |    3 
 public/index.html                                                                  |   52 
 src/tabviews/zshare/tablenodes/index.jsx                                           |    5 
 src/views/interface/workspace/request/index.jsx                                    |    4 
 src/views/pcdesign/index.jsx                                                       |   89 
 src/menu/datasource/verifycard/settingform/index.jsx                               |   49 
 src/menu/datasource/verifycard/customscript/index.scss                             |   67 
 src/tabviews/custom/components/form/simple-form/index.scss                         |    1 
 src/mob/components/tabs/tabcomponents/card.jsx                                     |    2 
 src/views/systemfunc/sidemenu/index.jsx                                            |    3 
 src/menu/components/share/actioncomponent/index.jsx                                |   86 
 src/tabviews/custom/components/form/step-form/index.jsx                            |  201 
 src/views/systemfunc/sidemenu/config.jsx                                           |   20 
 src/templates/zshare/editTable/index.jsx                                           |  109 
 src/templates/zshare/modalform/fieldtable/index.jsx                                |   20 
 src/menu/components/group/paste/index.jsx                                          |    2 
 src/mob/components/tabs/antv-tabs/index.jsx                                        |   26 
 src/tabviews/custom/components/tree/antd-tree/index.jsx                            |  236 
 src/tabviews/zshare/actionList/popupbutton/index.jsx                               |   21 
 src/tabviews/custom/components/tabs/antv-tabs/index.jsx                            |   38 
 src/tabviews/zshare/normalTable/index.jsx                                          |    7 
 src/components/thawmenu/index.jsx                                                  |    4 
 src/templates/comtableconfig/updatetable/index.jsx                                 |  200 
 src/views/mkiframe/index.jsx                                                       |  233 
 src/tabviews/custom/components/group/normal-group/index.scss                       |    3 
 src/views/menudesign/homeform/index.jsx                                            |   55 
 src/templates/treepageconfig/index.jsx                                             |   23 
 src/views/menudesign/menuform/index.jsx                                            |   53 
 src/menu/datasource/index.jsx                                                      |   99 
 src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx                     |    5 
 src/tabviews/zshare/automatic/index.jsx                                            |   37 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx              |   85 
 src/menu/components/tree/antd-tree/index.jsx                                       |   15 
 src/tabviews/custom/index.scss                                                     |   12 
 src/views/billprint/index.jsx                                                      |  592 
 src/tabviews/subtabtable/index.jsx                                                 |   68 
 src/tabviews/zshare/actionList/normalbutton/index.jsx                              |  598 
 src/views/menudesign/index.jsx                                                     |  177 
 src/menu/modulesource/option.jsx                                                   |    5 
 src/tabviews/custom/components/card/data-card/index.jsx                            |  563 
 src/tabviews/custom/components/module/voucher/index.jsx                            |   41 
 src/templates/sharecomponent/actioncomponent/actionform/index.jsx                  |   12 
 src/menu/modalconfig/tablecomponent/index.jsx                                      |    5 
 src/menu/components/card/double-data-card/index.jsx                                |   36 
 src/views/login/logincloudform.jsx                                                 |    4 
 src/menu/components/card/doublecardcomponent/index.jsx                             |   11 
 src/menu/stylecontroller/styleInput/index.jsx                                      |   39 
 src/router/index.js                                                                |    6 
 src/menu/pastecontroller/index.jsx                                                 |   10 
 src/menu/components/card/data-card/index.jsx                                       |   44 
 src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx                      |   22 
 src/menu/components/chart/antv-dashboard/index.jsx                                 |   15 
 src/views/appmanage/index.jsx                                                      |   18 
 src/views/design/header/versions/index.jsx                                         |    9 
 src/menu/components/search/main-search/options.jsx                                 |   14 
 src/menu/components/tabs/antv-tabs/index.jsx                                       |   26 
 src/tabviews/custom/components/card/tableHeader/index.jsx                          |    2 
 src/menu/modulesource/index.jsx                                                    |   53 
 src/components/tabview/index.scss                                                  |   17 
 src/templates/sharecomponent/settingcomponent/index.jsx                            |   63 
 src/views/design/index.jsx                                                         |   59 
 src/menu/components/chart/antv-G6/index.jsx                                        |   16 
 src/menu/components/share/sourcecomponent/inputform/index.jsx                      |   60 
 src/menu/components/table/normal-table/options.jsx                                 |   14 
 src/components/header/index.jsx                                                    |  245 
 src/components/sidemenu/index.scss                                                 |    2 
 src/views/pcdesign/menuform/index.jsx                                              |   62 
 src/mob/modulesource/dragsource/index.jsx                                          |    5 
 src/tabviews/custom/components/card/double-data-card/index.jsx                     |  385 
 src/templates/zshare/verifycard/callbackcustomscript/index.jsx                     |   73 
 src/tabviews/custom/components/card/cardItem/index.jsx                             |   14 
 src/menu/components/chart/antv-X6/index.jsx                                        |  684 
 src/menu/transfer/index.jsx                                                        |  118 
 src/pc/quotecomponent/index.jsx                                                    |    2 
 src/views/rolemanage/index.jsx                                                     |    8 
 src/tabviews/custom/components/carousel/data-card/index.jsx                        |  279 
 src/templates/sharecomponent/fieldscomponent/index.jsx                             |  107 
 src/menu/components/code/sandbox/index.jsx                                         |   17 
 src/tabviews/zshare/mutilform/mkSelect/index.jsx                                   |   27 
 src/views/billprint/index.scss                                                     |    6 
 src/views/tabledesign/menuform/index.jsx                                           |   14 
 src/tabviews/custom/components/calendar/board/index.jsx                            |  660 +
 src/templates/zshare/createfunc/utils.js                                           |  454 
 src/components/normalform/modalform/mkTable/index.jsx                              |    3 
 src/tabviews/custom/components/chart/custom-chart/index.jsx                        |  274 
 src/templates/sharecomponent/settingcomponent/settingform/utils.jsx                |    2 
 src/menu/components/card/balcony/index.jsx                                         |   53 
 src/tabviews/zshare/actionList/tabbutton/index.jsx                                 |   14 
 src/menu/components/calendar/board/index.jsx                                       |  513 
 src/components/normalform/modalform/index.jsx                                      |    2 
 src/menu/stylecontroller/index.jsx                                                 |  229 
 src/menu/components/chart/antv-X6/lane.json                                        | 1162 +
 src/templates/zshare/verifycard/index.jsx                                          |   24 
 src/menu/components/share/sourcecomponent/index.jsx                                |    2 
 src/tabviews/zshare/actionList/printbutton/index.jsx                               |  168 
 src/store/options.js                                                               |   11 
 src/menu/components/calendar/index.scss                                            |   84 
 src/menu/components/card/cardcellcomponent/formconfig.jsx                          |   31 
 src/templates/sharecomponent/actioncomponent/index.jsx                             |  515 
 src/menu/components/editor/braft-editor/index.jsx                                  |   16 
 src/components/normalform/modalform/mkTable/index.scss                             |    3 
 package.json                                                                       |    3 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx   |   20 
 src/tabviews/zshare/actionList/popupbutton/index.scss                              |   15 
 src/tabviews/zshare/topSearch/advanceform/index.jsx                                |    9 
 src/tabviews/zshare/topSearch/dategroup/index.scss                                 |    3 
 src/menu/components/share/markcomponent/markform/index.jsx                         |    3 
 src/views/systemproc/proc/index.jsx                                                |   14 
 src/menu/components/calendar/board/index.scss                                      |   40 
 src/menu/components/tree/antd-tree/options.jsx                                     |   12 
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx               |  154 
 src/menu/components/share/markcomponent/index.jsx                                  |   47 
 src/mob/components/tabs/antv-tabs/options.jsx                                      |   78 
 src/views/basedesign/updateFormTab/index.jsx                                       | 1358 ++
 src/menu/components/card/cardcellcomponent/dragaction/action.jsx                   |    7 
 src/menu/components/card/cardcellcomponent/elementform/index.jsx                   |   14 
 src/menu/viewnodes/index.jsx                                                       |    2 
 src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.scss       |    0 
 src/templates/modalconfig/index.jsx                                                |   51 
 src/views/systemfunc/index.jsx                                                     |   40 
 src/tabviews/custom/components/form/step-form/index.scss                           |    1 
 src/templates/sharecomponent/tablecomponent/index.jsx                              |  169 
 src/tabviews/zshare/actionList/newpagebutton/index.jsx                             |   59 
 src/views/design/sidemenu/index.jsx                                                |   25 
 src/mob/modalconfig/index.jsx                                                      |   38 
 src/tabviews/commontable/index.jsx                                                 |   69 
 src/assets/css/design.scss                                                         |   24 
 src/components/header/loginform.jsx                                                |   17 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx               |   48 
 src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx             |   20 
 src/menu/components/form/formaction/formconfig.jsx                                 |   48 
 src/tabviews/zshare/topSearch/mkCheckCard/index.jsx                                |  336 
 src/tabviews/custom/components/card/cardcellList/index.jsx                         |  103 
 src/tabviews/custom/components/card/prop-card/index.jsx                            |  387 
 src/tabviews/zshare/actionList/funczip/index.jsx                                   |    8 
 src/views/design/sidemenu/editsecmenu/index.jsx                                    |    6 
 src/menu/components/carousel/data-card/options.jsx                                 |   14 
 src/menu/components/card/data-card/options.jsx                                     |   31 
 src/mob/components/menubar/normal-menubar/index.jsx                                |   16 
 src/tabviews/custom/components/table/normal-table/index.jsx                        |  778 
 src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx |   21 
 src/mob/modulesource/index.jsx                                                     |   53 
 src/menu/components/tabs/antv-tabs/options.jsx                                     |   54 
 src/tabviews/custom/components/chart/antv-pie/index.jsx                            |  226 
 src/tabviews/custom/components/timeline/normal-timeline/index.jsx                  |  278 
 src/templates/subtableconfig/index.jsx                                             |   16 
 src/components/mkIcon/index.jsx                                                    |   31 
 src/tabviews/custom/components/table/edit-table/normalTable/index.jsx              |  101 
 src/menu/components/group/groupcomponents/card.jsx                                 |    8 
 src/components/breadview/index.jsx                                                 |   35 
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss                 |  231 
 src/tabviews/zshare/mutilform/index.jsx                                            |  164 
 src/menu/components/share/actioncomponent/actionform/index.jsx                     |  119 
 src/tabviews/custom/index.jsx                                                      |  528 
 src/menu/components/card/cardcomponent/index.scss                                  |    1 
 src/menu/components/table/normal-table/columns/index.jsx                           |    1 
 src/tabviews/zshare/mutilform/mkDatePicker/index.jsx                               |    4 
 src/tabviews/treepage/index.jsx                                                    |   28 
 src/menu/components/timeline/normal-timeline/options.jsx                           |   14 
 src/tabviews/custom/components/chart/antv-scatter/index.jsx                        |  256 
 src/menu/components/card/cardcellcomponent/dragaction/index.scss                   |    2 
 src/tabviews/custom/components/form/tab-form/index.scss                            |    7 
 src/views/design/header/index.jsx                                                  |   51 
 src/views/printTemplate/index.jsx                                                  |    7 
 src/menu/components/group/groupcomponents/index.jsx                                |    1 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx    |   10 
 src/menu/components/chart/antv-X6/chartcompile/index.jsx                           |  143 
 src/menu/components/form/formaction/actionform/index.jsx                           |  241 
 src/tabviews/custom/components/chart/antv-G6/index.jsx                             |  322 
 src/menu/components/table/base-table/columns/editColumn/formconfig.jsx             |   20 
 src/tabviews/zshare/actionList/exceloutbutton/index.jsx                            |  506 
 src/views/design/sidemenu/thdmenuform/index.jsx                                    |   15 
 src/menu/components/card/cardcellcomponent/dragaction/card.jsx                     |   13 
 src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx                 |   12 
 src/pc/modulesource/dragsource/index.jsx                                           |    5 
 src/menu/components/card/balcony/index.scss                                        |    4 
 src/menu/components/chart/antv-bar/index.jsx                                       |   23 
 src/views/tabledesign/index.jsx                                                    |   58 
 src/pc/modulesource/index.jsx                                                      |   53 
 src/tabviews/zshare/actionList/index.jsx                                           |    1 
 src/tabviews/custom/components/form/simple-form/index.jsx                          |  156 
 src/tabviews/subtable/index.jsx                                                    |   68 
 src/menu/components/table/edit-table/index.jsx                                     |   39 
 src/menu/components/carousel/data-card/index.jsx                                   |   23 
 src/views/basedesign/updateFormTab/index.scss                                      |   18 
 src/tabviews/custom/components/card/table-card/index.jsx                           |  295 
 src/menu/components/module/voucher/options.jsx                                     |    2 
 src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx                 |   33 
 src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx                     |   12 
 src/components/imgScale/index.scss                                                 |    2 
 src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx        |   89 
 src/menu/components/form/step-form/index.jsx                                       |   62 
 src/tabviews/zshare/mutilform/mkCheckCard/index.jsx                                |   26 
 public/manifest.json                                                               |    3 
 src/menu/components/chart/antv-X6/xflow.json                                       |  986 +
 src/views/mobdesign/popview/index.jsx                                              |    3 
 src/menu/components/search/main-search/index.jsx                                   |    1 
 src/tabviews/zshare/pageMessage/index.jsx                                          |    5 
 src/views/login/index.scss                                                         |   13 
 src/tabviews/zshare/topSearch/mkRadio/index.jsx                                    |   77 
 src/tabviews/zshare/topSearch/mkRadio/index.scss                                   |    0 
 src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx        |   94 
 src/tabviews/zshare/topSearch/mkDatePicker/index.jsx                               |    6 
 src/components/sidemenu/index.jsx                                                  |   80 
 src/views/login/index.jsx                                                          |  198 
 src/components/keyInterface/index.jsx                                              |    8 
 src/tabviews/zshare/mutilform/mkRadio/index.jsx                                    |   20 
 src/utils/utils-datamanage.js                                                      |  389 
 src/menu/picturecontroller/index.jsx                                               |   73 
 src/tabviews/custom/components/code/sand-box/index.jsx                             |  226 
 src/menu/components/table/edit-table/columns/tableIn/index.jsx                     |   12 
 src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx   |    4 
 src/menu/components/card/table-card/index.jsx                                      |   34 
 src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx                      |   77 
 src/utils/utils-custom.js                                                          |    7 
 src/views/main/index.jsx                                                           |   49 
 src/views/design/header/editfirstmenu/index.jsx                                    |    6 
 src/tabviews/zshare/actionList/excelInbutton/index.jsx                             |  111 
 public/options.json                                                                |    4 
 src/menu/components/share/searchcomponent/dragsearch/card.jsx                      |    2 
 src/menu/components/tabs/tabcomponents/index.jsx                                   |    2 
 src/menu/components/table/normal-table/columns/editColumn/index.jsx                |    3 
 src/tabviews/basetable/index.jsx                                                   |  263 
 src/menu/tablenodes/index.jsx                                                      |    2 
 src/menu/menushell/card.jsx                                                        |   13 
 src/tabviews/zshare/mutilform/mkVercode/index.jsx                                  |   50 
 src/menu/components/code/sandbox/options.jsx                                       |   12 
 src/menu/components/iframe/options.jsx                                             |    3 
 src/views/design/sidemenu/editthdmenu/index.jsx                                    |   24 
 src/views/mobdesign/index.jsx                                                      |   90 
 src/views/interface/history/index.jsx                                              |    2 
 src/api/cacheutils.js                                                              |    2 
 src/menu/components/card/double-data-card/options.jsx                              |   14 
 src/mob/colorsketch/index.jsx                                                      |   56 
 src/tabviews/custom/components/calendar/board/index.scss                           |  115 
 src/templates/zshare/modalform/datatable/index.jsx                                 |   13 
 src/menu/components/share/actioncomponent/formconfig.jsx                           |  177 
 src/tabviews/custom/components/group/normal-group/index.jsx                        |  296 
 README.md                                                                          |    2 
 src/tabviews/custom/components/carousel/prop-card/index.jsx                        |  241 
 src/templates/zshare/createinterface/index.jsx                                     |    5 
 src/menu/components/table/base-table/columns/index.jsx                             |   10 
 src/tabviews/custom/components/module/voucher/resetAttach/addAttach/index.jsx      |    2 
 src/views/imdesign/index.jsx                                                       |   50 
 src/menu/components/table/normal-table/index.jsx                                   |   45 
 src/views/design/sidemenu/thdmenuplus/index.jsx                                    |    8 
 src/menu/components/calendar/options.jsx                                           |  236 
 src/tabviews/zshare/actionList/asyncButtonComponent.jsx                            |    2 
 src/templates/sharecomponent/searchcomponent/searchform/index.jsx                  |   28 
 src/components/tabview/index.jsx                                                   |  122 
 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx           |   34 
 src/tabviews/custom/components/table/base-table/index.jsx                          |  260 
 src/tabviews/custom/components/card/double-data-card/index.scss                    |    2 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx |   61 
 src/components/resetPassword/resetpwd/index.jsx                                    |   25 
 src/tabviews/zshare/mutilform/mkSwitch/index.jsx                                   |   17 
 src/pc/components/navbar/normal-navbar/menusetting/menutable/index.scss            |    4 
 src/views/mobdesign/menuform/index.jsx                                             |   57 
 src/menu/datasource/verifycard/customscript/index.jsx                              |  156 
 src/templates/sharecomponent/searchcomponent/index.jsx                             |    1 
 src/tabviews/zshare/topSearch/mkSelect/index.jsx                                   |    2 
 src/tabviews/custom/components/calendar/index.jsx                                  |  380 
 src/tabviews/custom/components/share/normalTable/index.jsx                         |   90 
 src/tabviews/iframe/index.jsx                                                      |    1 
 src/tabviews/custom/components/calendar/index.scss                                 |   38 
 src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx                    |   22 
 src/components/breadview/index.scss                                                |   12 
 src/tabviews/custom/components/card/data-card/index.scss                           |    2 
 src/utils/utils.js                                                                 |  876 -
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx                  |  513 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx              |  347 
 src/index.js                                                                       |  134 
 src/tabviews/custom/components/form/tab-form/index.jsx                             |  177 
 src/views/sso/index.jsx                                                            |    8 
 src/templates/zshare/createfunc/index.jsx                                          |  256 
 src/tabviews/custom/components/share/tabtransfer/index.jsx                         |  267 
 src/tabviews/debugtable/index.jsx                                                  |   10 
 src/tabviews/rolemanage/index.jsx                                                  |   10 
 src/templates/treepageconfig/updatetable/index.jsx                                 | 1259 ++
 src/templates/treepageconfig/updatetable/index.scss                                |    0 
 src/templates/zshare/formconfig.jsx                                                |  117 
 src/tabviews/custom/components/interfaces/interItem/index.jsx                      |   21 
 src/tabviews/custom/components/module/voucher/resetAttach/index.jsx                |    4 
 src/menu/replaceField/index.jsx                                                    |    9 
 src/menu/components/chart/chart-custom/chartcompile/formconfig.jsx                 |   12 
 src/pc/createview/index.jsx                                                        |    6 
 /dev/null                                                                          |    0 
 src/tabviews/custom/components/chart/antv-X6/index.scss                            |  232 
 src/templates/sharecomponent/searchcomponent/settingform/index.jsx                 |   22 
 src/assets/mobimg/xflow.png                                                        |    0 
 src/menu/modalconfig/index.jsx                                                     |   40 
 src/tabviews/custom/components/card/balcony/index.jsx                              |  255 
 src/tabviews/custom/components/card/cardcellList/index.scss                        |    3 
 src/menu/components/table/base-table/index.jsx                                     |   10 
 src/templates/zshare/verifycard/baseform/index.jsx                                 |   38 
 src/menu/menushell/index.jsx                                                       |    1 
 src/utils/option.js                                                                |   35 
 src/menu/components/calendar/index.jsx                                             |  265 
 366 files changed, 24,446 insertions(+), 11,805 deletions(-)

diff --git a/README.md b/README.md
index 68eb8cd..a1068e0 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,8 @@
 
 See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
 
+node --max-old-space-size=9000 scripts/build.js
+
 ### `npm run eject`
 
 **Note: this is a one-way operation. Once you `eject`, you can鈥檛 go back!**
diff --git a/config/webpack.config.js b/config/webpack.config.js
index a793358..5826327 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -49,6 +49,14 @@
 const cssModuleRegex = /\.module\.css$/;
 const sassRegex = /\.(scss|sass)$/;
 const sassModuleRegex = /\.module\.(scss|sass)$/;
+const sign = (() => {
+  let uuid = []
+  let options = '0123456789abcdefghigklmnopqrstuv'
+  for (let i = 0; i < 8; i++) {
+    uuid.push(options.substr(Math.floor(Math.random() * 0x20), 1))
+  }
+  return uuid.join('')
+})()
 
 // src => @
 function resolves(dir) {
@@ -175,14 +183,14 @@
       // In development, it does not produce real files.
       // contenthash => hash
       filename: isEnvProduction
-        ? 'static/js/[name].[hash:8].js'
+        ? `static/js/[name].${sign}.js`
         : isEnvDevelopment && 'static/js/bundle.js',
       // TODO: remove this when upgrading to webpack 5
       futureEmitAssets: true,
       // There are also additional JS chunk files if you use code splitting.
       // contenthash => hash
       chunkFilename: isEnvProduction
-        ? 'static/js/[name].[hash:8].chunk.js'
+        ? `static/js/[name].${sign}.chunk.js`
         : isEnvDevelopment && 'static/js/[name].chunk.js',
       // We inferred the "public path" (such as / or /my-project) from homepage.
       // We use "/" in development.
@@ -354,7 +362,7 @@
               loader: require.resolve('url-loader'),
               options: {
                 limit: imageInlineSizeLimit,
-                name: 'static/media/[name].[hash:8].[ext]',
+                name: `static/media/[name].${sign}.[ext]`,
               },
             },
             // Process application JS with Babel.
@@ -494,7 +502,7 @@
               // by webpacks internal loaders.
               exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
               options: {
-                name: 'static/media/[name].[hash:8].[ext]',
+                name: `static/media/[name].${sign}.[ext]`,
               },
             },
             // ** STOP ** Are you adding a new loader?
@@ -568,8 +576,8 @@
           // Options similar to the same options in webpackOptions.output
           // both options are optional
           // contenthash => hash
-          filename: 'static/css/[name].[hash:8].css',
-          chunkFilename: 'static/css/[name].[hash:8].chunk.css',
+          filename: `static/css/[name].${sign}.css`,
+          chunkFilename: `static/css/[name].${sign}.chunk.css`,
         }),
       // Generate a manifest file which contains a mapping of all asset filenames
       // to their corresponding output file so that tools can pick it up without
diff --git a/package-lock.json b/package-lock.json
index 6f465c9..48029da 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -657,6 +657,11 @@
       "resolved": "https://registry.npmjs.org/@antv/x6-plugin-dnd/-/x6-plugin-dnd-2.0.5.tgz",
       "integrity": "sha512-g8GGJS2XmM8C59juOBiFqaR/f8i8y8tqw9sJNwta7s1Phh3hwDd7o4kk36Kk5eTKkfZfnjEyWHMOqp/h+EDibQ=="
     },
+    "@antv/x6-plugin-export": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-export/-/x6-plugin-export-2.1.6.tgz",
+      "integrity": "sha512-m0ukMmZhrFE5n7uCR43DVQBdiUfpjGN+vm1mc+6RTZdHK8pa6Mxr0RZztaxPy34YA4tli+bGY3ePslsNPfh6PQ=="
+    },
     "@antv/x6-plugin-history": {
       "version": "2.2.3",
       "resolved": "https://registry.npmjs.org/@antv/x6-plugin-history/-/x6-plugin-history-2.2.3.tgz",
@@ -5485,9 +5490,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001464",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001464.tgz",
-      "integrity": "sha512-oww27MtUmusatpRpCGSOneQk2/l5czXANDSFvsc7VuOQ86s3ANhZetpwXNf1zY/zdfP63Xvjz325DAdAoES13g=="
+      "version": "1.0.30001523",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz",
+      "integrity": "sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA=="
     },
     "canvg": {
       "version": "3.0.10",
diff --git a/package.json b/package.json
index ab2d13a..07d00b5 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
     "@antv/x6": "^2.11.1",
     "@antv/x6-plugin-clipboard": "^2.1.6",
     "@antv/x6-plugin-dnd": "^2.0.5",
+    "@antv/x6-plugin-export": "^2.1.6",
     "@antv/x6-plugin-history": "^2.2.3",
     "@antv/x6-plugin-keyboard": "^2.2.1",
     "@antv/x6-plugin-scroller": "^2.0.9",
@@ -124,7 +125,7 @@
   },
   "scripts": {
     "dev": "set PORT=3001 && node scripts/start.js",
-    "build": "node scripts/build.js",
+    "build": "node --max-old-space-size=2048 scripts/build.js",
     "test": "node scripts/test.js"
   },
   "eslintConfig": {
diff --git a/public/index.html b/public/index.html
index 2e1c8b4..3da241a 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,12 +3,62 @@
   <head>
     <meta charset="utf-8" />
     <meta name="renderer" content="webkit">
-    <!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" /> -->
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <meta name="theme-color" content="#000000" />
     <link rel="shortcut icon" href="#">
     <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
     <title></title>
+    <script>
+      let _href = window.location.href.split('#')[0]
+      let l_version = localStorage.getItem(_href + 'version')
+      let _ctime = parseInt(new Date().getTime() / 1000)
+      let _time = ''
+
+      if (l_version) {
+        let vers = l_version.split('-')
+        l_version = vers[0]
+        _time = +vers[1]
+      }
+
+      if (_time && _ctime - _time < 180) {
+        let meta1 = document.createElement('meta')
+        let meta2 = document.createElement('meta')
+        let meta3 = document.createElement('meta')
+        let meta4 = document.createElement('meta')
+        meta1.content = '0'
+        meta1.httpEquiv = 'Expires'
+        meta2.content = 'no-cache'
+        meta2.httpEquiv = 'Pragma'
+        meta3.content = 'no-cache'
+        meta3.httpEquiv = 'Cache-Control'
+        meta4.content = 'no-cache'
+        meta4.httpEquiv = 'Cache'
+        document.getElementsByTagName('head')[0].appendChild(meta1)
+        document.getElementsByTagName('head')[0].appendChild(meta2)
+        document.getElementsByTagName('head')[0].appendChild(meta3)
+        document.getElementsByTagName('head')[0].appendChild(meta4)
+      } else {
+        fetch('./manifest.json', { cache: 'no-cache'})
+          .then(response => response.json())
+          .then(res => {
+            if (res && res.mk_version) {
+              let version = res.mk_version
+              let nocache = false
+
+              if (l_version && version !== l_version) {
+                nocache = true
+                localStorage.setItem(_href + 'version', version + '-' + _ctime)
+              } else if (!l_version) {
+                localStorage.setItem(_href + 'version', version + '-' + (_ctime - 360))
+              }
+
+              if (nocache) {
+                window.location.reload()
+              }
+            }
+          })
+      }
+    </script>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>
diff --git a/public/manifest.json b/public/manifest.json
index 2895bc5..d3654ec 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -5,5 +5,6 @@
   "start_url": ".",
   "display": "standalone",
   "theme_color": "#000000",
-  "background_color": "#ffffff"
+  "background_color": "#ffffff",
+  "mk_version": "20230712"
 }
diff --git a/public/options.json b/public/options.json
index 2f15ea6..b1d737a 100644
--- a/public/options.json
+++ b/public/options.json
@@ -10,12 +10,12 @@
   "defaultLang": "zh-CN",
   "WXAppID": "",
   "WXminiAppID": "",
-  "WXNotice": "false",
+  "WXNotice": "true",
   "nginx": "true",
   "debugger": true,
   "licenseKey": "",
   "probation": "",
-  "transfer": true,
+  "transfer": "true",
   "keepPassword": "true",
   "platforms": ["H5", "wechat", "android", "ios", "wxMiniProgram"],
   "host": "http://dms-test.worx.cn",
diff --git a/src/api/cacheutils.js b/src/api/cacheutils.js
index 265071c..3184290 100644
--- a/src/api/cacheutils.js
+++ b/src/api/cacheutils.js
@@ -234,7 +234,7 @@
       request.onsuccess = (e) => {
         let cursor = e.target.result
         if (cursor) {
-          if (cursor.value.CreateDate < date) {
+          if (cursor.value.CreateDate < date || cursor.value.CreateDate.length === 10) {
             cursor.delete()
           }
           cursor.continue()
diff --git a/src/api/index.js b/src/api/index.js
index 1170c94..94aafcd 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -1,16 +1,18 @@
 import axios from 'axios'
 import qs from 'qs'
-import { notification } from 'antd'
+import { notification, Modal } from 'antd'
 import md5 from 'md5'
 import CryptoJS from 'crypto-js'
 import jsSHA from 'jssha'
 import moment from 'moment'
+
 import Utils from '@/utils/utils.js'
+import MKEmitter from '@/utils/events.js'
 import CacheUtils from './cacheutils'
-import options from '@/store/options.js'
 
 window.GLOB.IndexDB = null
 window.GLOB.OuterToken = {}
+window.GLOB.$error = false
 
 let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : ''
 let db = `mkdb${service}`
@@ -23,68 +25,66 @@
 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
 axios.defaults.withCredentials = false
 
-// axios.interceptors.request.use((config) => {
-//   return config
-// }, (error) => {
-//   return Promise.reject(error)
-// })
-
-const setCurrentUrl = (res) => {
-  if (!!(window.history && window.history.pushState)) {
-    if (window.location.href.indexOf('paramsmain') > -1) {
-      let _href = window.location.href.split('#')
-      localStorage.setItem(_href[0] + 'paramsmain', _href[1])
-    }
-    localStorage.removeItem('UserID')
-    localStorage.removeItem('LoginUID')
-    localStorage.removeItem('User_Name')
-    localStorage.removeItem('Full_Name')
-    localStorage.removeItem('avatar')
-    localStorage.removeItem('dataM')
-    localStorage.removeItem('localDataM')
-    localStorage.removeItem('debug')
-    localStorage.removeItem('role_id')
-    localStorage.removeItem('mk_user_type')
-
-    sessionStorage.clear()
-    sessionStorage.setItem('loginError', JSON.stringify({url: res.config ? res.config.url : '', request: res.config ? res.config.data : '', response: JSON.stringify(res.data)}))
-    window.history.replaceState(null, null, window.location.href.split('#')[0] + '#/login')
-    window.location.reload()
-  }
-}
-
 axios.interceptors.response.use((response) => {
   if (response.data.ErrCode === 'LoginError') {
-    if (window.debugger === true) {
-      response.data.ErrCode = 'E'
-      return Promise.resolve(response.data)
-    } else if (window.GLOB.developing) {
+    if (window.GLOB.developing) {
       sessionStorage.setItem('devError', 'true')
       response.data.ErrCode = 'E'
       return Promise.resolve(response.data)
-    } else if (!sessionStorage.getItem('loginError')) {
-      setCurrentUrl(response)
+    } else if (response.config.url.indexOf('https://sso.mk9h.cn/webapi/dostars') > -1) {
+      return Promise.reject(response.data)
+    } else if (response.config.url.indexOf('https://epc.mk9h.cn/webapi/dostars') > -1) {
+      return Promise.reject(response.data)
     }
+
+    if (!window.GLOB.$error) {
+      window.GLOB.$error = true
+
+      Modal.destroyAll()
+      Modal.error({
+        title: response.data.message,
+        okText: '鐭ラ亾浜�',
+        onOk: () => {
+          window.GLOB.$error = false
+
+          localStorage.removeItem('UserID')
+          localStorage.removeItem('LoginUID')
+          localStorage.removeItem('User_Name')
+          localStorage.removeItem('Full_Name')
+          localStorage.removeItem('avatar')
+          localStorage.removeItem('dataM')
+          localStorage.removeItem('localDataM')
+          localStorage.removeItem('debug')
+          localStorage.removeItem('role_id')
+          localStorage.removeItem('mk_user_type')
+
+          sessionStorage.clear()
+          if (!!(window.history && window.history.pushState)) {
+            window.history.replaceState(null, null, window.location.href.split('#')[0] + '#/login')
+            window.location.reload()
+          }
+        }
+      })
+    }
+
+    return Promise.reject(response.data)
   } else {
     return Promise.resolve(response.data)
   }
 }, (error) => {
-  let response = error.response
+  let response = error.response || ''
 
-  if (response) {
-    if (!response.data || !response.data.errors) { // 杩囨护鏃疯鎶ラ敊淇℃伅
-      notification.error({
-        className: 'notification-custom-error',
-        bottom: 0,
-        message: '鐘舵�佺爜-' + response.status + '锛岃鑱旂郴绠$悊鍛�',
-        placement: 'bottomRight',
-        duration: 15
-      })
-    }
-    return Promise.reject(response)
-  } else {
-    return Promise.reject()
+  if (response && response.status) {
+    notification.error({
+      className: 'notification-custom-error',
+      bottom: 0,
+      message: '鐘舵�佺爜-' + response.status + '锛岃鑱旂郴绠$悊鍛�',
+      placement: 'bottomRight',
+      duration: 15
+    })
   }
+
+  return Promise.reject(response)
 })
 
 class Api {
@@ -231,16 +231,20 @@
       param.thd_party_openid = openid
       param.thd_party_appid = appid
       param.id = scanId
-    } else if (binding_type === 'login_check') { // appid 姝ゆ椂涓虹洰鏍�
+    } else if (binding_type === 'login_check') { // appid 姝ゆ椂涓虹洰鏍囧湴鍧�
       param.v_type = 'login_check'
       param.LoginUID = sessionStorage.getItem('LoginUID') || ''
-      url = appid.replace(/\/webapi(.*)/, '/webapi/dologon/s_visitor_login')
-
+      
       if (!param.rduri) {
         param.rduri = window.GLOB.baseurl + 'webapi/dologon/s_visitor_login'
       }
-
-      param.linkurl = appid.replace(/\/webapi(.*)/, '/index.html')
+      
+      if (appid) {
+        url = appid.replace(/\/webapi(.*)/, '/webapi/dologon/s_visitor_login')
+        param.linkurl = appid.replace(/\/webapi(.*)/, '/index.html')
+      } else {
+        param.linkurl = window.GLOB.linkurl
+      }
     }
     
     param.LText = md5(window.btoa(_SessionUid + param.timestamp + (param.linkurl || '')))
@@ -269,7 +273,7 @@
       Password: '',
       check_code: checkcode,
       way_no: 'sms_vcode',
-      systemType: options.sysType,
+      systemType: window.GLOB.sysType,
       login_city: sessionStorage.getItem('city') || '',
       login_id_address: sessionStorage.getItem('ipAddress') || '',
       kei_id: window.btoa(window.encodeURIComponent(window.GLOB.host)),
@@ -280,11 +284,11 @@
     let url = '/webapi/dologon'
     if (isCloud) {
       param.debug = 'Y'
-      if (options.cloudServiceApi) {
-        param.rduri = options.cloudServiceApi.replace(/\/webapi(.*)/, '/webapi/dologon')
+      if (window.GLOB.cloudServiceApi) {
+        param.rduri = window.GLOB.cloudServiceApi.replace(/\/webapi(.*)/, '/webapi/dologon')
       }
     } else if (window.GLOB.mainSystemApi) {
-      if (options.sysType !== 'cloud' && window.GLOB.systemType !== 'production') {
+      if (window.GLOB.sysType !== 'cloud' && window.GLOB.systemType !== 'production') {
         param.linkurl = window.GLOB.linkurl
       }
       param.rduri = window.GLOB.mainSystemApi.replace(/\/webapi(.*)/, '/webapi/dologon')
@@ -305,7 +309,7 @@
     let param = {
       // func: 'webapi_login',
       UserName: username,
-      systemType: options.sysType,
+      systemType: window.GLOB.sysType,
       Type: 'S',
       login_city: sessionStorage.getItem('city') || '',
       login_id_address: sessionStorage.getItem('ipAddress') || '',
@@ -340,11 +344,11 @@
 
     if (isCloud) {
       param.debug = 'Y'
-      if (options.cloudServiceApi) {
-        param.rduri = options.cloudServiceApi.replace(/\/webapi(.*)/, '/webapi/dologon')
+      if (window.GLOB.cloudServiceApi) {
+        param.rduri = window.GLOB.cloudServiceApi.replace(/\/webapi(.*)/, '/webapi/dologon')
       }
     } else if (window.GLOB.mainSystemApi) {
-      if (options.sysType !== 'cloud' && window.GLOB.systemType !== 'production') {
+      if (window.GLOB.sysType !== 'cloud' && window.GLOB.systemType !== 'production') {
         param.linkurl = window.GLOB.linkurl
       }
       param.rduri = window.GLOB.mainSystemApi.replace(/\/webapi(.*)/, '/webapi/dologon')
@@ -358,36 +362,31 @@
   }
 
   delCacheConfig (type = '') {
-    let date = moment().subtract(7, 'days').format('YYYY-MM-DD')
+    let date = moment().subtract(7, 'days').format('YYYY-MM-DD HH:mm:ss')
     CacheUtils.delIndexDBCacheConfig(date, type)
   }
 
-  writeCacheConfig (menuid, data) {
+  writeCacheConfig (menuid, data, BID = '', id = '') {
     if (!menuid) return
-    let date = moment().format('YYYY-MM-DD')
+    let date = moment().format('YYYY-MM-DD HH:mm:ss')
     let _data = data ? JSON.stringify(data) : ''
+    let userid = sessionStorage.getItem('UserID') || ''
 
-    CacheUtils.writeCacheInIndexDB({menuid, CreateDate: date, LongParam: _data})
+    CacheUtils.writeCacheInIndexDB({menuid: md5(menuid + userid + BID + id), BID: BID, id: id, CreateDate: date, LongParam: _data})
   }
 
-  getLCacheConfig (menuid) {
+  getLCacheConfig (menuid, minutes, BID = '', id = '') {
     return new Promise((resolve, reject) => {
-      if (window.GLOB.IndexDB) {
-        CacheUtils.getIndexDBCacheConfig(menuid).then(res => {
-          if (res && res.LongParam) {
-            let _data = JSON.parse(res.LongParam)
-            if (_data.length === 0) {
-              resolve()
-            } else {
-              resolve(_data)
-            }
-          } else {
-            resolve()
-          }
-        })
-      } else {
-        resolve()
-      }
+      let limit = minutes ? moment().subtract(minutes, 'minutes').format('YYYY-MM-DD HH:mm:ss') : ''
+      let userid = sessionStorage.getItem('UserID') || ''
+
+      CacheUtils.getIndexDBCacheConfig(md5(menuid + userid + BID + id)).then(res => {
+        if (res && res.LongParam) {
+          resolve({data: JSON.parse(res.LongParam), valid: !limit || res.CreateDate > limit})
+        } else {
+          resolve({data: null, valid: false})
+        }
+      })
     })
   }
 
@@ -439,6 +438,11 @@
           modifydate: msg.createDate
         }
 
+        if (window.GLOB.initVersion && sessionStorage.getItem('visitorUserID')) {
+          param.userid = sessionStorage.getItem('visitorUserID')
+          param.LoginUID = sessionStorage.getItem('visitorLoginUID')
+        }
+
         param.TypeCharOne = ''
         param.typename = ''
 
@@ -480,7 +484,8 @@
           if (list.length > 0) {
             let clear = false
             let _appkey = window.GLOB.appkey.substr(-10)
-            let reg = new RegExp(_appkey + '$', 'ig')
+            let reg = new RegExp(_appkey + '$', 'i')
+            let reHome = list.includes('home_page_id')
 
             list.forEach(mid => {
               if (reg.test(mid)) {
@@ -491,6 +496,11 @@
               list = ''
             }
             CacheUtils.delIndexDBConfig(list)
+            this.delCacheConfig('all')
+
+            if (reHome) {
+              MKEmitter.emit('reloadMenuView', 'home_page_id')
+            }
           }
 
           CacheUtils.updateIndexDBversion({version: res.app_version || '1.00', createDate: curTime})
@@ -524,14 +534,14 @@
    */
   getCloudConfig (param) {
     param.lang = param.lang || sessionStorage.getItem('lang') || ''
-    param.appkey = window.GLOB.appkey || ''
+    param.appkey = param.appkey || window.GLOB.appkey || ''
     param.SessionUid = localStorage.getItem('SessionUid') || ''
-    param.userid = sessionStorage.getItem('CloudUserID') || ''
-    param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
+    param.userid = param.userid || sessionStorage.getItem('CloudUserID') || ''
+    param.LoginUID = param.LoginUID || sessionStorage.getItem('CloudLoginUID') || ''
 
     param = this.encryptParam(param)
 
-    let url = options.cloudServiceApi ? options.cloudServiceApi : '/webapi/dostars'
+    let url = window.GLOB.cloudServiceApi ? window.GLOB.cloudServiceApi : '/webapi/dostars'
     if (param.func) {
       url = url + '/' + param.func
     }
@@ -578,8 +588,8 @@
     param.appkey = param.appkey || window.GLOB.appkey
 
     let url = '/webapi/dostars'
-    if (sessionStorage.getItem('isEditState') === 'true' && options.cloudServiceApi) { // 缂栬緫鐘舵�侊紝涓斿瓨鍦ㄤ簯绔湴鍧�
-      url = options.cloudServiceApi
+    if (window.GLOB.mkHS && window.GLOB.cloudServiceApi) { // HS涓嬶紝涓斿瓨鍦ㄤ簯绔湴鍧�
+      url = window.GLOB.cloudServiceApi
       param.userid = sessionStorage.getItem('CloudUserID') || ''
       param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
     } else if (window.GLOB.mainSystemApi) {
@@ -607,12 +617,12 @@
     param.lang = param.lang || sessionStorage.getItem('lang') || ''
     param.SessionUid = localStorage.getItem('SessionUid') || ''
     param.LoginUID = sessionStorage.getItem('LoginUID') || ''
-    param.appkey = window.GLOB.appkey || ''
+    param.appkey = param.appkey || window.GLOB.appkey || ''
 
     let url = '/webapi/dostars'
-    if (sessionStorage.getItem('isEditState') === 'true') { // 缂栬緫鐘舵�侊紝鍗曠偣鐧诲綍鏈嶅姟鍣ㄤ负浜戠
-      if (options.cloudServiceApi) { // 瀛樺湪浜戠鍦板潃鏃讹紝浣跨敤浜戠绯荤粺鍙傛暟
-        url = options.cloudServiceApi
+    if (window.GLOB.mkHS) {          // HS涓嬶紝鍗曠偣鐧诲綍鏈嶅姟鍣ㄤ负浜戠
+      if (window.GLOB.cloudServiceApi) { // 瀛樺湪浜戠鍦板潃鏃讹紝浣跨敤浜戠绯荤粺鍙傛暟
+        url = window.GLOB.cloudServiceApi
         param.userid = sessionStorage.getItem('CloudUserID') || ''
         param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
       }
@@ -831,7 +841,7 @@
     } else {
       let _param = {
         UserName: token.username,
-        systemType: options.sysType,
+        systemType: window.GLOB.sysType,
         login_city: sessionStorage.getItem('city') || '',
         device_id: token.appkey || '',
         timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
@@ -899,14 +909,9 @@
       return new Promise(resolve => this.visitOuterSystem(param, resolve))
     }
 
-    if (['sPC_Get_TableData', 'sPC_Get_TableData_debug', 'sPC_TableData_InUpDe', 'sPC_TableData_InUpDe_debug', 'sPC_Get_structured_data'].includes(param.func)) {
-      if (sessionStorage.getItem('isEditState') === 'true') {
-        param.username = sessionStorage.getItem('CloudUserName') || ''
-        param.fullname = sessionStorage.getItem('CloudFullName') || ''
-      } else {
-        param.username = sessionStorage.getItem('User_Name') || ''
-        param.fullname = sessionStorage.getItem('Full_Name') || ''
-      }
+    if (['sPC_TableData_InUpDe', 'sPC_TableData_InUpDe_debug'].includes(param.func)) {
+      param.username = sessionStorage.getItem('User_Name') || ''
+      param.fullname = sessionStorage.getItem('Full_Name') || ''
     }
 
     let login = false
diff --git a/src/assets/css/design.scss b/src/assets/css/design.scss
index 5d11010..e7a8ac6 100644
--- a/src/assets/css/design.scss
+++ b/src/assets/css/design.scss
@@ -52,6 +52,30 @@
     }
   }
 }
+.ant-modal-wrap.mk-scroll-modal {
+  .ant-modal {
+    top: 50px;
+  }
+  .ant-modal-body {
+    min-height: 150px;
+    max-height: calc(100vh - 170px);
+    overflow-y: auto;
+  }
+  .ant-modal-body::-webkit-scrollbar {
+    width: 7px;
+  }
+  .ant-modal-body::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+  }
+  .ant-modal-body::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0.07);
+    background: rgba(0, 0, 0, 0);
+  }
+}
 
 .ant-modal {
   .ant-radio-group {
diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index a822a26..25d2b93 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -16,6 +16,18 @@
     outline: none;
   }
 }
+::selection {
+  color: #ffffff;
+  background: var(--mk-sys-color);
+}
+::-moz-selection {
+  color: #ffffff;
+  background: var(--mk-sys-color);
+}
+::-webkit-selection {
+  color: #ffffff;
+  background: var(--mk-sys-color);
+}
 
 .table-col-1, .table-col-2, .table-col-3, .table-col-4 {
   .ant-table colgroup > col.ant-table-selection-col {
@@ -296,6 +308,12 @@
     border: 1px solid rgba(0, 0, 0, 0.07);
     background: rgba(0, 0, 0, 0);
   }
+  .ant-modal-footer {
+    .ant-btn:not(.ant-btn-primary):active, .ant-btn:not(.ant-btn-primary).active, .ant-btn:not(.ant-btn-primary):hover, .ant-btn:not(.ant-btn-primary):focus {
+      color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+  }
 }
 
 // 璁剧疆妯℃�佹鏍峰紡锛岃瀹氭渶澶ф渶灏忛珮搴︼紝閲嶇疆婊氬姩鏉�
@@ -324,6 +342,17 @@
     border-radius: 3px;
     border: 1px solid rgba(0, 0, 0, 0.07);
     background: rgba(0, 0, 0, 0);
+  }
+
+  .ant-modal-footer {
+    .ant-btn:not(.ant-btn-primary):active, .ant-btn:not(.ant-btn-primary).active, .ant-btn:not(.ant-btn-primary):hover, .ant-btn:not(.ant-btn-primary):focus {
+      color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+    .ant-btn-primary {
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
   }
 }
 .moveable-modal {
@@ -442,6 +471,151 @@
   padding: 2px 8px!important;
   line-height: 1.5;
 }
+.ant-calendar-picker-container {
+  .ant-calendar-range {
+    .ant-calendar-selected-start-date .ant-calendar-date,
+    .ant-calendar-selected-end-date .ant-calendar-date {
+      background: var(--mk-sys-color);
+    }
+
+    .ant-calendar-in-range-cell::before {
+      background: var(--mk-sys-color1);
+    }
+
+    .ant-calendar-selected-start-date .ant-calendar-date:hover,
+    .ant-calendar-selected-end-date .ant-calendar-date:hover {
+      background: var(--mk-sys-color);
+    }
+  }
+
+  .ant-calendar-date:hover {
+    background: var(--mk-sys-color1);
+  }
+
+  .ant-calendar-date:active {
+    background: var(--mk-sys-color5);
+  }
+
+  .ant-calendar-today .ant-calendar-date {
+    color: var(--mk-sys-color);
+    border-color: var(--mk-sys-color);
+  }
+
+  .ant-calendar-header a:hover {
+    color: var(--mk-sys-color5);
+  }
+  .ant-calendar-year-panel-header a:hover {
+    color: var(--mk-sys-color5);
+  }
+  .ant-calendar-month-panel-cell-disabled .ant-calendar-month-panel-month,
+  .ant-calendar-month-panel-cell-disabled .ant-calendar-month-panel-month:hover {
+    color: rgba(0, 0, 0, 0.25);
+  }
+  .ant-calendar-decade-panel-decade:hover {
+    background: var(--mk-sys-color1);
+  }
+
+  .ant-calendar-decade-panel-selected-cell .ant-calendar-decade-panel-decade:hover,
+  .ant-calendar-decade-panel-selected-cell .ant-calendar-decade-panel-decade {
+    color: #ffffff;
+    background: var(--mk-sys-color);
+  }
+
+  .ant-calendar-year-panel-selected-cell .ant-calendar-year-panel-year {
+    background: var(--mk-sys-color);
+  }
+  .ant-calendar-year-panel-selected-cell .ant-calendar-year-panel-year:hover {
+    color: #fff;
+    background: var(--mk-sys-color);
+  }
+  .ant-calendar-year-panel-year:hover {
+    background: var(--mk-sys-color1);
+  }
+
+  .ant-calendar-month-panel-selected-cell:not(.ant-calendar-month-panel-cell-disabled) .ant-calendar-month-panel-month {
+    background: var(--mk-sys-color);
+  }
+  .ant-calendar-month-panel-selected-cell:not(.ant-calendar-month-panel-cell-disabled) .ant-calendar-month-panel-month:hover {
+    color: #fff;
+    background: var(--mk-sys-color);
+  }
+  .ant-calendar-month-panel-month:hover {
+    background: var(--mk-sys-color1);
+  }
+
+  .ant-calendar-time-picker-select li:hover {
+    background: var(--mk-sys-color1);
+  }
+  .ant-calendar-time-picker-select li:focus {
+    color: var(--mk-sys-color);
+  }
+
+  .ant-calendar {
+    tr td {
+      .ant-calendar-year-panel-year.ant-year-selected {
+        color: #fff;
+        background: var(--mk-sys-color);
+      }
+      .ant-calendar-year-panel-year:hover {
+        color: var(--mk-sys-color5);
+        background: var(--mk-sys-color1);
+      }
+    }
+  }
+
+  .ant-calendar-time-picker-btn {
+    color: var(--mk-sys-color);
+  }
+  .ant-calendar {
+    .ant-calendar-ok-btn {
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+
+    .ant-calendar-ok-btn:hover,
+    .ant-calendar-ok-btn:focus,
+    .ant-calendar-ok-btn:active,
+    .ant-calendar-ok-btn.active {
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+  }
+  .ant-calendar-footer-extra {
+    .ant-tag-blue {
+      color: var(--mk-sys-color);
+      background: var(--mk-sys-color1);
+      border-color: var(--mk-sys-color3);
+    }
+  }
+
+  .ant-calendar-selected-day .ant-calendar-date {
+    background: var(--mk-sys-color2);
+  }
+  .ant-calendar-today-btn {
+    color: var(--mk-sys-color);
+  }
+
+  .ant-calendar-week-number {
+    .ant-calendar-body tr.ant-calendar-active-week {
+      background: var(--mk-sys-color2);
+    }
+    .ant-calendar-body tr:hover {
+      background: var(--mk-sys-color1);
+    }
+  }
+}
+.ant-calendar-quarter-picker .ant-calendar {
+  tr:not(.ant-quarter-selected):hover {
+    background: var(--mk-sys-color1);
+  }
+  tr.ant-quarter-selected {
+    background: var(--mk-sys-color2);
+  }
+}
+.ant-calendar-picker:focus .ant-calendar-picker-input:not(.ant-input-disabled) {
+  border-color: var(--mk-sys-color5)!important;
+  box-shadow: 0 0 0 2px var(--mk-sys-color2)!important;
+}
 .mk-date-picker.minute {
   .ant-calendar-time-picker-combobox {
     .ant-calendar-time-picker-select {
@@ -513,4 +687,26 @@
 
 .ant-col.ant-col-0 {
   display: inline-block;
+}
+
+.ant-dropdown {
+  .ant-dropdown-menu-item:hover, .ant-dropdown-menu-submenu-title:hover {
+    background-color: var(--mk-sys-color1);
+  }
+}
+
+.ant-radio-group {
+  .ant-radio-button-wrapper.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled) {
+    color: var(--mk-sys-color);
+    border-color: var(--mk-sys-color);
+    box-shadow: -1px 0 0 0 var(--mk-sys-color);
+  }
+  .ant-radio-button-wrapper.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover {
+    color: var(--mk-sys-color);
+    border-color: var(--mk-sys-color);
+    box-shadow: -1px 0 0 0 var(--mk-sys-color);
+  }
+  .ant-radio-button-wrapper:not(.ant-radio-button-wrapper-checked):not(.ant-radio-button-wrapper-disabled):hover {
+    color: var(--mk-sys-color);
+  }
 }
\ No newline at end of file
diff --git a/src/assets/css/viewstyle.scss b/src/assets/css/viewstyle.scss
index 29384da..cd8538b 100644
--- a/src/assets/css/viewstyle.scss
+++ b/src/assets/css/viewstyle.scss
@@ -8,33 +8,7 @@
 // color8  8闃惰壊
 // color9  9闃惰壊
 // color10 10闃惰壊
-@mixin viewstyle($color1, $color2, $color3, $color4, $color5, $color6, $color7) {
-  #root > .mk-main-view {
-    >.mk-tabview-wrap {
-      >.content-header {
-        >.ant-tabs {
-          >.ant-tabs-bar {
-            .ant-tabs-tab:hover {
-              color: $color5;
-            }
-            .ant-tabs-tab.ant-tabs-tab-active {
-              color: $color6;
-            }
-            .ant-tabs-ink-bar {
-              background-color: $color6;
-            }
-          }
-        }
-      }
-    }
-    >.mk-breadview-wrap {
-      >.ant-breadcrumb {
-        .anticon-redo:hover, .anticon-home:hover {
-          color: $color5;
-        }
-      }
-    }
-  }
+@mixin viewstyle($color1, $color2, $color3, $color4, $color5, $color6) {
   .custom-data-card-box, .custom-prop-card-box {
     .data-zoom.radio.active, .data-zoom.checkbox.active {
       .mk-card:not(.active):not(.selected):hover {
@@ -106,34 +80,6 @@
       }
     }
   }
-  .normal-group-wrap {
-    .print-button:hover, .print-button:focus, .print-button:active {
-      color: $color5;
-    }
-  }
-  // 鎼滅储鏍�
-  .mk-search-wrap {
-    >.ant-row {
-      .ant-col.search-button {
-        .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link).active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):hover, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):focus {
-          color: $color7;
-          border-color: $color7;
-        }
-        .ant-btn-primary {
-          background-color: $color6;
-          border-color: $color6;
-        }
-        .ant-btn-link {
-          color: $color6;
-        }
-      }
-    }
-    .advanced-list {
-      .advance-value {
-        color: $color6;
-      }
-    }
-  }
   // 琛ㄦ牸
   .normal-data-table, .normal-custom-table, .edit-custom-table {
     table {
@@ -156,34 +102,12 @@
       }
     }
   }
-  // 寮圭獥鎸夐挳
-  .popview-modal {
-    .ant-modal-footer {
-      .ant-btn:not(.ant-btn-primary):active, .ant-btn:not(.ant-btn-primary).active, .ant-btn:not(.ant-btn-primary):hover, .ant-btn:not(.ant-btn-primary):focus {
-        color: $color7;
-        border-color: $color7;
-      }
-    }
-  }
-  // 琛ㄥ崟寮圭獥
-  .action-modal {
-    .ant-modal-footer {
-      .ant-btn:not(.ant-btn-primary):active, .ant-btn:not(.ant-btn-primary).active, .ant-btn:not(.ant-btn-primary):hover, .ant-btn:not(.ant-btn-primary):focus {
-        color: $color7;
-        border-color: $color7;
-      }
-      .ant-btn-primary {
-        background-color: $color6;
-        border-color: $color6;
-      }
-    }
-  }
   // 鏄惁妗�
   .ant-modal-confirm-confirm {
     .ant-modal-confirm-btns {
       .ant-btn:not(.ant-btn-primary):active, .ant-btn:not(.ant-btn-primary).active, .ant-btn:not(.ant-btn-primary):hover, .ant-btn:not(.ant-btn-primary):focus {
-        color: $color7;
-        border-color: $color7;
+        color: $color6;
+        border-color: $color6;
       }
       .ant-btn-primary {
         background-color: $color6;
@@ -199,7 +123,7 @@
     background-color: $color6;
   }
   .ant-tabs-nav .ant-tabs-tab:active {
-    color: $color7;
+    color: $color6;
   }
   .ant-tabs-nav .ant-tabs-tab:hover {
     color: $color5;
@@ -300,16 +224,6 @@
     color: $color6;
   }
 
-  .custom-tab-form-box .mk-normal-form-title.mkbtn {
-    .form-title {
-      color: $color6;
-      border-color: $color6;
-    }
-    .form-title.active {
-      background: $color6;
-      color: #ffffff;
-    }
-  }
   .ant-input-search .ant-input-group-addon .ant-input-search-button {
     background-color: $color6;
     border-color: $color6;
@@ -383,7 +297,7 @@
   --mk-sys-color3: #91d5ff;
   --mk-sys-color4: #69c0ff;
   --mk-sys-color5: #40a9ff;
-  @include viewstyle(#e6f7ff, #bae7ff, #91d5ff, #69c0ff, #40a9ff, #1890ff, #096dd9);
+  @include viewstyle(#e6f7ff, #bae7ff, #91d5ff, #69c0ff, #40a9ff, #1890ff);
 }
 
 body[class*='mk-red-'] {
@@ -393,7 +307,7 @@
   --mk-sys-color3: #ffa39e;
   --mk-sys-color4: #ff7875;
   --mk-sys-color5: #ff4d4f;
-  @include viewstyle(#fff1f0, #ffccc7, #ffa39e, #ff7875, #ff4d4f, #f5222d, #cf1322);
+  @include viewstyle(#fff1f0, #ffccc7, #ffa39e, #ff7875, #ff4d4f, #f5222d);
 }
 
 body[class*='mk-orange-red-'] {
@@ -403,7 +317,7 @@
   --mk-sys-color3: #ffbb96;
   --mk-sys-color4: #ff9c6e;
   --mk-sys-color5: #ff7a45;
-  @include viewstyle(#fff2e8, #ffd8bf, #ffbb96, #ff9c6e, #ff7a45, #fa541c, #d4380d);
+  @include viewstyle(#fff2e8, #ffd8bf, #ffbb96, #ff9c6e, #ff7a45, #fa541c);
 }
 
 body[class*='mk-orange-'] {
@@ -413,7 +327,7 @@
   --mk-sys-color3: #ffd591;
   --mk-sys-color4: #ffc069;
   --mk-sys-color5: #ffa940;
-  @include viewstyle(#fff7e6, #ffe7ba, #ffd591, #ffc069, #ffa940, #fa8c16, #d46b08);
+  @include viewstyle(#fff7e6, #ffe7ba, #ffd591, #ffc069, #ffa940, #fa8c16);
 }
 
 body[class*='mk-orange-yellow-'] {
@@ -423,7 +337,7 @@
   --mk-sys-color3: #ffe58f;
   --mk-sys-color4: #ffd666;
   --mk-sys-color5: #ffc53d;
-  @include viewstyle(#fffbe6, #fff1b8, #ffe58f, #ffd666, #ffc53d, #faad14, #d48806);
+  @include viewstyle(#fffbe6, #fff1b8, #ffe58f, #ffd666, #ffc53d, #faad14);
 }
 
 body[class*='mk-yellow-'] {
@@ -433,7 +347,7 @@
   --mk-sys-color3: #fffb8f;
   --mk-sys-color4: #fff566;
   --mk-sys-color5: #ffec3d;
-  @include viewstyle(#feffe6, #ffffb8, #fffb8f, #fff566, #ffec3d, #fadb14, #d4b106);
+  @include viewstyle(#feffe6, #ffffb8, #fffb8f, #fff566, #ffec3d, #fadb14);
 }
 
 body[class*='mk-yellow-green-'] {
@@ -443,7 +357,7 @@
   --mk-sys-color3: #eaff8f;
   --mk-sys-color4: #d3f261;
   --mk-sys-color5: #bae637;
-  @include viewstyle(#fcffe6, #f4ffb8, #eaff8f, #d3f261, #bae637, #a0d911, #7cb305);
+  @include viewstyle(#fcffe6, #f4ffb8, #eaff8f, #d3f261, #bae637, #a0d911);
 }
 
 body[class*='mk-green-'] {
@@ -453,7 +367,7 @@
   --mk-sys-color3: #b7eb8f;
   --mk-sys-color4: #95de64;
   --mk-sys-color5: #73d13d;
-  @include viewstyle(#f6ffed, #d9f7be, #b7eb8f, #95de64, #73d13d, #52c41a, #389e0d);
+  @include viewstyle(#f6ffed, #d9f7be, #b7eb8f, #95de64, #73d13d, #52c41a);
 }
 
 body[class*='mk-cyan-'] {
@@ -463,7 +377,7 @@
   --mk-sys-color3: #87e8de;
   --mk-sys-color4: #5cdbd3;
   --mk-sys-color5: #36cfc9;
-  @include viewstyle(#e6fffb, #b5f5ec, #87e8de, #5cdbd3, #36cfc9, #13c2c2, #08979c);
+  @include viewstyle(#e6fffb, #b5f5ec, #87e8de, #5cdbd3, #36cfc9, #13c2c2);
 }
 
 body[class*='mk-blue-purple-'] {
@@ -473,7 +387,7 @@
   --mk-sys-color3: #adc6ff;
   --mk-sys-color4: #85a5ff;
   --mk-sys-color5: #597ef7;
-  @include viewstyle(#f0f5ff, #d6e4ff, #adc6ff, #85a5ff, #597ef7, #2f54eb, #1d39c4);
+  @include viewstyle(#f0f5ff, #d6e4ff, #adc6ff, #85a5ff, #597ef7, #2f54eb);
 }
 
 body[class*='mk-purple-'] {
@@ -483,7 +397,7 @@
   --mk-sys-color3: #d3adf7;
   --mk-sys-color4: #b37feb;
   --mk-sys-color5: #9254de;
-  @include viewstyle(#f9f0ff, #efdbff, #d3adf7, #b37feb, #9254de, #722ed1, #531dab);
+  @include viewstyle(#f9f0ff, #efdbff, #d3adf7, #b37feb, #9254de, #722ed1);
 }
 
 body[class*='mk-magenta-'] {
@@ -493,7 +407,7 @@
   --mk-sys-color3: #ffadd2;
   --mk-sys-color4: #ff85c0;
   --mk-sys-color5: #f759ab;
-  @include viewstyle(#fff0f6, #ffd6e7, #ffadd2, #ff85c0, #f759ab, #eb2f96, #c41d7f);
+  @include viewstyle(#fff0f6, #ffd6e7, #ffadd2, #ff85c0, #f759ab, #eb2f96);
 }
 
 body[class*='mk-grass-green-'] {
@@ -503,7 +417,7 @@
   --mk-sys-color3: #d9d26c;
   --mk-sys-color4: #ccc845;
   --mk-sys-color5: #bfbf22;
-  @include viewstyle(#f2efda, #e6de97, #d9d26c, #ccc845, #bfbf22, #aeb303, #838c00);
+  @include viewstyle(#f2efda, #e6de97, #d9d26c, #ccc845, #bfbf22, #aeb303);
 }
 
 body[class*='mk-deep-red-'] {
@@ -513,7 +427,7 @@
   --mk-sys-color3: #e89b9e;
   --mk-sys-color4: #db7077;
   --mk-sys-color5: #cf4856;
-  @include viewstyle(#fff0f0, #f5cbcb, #e89b9e, #db7077, #cf4856, #c32539, #9c162c);
+  @include viewstyle(#fff0f0, #f5cbcb, #e89b9e, #db7077, #cf4856, #c32539);
 }
 
 body[class*='mk-deep-blue-'] {
@@ -523,5 +437,5 @@
   --mk-sys-color3: #dbdfe6;
   --mk-sys-color4: #c6cede;
   --mk-sys-color5: #394c6f;
-  @include viewstyle(#eff1f4, #e0e3e9, #dbdfe6, #c6cede, #394c6f, #1d3661, #1d3661);
+  @include viewstyle(#eff1f4, #e0e3e9, #dbdfe6, #c6cede, #394c6f, #1d3661);
 }
\ No newline at end of file
diff --git a/src/assets/mobimg/xflow.png b/src/assets/mobimg/xflow.png
index 3fa7da2..f15d8dd 100644
--- a/src/assets/mobimg/xflow.png
+++ b/src/assets/mobimg/xflow.png
Binary files differ
diff --git a/src/components/breadview/index.jsx b/src/components/breadview/index.jsx
index b1f59ca..3a44900 100644
--- a/src/components/breadview/index.jsx
+++ b/src/components/breadview/index.jsx
@@ -6,7 +6,6 @@
 
 import asyncComponent from '@/utils/asyncLoadComponent'
 import NotFount from '@/components/404'
-import options from '@/store/options.js'
 import MKEmitter from '@/utils/events.js'
 import Api from '@/api'
 import './index.scss'
@@ -15,11 +14,11 @@
 const CustomPage = asyncComponent(() => import('@/tabviews/custom'))
 const CommonTable = asyncComponent(() => import('@/tabviews/commontable'))
 const BaseTable = asyncComponent(() => import('@/tabviews/basetable'))
-const CalendarPage = asyncComponent(() => import('@/tabviews/calendar'))
 const TreePage = asyncComponent(() => import('@/tabviews/treepage'))
 const Iframe = asyncComponent(() => import('@/tabviews/iframe'))
 const RoleManage = asyncComponent(() => import('@/tabviews/rolemanage'))
-const FormTab = asyncComponent(() => import('@/tabviews/formtab'))
+
+moment.locale('zh-cn')
 
 class BreadView extends Component {
   state = {
@@ -31,7 +30,7 @@
     const { tabview } = this.state
     window.GLOB.CacheMap = new Map()
 
-    if (options.sysType === 'local' && window.GLOB.systemType !== 'production') {
+    if (window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
       let roledefer = new Promise(resolve => {
         Api.getSystemConfig({
           func: 's_Get_TrdMenu_Role',
@@ -88,35 +87,25 @@
   selectcomponent = (view) => {
     // 鏍规嵁tab椤典腑鑿滃崟淇℃伅锛岄�夋嫨鎵�闇�鐨勭粍浠�
     if (view.type === 'BaseTable') {
-      return (<BaseTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param} changeTemp={this.changeTemp}/>)
+      return (<BaseTable MenuID={view.MenuID} MenuName={view.MenuName} param={view.param} changeTemp={this.changeTemp}/>)
     } else if (view.type === 'CustomPage') {
-      return (<CustomPage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param} changeTemp={this.changeTemp}/>)
+      return (<CustomPage MenuID={view.MenuID} MenuName={view.MenuName} param={view.param} changeTemp={this.changeTemp}/>)
     } else if (view.type === 'Home') {
-      return (<Home MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>)
+      return (<Home MenuID={view.MenuID} MenuName={view.MenuName}/>)
     } else if (view.type === 'RolePermission') {
-      return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>)
+      return (<RoleManage MenuID={view.MenuID}/>)
     } else if (view.type === 'CommonTable') {
-      return (<CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param} changeTemp={this.changeTemp}/>)
+      return (<CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} param={view.param} changeTemp={this.changeTemp}/>)
     } else if (view.type === 'TreePage') {
-      return (<TreePage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>)
-    } else if (view.type === 'CalendarPage') {
-      return (<CalendarPage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>)
-    } else if (view.type === 'FormTab') {
-      return (<FormTab MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>)
+      return (<TreePage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} param={view.param}/>)
     } else if (view.type === 'iframe') {
-      return (<Iframe key={view.MenuID} MenuID={view.MenuID} MenuNo={view.MenuNo} title={view.MenuName} MenuName={view.MenuName} url={window.GLOB.baseurl + 'zh-CN/' + view.LinkUrl}/>)
+      return (<Iframe MenuID={view.MenuID} title={view.MenuName} url={view.src}/>)
     } else {
-      return (<NotFount key={view.MenuID} />)
+      return (<NotFount />)
     }
   }
 
   UNSAFE_componentWillMount () {
-    if (!sessionStorage.getItem('lang') || sessionStorage.getItem('lang') === 'zh-CN') {
-      moment.locale('zh-cn')
-    } else {
-      moment.locale('en')
-    }
-
     let home = {
       MenuID: 'home_page_id',
       MenuName: '棣栭〉',
@@ -163,7 +152,7 @@
     const { tabview, hasNavBar } = this.state
 
     return (
-      <section id="mk-breadview-wrap" className="mk-breadview-wrap">
+      <section id="mk-tabgroup-wrap" className="mk-breadview-wrap">
         {hasNavBar && tabview ? <Breadcrumb separator="">
           <Breadcrumb.Item>
             <HomeOutlined onClick={this.gotoHome} />
diff --git a/src/components/breadview/index.scss b/src/components/breadview/index.scss
index 810603f..bf7a267 100644
--- a/src/components/breadview/index.scss
+++ b/src/components/breadview/index.scss
@@ -13,15 +13,16 @@
       cursor: pointer;
       margin-right: 5px;
     }
+    .anticon-redo:hover, .anticon-home:hover {
+      color: var(--mk-sys-color5);
+    }
     .ant-breadcrumb-link + .ant-breadcrumb-separator {
       display: none;
     }
   }
-  >.commontable, >.calendar-page {
+  >.commontable {
     padding-left: 15px;
     padding-right: 15px;
-  }
-  >.commontable, >.calendar-page {
     > .mk-search-wrap {
       padding-left: 0;
       padding-right: 0;
@@ -30,10 +31,11 @@
   }
   iframe {
     width: 100%;
-    height: calc(100vh - 115px);
+    height: calc(100vh - 92px);
     overflow-y: scroll;
     border: 0;
-    margin-top: 16px;
+    margin: 0px;
+    vertical-align: top;
   }
   .ant-back-top {
     bottom: 10px;
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index def0339..7db59b7 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -1,21 +1,13 @@
 import React, {Component} from 'react'
 import { withRouter } from 'react-router-dom'
-import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { Dropdown, Menu, Modal, notification, Switch, Input } from 'antd'
 import { SearchOutlined, DownOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
 
-import {
-  toggleCollapse,
-  modifyMainMenu,
-  logout
-} from '@/store/action'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import asyncComponent from '@/utils/asyncComponent'
 import Api from '@/api'
 import MKEmitter from '@/utils/events.js'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import avatar from '@/assets/img/avatar.jpg'
 import './index.scss'
@@ -27,9 +19,6 @@
 const LoginForm = asyncSpinComponent(() => import('./loginform'))
 
 class Header extends Component {
-  static propTpyes = {
-    collapse: PropTypes.bool
-  }
   state = {
     menulist: null, // 涓�绾ц彍鍗�
     userName: '',
@@ -41,13 +30,73 @@
     systems: [],
     searchkey: '',
     thdMenuList: [],
-    debug: sessionStorage.getItem('debug') === 'true'
+    debug: sessionStorage.getItem('debug') === 'true' && window.GLOB.memberLevel > 0,
+    collapse: sessionStorage.getItem('collapse') === 'true'
+  }
+
+  UNSAFE_componentWillMount () {
+    window.GLOB.mainMenu = null
+    // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
+    this.getRolesMenu()
+
+    let fullName = sessionStorage.getItem('Full_Name') || ''
+    let userName = sessionStorage.getItem('User_Name') || ''
+
+    if (fullName.toLowerCase() === userName.toLowerCase()) {
+      userName = ''
+    }
+
+    this.setState({fullName, userName})
+  }
+
+  componentDidMount () {
+    // 鑾峰彇绯荤粺鐨勭増鏈俊鎭紝寤舵椂鏌ヨ
+    setTimeout(() => {
+      Api.getAppVersion()
+    }, 1000)
+
+    // sessionStorage 璺ㄩ〉闈㈠叡浜�
+    window.addEventListener('storage', (e) => {
+      if (e.key === 'getSessionStorage' && e.newValue === window.GLOB.appkey) {
+        localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage))
+      } else if (e.key === 'getSysPermission' && e.newValue === window.GLOB.appkey) {
+        localStorage.setItem('sysPermissions', JSON.stringify({mkThdMenus: window.GLOB.mkThdMenus, mkActions: window.GLOB.mkActions}))
+      } else if (e.key === 'menuUpdate') {
+        let vals = e.newValue.split(',')
+        let menuId = vals[1]
+        let position = vals[2] || ''
+        if (position === 'menu') {
+          MKEmitter.emit('reloadMenuView', menuId)
+        } else if (menuId) {
+          Api.getAppVersion(menuId).then(() => {
+            MKEmitter.emit('reloadMenuView', menuId)
+          })
+        }
+      }
+    })
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
   }
 
   handleCollapse = () => {
-    // 灞曞紑銆佹敹璧峰乏渚ц彍鍗曟爮
-    this.props.toggleCollapse(!this.props.collapse)
-    localStorage.setItem('collapse', !this.props.collapse)
+    const { collapse } = this.state
+
+    sessionStorage.setItem('collapse', !collapse)
+
+    this.setState({collapse: !collapse})
+
+    MKEmitter.emit('toggleCollapse', !collapse)
   }
 
   changePassword = () => {
@@ -55,7 +104,6 @@
     MKEmitter.emit('resetpassword', () => {
       setTimeout(() => {
         sessionStorage.clear()
-        this.props.logout()
         this.props.history.replace('/login')
       }, 2000)
     })
@@ -71,7 +119,6 @@
       cancelText: '鍙栨秷',
       onOk() {
         sessionStorage.clear()
-        _this.props.logout()
         _this.props.history.replace('/login')
       },
       onCancel() {}
@@ -80,16 +127,19 @@
 
   changeMenu (value) {
     // 涓昏彍鍗曞垏鎹�
-    if (value.OpenType === 'outpage') {
-      window.open(value.linkUrl)
+    if (value.OpenType === 'newpage') {
+      window.open(value.src)
+    } else if (value.OpenType === 'newtab') {
+      MKEmitter.emit('modifyTabs', value)
     } else if (value.OpenType === 'menu') {
-      this.props.modifyMainMenu(value)
+      window.GLOB.mainMenu = value
+      MKEmitter.emit('mainMenuChange')
     }
   }
 
   getRolesMenu () {
     // 鑾峰彇涓昏彍鍗曞弬鏁�
-    let _param = {func: 's_get_pc_menus', systemType: options.sysType}
+    let _param = {func: 's_get_pc_menus', systemType: window.GLOB.sysType}
     _param.pro_sys = window.GLOB.systemType === 'production' ? 'Y' : ''
     
     Api.getSystemConfig(_param).then(result => {
@@ -105,10 +155,10 @@
       const { menulist, thdMenuList } = this.getMenulist(result)
 
       let systems = []
-      if ((options.sysType === 'local' || options.sysType === 'SSO') && result.sys_list) {
+      if ((window.GLOB.sysType === 'local' || window.GLOB.sysType === 'SSO') && result.sys_list) {
         systems = result.sys_list
 
-        if (options.sysType === 'local' && window.GLOB.systemType !== 'production' && systems.length > 10) {
+        if (window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production' && systems.length > 10) {
           systems.length = 10
         }
       }
@@ -129,16 +179,14 @@
         sessionStorage.removeItem('ThirdMenu')
       }
 
-      this.props.modifyMainMenu(mainMenu)
-
+      window.GLOB.mainMenu = mainMenu
       window.GLOB.mkThdMenus = [...thdMenuList, {MenuID: 'home_page_id', EasyCode: '', MenuName: 'home', type: 'CustomPage'}]
 
-      if (_menu) { // 寤舵椂鎵撳紑锛岄槻姝㈡爣绛剧粍鏈畬鎴愬姞杞�
-        setTimeout(() => {
-          MKEmitter.emit('modifyTabs', _menu)
-        }, 200)
+      MKEmitter.emit('mainMenuChange')
+
+      if (_menu) {
+        this.openTab(_menu, 0)
       }
-      MKEmitter.emit('mkMenuLoaded')
     })
     
     // 鑾峰彇瑙掕壊鏉冮檺, edition_type 鎺ュ彛鐗堟湰鎺у埗 ''銆�'Y'銆�'A'
@@ -165,10 +213,24 @@
           })
         }
 
-        MKEmitter.emit('mkActionLoaded')
         window.GLOB.mkActions = _permAction
       })
     }, 50)
+  }
+
+  openTab = (menu, times) => {
+    if (times > 50) return
+    times++
+
+    let tabgroup = document.getElementById('mk-tabgroup-wrap')
+
+    if (window.GLOB.mkActions.loaded && tabgroup) {
+      MKEmitter.emit('modifyTabs', menu)
+    } else {
+      setTimeout(() => {
+        this.openTab(times)
+      }, 200)
+    }
   }
 
   getMenulist = (result) => {
@@ -188,8 +250,13 @@
           let PageParam = JSON.parse(fst.PageParam)
 
           if (PageParam.OpenType === 'outpage' && PageParam.linkUrl) {
-            fstItem.OpenType = 'outpage'
-            fstItem.linkUrl = PageParam.linkUrl
+            fstItem.OpenType = 'newpage'
+            fstItem.src = PageParam.linkUrl
+            if (/#\/iframe\//.test(fstItem.src)) {
+              fstItem.src = fstItem.src.replace(/@loginuid@/ig, sessionStorage.getItem('LoginUID'))
+              fstItem.type = 'iframe'
+              fstItem.OpenType = 'newtab'
+            }
           }
         } catch (e) {}
       }
@@ -237,16 +304,23 @@
                   trdItem.hidden = PageParam.hidden || 'false'
 
                   if (trdItem.type === 'NewPage') {
+                    trdItem.OpenType = 'newpage'
                     trdItem.src = PageParam.url || ''
+                    if (/#\/iframe\//.test(trdItem.src)) {
+                      trdItem.src = trdItem.src.replace(/@loginuid@/ig, sessionStorage.getItem('LoginUID'))
+                      trdItem.type = 'iframe'
+                      trdItem.OpenType = 'newtab'
+                    }
+                  } else if (trdItem.OpenType === 'view') {
+                    trdItem.OpenType = 'newpage'
+                    trdItem.src = '#/view/' + trd.MenuID
+                  } else {
+                    trdItem.src = '#/tab/' + trd.MenuID
                   }
                 } catch (e) {}
-              }
-
-              if (trdItem.type !== 'NewPage') {
+              } else {
                 trdItem.src = '#/tab/' + trd.MenuID
               }
-
-              trdItem.OpenType = trdItem.OpenType.toLowerCase() // NewPage涓烘墦寮�澶栭儴椤甸潰鍦板潃
 
               if (names.has(trdItem.menu_name)) {
                 doublenames.set(trdItem.menu_name, true)
@@ -289,10 +363,7 @@
         loginVisible: true
       })
     } else {
-      sessionStorage.setItem('isEditState', 'true')
-
-      this.props.modifyMainMenu(null)
-
+      window.GLOB.mainMenu = null
       this.props.history.replace('/design')
     }
   }
@@ -331,15 +402,15 @@
           sessionStorage.setItem('cloudDataM', res.dataM ? 'true' : '')
           sessionStorage.setItem('cloudRole_id', res.role_id || '')
 
-          sessionStorage.setItem('isEditState', 'true')
-
+          let _url = window.location.href.split('#')[0] + 'cloud'
           if (param.remember) {
-            let _url = window.location.href.split('#')[0] + 'cloud'
-
             localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify({time: new Date().getTime(), username: param.username, password: param.password}))))
+          } else {
+            localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify({time: new Date().getTime(), username: param.username, password: ''}))))
           }
 
-          this.props.modifyMainMenu(null)
+          window.GLOB.mainMenu = null
+
           this.props.history.replace('/design')
         } else {
           if (res.message.indexOf('瀵嗙爜閿欒') > -1) {
@@ -421,69 +492,23 @@
       }
     })
   }
-  
-  UNSAFE_componentWillMount () {
-    // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
-    this.getRolesMenu()
-
-    let fullName = sessionStorage.getItem('Full_Name') || ''
-    let userName = sessionStorage.getItem('User_Name') || ''
-
-    if (fullName.toLowerCase() === userName.toLowerCase()) {
-      userName = ''
-    }
-
-    this.setState({fullName, userName})
-  }
-
-  componentDidMount () {
-    // 鑾峰彇绯荤粺鐨勭増鏈俊鎭紝寤舵椂鏌ヨ
-    setTimeout(() => {
-      Api.getAppVersion()
-    }, 1000)
-
-    // sessionStorage 璺ㄩ〉闈㈠叡浜�
-    window.addEventListener('storage', (e) => {
-      if (e.key === 'getSessionStorage' && e.newValue === window.GLOB.appkey) {
-        localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage))
-      } else if (e.key === 'menuUpdate') {
-        let menuId = e.newValue.split(',')[1]
-        if (menuId) {
-          Api.getAppVersion(menuId).then(() => {
-            MKEmitter.emit('reloadMenuView', menuId)
-          })
-        }
-      }
-    })
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-  }
 
   gotoDoc = () => {
-    if (options.sysType === 'local' && window.GLOB.mainSystemApi) {
+    if (window.GLOB.sysType === 'local' && window.GLOB.mainSystemApi) {
       let ssodomain = window.GLOB.mainSystemApi.replace('/webapi/dostars', '')
       let url = `${ssodomain}/doc/index.html#?appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
       window.open(url)
-    } else if (options.sysType === 'SSO' || options.sysType === 'cloud') {
+    } else if (window.GLOB.sysType === 'SSO' || window.GLOB.sysType === 'cloud') {
       window.open(`${window.location.href.replace(/\/admin(.*)|\/index.html(.*)|\/#(.*)/ig, '')}/doc/index.html#?appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`)
     }
   }
 
   changeVerMenu(menu, type) {
     if (type === 'first') {
-      if (menu.OpenType === 'outpage') {
-        window.open(menu.linkUrl)
+      if (menu.OpenType === 'newpage') {
+        window.open(menu.src)
+      } else if (menu.OpenType === 'newtab') {
+        MKEmitter.emit('modifyTabs', menu)
       }
     } else {
       if (menu.OpenType === 'newpage') {
@@ -550,8 +575,7 @@
   }
 
   render () {
-    const { mainMenu, collapse } = this.props
-    const { thdMenuList, searchkey, debug, menulist } = this.state
+    const { thdMenuList, searchkey, debug, menulist, collapse } = this.state
     const navBar = window.GLOB.navBar
 
     const menu = (
@@ -593,7 +617,7 @@
           <ul className="header-menu">{
             menulist.map(item => {
               return (
-                <li key={item.MenuID} onClick={() => {this.changeMenu(item)}} className={mainMenu && mainMenu.MenuID === item.MenuID ? 'active' : ''}>
+                <li key={item.MenuID} onClick={() => {this.changeMenu(item)}} className={window.GLOB.mainMenu && window.GLOB.mainMenu.MenuID === item.MenuID ? 'active' : ''}>
                   <span>{item.MenuName}</span>
                 </li>
               )
@@ -748,19 +772,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    collapse: state.collapse,
-    mainMenu: state.mainMenu
-  }
-}
-
-const mapDispatchToProps = (dispatch) => {
-  return {
-    toggleCollapse: (collapse) => dispatch(toggleCollapse(collapse)),
-    modifyMainMenu: (mainMenu) => dispatch(modifyMainMenu(mainMenu)),
-    logout: () => dispatch(logout())
-  }
-}
-
-export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header))
\ No newline at end of file
+export default withRouter(Header)
\ No newline at end of file
diff --git a/src/components/header/index.scss b/src/components/header/index.scss
index d38a22d..dc9c47d 100644
--- a/src/components/header/index.scss
+++ b/src/components/header/index.scss
@@ -7,8 +7,8 @@
   width: 100%;
   height: 48px;
   display: flex;
-  background: var(--mk-sys-background);
-  color: var(--mk-sys-font-color);
+  background: var(--mk-sys-background)!important;
+  color: var(--mk-sys-font-color)!important;
 
   .header-logo {
     width: 180px;
diff --git a/src/components/header/loginform.jsx b/src/components/header/loginform.jsx
index b20fc13..95e702f 100644
--- a/src/components/header/loginform.jsx
+++ b/src/components/header/loginform.jsx
@@ -43,7 +43,7 @@
       this.setState({
         remember: true,
         username: _user.username,
-        password: '*********',
+        password: _user.password ? '*********' : '',
         oripassword: _user.password
       })
     }
@@ -59,8 +59,8 @@
             values.password = oripassword
           }
           
-          values.username = values.username.replace(/\t*|\v*|\s*/g, '')
-          values.password = values.password.replace(/\t*|\v*|\s*/g, '')
+          values.username = values.username.replace(/\t+|\v+|\s+/g, '')
+          values.password = values.password.replace(/\t+|\v+|\s+/g, '')
 
           resolve(values)
         } else {
@@ -94,8 +94,15 @@
   }
 
   componentDidMount () {
-    const input = document.getElementById('username')
-    input && input.focus()
+    const { username, password } = this.state
+
+    if (username && !password) {
+      const input = document.getElementById('password')
+      input && input.focus()
+    } else {
+      const input = document.getElementById('username')
+      input && input.focus()
+    }
   }
 
   render() {
diff --git a/src/components/imgScale/index.scss b/src/components/imgScale/index.scss
index 8d8c762..8bc7646 100644
--- a/src/components/imgScale/index.scss
+++ b/src/components/imgScale/index.scss
@@ -129,7 +129,7 @@
   margin-left: 12px;
   padding: 10px 12px;
   cursor: pointer;
-  font-size: 18px;
+  font-size: 1.5vw;
 }
 .mk-image-preview-operations-operation-disabled {
   color: rgba(255, 255, 255, 0.25);
diff --git a/src/components/keyInterface/index.jsx b/src/components/keyInterface/index.jsx
index 1319549..4e11761 100644
--- a/src/components/keyInterface/index.jsx
+++ b/src/components/keyInterface/index.jsx
@@ -205,8 +205,8 @@
                       message: '璇疯緭鍏ユ帴鍙e湴鍧�!'
                     },
                     {
-                      pattern: /^[0-9a-zA-Z:_./]+$/,
-                      message: '鍙彲浣跨敤鑻辨枃銆佹暟瀛椾互鍙�:_./'
+                      pattern: /^[0-9a-zA-Z:_\-./]+$/,
+                      message: '鍙彲浣跨敤鑻辨枃銆佹暟瀛椾互鍙�:_-./'
                     }
                   ]
                 })(<TextArea placeholder="http://******/webapi/dostars" rows={2}/>)}
@@ -216,8 +216,8 @@
                   initialValue: setting.ssoInterface || '',
                   rules: [
                     {
-                      pattern: /^[0-9a-zA-Z:_./]+$/,
-                      message: '鍙彲浣跨敤鑻辨枃銆佹暟瀛椾互鍙�:_./'
+                      pattern: /^[0-9a-zA-Z:_\-./]+$/,
+                      message: '鍙彲浣跨敤鑻辨枃銆佹暟瀛椾互鍙�:_-./'
                     }
                   ]
                 })(<TextArea placeholder="http://sso.mk9h.cn/cloud/webapi/dostars" rows={2}/>)}
diff --git a/src/components/mkIcon/index.jsx b/src/components/mkIcon/index.jsx
index 105f627..3427f4b 100644
--- a/src/components/mkIcon/index.jsx
+++ b/src/components/mkIcon/index.jsx
@@ -46,12 +46,8 @@
   }
 
   componentDidMount() {
-    if (!window.GLOB.designView) {
-      if (sessionStorage.getItem('systemIcons')) {
-        this.setState({cusicons: JSON.parse(sessionStorage.getItem('systemIcons'))})
-      } else {
-        this.getIcons()
-      }
+    if (!window.GLOB.designView && window.GLOB.systemIcons) {
+      this.setState({cusicons: window.GLOB.systemIcons})
     }
   }
 
@@ -65,27 +61,34 @@
   }
 
   getIcons = () => {
-    Api.getSystemConfig({ func: 's_get_icons' }).then(res => {
+    const { selectIcon } = this.state
+    
+    Api.getCloudConfig({ func: 's_get_icons' }).then(res => {
       if (!res.status) {
         notification.warning({
           top: 92,
           message: res.message,
           duration: 5
         })
-        sessionStorage.setItem('systemIcons', JSON.stringify([]))
-        return
-      } else if (!res.data) {
+        window.GLOB.systemIcons = []
         return
       }
 
-      let icons = res.data.map(item => {
+      let icons = (res.data || []).map(item => {
         item.icon_svg = window.decodeURIComponent(window.atob(item.icon_svg))
         return item
       })
 
-      sessionStorage.setItem('systemIcons', JSON.stringify(icons))
+      window.GLOB.systemIcons = icons
 
       this.setState({cusicons: icons})
+
+      if (icons.length > 0 && selectIcon && /<svg/.test(selectIcon)) {
+        setTimeout(() => {
+          let node = document.getElementById('mk-custom-tab')
+          node && node.click()
+        }, 200)
+      }
     })
   }
 
@@ -94,7 +97,9 @@
 
     this.setState({visible: true})
 
-    if (cusicons.length > 0 && selectIcon && /<svg/.test(selectIcon)) {
+    if (!window.GLOB.designView && !window.GLOB.systemIcons) {
+      this.getIcons()
+    } else if (cusicons.length > 0 && selectIcon && /<svg/.test(selectIcon)) {
       setTimeout(() => {
         let node = document.getElementById('mk-custom-tab')
         node && node.click()
diff --git a/src/components/normalform/modalform/index.jsx b/src/components/normalform/modalform/index.jsx
index 7ce6bc5..2b9b80c 100644
--- a/src/components/normalform/modalform/index.jsx
+++ b/src/components/normalform/modalform/index.jsx
@@ -299,7 +299,7 @@
       } else if (item.type === 'source') {
         content = (<SourceComponent type="" placement="right"/>)
       } else if (item.type === 'table') {
-        content = (<MKTable tip={item.tip || ''} columns={item.columns || []} actions={item.actions || []}/>)
+        content = (<MKTable tip={item.tip || ''} fixed={item.fixed === true} columns={item.columns || []} actions={item.actions || []}/>)
       } else if (item.type === 'hint') {
         fields.push(
           <Col span={24} key={index}>
diff --git a/src/components/normalform/modalform/mkTable/index.jsx b/src/components/normalform/modalform/mkTable/index.jsx
index ae23f22..3fdd300 100644
--- a/src/components/normalform/modalform/mkTable/index.jsx
+++ b/src/components/normalform/modalform/mkTable/index.jsx
@@ -392,6 +392,7 @@
   }
 
   render() {
+    const { fixed } = this.props
     let components = {
       body: {
         cell: EditableCell
@@ -436,7 +437,7 @@
     return (
       <EditableContext.Provider value={this.props.form}>
         <div className="modal-editable-table">
-          <Button disabled={!!this.state.editingKey} type="link" onClick={this.addline}><PlusOutlined style={{}}/></Button>
+          {!fixed ? <Button disabled={!!this.state.editingKey} type="link" onClick={this.addline}><PlusOutlined style={{}}/></Button> : null}
           <DndProvider>
             <Table
               bordered
diff --git a/src/components/normalform/modalform/mkTable/index.scss b/src/components/normalform/modalform/mkTable/index.scss
index d4bba52..a5620f0 100644
--- a/src/components/normalform/modalform/mkTable/index.scss
+++ b/src/components/normalform/modalform/mkTable/index.scss
@@ -20,7 +20,8 @@
     .color-sketch-block {
       width: 200px;
       position: relative;
-      top: 8px;
+      top: 4px;
+      white-space: nowrap;
     }
     .ant-select {
       width: 100%;
diff --git a/src/components/resetPassword/resetpwd/index.jsx b/src/components/resetPassword/resetpwd/index.jsx
index ee7a60a..514bab5 100644
--- a/src/components/resetPassword/resetpwd/index.jsx
+++ b/src/components/resetPassword/resetpwd/index.jsx
@@ -142,7 +142,30 @@
           })
           message.warning(res.message)
         }
-      }, () => {
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') {
+          let param = {
+            func: 's_visitor_login',
+            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), 
+            SessionUid: 'bh0bapabtd45epsgra79segbch6c1ibk',
+            TypeCharOne: 'pc',
+            appkey: '202004041613277377A6A2456D34A4948AE84'
+          }
+          
+          param.LText = md5(window.btoa('bh0bapabtd45epsgra79segbch6c1ibk' + param.timestamp))
+          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
+  
+          let params = {
+            url: 'https://sso.mk9h.cn/webapi/dologon',
+            method: 'post',
+            data: JSON.stringify(param)
+          }
+
+          Api.directRequest(params)
+
+          return
+        }
+
         clearTimeout(this.LoginTimer)
         this.setState({
           verdisabled: false,
diff --git a/src/components/sidemenu/index.jsx b/src/components/sidemenu/index.jsx
index 94686bd..263d66f 100644
--- a/src/components/sidemenu/index.jsx
+++ b/src/components/sidemenu/index.jsx
@@ -1,6 +1,4 @@
 import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { Menu } from 'antd'
 
@@ -11,17 +9,44 @@
 const { SubMenu } = Menu
 
 class Sidemenu extends Component {
-  static propTypes = {
-    collapse: PropTypes.bool
-  }
-
   state = {
     subMenulist: [],         // 浜岀骇鑿滃崟
     rootSubmenuKeys: null,
+    collapse: sessionStorage.getItem('collapse') === 'true',
     openKeys: null
   }
 
-  async loadsubmenu (menu) {
+  componentDidMount() {
+    MKEmitter.addListener('mainMenuChange', this.loadsubmenu)
+    MKEmitter.addListener('toggleCollapse', this.toggleCollapse)
+
+    if (window.GLOB.mainMenu) {
+      this.loadsubmenu()
+    }
+  }
+
+  shouldComponentUpdate(nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('mainMenuChange', this.loadsubmenu)
+    MKEmitter.removeListener('toggleCollapse', this.toggleCollapse)
+  }
+
+  toggleCollapse = (collapse) => {
+    this.setState({
+      collapse: collapse,
+      openKeys: []
+    })
+  }
+
+  loadsubmenu = () => {
+    let menu = window.GLOB.mainMenu
+
     if (!menu || !menu.MenuID) { // 娌℃湁涓昏彍鍗曟椂锛屾竻绌轰笅绾ц彍鍗�
       this.setState({
         subMenulist: [],
@@ -41,7 +66,7 @@
     this.setState({
       subMenulist: menu.children,
       rootSubmenuKeys: menu.children.map(item => item.MenuID),
-      openKeys: this.props.collapse ? [] : [openKey],
+      openKeys: this.state.collapse ? [] : [openKey],
     })
   }
 
@@ -59,22 +84,6 @@
     }
   }
 
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (!is(fromJS(this.props.mainMenu), fromJS(nextProps.mainMenu))) {
-      // 涓昏彍鍗曞垏鎹紝璇锋眰2銆�3绾ц彍鍗曟暟鎹�
-      this.loadsubmenu(nextProps.mainMenu)
-    } else if (nextProps.collapse && this.props.collapse !== nextProps.collapse) {
-      // 灞曞紑鍚堝苟鏃讹紝鍏抽棴灞曞紑鑿滃崟
-      this.setState({
-        openKeys: []
-      })
-    }
-  }
-
-  shouldComponentUpdate(nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
   onOpenChange = openKeys => {
     const latestOpenKey = openKeys.find(key => this.state.openKeys.indexOf(key) === -1)
     if (this.state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
@@ -87,13 +96,13 @@
   }
 
   render () {
-    const { mainMenu } = this.props
+    const { collapse } = this.state
 
-    if (mainMenu === '') return (<span className="mk-side-menu-hidden"></span>)
+    if (window.GLOB.mainMenu === '') return (<span className="mk-side-menu-hidden"></span>)
 
     return (
-      <aside id="mk-sidemenu-wrap" className={'mk-side-menu ant-menu-dark' + (this.props.collapse ? ' collapsed' : '')}>
-        <Menu openKeys={this.state.openKeys} onOpenChange={this.onOpenChange} mode="inline" theme="dark" inlineCollapsed={this.props.collapse}>
+      <aside id="mk-sidemenu-wrap" className={'mk-side-menu ant-menu-dark' + (collapse ? ' collapsed' : '')}>
+        <Menu openKeys={this.state.openKeys} onOpenChange={this.onOpenChange} mode="inline" theme="dark" inlineCollapsed={collapse}>
           {this.state.subMenulist && this.state.subMenulist.map((item) => {
             return (
               <SubMenu
@@ -108,7 +117,7 @@
                 {item.children.map(cell => {
                   return (
                     <Menu.Item key={cell.MenuID}>
-                      <a href={cell.src} id={cell.MenuID} onClick={(e) => this.changemenu(e, cell)}>{cell.MenuName}</a>
+                      <a href={cell.src} onClick={(e) => this.changemenu(e, cell)}>{cell.MenuName}</a>
                     </Menu.Item>
                   )
                 })}
@@ -121,15 +130,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    collapse: state.collapse,
-    mainMenu: state.mainMenu,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(Sidemenu)
\ No newline at end of file
+export default Sidemenu
\ No newline at end of file
diff --git a/src/components/sidemenu/index.scss b/src/components/sidemenu/index.scss
index b92ca04..c69265a 100644
--- a/src/components/sidemenu/index.scss
+++ b/src/components/sidemenu/index.scss
@@ -6,7 +6,7 @@
   padding: 48px 0 40px;
   transition: width 0.2s, flex 0.2s;
   border-right: 1px solid #d9d9d9;
-  background: var(--mk-sys-background);
+  background: var(--mk-sys-background)!important;
   .ant-menu-item {
     padding-left: 0!important;
     cursor: default;
diff --git a/src/components/tabview/index.jsx b/src/components/tabview/index.jsx
index 1b5e633..06635eb 100644
--- a/src/components/tabview/index.jsx
+++ b/src/components/tabview/index.jsx
@@ -1,6 +1,4 @@
 import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { fromJS } from 'immutable'
 import {Tabs, BackTop, notification} from 'antd'
 import { RedoOutlined, CloseOutlined } from '@ant-design/icons'
@@ -9,7 +7,6 @@
 
 import asyncComponent from '@/utils/asyncLoadComponent'
 import NotFount from '@/components/404'
-import options from '@/store/options.js'
 import MKEmitter from '@/utils/events.js'
 import Api from '@/api'
 import './index.scss'
@@ -18,21 +15,46 @@
 const CustomPage = asyncComponent(() => import('@/tabviews/custom'))
 const CommonTable = asyncComponent(() => import('@/tabviews/commontable'))
 const BaseTable = asyncComponent(() => import('@/tabviews/basetable'))
-const CalendarPage = asyncComponent(() => import('@/tabviews/calendar'))
 const TreePage = asyncComponent(() => import('@/tabviews/treepage'))
 const Iframe = asyncComponent(() => import('@/tabviews/iframe'))
 const RoleManage = asyncComponent(() => import('@/tabviews/rolemanage'))
-const FormTab = asyncComponent(() => import('@/tabviews/formtab'))
+
+moment.locale('zh-cn')
 
 class TabViews extends Component {
-  static propTpyes = {
-    collapse: PropTypes.bool
-  }
-
   state = {
     activeId: '',
-    tabviews: null, // 鏍囩闆�
+    tabviews: [],
     iFrameHeight: 0,
+  }
+
+  UNSAFE_componentWillMount () {
+    if (!window.GLOB.mkHS) {
+      this.setState({
+        activeId: 'home_page_id',
+        tabviews: [{
+          MenuID: 'home_page_id',
+          MenuName: '棣栭〉',
+          type: 'Home'
+        }]
+      })
+    }
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('modifyTabs', this.modifyTabs)
+    MKEmitter.addListener('closeTabView', this.closeTabView)
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('modifyTabs', this.modifyTabs)
+    MKEmitter.removeListener('closeTabView', this.closeTabView)
   }
 
   // 鍏抽棴tab椤碉紝閲嶆柊閫夋嫨鏄剧ず椤�
@@ -75,7 +97,7 @@
     e.stopPropagation()
     window.GLOB.CacheMap = new Map()
 
-    if (options.sysType === 'local' && window.GLOB.systemType !== 'production') {
+    if (window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
       let roledefer = new Promise(resolve => {
         Api.getSystemConfig({
           func: 's_Get_TrdMenu_Role',
@@ -195,75 +217,31 @@
   selectcomponent = (view) => {
     // 鏍规嵁tab椤典腑鑿滃崟淇℃伅锛岄�夋嫨鎵�闇�鐨勭粍浠�
     if (view.type === 'Home') {
-      return (<Home MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>)
-    } else if (view.type === 'CommonTable') {
-      return (<CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param} changeTemp={this.changeTemp}/>)
+      return (<Home MenuID={view.MenuID} MenuName={view.MenuName}/>)
     } else if (view.type === 'BaseTable') {
-      return (<BaseTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param} changeTemp={this.changeTemp}/>)
+      return (<BaseTable MenuID={view.MenuID} MenuName={view.MenuName} param={view.param} changeTemp={this.changeTemp}/>)
     } else if (view.type === 'CustomPage') {
-      return (<CustomPage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param} changeTemp={this.changeTemp}/>)
+      return (<CustomPage MenuID={view.MenuID} MenuName={view.MenuName} param={view.param} changeTemp={this.changeTemp}/>)
+    } else if (view.type === 'CommonTable') {
+      return (<CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} param={view.param} changeTemp={this.changeTemp}/>)
     } else if (view.type === 'TreePage') {
-      return (<TreePage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>)
-    } else if (view.type === 'CalendarPage') {
-      return (<CalendarPage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>)
+      return (<TreePage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} param={view.param}/>)
     } else if (view.type === 'RolePermission') {
-      return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>)
-    } else if (view.type === 'FormTab') {
-      return (<FormTab MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>)
+      return (<RoleManage MenuID={view.MenuID}/>)
     } else if (view.type === 'iframe') {
-      return (<Iframe key={view.MenuID} MenuID={view.MenuID} MenuNo={view.MenuNo} title={view.MenuName} MenuName={view.MenuName} url={window.GLOB.baseurl + 'zh-CN/' + view.LinkUrl}/>)
+      return (<Iframe MenuID={view.MenuID} title={view.MenuName} url={view.src}/>)
     } else {
-      return (<NotFount key={view.MenuID} />)
+      return (<NotFount />)
     }
-  }
-
-  UNSAFE_componentWillMount () {
-    if (!sessionStorage.getItem('lang') || sessionStorage.getItem('lang') === 'zh-CN') {
-      moment.locale('zh-cn')
-    } else {
-      moment.locale('en')
-    }
-
-    if (sessionStorage.getItem('isEditState') !== 'true') {
-      this.setState({
-        activeId: 'home_page_id',
-        tabviews: [{
-          MenuID: 'home_page_id',
-          MenuName: '棣栭〉',
-          type: 'Home'
-        }]
-      })
-    } else {
-      this.setState({
-        activeId: '',
-        tabviews: []
-      })
-    }
-  }
-
-  componentDidMount () {
-    MKEmitter.addListener('modifyTabs', this.modifyTabs)
-    MKEmitter.addListener('closeTabView', this.closeTabView)
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    MKEmitter.removeListener('modifyTabs', this.modifyTabs)
-    MKEmitter.removeListener('closeTabView', this.closeTabView)
   }
 
   render () {
     const { tabviews, activeId } = this.state
 
     return (
-      <section className={'mk-tabview-wrap' + (this.props.collapse ? ' collapsed' : '')}>
+      <section id="mk-tabgroup-wrap" className="mk-tabview-wrap">
         <div className="content-header">
-          {tabviews && tabviews.length > 0 &&
+          {tabviews.length > 0 &&
             <Tabs activeKey={activeId}>
               {tabviews.map(view => {
                 return (
@@ -300,14 +278,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    collapse: state.collapse,
-  }
-}
-
-const mapDispatchToProps = (dispatch) => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(TabViews)
\ No newline at end of file
+export default TabViews
\ No newline at end of file
diff --git a/src/components/tabview/index.scss b/src/components/tabview/index.scss
index 6f2fee2..5b85043 100644
--- a/src/components/tabview/index.scss
+++ b/src/components/tabview/index.scss
@@ -47,6 +47,7 @@
           }
         }
         .ant-tabs-tab:hover {
+          color: var(--mk-sys-color5);
           span.tab-control .anticon-close {
             display: inline-block;
           }
@@ -55,6 +56,12 @@
           span.tab-control .anticon-redo {
             display: inline-block;
           }
+        }
+        .ant-tabs-tab.ant-tabs-tab-active {
+          color: var(--mk-sys-color);
+        }
+        .ant-tabs-ink-bar {
+          background-color: var(--mk-sys-color);
         }
       }
       >.ant-tabs-content {
@@ -68,10 +75,11 @@
     }
     iframe {
       width: 100%;
-      height: calc(100vh - 115px);
+      height: calc(100vh - 92px);
       overflow-y: scroll;
       border: 0;
-      margin-top: 16px;
+      margin: 0px;
+      vertical-align: top;
     }
   }
   .ant-back-top {
@@ -89,10 +97,11 @@
 .header-container + .mk-tabview-wrap {
   max-width: 100%;
 }
-.mk-tabview-wrap.collapsed {
+
+.mk-side-menu.collapsed + .mk-tabview-wrap {
   max-width: calc(100% - 80px);
 }
-.mk-side-menu-hidden + .mk-tabview-wrap, .mk-side-menu-hidden + .mk-tabview-wrap.collapsed {
+.mk-side-menu-hidden + .mk-tabview-wrap {
   max-width: 100%;
   >.content-header >.ant-tabs >.ant-tabs-bar {
     display: none;
diff --git a/src/components/thawmenu/index.jsx b/src/components/thawmenu/index.jsx
index dbf1672..6a5eaa7 100644
--- a/src/components/thawmenu/index.jsx
+++ b/src/components/thawmenu/index.jsx
@@ -28,7 +28,7 @@
       loading: false
     })
 
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 'sPC_Get_FrozenMenu',
       ParentID: this.props.ParentId,
       TYPE: +this.props.Type
@@ -72,7 +72,7 @@
     })
     let defers = targetKeys.map(item => {
       return new Promise((resolve) => {
-        Api.getSystemConfig({
+        Api.getCloudConfig({
           func: 'sPC_MainMenu_ReDel',
           MenuID: item
         }).then(res => {
diff --git a/src/index.js b/src/index.js
index 761e47e..962edfd 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,28 +1,12 @@
 import React from 'react'
 import ReactDOM from 'react-dom'
 import Route from './router'
-import { Provider } from 'react-redux'
 import md5 from 'md5'
-import store from '@/store'
 import * as serviceWorker from './serviceWorker'
 import options, { styles } from '@/store/options.js'
 import '@/assets/css/main.scss'
 import '@/assets/css/action.scss'
-// import '@/assets/css/minkeicon.css'
 import '@/assets/css/viewstyle.scss'
-
-if (window.location.href.indexOf('#/design') > -1) { // 缂栬緫椤甸潰鍒锋柊鏃讹紝璺宠浆鑷充富椤�
-  window.location.replace(window.location.href.replace(/design/ig, 'main'))
-}
-
-options.sysType = window.atob(options.sysType.replace('$mk', ''))
-options.caId = window.atob(options.caId.replace('$mk', ''))
-options.cakey = window.atob(options.cakey.replace('$mk', ''))
-options.cdomain = window.atob(options.cdomain.replace('$mk', ''))
-
-if (options.cdomain && options.sysType !== 'cloud') {
-  options.cloudServiceApi = options.cdomain + '/webapi/dostars'
-}
 
 if (!localStorage.getItem('SessionUid')) {
   localStorage.setItem('SessionUid', (() => {
@@ -37,14 +21,11 @@
 
 const render = Component => {
   ReactDOM.render(
-    <Provider store={store}>
-      <Component/>
-    </Provider>,
+    <Component/>,
     document.getElementById('root')
   )
 }
 
-// bms
 sessionStorage.setItem('UserID', localStorage.getItem('UserID') || '')
 sessionStorage.setItem('LoginUID', localStorage.getItem('LoginUID') || '')
 sessionStorage.setItem('User_Name', localStorage.getItem('User_Name') || '')
@@ -57,18 +38,6 @@
 sessionStorage.setItem('departmentcode', localStorage.getItem('departmentcode') || '')
 sessionStorage.setItem('organization', localStorage.getItem('organization') || '')
 sessionStorage.setItem('mk_user_type', localStorage.getItem('mk_user_type') || '')
-sessionStorage.setItem('lang', 'zh-CN')
-
-if (sessionStorage.getItem('loginError')) {
-  try {
-    let res = JSON.parse(sessionStorage.getItem('loginError'))
-    console.info(res.request)
-    console.info(res.response)
-  } catch (e) {}
-}
-sessionStorage.removeItem('isEditState')
-
-// 鏂扮郴缁熸枃浠剁疆浜巃dmin涓� ../options.json , { cache: 'no-cache'}
 
 fetch('../options.json')
   .then(response => response.json())
@@ -99,6 +68,15 @@
     GLOB.WXNotice = config.WXNotice + '' === 'true'
     GLOB.accessToken = {}
     GLOB.mkHS = false
+    GLOB.debugger = false
+    GLOB.dataFormat = false
+    GLOB.navBar = 'shutter' // 榛樿涓虹櫨鍙剁獥
+    GLOB.style = 'bg_black_style_blue'
+
+    GLOB.sysType = options.sysType
+    if (GLOB.sysType !== 'cloud') {
+      GLOB.cloudServiceApi = options.cdomain + '/webapi/dostars'
+    }
 
     if (sessionStorage.getItem('externalDatabase')) {
       GLOB.externalDatabase = `[${sessionStorage.getItem('externalDatabase')}]..`
@@ -109,7 +87,7 @@
     }
 
     // 鍙湁涓氬姟绯荤粺鎵嶅彲浠ヨ缃负姝e紡绯荤粺
-    if (options.sysType === 'local' && (config.systemType === 'official' || config.systemType === 'production')) {
+    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
@@ -125,8 +103,9 @@
         document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">姝e紡绯荤粺涓嶅彲浣跨敤 http://cloud.mk9h.cn 鍋氫负鍗曠偣鍦板潃锛岃鑱旂郴绠$悊鍛橈紒</div>'
         return
       }
-    } else if (options.sysType === 'local') {
+    } else if (GLOB.sysType === 'local') {
       GLOB.probation = true
+      GLOB.debugger = true
       GLOB.systemType = ''
 
       GLOB.mainSystemApi = 'https://cloud.positecgroup.com/webapi/dostars'
@@ -144,25 +123,24 @@
       GLOB.mainSystemApi = ''
     }
 
-    GLOB.debugger = options.sysType === 'local' && GLOB.systemType !== 'production'
-
     if (/#\/hs$/.test(window.location.href)) { // hs涓嬩笉鎵撳嵃鑴氭湰
       GLOB.debugger = false
     }
 
-    if (options.sysType !== 'cloud') {
+    if (GLOB.sysType !== 'cloud') {
       if (config.appkey === options.cakey) {
         document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">涓嶅彲浣跨敤浜戠appkey锛岃鑱旂郴绠$悊鍛橈紒</div>'
         return
       }
     }
 
-    if (options.sysType === 'cloud') { // cloud涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�,浜戠appkey涓虹郴缁熻缃�
+    if (GLOB.sysType === 'cloud') { // cloud涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�,浜戠appkey涓虹郴缁熻缃�
       GLOB.appkey = options.cakey
+      GLOB.appId = options.caId
       GLOB.WXNotice = false
-    } else if (options.sysType === 'SSO') { // sso涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�
+    } else if (GLOB.sysType === 'SSO') { // sso涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�
       GLOB.appkey = config.appkey
-    } else if (options.sysType === 'local') { // 涓氬姟绯荤粺
+    } else if (GLOB.sysType === 'local') { // 涓氬姟绯荤粺
       GLOB.appkey = config.appkey
       if (GLOB.systemType === 'production') {
         let systemApi = config.mainSystemApi
@@ -181,10 +159,7 @@
     }
 
     let _href = window.location.href.split('#')[0]
-
     let _systemMsg = localStorage.getItem(_href + 'system')
-
-    GLOB.navBar = 'shutter' // 榛樿涓虹櫨鍙剁獥
     let className = 'mk-blue-black'
 
     if (_systemMsg) {
@@ -201,7 +176,7 @@
         GLOB.mainlogo = _systemMsg.mainlogo
         GLOB.doclogo = _systemMsg.doclogo
         GLOB.webSite = _systemMsg.webSite
-        GLOB.style = _systemMsg.style
+        GLOB.style = _systemMsg.style || 'bg_black_style_blue'
         GLOB.showline = _systemMsg.showline || ''
         GLOB.navBar = _systemMsg.navBar || 'shutter'
         GLOB.appVersion = _systemMsg.app_version || ''
@@ -213,17 +188,12 @@
           link.href = GLOB.favicon
           document.getElementsByTagName('head')[0].appendChild(link)
         }
-        if (GLOB.style && styles[GLOB.style]) {
+        if (styles[GLOB.style]) {
           className = styles[GLOB.style] + ' ' + (GLOB.showline === 'false' ? 'hidden-split-line' : '')
         }
       } catch (e) {
         console.warn('Parse Failure')
       }
-    }
-
-    // 涓嶄娇鐢ㄧ櫨鍙剁獥鎵撳紑鑿滃崟鏃讹紝鍘绘帀鍚堝苟鏍囪
-    if (GLOB.navBar !== 'shutter') {
-      localStorage.removeItem('collapse')
     }
 
     document.body.className = className
@@ -248,27 +218,25 @@
       GLOB.baseurl = document.location.origin + '/' + GLOB.service
       GLOB.linkurl = GLOB.baseurl + 'index.html'
     } else {
-      GLOB.linkurl = ''
       GLOB.location = config.host
       GLOB.service = config.service
       GLOB.host = config.host.replace(/http(s)?:\/\//ig, '') + (config.service ? '_' + config.service.replace(/\//ig, '') : '')
       GLOB.baseurl = GLOB.location + '/' + GLOB.service
+      GLOB.linkurl = GLOB.baseurl + 'index.html'
+      GLOB.dataFormat = false
+
+      let mark = sessionStorage.getItem('system_mark')
+      let _mark = `sys_${GLOB.service.replace('/', '') || 'service'}`
+      if (mark && mark !== _mark) {
+        sessionStorage.clear()
+      }
+      sessionStorage.setItem('system_mark', _mark)
     }
 
-    let mark = sessionStorage.getItem('system_mark')
-    let _mark = `sys_${GLOB.service.replace('/', '') || 'service'}`
-    if (mark && mark !== _mark) {
-      sessionStorage.clear()
-    }
-    sessionStorage.setItem('system_mark', _mark)
+    let lang = localStorage.getItem(_href + 'lang') || (config.defaultLang !== 'en-US' ? 'zh-CN' : 'en-US')
+    sessionStorage.setItem('lang', lang)
 
-    if (localStorage.getItem(_href + 'lang')) {
-      sessionStorage.setItem('lang', localStorage.getItem(_href + 'lang'))
-    } else {
-      sessionStorage.setItem('lang', config.defaultLang !== 'en-US' ? 'zh-CN' : 'en-US')
-    }
-
-    let _level = 10
+    let _level = 0
     let _Mlevel = sessionStorage.getItem('Member_Level')
 
     if (_Mlevel) {
@@ -284,13 +252,6 @@
     GLOB.mkThdMenus = [] // 涓夌骇鑿滃崟
     GLOB.mkActions = {}  // 鎸夐挳鏉冮檺闆�
 
-    if (sessionStorage.getItem('breakpoint')) {
-      window.debugger = true
-      GLOB.breakpoint = sessionStorage.getItem('breakpoint')
-    } else {
-      GLOB.breakpoint = false
-    }
-
     Object.defineProperty(GLOB, 'appId', {
       writable: false,
       value: GLOB.appId
@@ -303,10 +264,6 @@
       writable: false,
       value: GLOB.systemType
     })
-    Object.defineProperty(GLOB, 'debugger', {
-      writable: false,
-      value: GLOB.debugger
-    })
     Object.defineProperty(GLOB, 'mainSystemApi', {
       writable: false,
       value: GLOB.mainSystemApi
@@ -315,6 +272,31 @@
       writable: false,
       value: GLOB.linkurl
     })
+    Object.defineProperty(GLOB, 'sysType', {
+      writable: false,
+      value: GLOB.sysType
+    })
+    Object.defineProperty(GLOB, 'cloudServiceApi', {
+      writable: false,
+      value: GLOB.cloudServiceApi || ''
+    })
+
+    if (GLOB.sysType === 'cloud') {
+      Object.defineProperty(GLOB, 'debugger', {
+        writable: false,
+        value: GLOB.debugger
+      })
+
+      GLOB.breakpoint = false
+    } else {
+      if (sessionStorage.getItem('breakpoint')) {
+        GLOB.debugger = true
+        GLOB.breakpoint = sessionStorage.getItem('breakpoint')
+      } else {
+        GLOB.breakpoint = false
+      }
+    }
+
     Object.defineProperty(window, 'GLOB', {
       writable: false,
       value: GLOB
@@ -324,6 +306,8 @@
     window.GLOB.CacheVoucher = new Map() // 缂撳瓨鍑瘉淇℃伅
     window.GLOB.UserCacheMap = new Map() // 缂撳瓨鐢ㄦ埛鑷畾涔夎缃�
     window.GLOB.CacheData = new Map()    // 瀛樺偍閫変腑鏁版嵁
+    window.GLOB.SearchBox = new Map()    // 瀛樺偍鎼滅储鏉′欢
+    window.GLOB.SyncData = new Map()     // 瀛樺偍鍚屾鏌ヨ鏁版嵁
 
     render(Route)
   })
diff --git a/src/locales/en-US/main.js b/src/locales/en-US/main.js
deleted file mode 100644
index c979dee..0000000
--- a/src/locales/en-US/main.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export default {
-  'main.search': 'Search',
-  'main.reset': 'Reset',
-  'main.confirm': 'OK',
-  'main.submit': 'Submit',
-  'main.return': 'Return',
-  'main.close': 'Close',
-  'main.cancel': 'Cancel',
-  'main.action.confirm.tip': 'Do you want to execute?',
-  'main.action.confirm.success': 'Execute successfully!',
-  'main.action.confirm.selectline': 'Please select a line!',
-  'main.action.confirm.selectSingleLine': 'Please select a single row of data!',
-  'main.view.unenabled': '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��',
-  'main.role.title': 'The role list',
-  'form.required.input': 'Please enter the ',
-  'form.required.select': 'Please select a '
-}
\ No newline at end of file
diff --git a/src/locales/zh-CN/main.js b/src/locales/zh-CN/main.js
deleted file mode 100644
index 5fc8412..0000000
--- a/src/locales/zh-CN/main.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export default {
-  'main.search': '鎼滅储',
-  'main.reset': '閲嶇疆',
-  'main.confirm': '纭畾',
-  'main.submit': '鎻愪氦',
-  'main.return': '杩斿洖',
-  'main.close': '鍏抽棴',
-  'main.cancel': '鍙栨秷',
-  'main.action.confirm.tip': '纭畾瑕佹墽琛屽悧?',
-  'main.action.confirm.success': '鎵ц鎴愬姛锛�',
-  'main.action.confirm.selectline': '璇烽�夋嫨琛岋紒',
-  'main.action.confirm.selectSingleLine': '璇烽�夋嫨鍗曡鏁版嵁锛�',
-  'main.view.unenabled': '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��',
-  'main.role.title': '瑙掕壊鍒楄〃',
-  'form.required.input': '璇疯緭鍏�',
-  'form.required.select': '璇烽�夋嫨'
-}
\ No newline at end of file
diff --git a/src/menu/components/calendar/board/index.jsx b/src/menu/components/calendar/board/index.jsx
new file mode 100644
index 0000000..4796157
--- /dev/null
+++ b/src/menu/components/calendar/board/index.jsx
@@ -0,0 +1,513 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Select, Radio, Row, Col } from 'antd'
+import moment from 'moment'
+import 'moment/locale/zh-cn'
+
+import './index.scss'
+
+const { Option } = Select
+
+moment.locale('zh-cn')
+
+class CalendarBoard extends Component {
+  static propTpyes = {
+    data: PropTypes.any,            // 浜嬩欢鏁版嵁
+    config: PropTypes.any
+  }
+
+  state = {
+    level: 'day',
+    levels: null,
+    yearlist: null,
+    selectYear: moment().format('YYYY'),
+    selectMonth: moment().format('MM'),
+    datelist: null,
+    monthlist: null
+  }
+
+  UNSAFE_componentWillMount() {
+    const { config } = this.props
+
+    let yearlist = []
+    let _selectYear = +this.state.selectYear
+    yearlist.push(`${_selectYear}`)
+    
+    for (let i = 1; i <= 10; i++) {
+      yearlist.unshift(`${_selectYear - i}`)
+      yearlist.push(`${_selectYear + i}`)
+    }
+
+    let datelist = this.getDateList(this.state.selectYear)
+
+    let _levels = config.wrap.levels
+    let level = _levels[0]
+    let monthlist = datelist.filter(item => item.month === moment().format('MM'))[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
+
+    this.setState({
+      yearlist,
+      datelist,
+      monthlist,
+      level,
+      levels: _levels
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    if (!is(fromJS(this.props.config.wrap), fromJS(nextProps.config.wrap))) {
+      this.setState({
+        levels: nextProps.config.wrap.levels,
+        level: nextProps.config.wrap.levels[0]
+      })
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  getNongLi = (nyear, nmonth, nday, week) => {
+    let lmonth;
+    let lday;
+    let lleap; //鍐滃巻鍙傛暟
+    
+    //闃村巻鍑芥暟寮�濮�
+    // eslint-disable-next-line
+    let lunarInfo = new Array(0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0,
+      0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63)
+    let lYearDays = (y) => {
+      let i, sum = 348;
+      for (i = 0x8000; i > 0x8; i >>= 1) {
+        sum += (lunarInfo[y - 1900] & i) ? 1 : 0
+      }
+      return (sum + leapDays(y))
+    }
+    let leapDays = (y) => {
+      if (leapMonth(y)) return ((lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
+      return 0
+    }
+    let leapMonth = (y) => {
+      return (lunarInfo[y - 1900] & 0xf)
+    }
+    let monthDays = (y, m) => {
+      return ((lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
+    }
+    let Lunar = (y, m, d) => {
+      let i, leap = 0, temp = 0;
+      let offset = (Date.UTC(y, m, d) - Date.UTC(1900, 0, 31)) / 86400000;
+      for (i = 1900; i < 2050 && offset > 0; i++) {
+        temp = lYearDays(i)
+        offset -= temp
+      }
+      if (offset < 0) {
+        offset += temp
+        i--
+      }
+
+      let year = i
+      leap = leapMonth(i)
+      let isLeap = false
+
+      for (i = 1; i < 13 && offset > 0; i++) {
+        if (leap > 0 && i === (leap + 1) && isLeap === false) {
+          --i
+          isLeap = true
+          temp = leapDays(year)
+        } else {
+          temp = monthDays(year, i)
+        }
+        if (isLeap === true && i === (leap + 1)) {
+          isLeap = false
+        }
+        offset -= temp
+      }
+      if (offset === 0 && leap > 0 && i === leap + 1) {
+        if (isLeap) {
+          isLeap = false
+        } else {
+          isLeap = true
+          --i
+        }
+      }
+      if (offset < 0) {
+        offset += temp
+        --i
+      }
+
+      return {
+        month: i,
+        day: offset + 1,
+        isLeap: isLeap
+      }
+    }
+
+    let nStr1 = ['', '涓�', '浜�', '涓�', '鍥�', '浜�', '鍏�', '涓�', '鍏�', '涔�', '鍗�', '鍗佷竴', '鍗佷簩']
+    let nStr2 = ['鍒�', '鍗�', '寤�', '鍗�']
+    let GetcDay = (d) => {
+      let s
+      switch (d) {
+        case 10:
+          s = '鍒濆崄'
+          break
+        case 20:
+          s = '浜屽崄'
+          break
+        case 30:
+          s = '涓夊崄'
+          break
+        default:
+          s = nStr2[Math.floor(d / 10)]
+          s += nStr1[d % 10]
+          break
+      }
+      return s
+    }
+    let GetcMon = (m) => {
+      if (m === 1) return '姝�'
+      return nStr1[m]
+    }
+    
+    let lObj = Lunar(nyear, nmonth - 1, nday)
+    lmonth = GetcMon(lObj.month)
+    lday = GetcDay(lObj.day)
+    lleap = lObj.isLeap
+    if (lleap === 1) {
+      lmonth = '闂�' + lmonth
+    }
+
+    lmonth = lmonth + '鏈�'
+
+    if (!week) {
+      return lmonth + lday
+    }
+
+    let jq = this.getjq(nyear, nmonth, nday)
+
+    let nl = lday
+
+    if (lday === '鍒濅竴') {
+      nl = lmonth
+    }
+    if (jq) {
+      nl = jq
+    }
+
+    let sign = '鐝�'
+    if (week > 5) {
+      sign = '浼�'
+    }
+
+    let jr = ''
+    let gr = '' + nmonth + '-' + nday
+    let nr = lmonth + lday
+    if (gr === '1-1') {
+      jr = '鍏冩棪'
+      sign = '浼�'
+    } else if (nr === '姝f湀鍒濅竴') {
+      jr = '鏄ヨ妭'
+      sign = '浼�'
+    } else if (nr === '姝f湀鍗佷簲') {
+      jr = '鍏冨鑺�'
+    } else if (jq === '娓呮槑') {
+      sign = '浼�'
+    } else if (gr === '3-8') {
+      jr = '濡囧コ鑺�'
+    } else if (gr === '5-1') {
+      jr = '鍔冲姩鑺�'
+      sign = '浼�'
+    } else if (nr === '浜旀湀鍒濅簲') {
+      jr = '绔崍鑺�'
+      sign = '浼�'
+    } else if (nr === '涓冩湀鍒濅竷') {
+      jr = '涓冨鑺�'
+    } else if (nr === '涓冩湀鍗佷簲') {
+      jr = '涓厓鑺�'
+    } else if (nr === '鍏湀鍗佷簲') {
+      jr = '涓鑺�'
+      sign = '浼�'
+    } else if (gr === '7-1') {
+      jr = '寤哄厷鑺�'
+    } else if (gr === '8-1') {
+      jr = '寤哄啗鑺�'
+    } else if (gr === '9-10') {
+      jr = '鏁欏笀鑺�'
+    } else if (gr === '10-1') {
+      jr = '鍥藉簡鑺�'
+      sign = '浼�'
+    } else if (nr === '涔濇湀鍒濅節') {
+      jr = '閲嶉槼鑺�'
+    } else if (nr === '鍗佷簩鏈堜笁鍗�') {
+      jr = '闄ゅ'
+      sign = '浼�'
+    } else if (['姝f湀鍒濅簩', '姝f湀鍒濅笁', '姝f湀鍒濆洓', '姝f湀鍒濅簲', '姝f湀鍒濆叚'].includes(nr)) {
+      sign = '浼�'
+    } else if (['10-2', '10-3'].includes(gr)) {
+      sign = '浼�'
+    } else if (nr === '鍗佷簩鏈堝豢涔�') {
+      let tis = moment(`${nyear}${nmonth < 10 ? '0' + nmonth : nmonth}${nday < 10 ?  '0' + nday : nday}`, 'YYYYMMDD').add(1, 'days').format('YYYY-MM-DD').split('-')
+      let nd = this.getNongLi(+tis[0], +tis[1], +tis[2])
+
+      if (nd === '姝f湀鍒濅竴') {
+        jr = '闄ゅ'
+        sign = '浼�'
+      }
+    }
+
+    return {
+      nlday: lday,
+      nlmonth: lmonth,
+      nljq: jq,
+      nl: nl,
+      jr: jr,
+      week: week,
+      sign: sign
+    }
+  }
+
+  getjq = (yyyy, mm, dd) => {
+    mm = mm - 1
+    // eslint-disable-next-line
+    let sTermInfo = new Array(0,21208,42467,63836,85337,107014,128867,150921,173149,195551,218072,240693,263343,285989,308563,331033,353350,375494,397447,419210,440795,462224,483532,504758)
+    let solarTerm = ['灏忓瘨', '澶у瘨', '绔嬫槬', '闆ㄦ按', '鎯婅洶', '鏄ュ垎', '娓呮槑', '璋烽洦', '绔嬪', '灏忔弧', '鑺掔', '澶忚嚦', '灏忔殤', '澶ф殤', '绔嬬', '澶勬殤', '鐧介湶', '绉嬪垎', '瀵掗湶', '闇滈檷', '绔嬪啲', '灏忛洩', '澶ч洩', '鍐嚦']
+    let tmp1 = new Date((31556925974.7 * (yyyy - 1900) + sTermInfo[mm * 2 + 1] * 60000) + Date.UTC(1900, 0, 6, 2, 5))
+    let tmp2 = tmp1.getUTCDate()
+    let solarTerms = ''
+    if (tmp2 === dd) {
+      solarTerms = solarTerm[mm * 2 + 1]
+    }
+    tmp1 = new Date((31556925974.7 * (yyyy - 1900) + sTermInfo[mm * 2] * 60000) + Date.UTC(1900, 0, 6, 2, 5))
+    tmp2= tmp1.getUTCDate()
+    if (tmp2 === dd) {
+      solarTerms = solarTerm[mm * 2]
+    }
+
+    return solarTerms
+  }
+
+  getDateList = (selectYear) => {
+    let datelist = []
+    let months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
+    let monthName = {
+      '01': '涓�鏈�', '02': '浜屾湀', '03': '涓夋湀', '04': '鍥涙湀', '05': '浜旀湀', '06': '鍏湀',
+      '07': '涓冩湀', '08': '鍏湀', '09': '涔濇湀', '10': '鍗佹湀', '11': '鍗佷竴鏈�', '12': '鍗佷簩鏈�'
+    }
+
+    months.forEach(month => {
+      let _weeklist = []
+      let weekday = moment(`${selectYear}${month}01`, 'YYYYMMDD').weekday()
+      let end = +moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').format('DD')
+
+      let children = []
+      if (weekday > 0) {
+        let times = moment(`${selectYear}${month}01`, 'YYYYMMDD').subtract(1, 'days').format('YYYY-MM-DD').split('-')
+        for (let i = 0; i < weekday; i++) {
+          let _day = times[2] - i
+          let nl = this.getNongLi(+times[0], +times[1], +_day, weekday - i)
+  
+          let item = {
+            day: _day,
+            time: times[0] + times[1] + _day,
+            label: _day,
+            subData: [],
+            $disable: true,
+            ...nl
+          }
+          children.unshift(item)
+        }
+      }
+
+      for (let i = 1; i <= end; i++) {
+        let _day = i < 10 ? `0${i}` : `${i}`
+        let nl = this.getNongLi(+selectYear, +month, +_day, children.length + 1)
+
+        let item = {
+          day: _day,
+          time: selectYear + month + _day,
+          label: i,
+          subData: [],
+          ...nl
+        }
+
+        children.push(item)
+
+        if (children.length === 7) {
+          _weeklist.push({
+            children: [...children]
+          })
+          children = []
+        }
+      }
+
+      let times = moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').add(1, 'days').format('YYYY-MM-DD').split('-')
+      let tick = 42 - _weeklist.length * 7 - children.length
+
+      for (let i = 1; i <= tick; i++) {
+        let _day = i < 10 ? '0' + i : i
+        let nl = this.getNongLi(+times[0], +times[1], +_day, children.length + 1)
+  
+        let item = {
+          day: _day,
+          time: times[0] + times[1] + _day,
+          label: i,
+          subData: [],
+          $disable: true,
+          ...nl
+        }
+        children.push(item)
+
+        if (children.length === 7) {
+          _weeklist.push({
+            children: [...children]
+          })
+          children = []
+        }
+      }
+
+      datelist.push({
+        month: month,
+        time: selectYear + month,
+        label: monthName[month],
+        children: _weeklist,
+        subData: []
+      })
+    })
+
+    return datelist
+  }
+
+  levelChange = (e) => {
+    this.setState({ level: e.target.value })
+  }
+
+  yearChange = (value) => {
+    const { selectMonth } = this.state
+    let datelist = this.getDateList(value)
+    let monthlist = datelist.filter(item => item.month === selectMonth)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
+
+    this.setState({ selectYear: value, datelist, monthlist })
+  }
+
+  monthChange = (value) => {
+    const { datelist, levels } = this.state
+
+    if (!levels.includes('month')) {
+      return
+    }
+
+    this.setState({
+      level: 'month',
+      selectMonth: value,
+      monthlist: datelist.filter(item => item.month === value)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
+    })
+  }
+
+  render() {
+    const { level, selectYear, selectMonth, yearlist, levels, datelist, monthlist } = this.state
+    const _levelName = {day: '鏃�', month: '鏈�', year: '骞�'}
+
+    return (
+      <div className="mk-calendar">
+        <div className="mk-calendar-control">
+          <Select value={selectYear} onChange={this.yearChange}>
+            {yearlist.map(item => (<Option key={item} value={item}>{item}骞�</Option>))}
+          </Select>
+          {level === 'month' ? <Select value={selectMonth} onChange={this.monthChange}>
+            <Option value="01">1鏈�</Option>
+            <Option value="02">2鏈�</Option>
+            <Option value="03">3鏈�</Option>
+            <Option value="04">4鏈�</Option>
+            <Option value="05">5鏈�</Option>
+            <Option value="06">6鏈�</Option>
+            <Option value="07">7鏈�</Option>
+            <Option value="08">8鏈�</Option>
+            <Option value="09">9鏈�</Option>
+            <Option value="10">10鏈�</Option>
+            <Option value="11">11鏈�</Option>
+            <Option value="12">12鏈�</Option>
+          </Select> : null}
+          {levels.length > 1 ? <Radio.Group value={level} onChange={this.levelChange}>
+            {levels.map(item => (<Radio.Button key={item} value={item}>{_levelName[item]}</Radio.Button>))}
+          </Radio.Group> : null}
+        </div>
+        <div className="mk-calendar-content">
+          {level === 'day' ? <Row className="day-calendar" gutter={16}>
+            {datelist.map(item => (
+              <Col span={4} key={item.month}>
+                <table>
+                  <thead>
+                    <tr>
+                      <th colSpan="7">{item.label}</th>
+                    </tr>
+                    <tr>
+                      <th>涓�</th><th>浜�</th><th>涓�</th><th>鍥�</th><th>浜�</th><th>鍏�</th><th>鏃�</th>
+                    </tr>
+                  </thead>
+                  <tbody>
+                    {item.children.map((cell, m) => (
+                      <tr key={m}>
+                        {cell.children.map((d, i) => (
+                          <td key={i}>
+                            <div className={'day-wrap' + (d.$disable ? ' disabled' : '')}>
+                              {d.label}
+                            </div>
+                          </td>
+                        ))}
+                      </tr>
+                    ))}
+                  </tbody>
+                </table>
+              </Col>
+            ))}
+          </Row> : null}
+          {level === 'month' && monthlist ? <div className="month-calendar">
+            <table>
+              <thead>
+                <tr>
+                  <th>鏄熸湡涓�</th><th>鏄熸湡浜�</th><th>鏄熸湡涓�</th><th>鏄熸湡鍥�</th><th>鏄熸湡浜�</th><th>鏄熸湡鍏�</th><th>鏄熸湡鏃�</th>
+                </tr>
+              </thead>
+              <tbody>
+                {monthlist.map((cell, m) => (
+                  <tr key={m}>
+                    {cell.children.map((d, i) => (
+                      <td key={i}>
+                        <div className={'month-wrap' + (d.$disable ? ' disabled' : '')}>
+                          <div className="header">
+                            <div className="message">
+                              {d.label}
+                              <span className={'right' + (d.sign === '浼�' ? ' danger' : '')}>{d.sign}</span>
+                            </div>
+                            <div className="message">
+                              {d.nl}
+                              <span className="right">{d.jr}</span>
+                            </div>
+                          </div>
+                          <ul className="content"></ul>
+                        </div>
+                      </td>
+                    ))}
+                  </tr>
+                ))}
+              </tbody>
+            </table>
+          </div>: null}
+          {level === 'year' ? <Row className="year-calendar">
+            {datelist.map(item => (
+              <Col span={8} key={item.month}>
+                <div className="year-wrap">
+                  <div className="header" style={{color: '#1890ff'}}>
+                    {item.label}
+                  </div>
+                  <ul className="content"></ul>
+                </div>
+              </Col>
+            ))}
+          </Row>: null}
+        </div>
+      </div>
+    )
+  }
+}
+
+export default CalendarBoard
\ No newline at end of file
diff --git a/src/tabviews/zshare/calendar/index.scss b/src/menu/components/calendar/board/index.scss
similarity index 83%
rename from src/tabviews/zshare/calendar/index.scss
rename to src/menu/components/calendar/board/index.scss
index 52faea5..a81b171 100644
--- a/src/tabviews/zshare/calendar/index.scss
+++ b/src/menu/components/calendar/board/index.scss
@@ -2,6 +2,7 @@
   position: relative;
   width: 100%;
   padding: 20px;
+  color: rgba(0, 0, 0, 0.85);
 
   .loading-data {
     position: absolute;
@@ -23,6 +24,9 @@
     .ant-select {
       width: 90px;
       margin-right: 15px;
+    }
+    .ant-select + .ant-select {
+      width: 80px;
     }
   }
   .mk-calendar-content {
@@ -58,7 +62,11 @@
                   height: 100%;
                 }
               }
-              .day-wrap:hover {
+              .day-wrap.disabled {
+                cursor: default;
+                color: rgba(0, 0, 0, 0.35);
+              }
+              .day-wrap:not(.disabled):hover {
                 background: #bae7ff;
               }
             }
@@ -71,7 +79,7 @@
         width: 100%;
         thead {
           text-align: center;
-          color: #1890ff;
+          // color: #1890ff;
           font-size: 16px;
           tr {
             height: 35px;
@@ -90,12 +98,21 @@
                 margin-bottom: 2px;
                 box-shadow: 0px 0px 3px #bae7ff;
                 .header {
-                  text-align: center;
                   font-size: 16px;
+                  padding: 5px 10px;
+
+                  .message {
+                    .right {
+                      float: right;
+                    }
+                    .right.danger {
+                      color: #ff4d4f;
+                    }
+                  }
                 }
                 .content {
                   padding: 0 10px 10px;
-                  height: 90px;
+                  height: 70px;
                   overflow-y: auto;
                   position: absolute;
                   left: 0;
@@ -122,7 +139,20 @@
                   background: rgba(0, 0, 0, 0);
                 }
               }
-              .month-wrap:hover {
+
+              .month-wrap.disabled {
+                cursor: default;
+                color: rgba(0, 0, 0, 0.35);
+                .header {
+                  .message {
+                    .right.danger {
+                      color: rgba(0, 0, 0, 0.35);
+                    }
+                  }
+                }
+              }
+
+              .month-wrap:not(.disabled):hover {
                 background: #e6f7ff;
               }
             }
diff --git a/src/menu/components/calendar/index.jsx b/src/menu/components/calendar/index.jsx
new file mode 100644
index 0000000..00a1663
--- /dev/null
+++ b/src/menu/components/calendar/index.jsx
@@ -0,0 +1,265 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Popover, message } from 'antd'
+import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, PlusCircleOutlined } from '@ant-design/icons'
+
+import asyncComponent from '@/utils/asyncComponent'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
+import MKEmitter from '@/utils/events.js'
+import getWrapForm from './options'
+import Utils from '@/utils/utils.js'
+import './index.scss'
+
+const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
+const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
+const SearchComponent = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent'))
+const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
+const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
+const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
+const CalendarBoard = asyncComponent(() => import('./board'))
+
+class NormalCalendarComponent extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    deletecomponent: PropTypes.func,
+    updateConfig: PropTypes.func,
+  }
+
+  state = {
+    card: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+
+    if (card.isNew) {
+      let btnId = Utils.getuuid()
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        format: 'array',    // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+        pageable: false,    // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+        switchable: false,  // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+        width: card.width || 24,
+        name: card.name,
+        subtype: card.subtype,
+        setting: { interType: 'system' },
+        wrap: { title: '', name: card.name, width: card.width || 24, levels: ['day', 'month', 'year'] },
+        style: { marginLeft: '0px', marginRight: '0px', marginTop: '0px', marginBottom: '0px' },
+        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
+        search: [],
+        columns: [],
+        scripts: [],
+        action: [{
+          $fixed: true,
+          uuid: btnId,
+          label: '娣诲姞',
+          OpenType: 'popview',
+          popClose: 'grid',
+          display: 'modal',
+          icon: '',
+          class: 'green',
+          ratio: 85,
+          style: {
+            color: 'rgb(255, 255, 255)',
+            background: 'rgb(38, 194, 129)',
+            marginRight: '15px'
+          },
+          config: {
+            uuid: btnId,
+            MenuID: btnId,
+            ParentId: card.uuid,
+            enabled: false,
+            MenuName: '娣诲姞',
+            tables: [],
+            Template: 'CustomPage',
+            components: [],
+            viewType: 'popview',
+            style: { backgroundColor: '#ffffff', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+          }
+        }]
+      }
+
+      if (card.config) {
+        let config = fromJS(card.config).toJS()
+
+        _card.wrap = config.wrap
+        _card.wrap.name = card.name
+        _card.style = config.style
+
+        _card.setting = config.setting
+        _card.columns = config.columns
+        _card.scripts = config.scripts
+      }
+
+      this.updateComponent(_card)
+    } else {
+      this.setState({
+        card: fromJS(card).toJS()
+      })
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  /**
+   * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
+   */
+  updateComponent = (card) => {
+    card.width = card.wrap.width
+    card.name = card.wrap.name
+    if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
+      card.$c_ds = true
+      
+      card.errors = checkComponent(card)
+
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
+    }
+
+    this.setState({
+      card: card
+    })
+
+    this.props.updateConfig(card)
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', ['height', 'background', 'border', 'padding', 'margin', 'shadow', 'clear', 'minHeight'], card.style, this.getStyle)
+  }
+
+  getStyle = (style) => {
+    let _card = {...this.state.card, style}
+    
+    this.updateComponent(_card)
+  }
+
+  addSearch = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('plusSearch', card.uuid, {uuid: Utils.getuuid(), focus: true, label: 'label', type: 'text', match: '='}, 'simple')
+  }
+
+  getWrapForms = () => {
+    const { card } = this.state
+
+    return getWrapForm(card.wrap, card.columns)
+  }
+
+  updateWrap = (res) => {
+    const { card } = this.state
+
+    res.show = card.wrap.show || 'true'
+    res.advanceType = card.wrap.advanceType || 'modal'
+    res.advanceWidth = card.wrap.advanceWidth || 1000
+    res.drawerPlacement = card.wrap.drawerPlacement || 'right'
+    res.searchRatio = card.wrap.searchRatio || 6
+    res.searchLwidth = card.wrap.searchLwidth !== undefined ? card.wrap.searchLwidth : 33.3
+    res.borderRadius = card.wrap.borderRadius || 0
+    res.resetContrl = card.wrap.resetContrl || 'init'
+
+    if (res.colorField && res.signs) {
+      res.signs = res.signs.map((item, i) => {
+        try {
+          let colors = item.background.match(/\d+/g)
+          if ((colors[0] * 0.299 + colors[1] * 0.578 + colors[2] * 0.114) * colors[3] < 192) {
+            item.fontColor = '#ffffff'
+          } else {
+            item.fontColor = ''
+          }
+        } catch (e) {
+          item.fontColor = ''
+        }
+
+        item.style = {background: item.background}
+        if (item.fontColor) {
+          item.style.color = item.fontColor
+        }
+
+        item.$index = i + 1
+
+        return item
+      })
+    }
+
+    this.updateComponent({...card, wrap: res})
+  }
+
+  setSubConfig = (item) => {
+    const { card } = this.state
+    let btn = fromJS(item).toJS()
+
+    if (btn.OpenType === 'popview') {
+      MKEmitter.emit('changePopview', card, btn)
+    }
+  }
+
+  render() {
+    const { card } = this.state
+
+    let _style = resetStyle(card.style)
+
+    return (
+      <div className="menu-calendar-edit-box" style={_style} id={card.uuid}>
+        <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <PlusCircleOutlined className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch}/>
+            <NormalForm title="鏃ュ巻璁剧疆" width={850} update={this.updateWrap} getForms={this.getWrapForms}>
+              <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
+            </NormalForm>
+            <CopyComponent type="calendar" card={card}/>
+            <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
+            <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
+            <SettingComponent config={card} updateConfig={this.updateComponent} />
+          </div>
+        } trigger="hover">
+          <ToolOutlined />
+        </Popover>
+        <SearchComponent config={card} updatesearch={this.updateComponent}/>
+        <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
+        <CalendarBoard config={card} />
+        <div className="component-name">
+          <div className="center">
+            <div className="title" onDoubleClick={() => {
+              let oInput = document.createElement('input')
+              oInput.value = 'anchor' + card.uuid
+              document.body.appendChild(oInput)
+              oInput.select()
+              document.execCommand('Copy')
+              document.body.removeChild(oInput)
+              message.success('澶嶅埗鎴愬姛銆�')
+            }}>{card.name}</div>
+            <div className="content">
+              {card.errors && card.errors.map((err, index) => {
+                if (err.level === 0) {
+                  return <span key={index} className="error">{err.detail}</span>
+                } else {
+                  return <span key={index} className="waring">{err.detail}锛�</span>
+                }
+              })}
+            </div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default NormalCalendarComponent
\ No newline at end of file
diff --git a/src/menu/components/calendar/index.scss b/src/menu/components/calendar/index.scss
new file mode 100644
index 0000000..b110ec4
--- /dev/null
+++ b/src/menu/components/calendar/index.scss
@@ -0,0 +1,84 @@
+.menu-calendar-edit-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  min-height: 50px;
+
+  .model-table-search-list {
+    padding: 10px 0px 15px;
+    min-height: 65px;
+    border-bottom: 1px solid #f0f0f0;
+    .page-card {
+      background: transparent;
+    }
+    .quickly-add {
+      display: inline-block;
+      position: absolute;
+      z-index: 3;
+      right: 70px;
+      bottom: 5px;
+      .ant-btn-block {
+        background-color: transparent;
+        color: #1890ff;
+        border: none;
+        box-shadow: none !important;
+        height: 18px;
+        padding: 0 10px;
+      }
+    }
+  }
+  .model-table-search-list.length0 {
+    min-height: 10px;
+    border-bottom: 0;
+    >.quickly-add {
+      right: unset;
+      left: -8px;
+      bottom: 0;
+    }
+    >.ant-row {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      min-height: 10px;
+      .common-drawarea-placeholder {
+        display: none;
+      }
+    }
+    >.ant-switch {
+      display: none;
+    }
+  }
+
+  .model-menu-action-list {
+    .page-card {
+      position: absolute;
+      top: 20px;
+      z-index: 1;
+    }
+  }
+
+  >.anticon-tool {
+    position: absolute;
+    z-index: 2;
+    font-size: 16px;
+    right: 1px;
+    top: 1px;
+    cursor: pointer;
+    padding: 5px;
+    background: rgba(255, 255, 255, 0.55);
+  }
+}
+.menu-calendar-edit-box::after {
+  display: block;
+  content: ' ';
+  clear: both;
+}
+.menu-calendar-edit-box:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
diff --git a/src/menu/components/calendar/options.jsx b/src/menu/components/calendar/options.jsx
new file mode 100644
index 0000000..aff9975
--- /dev/null
+++ b/src/menu/components/calendar/options.jsx
@@ -0,0 +1,236 @@
+import React from 'react'
+/**
+ * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
+ */
+export default function (wrap, columns) {
+  let roleList = sessionStorage.getItem('sysRoles')
+  let appType = sessionStorage.getItem('appType')
+
+  if (roleList) {
+    try {
+      roleList = JSON.parse(roleList)
+    } catch (e) {
+      roleList = []
+    }
+  } else {
+    roleList = []
+  }
+
+  let menulist = sessionStorage.getItem('fstMenuList')
+  if (menulist) {
+    try {
+      menulist = JSON.parse(menulist)
+    } catch (e) {
+      menulist = []
+    }
+  } else {
+    menulist = []
+  }
+
+  const calendarWrapForm = [
+    {
+      type: 'text',
+      field: 'title',
+      label: '鏍囬',
+      initval: wrap.title || '',
+      required: false
+    },
+    {
+      type: 'text',
+      field: 'name',
+      label: '缁勪欢鍚嶇О',
+      initval: wrap.name || '',
+      tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�',
+      required: true
+    },
+    {
+      type: 'number',
+      field: 'width',
+      label: '瀹藉害',
+      initval: wrap.width || 24,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+      min: 1,
+      max: 24,
+      precision: 0,
+      required: true
+    },
+    {
+      type: 'checkbox',
+      field: 'levels',
+      label: '鏃ュ巻绛夌骇',
+      initval: wrap.levels || [],
+      required: true,
+      options: [
+        {value: 'day', label: '鏃�'},
+        {value: 'month', label: '鏈�'},
+        {value: 'year', label: '骞�'},
+      ]
+    },
+    {
+      type: 'select',
+      field: 'timeField',
+      label: '鏃堕棿瀛楁',
+      initval: wrap.timeField || '',
+      tooltip: '鏁版嵁涓殑鏃堕棿瀛楁锛岀敤浜庡湪鏃ュ巻涓爣璁颁簨浠朵綅缃��',
+      required: true,
+      options: columns
+    },
+    {
+      type: 'select',
+      field: 'endField',
+      label: '缁撴潫鏃堕棿',
+      initval: wrap.endField || '',
+      tooltip: '鏁版嵁涓簨浠剁殑缁撴潫鏃堕棿锛岀敤浜庡湪鏃ュ巻涓爣璁颁簨浠朵綅缃��',
+      required: false,
+      options: columns
+    },
+    {
+      type: 'select',
+      field: 'remarkField',
+      label: '淇℃伅瀛楁',
+      initval: wrap.remarkField || '',
+      required: true,
+      options: columns
+    },
+    {
+      type: 'select',
+      field: 'colorField',
+      label: '棰滆壊瀛楁',
+      initval: wrap.colorField || '',
+      required: false,
+      options: columns,
+      controlFields: [
+        {field: 'signs', notNull: true},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'permission',
+      label: '鏉冮檺楠岃瘉',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
+      required: false,
+      options: [
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'click',
+      label: '鐐瑰嚮浜嬩欢',
+      initval: wrap.click || '',
+      tooltip: '鍙�氳繃鐐瑰嚮浜嬩欢璺宠浆鑷虫寚瀹氶〉闈€��',
+      required: false,
+      options: [
+        {value: '', label: '鏃�'},
+        {value: 'menu', label: '鑿滃崟'},
+        {value: 'menus', label: '鑿滃崟缁�'}
+      ],
+      controlFields: [
+        {field: 'menu', values: ['menu']},
+        {field: 'menuType', values: ['menus']},
+        {field: 'menus', values: ['menus']},
+      ]
+    },
+    {
+      type: 'select',
+      field: 'menuType',
+      label: '鑿滃崟绫诲瀷',
+      initval: wrap.menuType || '',
+      required: true,
+      options: columns,
+    },
+    {
+      type: 'cascader',
+      field: 'menu',
+      label: '鍏宠仈鑿滃崟',
+      initval: wrap.menu || [],
+      required: true,
+      extendName: 'MenuNo',
+      options: menulist,
+    },
+    {
+      type: 'multiselect',
+      field: 'blacklist',
+      label: '榛戝悕鍗�',
+      initval: wrap.blacklist || [],
+      required: false,
+      options: roleList,
+      forbid: !!appType
+    },
+    {
+      type: 'table',
+      field: 'signs',
+      label: '棰滆壊鏍囪瘑',
+      initval: wrap.signs || [],
+      required: false,
+      span: 24,
+      columns: [
+        {
+          title: '鏍囪瘑',
+          dataIndex: 'sign',
+          inputType: 'input',
+          editable: true,
+          unique: true,
+          required: false,
+          width: '30%'
+        },
+        {
+          title: '棰滆壊',
+          dataIndex: 'background',
+          inputType: 'color',
+          editable: true,
+          required: true,
+          render: (text, record) => (<div style={{background: text, width: '100px', height: '25px'}}></div>),
+          width: '40%'
+        }
+      ]
+    },
+    {
+      type: 'table',
+      field: 'menus',
+      label: '鑿滃崟缁�',
+      initval: wrap.menus || [],
+      required: true,
+      span: 24,
+      actions: ['view'],
+      columns: [
+        {
+          title: '鏍囪瘑',
+          dataIndex: 'sign',
+          inputType: 'input',
+          editable: true,
+          unique: true,
+          required: false,
+          width: '30%'
+        },
+        {
+          title: '鑿滃崟',
+          dataIndex: 'menu',
+          inputType: 'cascader',
+          editable: true,
+          required: true,
+          extends: 'Menu',
+          width: '40%',
+          render: (text, record) => record.label,
+          options: menulist
+        }
+      ]
+    },
+  ]
+
+  return calendarWrapForm
+} 
\ No newline at end of file
diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx
index 691e7f3..756ffcc 100644
--- a/src/menu/components/card/balcony/index.jsx
+++ b/src/menu/components/card/balcony/index.jsx
@@ -17,7 +17,6 @@
 const CardCellComponent = asyncComponent(() => import('../cardcellcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 
 class BalconyEditComponent extends Component {
@@ -46,34 +45,41 @@
         name: card.name,
         subtype: card.subtype,
         setting: { interType: 'system' },
-        wrap: { name: card.name, width: card.width || 24, linkType: 'static', position: 'relative', datatype: 'static' },
-        style: { marginLeft: '0px', marginRight: '0px', marginTop: '0px', marginBottom: '0px' },
+        wrap: { name: card.name, width: card.width || 24, linkType: 'static', datatype: 'static' },
+        style: { marginLeft: '0px', marginRight: '0px', marginTop: '0px', marginBottom: '0px', position: 'unset' },
         columns: [],
         scripts: [],
         elements: [],
       }
 
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.elements = _card.elements.map(elem => {
-          elem.uuid = Utils.getuuid()
-          return elem
-        })
-      }
-
       this.updateComponent(_card)
     } else {
+      let _card = fromJS(card).toJS()
+
+      if (!_card.style.position) { // 鍏煎
+        if (_card.wrap.position === 'fixed' || _card.wrap.position === 'absolute') {
+          _card.style.position = _card.wrap.position
+          _card.style.zIndex = _card.wrap.position === 'fixed' ? 3 : 2
+          _card.style.left = _card.wrap.left || ''
+          _card.style.right = _card.wrap.right || ''
+          _card.style.top = _card.wrap.top || ''
+          _card.style.bottom = _card.wrap.bottom || ''
+          _card.style.transform = _card.wrap.transform || ''
+          _card.style.width = _card.wrap.realwidth || ''
+        } else if (_card.wrap.left || _card.wrap.right || _card.wrap.top || _card.wrap.bottom) {
+          _card.style.position = 'relative'
+          _card.style.zIndex = 1
+          _card.style.left = _card.wrap.left || ''
+          _card.style.right = _card.wrap.right || ''
+          _card.style.top = _card.wrap.top || ''
+          _card.style.bottom = _card.wrap.bottom || ''
+        } else {
+          _card.style.position = 'unset'
+        }
+      }
+
       this.setState({
-        card: fromJS(card).toJS()
+        card: _card
       })
     }
   }
@@ -155,7 +161,7 @@
   changeStyle = () => {
     const { card } = this.state
 
-    MKEmitter.emit('changeStyle', ['height', 'background', 'border', 'padding', 'margin', 'shadow', 'clear', 'minHeight'], card.style, this.getStyle)
+    MKEmitter.emit('changeStyle', ['width', 'height', 'background', 'border', 'padding', 'margin', 'shadow', 'clear', 'minHeight', 'position', 'transform'], card.style, this.getStyle)
   }
 
   getStyle = (style) => {
@@ -232,6 +238,8 @@
   updateWrap = (res) => {
     delete res.quick
 
+    res.linkType = res.linkType || 'static'
+
     let _card = {...this.state.card, wrap: res}
 
     if (res.datatype === 'public') {
@@ -279,7 +287,6 @@
             <PasteComponent options={['action', 'customCardElement']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} />
             {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
           </div>
diff --git a/src/menu/components/card/balcony/index.scss b/src/menu/components/card/balcony/index.scss
index 1108b2c..418b226 100644
--- a/src/menu/components/card/balcony/index.scss
+++ b/src/menu/components/card/balcony/index.scss
@@ -1,5 +1,5 @@
 .menu-balcony-edit-box {
-  position: relative;
+  position: unset!important;
   box-sizing: border-box;
   background: #ffffff;
   background-position: center center;
@@ -8,6 +8,8 @@
   min-height: 30px;
   display: flex;
   overflow: hidden;
+  max-width: 100%;
+  transform: none!important;
   
   .check-all {
     width: 70px;
diff --git a/src/menu/components/card/balcony/options.jsx b/src/menu/components/card/balcony/options.jsx
index b7dd426..d9694b2 100644
--- a/src/menu/components/card/balcony/options.jsx
+++ b/src/menu/components/card/balcony/options.jsx
@@ -6,6 +6,7 @@
  */
 export default function (wrap, buttons, columns) {
   let menu = window.GLOB.customMenu
+  let MenuType = menu.parentId === 'BillPrintTemp' ? 'billPrint' : ''
 
   let modules = MenuUtils.getLinkModules(menu.components) || []
   let supmodules = MenuUtils.getSupModules(menu.components, '', menu.interfaces)
@@ -122,7 +123,8 @@
         {field: 'supControl', values: ['sup']},
         {field: 'syncModule', values: ['sync']},
         {field: 'checkAll', values: ['sync']},
-      ]
+      ],
+      forbid: MenuType === 'billPrint'
     },
     {
       type: 'cascader',
@@ -168,95 +170,6 @@
     },
     {
       type: 'radio',
-      field: 'position',
-      label: '浣嶇疆',
-      initval: wrap.position || 'relative',
-      tooltip: '鐩稿瀹氫綅鏄浉瀵瑰叾姝e父浣嶇疆鐨勫亸绉伙紱缁濆瀹氫綅鏄浉瀵逛簬鍘熺粍浠剁殑鍋忕Щ锛屽師缁勪欢楂樺害鍙涓�0锛涘浐瀹氬畾浣嶆槸鐩稿浜庣獥鍙g殑浣嶇疆锛屽畾浣嶆晥鏋滄祴璇曠幆澧冧腑鏌ョ湅銆�',
-      required: false,
-      options: [
-        {value: 'relative', label: '鐩稿瀹氫綅'},
-        {value: 'absolute', label: '缁濆瀹氫綅'},
-        {value: 'fixed', label: '鍥哄畾瀹氫綅'},
-      ],
-      controlFields: [
-        {field: 'quick', values: ['fixed']},
-        {field: 'realwidth', values: ['fixed', 'absolute']},
-        {field: 'transform', values: ['fixed', 'absolute']},
-      ]
-    },
-    {
-      type: 'select',
-      field: 'quick',
-      label: '蹇嵎閫夋嫨',
-      initval: '',
-      required: false,
-      subFields: ['top', 'left', 'right', 'bottom', 'transform'],
-      options: [
-        {value: 'top', label: '涓�', top: '0px', left: '0px', right: '0px', bottom: '', transform: ''},
-        {value: 'top-left', label: '宸︿笂', top: '0px', left: '0px', right: '', bottom: '', transform: ''},
-        {value: 'top-right', label: '鍙充笂', top: '0px', left: '', right: '0px', bottom: '', transform: ''},
-        {value: 'left-middle', label: '宸︿腑', top: '50%', left: '0px', right: '', bottom: '', transform: 'translateY(-50%)'},
-        {value: 'right-middle', label: '鍙充腑', top: '50%', left: '', right: '0px', bottom: '', transform: 'translateY(-50%)'},
-        {value: 'bottom-left', label: '宸︿笅', top: '', left: '0px', right: '', bottom: '0px', transform: ''},
-        {value: 'bottom-right', label: '鍙充笅', top: '', left: '', right: '0px', bottom: '0px', transform: ''},
-        {value: 'bottom', label: '涓�', top: '', left: '0px', right: '0px', bottom: '0px', transform: ''},
-        {value: 'middle', label: '涓棿', top: '50%', left: '50%', right: '', bottom: '', transform: 'translate(-50%, -50%)'}
-      ]
-    },
-    {
-      type: 'styleInput',
-      field: 'top',
-      label: '璺濅笂',
-      initval: wrap.top || '',
-      required: false
-    },
-    {
-      type: 'styleInput',
-      field: 'right',
-      label: '璺濆彸',
-      initval: wrap.right || '',
-      required: false
-    },
-    {
-      type: 'styleInput',
-      field: 'bottom',
-      label: '璺濅笅',
-      initval: wrap.bottom || '',
-      required: false
-    },
-    {
-      type: 'styleInput',
-      field: 'left',
-      label: '璺濆乏',
-      initval: wrap.left || '',
-      required: false
-    },
-    {
-      type: 'styleInput',
-      field: 'realwidth',
-      label: '瀹為檯瀹藉害',
-      initval: wrap.realwidth || '',
-      required: false
-    },
-    {
-      type: 'select',
-      field: 'transform',
-      label: '鍙樻崲',
-      initval: wrap.transform || '',
-      required: false,
-      options: [
-        {value: 'translateY(-50%)', label: '涓婄Щ50%'},
-        {value: 'translateY(50%)', label: '涓嬬Щ50%'},
-        {value: 'translateX(-50%)', label: '宸︾Щ50%'},
-        {value: 'translateX(50%)', label: '鍙崇Щ50%'},
-        {value: 'translate(-50%, -50%)', label: '宸︿笂绉�50%'},
-        {value: 'translate(-50%, 50%)', label: '宸︿笅绉�50%'},
-        {value: 'translate(50%, -50%)', label: '鍙充笂绉�50%'},
-        {value: 'translate(50%, 50%)', label: '鍙充笅绉�50%'},
-      ]
-    },
-    {
-      type: 'radio',
       field: 'empty',
       label: '绌哄�奸殣钘�',
       initval: wrap.empty || 'show',
@@ -279,12 +192,37 @@
     },
     {
       type: 'radio',
+      field: 'printType',
+      label: '缁勪欢绫诲瀷',
+      initval: wrap.printType || 'content',
+      tooltip: '閫夋嫨绫诲瀷涓恒�婇〉鐪�/椤佃剼銆嬫椂锛屾墦鍗扮殑姣忛〉閲岄兘浼氬甫鏈夎缁勪欢銆傛敞锛氶〉鐪夐〉鑴氫腑鏂囨湰鍏冪礌灏嗘浛鎹� @pageIndex@锛堥〉鐮侊級銆丂total@锛堟�绘暟锛夈�丂date@锛堝綋鍓嶆棩鏈燂級銆丂datetime@锛堝綋鍓嶆椂闂达級锛屼娇鐢ㄥ垎椤靛弬鏁版椂娉ㄦ剰鎵撳嵃妯℃澘鐨勯〉闈㈠竷灞�浣跨敤鍒嗛〉銆�',
+      required: false,
+      options: [
+        {value: 'content', label: '娴姩鍗�'},
+        {value: 'headerOrfooter', label: '椤电湁/椤佃剼'},
+      ],
+      forbid: MenuType !== 'billPrint'
+    },
+    {
+      type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
       initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
         {value: 'false', label: '绂佺敤'},
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
@@ -295,7 +233,8 @@
       label: '鍏宠仈鎸夐挳',
       initval: wrap.linkbtn || '',
       required: false,
-      options: buttons
+      options: buttons,
+      forbid: MenuType === 'billPrint'
     },
     {
       type: 'multiselect',
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
index 0fb5013..14b00e5 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
@@ -39,6 +39,9 @@
   let warning = null
   if (['pop', 'prompt', 'exec', 'form'].includes(card.OpenType)) {
     hasProfile = true
+    if (card.formType === 'count_line') {
+      hasProfile = false
+    }
   } else if (card.OpenType === 'excelIn' || card.OpenType === 'excelOut') {
     hasProfile = true
   } else if (card.funcType === 'print') {
@@ -53,7 +56,7 @@
   if (card.OpenType === 'form') {
     if (card.formType === 'switch') {
       btnElement = (<Switch style={_style} className={card.size === 'large' ? 'ant-switch-large' : ''} size={card.size} checkedChildren={card.openText || ''} unCheckedChildren={card.closeText || ''}/>)
-    } else if (card.formType === 'counter') {
+    } else if (card.formType === 'counter' || card.formType === 'count_line') {
       btnElement = (<div style={_style} className={'mk-counter ' + card.size}><span><MinusOutlined /></span><span>1</span><span><PlusOutlined /></span></div>)
     } else if (card.formType === 'radio') {
       btnElement = (<Checkbox style={_style}></Checkbox>)
@@ -72,6 +75,8 @@
 
   if (card.style && card.style.clear === 'left') {
     _style_ = {clear: 'left'}
+  } else if (card.style && card.style.clear === 'right') {
+    _style_ = {float: 'right'}
   }
 
   let className = card.width || ''
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
index 6494683..4cbb8a3 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -92,6 +92,9 @@
         <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight || 'auto'}}>{val}</div>
       )
     } else if (card.eleType === 'icon') {
+      if (card.tipType === 'text') {
+        return <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight || 'auto'}}>{card.value || card.field || ''}</div>
+      }
       return (<MkIcon style={{height: card.innerHeight || 'auto'}} className="ant-mk-icon" type={card.icon || 'bell'}/>)
     } else if (card.eleType === 'slider') {
       let val = card.value ? (card.value / card.maxValue) * 100 : 30
@@ -212,11 +215,15 @@
 
   if (card.style && card.style.clear === 'left') {
     _style_ = {clear: 'left'}
+  } else if (card.style && card.style.clear === 'right') {
+    _style_ = {float: 'right'}
   }
 
-  let tableHCell = false
+  let mark = ['text', 'number', 'slider', 'sequence', 'formula'].includes(card.eleType)
   if (parent.setting && parent.setting.cardRole === 'header') {
-    tableHCell = true
+    mark = false
+  } else if (card.eleType === 'formula' && card.eval === 'func') {
+    mark = false
   }
 
   return (
@@ -226,7 +233,7 @@
         <CopyOutlined className="copy" title="澶嶅埗" onClick={() => copyCard(id)} />
         <CloseOutlined className="close" title="鍒犻櫎" onClick={() => delCard(id)} />
         <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)}/>
-        {['text', 'number', 'slider', 'sequence', 'formula'].includes(card.eleType) && !tableHCell ? <MarkColumn field={card.field || ''} columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null }
+        {mark ? <MarkColumn field={card.field || ''} columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null }
       </div>
     } trigger="hover">
       <div ref={node => drag(drop(node))} style={_style_} className={'ant-col card-cell ant-col-' + card.width}>
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.scss b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
index 51310de..a492bac 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.scss
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -213,6 +213,8 @@
     background-position: center center;
     background-repeat: no-repeat;
     background-size: cover;
+    position: unset!important;
+    vertical-align: top;
   }
   .sort-wrap {
     position: relative;
diff --git a/src/menu/components/card/cardcellcomponent/elementform/index.jsx b/src/menu/components/card/cardcellcomponent/elementform/index.jsx
index 10007af..3d140fc 100644
--- a/src/menu/components/card/cardcellcomponent/elementform/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/elementform/index.jsx
@@ -19,7 +19,7 @@
   number: ['eleType', 'datatype', 'width', 'height', 'prefix', 'postfix', 'noValue', 'fixStyle', 'alignItems'],
   picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'maxWidth', 'link', 'noValue'],
   video: ['eleType', 'datatype', 'width', 'aspectRatio', 'autoPlay', 'loop', 'startTime', 'noValue', 'posterType'],
-  icon: ['eleType', 'datatype', 'width', 'tooltip'],
+  icon: ['eleType', 'datatype', 'tipType', 'width', 'tooltip'],
   slider: ['eleType', 'datatype', 'width', 'color', 'maxValue', 'showInfo', 'showType', 'strokeWidth', 'strokeLinecap', 'trailColor'],
   splitline: ['eleType', 'color', 'width', 'borderWidth'],
   barcode: ['eleType', 'datatype', 'width', 'barHeight', 'displayValue', 'interval', 'noValue'],
@@ -199,8 +199,13 @@
     } else if (this.record.eleType === 'icon') {
       if (this.record.datatype === 'dynamic') {
         _options.push('field', 'noValue')
+      } else if (this.record.tipType === 'text') {
+        _options.push('value')
       } else {
         _options.push('icon')
+      }
+      if (this.record.tipType === 'text') {
+        _options.push('height')
       }
     } else if (this.record.eleType === 'formula' && this.record.eval === 'true') {
       _options.push('decimal')
@@ -336,7 +341,7 @@
           return item
         })
       })
-    } else if (['datatype', 'showInfo', 'showType', 'fixStyle', 'posterType', 'eval', 'linkType'].includes(key)) {
+    } else if (['datatype', 'showInfo', 'showType', 'fixStyle', 'posterType', 'eval', 'linkType', 'tipType'].includes(key)) {
       let _options = this.getOptions()
 
       this.setState({
@@ -556,10 +561,11 @@
           </Col>
         )
       } else if (item.type === 'file') {
-        let type = this.state.eleType
+        let type = this.record.eleType
         if (item.key === 'posterUrl') {
           type = 'picture'
         }
+
         fields.push(
           <Col span={12} key={index}>
             <Form.Item label={item.tooltip ?
@@ -621,7 +627,7 @@
           values.marks = this.props.card.marks || null
 
           // eslint-disable-next-line
-          if (values.eleType === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
+          if (values.eleType === 'formula' && values.eval === 'true' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
             let cols = []
             config.subColumns && config.subColumns.forEach(col => {
               if (/^(Int|Decimal)/ig.test(col.datatype)) {
diff --git a/src/menu/components/card/cardcellcomponent/formconfig.jsx b/src/menu/components/card/cardcellcomponent/formconfig.jsx
index 76dc518..d682050 100644
--- a/src/menu/components/card/cardcellcomponent/formconfig.jsx
+++ b/src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -6,12 +6,14 @@
  * @param {*} type
  */
 export function getCardCellForm (card, cards, cardCell) {
+  let appType = sessionStorage.getItem('appType')
+
   let _options = [
     { value: 'text', text: '鏂囨湰'},
     { value: 'number', text: '鏁板��'},
     { value: 'picture', text: '鍥剧墖'},
     { value: 'video', text: '瑙嗛'},
-    { value: 'icon', text: '鍥炬爣'},
+    { value: 'icon', text: '鎻愮ず锛堝浘鏍囷級'},
     { value: 'slider', text: '杩涘害鏉�'},
     { value: 'splitline', text: '鍒嗗壊绾�'},
     { value: 'barcode', text: '鏉″舰鐮�'},
@@ -36,7 +38,6 @@
   if (card.eleType === 'icon' && card.datatype === 'dynamic' && !card.field) { // 鎷栨嫿娣诲姞绫诲瀷杞崲
     card.datatype = 'static'
   }
-  let appType = sessionStorage.getItem('appType')
 
   let tooltip = ''
   if (cardCell.$cardType === 'extendCard') {
@@ -127,6 +128,17 @@
       options: [
         { value: 'dynamic', text: '鍔ㄦ��' },
         { value: 'static', text: '闈欐��' }
+      ]
+    },
+    {
+      type: 'radio',
+      key: 'tipType',
+      label: '鎻愮ず鍐呭',
+      initVal: card.tipType || 'icon',
+      required: false,
+      options: [
+        { value: 'icon', text: '鍥炬爣' },
+        { value: 'text', text: '鏂囨湰' }
       ]
     },
     {
@@ -223,16 +235,19 @@
     {
       type: 'radio',
       key: 'eval',
-      label: '瑙f瀽',
+      label: '瑙f瀽鏂瑰紡',
       initVal: card.eval || 'false',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滆绠椻�濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃瓧娈垫浛鎹⑩�濓紝浣跨敤鍑芥暟鏃跺叆鍙備负data锛堟暟缁勶級銆�',
       required: false,
       options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
         value: 'false',
-        text: '鍚�'
+        text: '瀛楁鏇挎崲'
+      }, {
+        value: 'true',
+        text: '璁$畻'
+      }, {
+        value: 'func',
+        text: '鍑芥暟'
       }]
     },
     {
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index 756e8a2..1100466 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -7,8 +7,6 @@
 import asyncComponent from '@/utils/asyncComponent'
 import { getCardCellForm } from './formconfig'
 import { getActionForm, getBaseTableActionForm } from '@/menu/components/share/actioncomponent/formconfig'
-
-import Utils, { FuncUtils } from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import MenuUtils from '@/utils/utils-custom.js'
 import ElementForm from './elementform'
@@ -160,6 +158,8 @@
       options = ['background', 'border', 'margin']
     } else if (element.eleType === 'color') {
       options = ['border', 'margin', 'padding']
+    } else if (element.eleType === 'number' || element.eleType === 'icon') {
+      options.push('display')
     } else if (element.eleType === 'text') {
       options[0] = 'font2'
       options.push('display')
@@ -167,6 +167,10 @@
       options = ['padding', 'margin']
     } else if (element.eleType === 'splitline') {
       options = ['padding', 'margin']
+    }
+
+    if (element.eleType !== 'button') {
+      options.push('position')
     }
 
     options.push('clear')
@@ -202,7 +206,7 @@
       _card.style = style
       let line = _card.height || null
 
-      if (['currentDate', 'sequence', 'icon'].includes(_card.eleType)) {
+      if (['currentDate', 'sequence'].includes(_card.eleType) || (_card.eleType === 'icon' && _card.tipType !== 'text')) {
         line = 1
       }
 
@@ -367,7 +371,7 @@
         if (cell.uuid === res.uuid) {
           res.style = cell.style || {}
 
-          if (res.eleType !== 'text') {
+          if (!['text', 'number', 'icon'].includes(res.eleType)) {
             delete res.style.display
           }
           
@@ -377,7 +381,7 @@
           } else if (['text', 'number', 'formula', 'currentDate', 'sequence', 'icon'].includes(res.eleType)) {
             let line = res.height || null
 
-            if (['currentDate', 'sequence', 'icon'].includes(res.eleType)) {
+            if (['currentDate', 'sequence'].includes(res.eleType) || (res.eleType === 'icon' && res.tipType !== 'text')) {
               line = 1
             }
 
@@ -655,47 +659,47 @@
    * @description 鍒涘缓鎸夐挳瀛樺偍杩囩▼
    */
   creatFunc = () => {
+    const { cards } = this.props
     const menu = window.GLOB.customMenu
-    let _config = fromJS(this.props.cards).toJS()
 
-    this.actionFormRef.handleConfirm().then(res => {
-      let btn = res         // 鎸夐挳淇℃伅
-      let newLText = ''     // 鍒涘缓瀛樺偍杩囩▼sql
-      let DelText = ''      // 鍒犻櫎瀛樺偍杩囩▼sql
+    return new Promise((resolve) => {
+      this.actionFormRef.handleConfirm().then(res => {
+        let btn = fromJS(res).toJS()
+        let _config = fromJS(cards).toJS()
 
-      if (btn.intertype !== 'inner') return
+        if (btn.OpenType === 'excelIn') {
+          btn.func = btn.innerFunc
+          btn.menuNo = menu.MenuNo
+          btn.MenuName = menu.MenuName + _config.name
+          btn.$type = 'excelIn'
 
-      if (btn.OpenType === 'pop') {
-        let _param = {
-          funcName: btn.innerFunc,
-          name: _config.setting.tableName || '',
-          fields: btn.modal ? btn.modal.fields : [],
-          menuNo: menu.MenuNo
+          resolve(btn)
+        } else if (btn.OpenType === 'excelOut') {
+          _config.MenuName = menu.MenuName + '-' + _config.name
+          _config.menuNo = menu.MenuNo
+          _config.MenuID = menu.MenuID
+          _config.func = btn.innerFunc
+          _config.$type = 'table'
+          
+          resolve(_config)
+        } else {
+          btn.func = btn.innerFunc
+          btn.name = _config.setting.tableName || ''
+          btn.menuNo = menu.MenuNo
+          btn.MenuID = menu.MenuID
+          btn.MenuName = menu.MenuName + _config.name
+          btn.fields = []
+          btn.columns = _config.columns
+          btn.primaryKey = _config.setting.primaryKey || 'ID'
+          btn.$type = 'btn'
+
+          if (btn.OpenType === 'pop') {
+            btn.fields = btn.modal ? btn.modal.fields : []
+          }
+
+          resolve(btn)
         }
-        newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config))
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      } else if (btn.OpenType === 'excelIn') {
-        let _param = {
-          funcName: btn.innerFunc,
-          menuNo: menu.MenuNo
-        }
-        newLText = Utils.formatOptions(FuncUtils.getexcelInfunc(_param, btn, menu))
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      } else if (btn.OpenType === 'excelOut') {
-        newLText = Utils.formatOptions(FuncUtils.getTableFunc(btn.innerFunc, menu, _config)) // 鍒涘缓瀛樺偍杩囩▼sql
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      } else {
-        let _param = {
-          funcName: btn.innerFunc,
-          name: _config.setting.tableName || '',
-          fields: '',
-          menuNo: menu.MenuNo
-        }
-        newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config))
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      }
-
-      this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText)
+      })
     })
   }
 
@@ -756,6 +760,7 @@
           {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
           <Modal
             title="缂栬緫鍏冪礌"
+            wrapClassName="mk-scroll-modal"
             visible={visible}
             width={850}
             maskClosable={false}
@@ -775,12 +780,13 @@
           {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
           <Modal
             title="鎸夐挳路缂栬緫"
+            wrapClassName="mk-scroll-modal"
             visible={actvisible}
             width={920}
             maskClosable={false}
             onCancel={this.editModalCancel}
             footer={[
-              record && record.intertype === 'inner' && cards.subtype === 'dualdatacard' ? <CreateFunc key="create" ref="btnCreatFunc" trigger={this.creatFunc}/> : null,
+              record && record.intertype === 'inner' && cards.subtype === 'dualdatacard' ? <CreateFunc key="create" getMsg={this.creatFunc}/> : null,
               <Button key="cancel" onClick={this.editModalCancel}>鍙栨秷</Button>,
               <Button key="confirm" type="primary" onClick={this.handleActionSubmit}>纭畾</Button>
             ]}
diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx
index 0d6a97d..2e45d8c 100644
--- a/src/menu/components/card/cardcomponent/index.jsx
+++ b/src/menu/components/card/cardcomponent/index.jsx
@@ -157,7 +157,7 @@
     const { card, side } = this.state
 
     let _style = null
-    let options = ['height', 'background', 'border', 'padding', 'margin', 'shadow']
+    let options = ['height', 'background', 'border', 'padding', 'margin', 'shadow', 'clear']
     if (side === 'front') {
       _style = card.style ? fromJS(card.style).toJS() : {}
     } else if (side === 'back') {
@@ -378,8 +378,16 @@
       tablerole = ' mk-table-header'
     }
 
+    let _style_ = null
+
+    if (card.style.clear === 'left') {
+      _style_ = {clear: 'left'}
+    } else if (card.style.clear === 'right') {
+      _style_ = {float: 'right'}
+    }
+
     return (
-      <Col span={card.setting.width || 6}>
+      <Col span={card.setting.width || 6} style={_style_}>
         <div className={'card-item ' + (card.setting.btnControl || '') + checkAll + tablerole} style={_style} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard()}} id={card.uuid}>
           <span className="circle-select"></span>
           <CardCellComponent cards={cards} cardCell={card} side={side} elements={elements} updateElement={this.updateCard}/>
diff --git a/src/menu/components/card/cardcomponent/index.scss b/src/menu/components/card/cardcomponent/index.scss
index 930a06f..35933f8 100644
--- a/src/menu/components/card/cardcomponent/index.scss
+++ b/src/menu/components/card/cardcomponent/index.scss
@@ -68,6 +68,7 @@
     display: none;
     width: 16px;
     height: 16px;
+    min-width: 16px;
     border: 1px solid #cccccc;
     border-radius: 50%;
     box-sizing: content-box;
diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx
index 3b75676..5822912 100644
--- a/src/menu/components/card/data-card/index.jsx
+++ b/src/menu/components/card/data-card/index.jsx
@@ -17,7 +17,6 @@
 const CardComponent = asyncComponent(() => import('../cardcomponent'))
 const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
@@ -78,40 +77,6 @@
           backElements: [],
           menus: []
         }]
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.elements = scard.elements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          scard.backElements = scard.backElements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
-        _card.action = config.action.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
-        _card.search = config.search.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
       }
 
       this.updateComponent(_card)
@@ -313,8 +278,12 @@
         }
       }
       MKEmitter.emit('changeModal', card, btn)
-    } else if (btn.OpenType === 'popview' && appType !== 'mob') {
-      MKEmitter.emit('changePopview', card, btn)
+    } else if (btn.OpenType === 'popview') {
+      if (appType === 'mob') {
+        message.warning('婊戝姩鎸夐挳涓嶆敮鎸佸脊绐楅〉闈紒')
+      } else {
+        MKEmitter.emit('changePopview', card, btn)
+      }
     }
   }
 
@@ -554,7 +523,6 @@
             <PasteComponent options={['action', 'search', 'form', 'cardcell']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent} />
           </div>
diff --git a/src/menu/components/card/data-card/options.jsx b/src/menu/components/card/data-card/options.jsx
index 9f2edb2..b4ec305 100644
--- a/src/menu/components/card/data-card/options.jsx
+++ b/src/menu/components/card/data-card/options.jsx
@@ -107,7 +107,6 @@
         {field: 'empty', values: ['dynamic', 'public']},
         {field: 'jump', values: ['dynamic', 'public']},
         {field: 'broadcast', values: ['dynamic', 'public']},
-        {field: 'autoExec', values: ['dynamic', 'public']},
         {field: 'supModule', values: ['static']},
         {field: 'publicId', values: ['public']},
       ],
@@ -280,18 +279,6 @@
       ],
       forbid: subtype === 'tablecard'
     },
-    // {
-    //   type: 'radio',
-    //   field: 'checkAll',
-    //   label: '鍏ㄩ��',
-    //   initval: wrap.checkAll || 'hidden',
-    //   required: false,
-    //   options: [
-    //     {value: 'hidden', label: '闅愯棌'},
-    //     {value: 'show', label: '鏄剧ず'},
-    //   ],
-    //   forbid: subtype !== 'datacard' || appType !== 'mob'
-    // },
     {
       type: 'radio',
       field: 'cardFloat',
@@ -337,10 +324,10 @@
       field: 'printType',
       label: '缁勪欢绫诲瀷',
       initval: wrap.printType || 'content',
-      tooltip: '閫夋嫨绫诲瀷涓恒�婇〉鐪�/椤佃剼銆嬫椂锛屾墦鍗扮殑姣忛〉閲岄兘浼氬甫鏈夎缁勪欢銆�',
+      tooltip: '閫夋嫨绫诲瀷涓恒�婇〉鐪�/椤佃剼銆嬫椂锛屾墦鍗扮殑姣忛〉閲岄兘浼氬甫鏈夎缁勪欢銆傛敞锛氶〉鐪夐〉鑴氫腑鏂囨湰鍏冪礌灏嗘浛鎹� @pageIndex@锛堥〉鐮侊級銆丂total@锛堟�绘暟锛夈�丂date@锛堝綋鍓嶆棩鏈燂級銆丂datetime@锛堝綋鍓嶆椂闂达級锛屼娇鐢ㄥ垎椤靛弬鏁版椂娉ㄦ剰鎵撳嵃妯℃澘鐨勯〉闈㈠竷灞�浣跨敤鍒嗛〉銆�',
       required: false,
       options: [
-        {value: 'content', label: '鍐呭'},
+        {value: 'content', label: '灞炴�у崱'},
         {value: 'headerOrfooter', label: '椤电湁/椤佃剼'},
       ],
       controlFields: [
@@ -562,7 +549,19 @@
       initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
         {value: 'false', label: '绂佺敤'},
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
diff --git a/src/menu/components/card/double-data-card/index.jsx b/src/menu/components/card/double-data-card/index.jsx
index 1374635..81cf755 100644
--- a/src/menu/components/card/double-data-card/index.jsx
+++ b/src/menu/components/card/double-data-card/index.jsx
@@ -18,7 +18,6 @@
 const DoubleCardComponent = asyncComponent(() => import('../doublecardcomponent'))
 const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
@@ -92,40 +91,6 @@
             value: '瀛愯〃鍖哄煙'
           }]
         }]
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.elements = scard.elements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          scard.backElements = scard.backElements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
-        _card.action = config.action.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
-        _card.search = config.search.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
       }
 
       this.updateComponent(_card)
@@ -540,7 +505,6 @@
             <PasteComponent options={['action', 'search', 'form', 'cardcell']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent} />
           </div>
diff --git a/src/menu/components/card/double-data-card/options.jsx b/src/menu/components/card/double-data-card/options.jsx
index 522c7ed..778fe4c 100644
--- a/src/menu/components/card/double-data-card/options.jsx
+++ b/src/menu/components/card/double-data-card/options.jsx
@@ -236,7 +236,19 @@
       initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
         {value: 'false', label: '绂佺敤'},
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
diff --git a/src/menu/components/card/doublecardcomponent/index.jsx b/src/menu/components/card/doublecardcomponent/index.jsx
index c5853a4..98acc31 100644
--- a/src/menu/components/card/doublecardcomponent/index.jsx
+++ b/src/menu/components/card/doublecardcomponent/index.jsx
@@ -127,6 +127,7 @@
     if (type === 'sub') {
       _style = fromJS(card.backStyle).toJS()
     } else {
+      options.push('clear')
       _style = fromJS(card.style).toJS()
     }
 
@@ -264,8 +265,16 @@
       mainBox = 'flex-card '
     }
 
+    let _style_ = null
+
+    if (card.style.clear === 'left') {
+      _style_ = {clear: 'left'}
+    } else if (card.style.clear === 'right') {
+      _style_ = {float: 'right'}
+    }
+
     return (
-      <Col span={card.setting.width || 24}>
+      <Col span={card.setting.width || 24} style={_style_}>
         <div className="card-item-wrap" style={_wrapStyle}>
           <div className={`card-item ${card.setting.btnControl || ''} ${checkAll} mk-${card.setting.display} ${mainBox}`} style={_style} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard()}} id={card.uuid}>
             <span className="circle-select"></span>
diff --git a/src/menu/components/card/doublecardcomponent/index.scss b/src/menu/components/card/doublecardcomponent/index.scss
index 344ab73..63e0e13 100644
--- a/src/menu/components/card/doublecardcomponent/index.scss
+++ b/src/menu/components/card/doublecardcomponent/index.scss
@@ -69,6 +69,7 @@
     display: none;
     width: 16px;
     height: 16px;
+    min-width: 16px;
     border: 1px solid #cccccc;
     border-radius: 50%;
     box-sizing: content-box;
diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx
index 12c8c19..880a042 100644
--- a/src/menu/components/card/prop-card/index.jsx
+++ b/src/menu/components/card/prop-card/index.jsx
@@ -17,7 +17,6 @@
 const CardComponent = asyncComponent(() => import('../cardcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 
@@ -70,31 +69,6 @@
         }],
       }
 
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.elements = scard.elements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          scard.backElements = scard.backElements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
-      }
       this.updateComponent(_card)
     } else {
       this.setState({
@@ -416,7 +390,6 @@
             <PasteComponent options={['cardcell']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
           </div>
diff --git a/src/menu/components/card/table-card/index.jsx b/src/menu/components/card/table-card/index.jsx
index 5eb5acd..dd96ddb 100644
--- a/src/menu/components/card/table-card/index.jsx
+++ b/src/menu/components/card/table-card/index.jsx
@@ -18,7 +18,6 @@
 const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
@@ -67,38 +66,6 @@
           elements: []
         }],
         action: [],
-      }
-      
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.elements = scard.elements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
-        _card.search = config.search.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
-        if (config.action) {
-          _card.action = config.action.map(col => {
-            col.uuid = Utils.getuuid()
-            return col
-          })
-        }
       }
 
       this.updateComponent(_card)
@@ -456,7 +423,6 @@
             <PasteComponent options={['cardcell', 'search', 'form']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
           </div>
diff --git a/src/menu/components/carousel/data-card/index.jsx b/src/menu/components/carousel/data-card/index.jsx
index 5d84aea..7fd4050 100644
--- a/src/menu/components/carousel/data-card/index.jsx
+++ b/src/menu/components/carousel/data-card/index.jsx
@@ -18,7 +18,6 @@
 const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 
 const { confirm } = Modal
 
@@ -60,27 +59,6 @@
           },
           elements: []
         }]
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.elements = scard.elements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
       }
 
       this.updateComponent(_card)
@@ -232,7 +210,6 @@
             <CopyComponent type="datacard" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)}/>
             <SettingComponent config={card} updateConfig={this.updateComponent}/>
           </div>
diff --git a/src/menu/components/carousel/data-card/options.jsx b/src/menu/components/carousel/data-card/options.jsx
index 20aeec8..d5116a2 100644
--- a/src/menu/components/carousel/data-card/options.jsx
+++ b/src/menu/components/carousel/data-card/options.jsx
@@ -209,7 +209,19 @@
       initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
         {value: 'false', label: '绂佺敤'},
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
diff --git a/src/menu/components/carousel/prop-card/index.jsx b/src/menu/components/carousel/prop-card/index.jsx
index 755b7e7..c9afca3 100644
--- a/src/menu/components/carousel/prop-card/index.jsx
+++ b/src/menu/components/carousel/prop-card/index.jsx
@@ -19,7 +19,6 @@
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 
 const { confirm } = Modal
 
@@ -59,27 +58,6 @@
           style: {},
           elements: [],
         }]
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.elements = scard.elements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
       }
  
       this.updateComponent(_card)
@@ -279,7 +257,6 @@
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
           </div>
diff --git a/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
index 9eed12a..970e06e 100644
--- a/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
@@ -90,6 +90,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: card.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'multiselect',
       field: 'blacklist',
       label: '榛戝悕鍗�',
@@ -102,11 +114,11 @@
       type: 'radio',
       field: 'click',
       label: '鐐瑰嚮浜嬩欢',
-      initval: card.click || '',
+      initval: card.click || 'switch',
       tooltip: '鐐瑰嚮鑺傜偣鏃惰Е鍙戠殑浜嬩欢銆�',
       required: false,
       options: [
-        {value: '', label: '鏁版嵁鍒囨崲'},
+        {value: 'switch', label: '鏁版嵁鍒囨崲'},
         {value: 'menu', label: '鑿滃崟'},
         {value: 'menus', label: '鑿滃崟缁�'}
       ],
@@ -236,7 +248,7 @@
         label: '涓婄骇缁勪欢'
       }, {
         value: 'line',
-        label: '琛�'
+        label: '鏁版嵁婧�'
       }],
       controlFields: [
         {field: 'rootLabel', values: ['fixed', 'supvalue']},
@@ -249,6 +261,7 @@
       field: 'rootValue',
       label: '鏍硅妭鐐瑰��',
       initval: card.rootValue || '',
+      tooltip: '鏍硅妭鐐逛娇鐢ㄤ笂绾х粍浠舵椂锛岃濉啓涓婄骇缁勪欢涓搴旂殑瀛楁銆�',
       required: true
     },
     {
@@ -256,6 +269,7 @@
       field: 'rootLabel',
       label: '鏍硅妭鐐规枃鏈�',
       initval: card.rootLabel || '',
+      tooltip: '鏍硅妭鐐逛娇鐢ㄤ笂绾х粍浠舵椂锛岃濉啓涓婄骇缁勪欢涓搴旂殑瀛楁銆�',
       required: true
     },
     {
@@ -345,7 +359,7 @@
       field: 'collapsed',
       label: '鑺傜偣鍚堝苟',
       initval: card.collapsed || 'false',
-      tooltip: '涓�绾ц妭鐐规槸鍚﹀悎骞躲��',
+      tooltip: '鍒濆鍖栨椂锛屼竴绾ц妭鐐规槸鍚﹀悎骞躲��',
       required: false,
       options: [
         {value: 'false', label: '鍚�'},
diff --git a/src/menu/components/chart/antv-G6/index.jsx b/src/menu/components/chart/antv-G6/index.jsx
index 652fbe6..658e69c 100644
--- a/src/menu/components/chart/antv-G6/index.jsx
+++ b/src/menu/components/chart/antv-G6/index.jsx
@@ -17,7 +17,6 @@
 const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 
 const MindData = [
   'Modeling Methods',
@@ -961,6 +960,7 @@
         width: card.width || 24,
         height: 400,
         subtype: card.subtype,
+        click: 'switch',
         name: card.name
       }
 
@@ -984,19 +984,6 @@
         search: [],
         action: [],
         plot: _plot,
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.plot = config.plot
-        _card.plot.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
       }
 
       this.updateComponent(_card)
@@ -1410,7 +1397,6 @@
             <ChartCompileForm config={card} plotchange={this.updateComponent}/>
             <CopyComponent type="antvG6" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/>
             <SettingComponent config={card} updateConfig={this.updateComponent}/>
           </div>
diff --git a/src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx
index 39827f8..f3ef986 100644
--- a/src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx
@@ -1,3 +1,6 @@
+
+import MenuUtils from '@/utils/utils-custom.js'
+
 /**
  * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
  * @param {object} card       // 鍥捐〃瀵硅薄
@@ -107,6 +110,7 @@
       required: false,
       options: [
         {value: '', label: '鏃�'},
+        {value: 'switch', label: '鏁版嵁鍒囨崲'},
         {value: 'menu', label: '鑿滃崟'},
         {value: 'menus', label: '鑿滃崟缁�'}
       ],
@@ -115,7 +119,6 @@
         {field: 'menus', values: ['menus']},
         {field: 'menuType', values: ['menus']},
         {field: 'open', values: ['menu', 'menus']},
-        {field: 'joint', values: ['menu', 'menus']},
       ]
     },
     {
@@ -146,17 +149,6 @@
         {value: 'self', label: '褰撳墠绐楀彛'},
       ],
       forbid: appType !== 'pc'
-    },
-    {
-      type: 'radio',
-      field: 'joint',
-      label: '鍙傛暟鎷兼帴',
-      initval: card.joint || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ],
     },
     {
       type: 'table',
@@ -197,24 +189,71 @@
  * @param {object} card       // 鍥捐〃瀵硅薄
  * @param {Array}  columns    // 鏄剧ず鍒�
  */
-export function getOptionForm (card, columns) {
+export function getOptionForm (card, uuid) {
+  let menu = window.GLOB.customMenu
+  let modules = MenuUtils.getSupModules(menu.components, uuid, menu.interfaces)
+
   return [
     {
       type: 'select',
       field: 'subtype',
-      label: '绫诲瀷',
+      label: '鍥捐〃绫诲瀷',
       initval: card.subtype || 'xflow',
       required: true,
       options: [{
         value: 'xflow',
         label: '娴佺▼鍥�'
       }, {
-        value: 'indentTree',
+        value: 'lane',
         label: '娉抽亾鍥�'
-      }, {
-        value: 'kapmap',
-        label: '缁勭粐缁撴瀯鍥�'
-      }]
+      }],
+      controlFields: [
+        {field: 'gridType', values: ['xflow']},
+        {field: 'backgroundColor', values: ['xflow']}
+      ],
+    },
+    {
+      type: 'radio',
+      field: 'function',
+      label: '鍔熻兘',
+      initval: card.function || 'show',
+      required: true,
+      options: [
+        {value: 'edit', label: '娴佺▼缂栬緫'},
+        {value: 'show', label: '娴佺▼灞曠ず'},
+      ],
+      controlFields: [
+        {field: 'empty', values: ['show']}
+      ]
+    },
+    {
+      type: 'cascader',
+      field: 'supModule',
+      label: '涓婄骇缁勪欢',
+      initval: card.supModule || [],
+      required: false,
+      options: modules,
+      allowClear: true
+    },
+    {
+      type: 'radio',
+      field: 'gridType',
+      label: '缃戞牸',
+      initval: card.gridType || 'none',
+      required: false,
+      options: [
+        {value: 'none', label: '鏃�'},
+        {value: 'dot', label: '鐐圭姸缃戞牸'},
+        {value: 'mesh', label: '缃戠姸缃戞牸'}
+      ],
+    },
+    {
+      type: 'color',
+      field: 'backgroundColor',
+      label: '鑳屾櫙鑹�',
+      initval: card.backgroundColor || '',
+      required: false,
+      allowClear: true
     },
     {
       type: 'radio',
diff --git a/src/menu/components/chart/antv-X6/chartcompile/index.jsx b/src/menu/components/chart/antv-X6/chartcompile/index.jsx
index 4396a49..6942006 100644
--- a/src/menu/components/chart/antv-X6/chartcompile/index.jsx
+++ b/src/menu/components/chart/antv-X6/chartcompile/index.jsx
@@ -34,95 +34,84 @@
       view: 'normal',
       plot: fromJS(config.plot).toJS(),
       baseFormlist: getBaseForm(config.plot, config.columns),
-      formlist: getOptionForm(config.plot, config.columns)
+      formlist: getOptionForm(config.plot, config.uuid)
     })
   }
 
   onSubmit = () => {
-    const { config } = this.props
     const { plot, view } = this.state
 
     if (view === 'normal') {
       this.norRef.handleConfirm().then(res => {
-        let _plot = {...plot, ...res}
-
-        if (_plot.click !== 'menus') {
-          delete _plot.menus
-        }
-        if (_plot.click !== 'menu') {
-          delete _plot.menu
-          delete _plot.MenuID
-          delete _plot.MenuName
-          delete _plot.MenuNo
-          delete _plot.tabType
-        } else if (sessionStorage.getItem('appType') === '' && _plot.menu) {
-          let list = null
-          try {
-            list = JSON.parse(sessionStorage.getItem('thdMenuList')) || []
-          } catch (e) {
-            list = []
-          }
-    
-          let id = _plot.menu[_plot.menu.length - 1]
-    
-          list.forEach(item => {
-            if (item.MenuID === id) {
-              _plot.MenuID = id
-              _plot.MenuName = item.MenuName
-              _plot.MenuNo = item.MenuNo
-              _plot.tabType = item.type
-            }
-          })
-        }
-
-        this.setState({
-          plot: _plot,
-          visible: false
-        })
-
-        this.props.plotchange({...config, plot: _plot})
+        this.resetPlot({...plot, ...res})
       })
     } else if (view === 'base') {
       this.baseRef.handleConfirm().then(res => {
-        let _plot = {...plot, ...res}
-
-        if (_plot.click !== 'menus') {
-          delete _plot.menus
-        }
-        if (_plot.click !== 'menu') {
-          delete _plot.menu
-          delete _plot.MenuID
-          delete _plot.MenuName
-          delete _plot.MenuNo
-          delete _plot.tabType
-        } else if (sessionStorage.getItem('appType') === '' && _plot.menu) {
-          let list = null
-          try {
-            list = JSON.parse(sessionStorage.getItem('thdMenuList')) || []
-          } catch (e) {
-            list = []
-          }
-    
-          let id = _plot.menu[_plot.menu.length - 1]
-    
-          list.forEach(item => {
-            if (item.MenuID === id) {
-              _plot.MenuID = id
-              _plot.MenuName = item.MenuName
-              _plot.MenuNo = item.MenuNo
-              _plot.tabType = item.type
-            }
-          })
-        }
-        
-        this.setState({
-          plot: _plot,
-          visible: false
-        })
-
-        this.props.plotchange({...config, plot: _plot})
+        this.resetPlot({...plot, ...res})
       })
     }
+  }
+
+  resetPlot = (plot) => {
+    const { config } = this.props
+
+    if (plot.click !== 'menus') {
+      delete plot.menus
+    }
+    if (plot.click !== 'menu') {
+      delete plot.menu
+      delete plot.MenuID
+      delete plot.MenuName
+      delete plot.MenuNo
+      delete plot.tabType
+    } else if (sessionStorage.getItem('appType') === '' && plot.menu) {
+      let list = null
+      try {
+        list = JSON.parse(sessionStorage.getItem('thdMenuList')) || []
+      } catch (e) {
+        list = []
+      }
+
+      let id = plot.menu[plot.menu.length - 1]
+
+      list.forEach(item => {
+        if (item.MenuID === id) {
+          plot.MenuID = id
+          plot.MenuName = item.MenuName
+          plot.MenuNo = item.MenuNo
+          plot.tabType = item.type
+        }
+      })
+    }
+
+    if (plot.gridType === 'none') {
+      plot.grid = {visible: false}
+    } else if (plot.gridType === 'dot') {
+      plot.grid = {
+        visible: true,
+        type: 'dot',
+        args: {
+          color: '#a0a0a0',
+          thickness: 1
+        }
+      }
+    } else if (plot.gridType === 'mesh') {
+      plot.grid = {
+        visible: true,
+        type: 'mesh',
+        args: {
+          color: '#ddd',
+          thickness: 1
+        }
+      }
+    }
+    
+    this.setState({
+      plot: plot,
+      visible: false
+    })
+
+    this.props.plotchange({...config, plot: plot})
   }
 
   changeTab = (tab) => {
@@ -155,7 +144,7 @@
         <Modal
           wrapClassName="mk-pop-modal"
           visible={visible}
-          width={850}
+          width={900}
           maskClosable={false}
           onOk={this.onSubmit}
           onCancel={() => { this.setState({ visible: false }) }}
diff --git a/src/menu/components/chart/antv-X6/index.jsx b/src/menu/components/chart/antv-X6/index.jsx
index 6d20b17..4c5cc7c 100644
--- a/src/menu/components/chart/antv-X6/index.jsx
+++ b/src/menu/components/chart/antv-X6/index.jsx
@@ -1,92 +1,68 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Popover, Tooltip, message } from 'antd'
-import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DoubleLeftOutlined } from '@ant-design/icons'
-import { Graph, Shape } from '@antv/x6'
-import { Stencil } from '@antv/x6-plugin-stencil'
-import { Transform } from '@antv/x6-plugin-transform'
-import { Selection } from '@antv/x6-plugin-selection'
-import { Snapline } from '@antv/x6-plugin-snapline'
-import { Keyboard } from '@antv/x6-plugin-keyboard'
-import { Clipboard } from '@antv/x6-plugin-clipboard'
-import { History } from '@antv/x6-plugin-history'
+import { Popover } from 'antd'
+import { ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
+import { Graph } from '@antv/x6'
 
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
+import { resetStyle } from '@/utils/utils-custom.js'
+import lanes from './lane.json'
+import xflows from './xflow.json'
 import './index.scss'
 
-const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
 const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
-const NodeUpdate = asyncIconComponent(() => import('./nodeupdate'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 
-// #region 鍒濆鍖栧浘褰�
-const groups = {
-  top: {
-    position: 'top',
+Graph.registerNode(
+  'lane',
+  {
+    inherit: 'rect',
+    markup: [
+      {
+        tagName: 'rect',
+        selector: 'body',
+      },
+      {
+        tagName: 'rect',
+        selector: 'name-rect',
+      },
+      {
+        tagName: 'text',
+        selector: 'name-text',
+      },
+    ],
     attrs: {
-      circle: {
-        r: 4,
-        magnet: true,
-        stroke: 'var(--mk-sys-color)',
+      body: {
+        fill: '#FFF',
+        stroke: '#5F95FF',
         strokeWidth: 1,
+      },
+      'name-rect': {
+        width: 200,
+        height: 36,
+        fill: '#5F95FF',
+        stroke: '#fff',
+        strokeWidth: 1,
+        x: -1,
+      },
+      'name-text': {
+        ref: 'name-rect',
+        refY: 0.5,
+        refX: 0.5,
+        textAnchor: 'middle',
+        fontWeight: 'bold',
         fill: '#fff',
-        style: {
-          visibility: 'hidden'
-        }
-      }
-    }
+        fontSize: 14,
+      },
+    },
+    zIndex: 0
   },
-  right: {
-    position: 'right',
-    attrs: {
-      circle: {
-        r: 4,
-        magnet: true,
-        stroke: 'var(--mk-sys-color)',
-        strokeWidth: 1,
-        fill: '#fff',
-        style: {
-          visibility: 'hidden'
-        }
-      }
-    }
-  },
-  bottom: {
-    position: 'bottom',
-    attrs: {
-      circle: {
-        r: 4,
-        magnet: true,
-        stroke: 'var(--mk-sys-color)',
-        strokeWidth: 1,
-        fill: '#fff',
-        style: {
-          visibility: 'hidden'
-        }
-      }
-    }
-  },
-  left: {
-    position: 'left',
-    attrs: {
-      circle: {
-        r: 4,
-        magnet: true,
-        stroke: 'var(--mk-sys-color)',
-        strokeWidth: 1,
-        fill: '#fff',
-        style: {
-          visibility: 'hidden'
-        }
-      }
-    }
-  }
-}
+  true,
+)
 
 Graph.registerNode(
   'mk-rect',
@@ -97,22 +73,13 @@
     attrs: {
       body: {
         strokeWidth: 1,
-        stroke: '#5F95FF',
-        fill: '#EFF4FF'
+        stroke: '#000000',
+        fill: '#FFFFFF'
       },
       text: {
         fontSize: 12,
         fill: '#262626'
       }
-    },
-    ports: {
-      groups,
-      items: [
-        { group: 'top' },
-        { group: 'right' },
-        { group: 'bottom' },
-        { group: 'left' }
-      ]
     }
   },
   true
@@ -127,22 +94,13 @@
     attrs: {
       body: {
         strokeWidth: 1,
-        stroke: '#5F95FF',
-        fill: '#EFF4FF'
+        stroke: '#000000',
+        fill: '#FFFFFF'
       },
       text: {
         fontSize: 12,
         fill: '#262626'
       }
-    },
-    ports: {
-      groups,
-      items: [
-        { group: 'top' },
-        { group: 'right' },
-        { group: 'bottom' },
-        { group: 'left' }
-      ]
     }
   },
   true
@@ -157,22 +115,13 @@
     attrs: {
       body: {
         strokeWidth: 1,
-        stroke: '#5F95FF',
-        fill: '#EFF4FF'
+        stroke: '#000000',
+        fill: '#FFFFFF'
       },
       text: {
         fontSize: 12,
         fill: '#262626'
       }
-    },
-    ports: {
-      groups,
-      items: [
-        { group: 'top' },
-        { group: 'right' },
-        { group: 'bottom' },
-        { group: 'left' }
-      ]
     }
   },
   true
@@ -187,22 +136,13 @@
     attrs: {
       body: {
         strokeWidth: 1,
-        stroke: '#5F95FF',
-        fill: '#EFF4FF'
+        stroke: '#000000',
+        fill: '#FFFFFF'
       },
       text: {
         fontSize: 12,
         fill: '#262626'
       }
-    },
-    ports: {
-      groups,
-      items: [
-        { group: 'top' },
-        { group: 'right' },
-        { group: 'bottom' },
-        { group: 'left' }
-      ]
     }
   },
   true
@@ -217,8 +157,8 @@
     points: '100,10 40,198 190,78 10,78 160,198',
     attrs: {
       body: {
-        fill: '#EFF4FF',
-        stroke: '#5F95FF',
+        fill: '#FFFFFF',
+        stroke: '#000000',
         strokeWidth: 1,
         fillRule: 'nonzero'
       },
@@ -226,15 +166,26 @@
         fontSize: 12,
         fill: '#262626'
       }
-    },
-    ports: {
-      groups,
-      items: [
-        { group: 'top' },
-        { group: 'right' },
-        { group: 'bottom' },
-        { group: 'left' }
-      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-text',
+  {
+    inherit: 'rect',
+    width: 66,
+    height: 36,
+    attrs: {
+      body: {
+        strokeWidth: 0,
+        fill: 'transparent'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
     }
   },
   true
@@ -248,15 +199,8 @@
   }
 
   state = {
-    card: null,
-    eventListener: null,
-    toolunfold: true,
-    nodeunfold: true,
-    node: null
+    card: null
   }
-
-  selectNode = null
-  mkGraph = null
 
   UNSAFE_componentWillMount () {
     const { card } = this.props
@@ -264,9 +208,20 @@
     if (card.isNew) {
       let _plot = {
         width: card.width || 24,
-        height: 400,
+        height: 500,
         subtype: card.subtype,
-        name: card.name
+        name: card.name,
+        grid: {
+          visible: true,
+          type: 'dot',
+          args: {
+            color: '#a0a0a0',
+            thickness: 1
+          }
+        },
+        gridType: 'dot',
+        function: 'show',
+        supModule: []
       }
 
       let _card = {
@@ -278,7 +233,7 @@
         width: _plot.width,
         name: _plot.name,
         subtype: card.subtype,
-        setting: { interType: 'system' },
+        setting: { interType: '' },
         style: {
           borderWidth: '1px', borderColor: 'rgb(217, 217, 217)',
           marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
@@ -318,47 +273,50 @@
     }, 1000)
   }
 
-  viewrender = () => {
-    // const { card } = this.state
-
-    // if (card.plot.subtype === 'mindmap') {
-    //   this.ponitrender()
-    // } else if (card.plot.subtype === 'indentTree') {
-    //   this.indentrender()
-    // } else if (card.plot.subtype === 'kapmap') {
-      this.kapmaprender()
-    // }
-  }
-
-  kapmaprender = () => {
+  plotchange = (res) => {
     const { card } = this.state
 
-    // #region 鍒濆鍖栫敾甯�
+    if (
+      card.plot.subtype !== res.plot.subtype ||
+      (res.plot.gridType && card.plot.gridType !== res.plot.gridType) ||
+      (res.plot.gridType && card.plot.backgroundColor !== res.plot.backgroundColor)
+    ) {
+      let _element = document.getElementById(card.uuid + 'container')
+      if (_element) {
+        _element.innerHTML = ''
+      }
+      setTimeout(() => {
+        this.viewrender()
+      }, 50)
+    }
+
+    this.updateComponent(res)
+  }
+
+  viewrender = () => {
+    const { card } = this.state
+
+    if (card.plot.subtype === 'xflow') {
+      this.xflowrender()
+    } else if (card.plot.subtype === 'lane') {
+      this.lanerender()
+    }
+  }
+
+  xflowrender = () => {
+    const { card } = this.state
+
     const graph = new Graph({
       container: document.getElementById(card.uuid + 'container'),
-      // grid: {
-      //   visible: true,
-      //   type: 'doubleMesh',
-      //   args: [
-      //     {
-      //       color: '#eee', // 涓荤綉鏍肩嚎棰滆壊
-      //       thickness: 1   // 涓荤綉鏍肩嚎瀹藉害
-      //     },
-      //     {
-      //       color: '#ddd', // 娆$綉鏍肩嚎棰滆壊
-      //       thickness: 1,  // 娆$綉鏍肩嚎瀹藉害
-      //       factor: 4      // 涓绘缃戞牸绾块棿闅�
-      //     }
-      //   ]
-      // },
+      grid: card.plot.grid,
       scaling: {
         min: 0.5,
         max: 2
       },
       autoResize: true,
-      panning: true,
+      interacting: false,
       background: {
-        color: '#ffffff'
+        color: card.plot.backgroundColor || 'transparent'
       },
       mousewheel: {
         enabled: true,
@@ -378,306 +336,74 @@
         allowBlank: false,
         snap: {
           radius: 20
-        },
-        createEdge() {
-          return new Shape.Edge({
-            attrs: {
-              line: {
-                stroke: '#A2B1C3',
-                strokeWidth: 2,
-                targetMarker: {
-                  name: 'block',
-                  width: 12,
-                  height: 8
-                }
-              }
-            },
-            zIndex: 0
-          })
-        },
-        validateConnection({ targetMagnet }) {
-          return !!targetMagnet
         }
+      }
+    })
+
+    let cells = []
+    xflows.forEach((item) => {
+      if (item.shape === 'edge') {
+        cells.push(graph.createEdge(item))
+      } else {
+        cells.push(graph.createNode(item))
+      }
+    })
+    graph.resetCells(cells)
+    graph.positionContent('center')
+  }
+
+  lanerender = () => {
+    const { card } = this.state
+
+    const graph = new Graph({
+      container: document.getElementById(card.uuid + 'container'),
+      scaling: {
+        min: 0.5,
+        max: 2
       },
-      highlighting: {
-        magnetAdsorbed: {
-          name: 'stroke',
+      autoResize: true,
+      interacting: false,
+      background: { color: '#ffffff' },
+      mousewheel: {
+        enabled: true,
+        zoomAtMousePosition: true,
+        modifiers: 'ctrl'
+      },
+      connecting: {
+        router: 'manhattan',
+        connector: {
+          name: 'rounded',
           args: {
-            attrs: {
-              fill: '#5F95FF',
-              stroke: '#5F95FF'
-            }
+            radius: 8
           }
-        }
-      }
-    })
-
-    // #region 浣跨敤鎻掍欢
-    graph
-      .use(new Transform({
-        resizing: true,
-        rotating: true
-      }))
-      .use(new Selection())
-      .use(new Snapline())
-      .use(new Keyboard())
-      .use(new Clipboard())
-      .use(new History())
-
-    // #region 鍒濆鍖� stencil
-    const stencil = new Stencil({
-      title: '娴佺▼鍥�',
-      target: graph,
-      stencilGraphWidth: 180,
-      stencilGraphHeight: 180,
-      groups: [
-        {
-          title: '閫氱敤鑺傜偣',
-          name: 'group1'
         },
-        {
-          title: '鑷畾涔�',
-          name: 'group2',
-          graphHeight: 120,
-          layoutOptions: {
-            rowHeight: 70
-          }
-        }
-      ],
-      layoutOptions: {
-        columns: 2,
-        columnWidth: 80,
-        rowHeight: 55
-      }
-    })
-
-    document.getElementById(card.uuid + 'stencil').appendChild(stencil.container)
-
-    // #region 蹇嵎閿笌浜嬩欢
-    graph.bindKey(['meta+c', 'ctrl+c'], () => {
-      const cells = graph.getSelectedCells()
-      if (cells.length) {
-        graph.copy(cells)
-      }
-      return false
-    })
-    graph.bindKey(['meta+x', 'ctrl+x'], () => {
-      const cells = graph.getSelectedCells()
-      if (cells.length) {
-        graph.cut(cells)
-      }
-      return false
-    })
-    graph.bindKey(['meta+v', 'ctrl+v'], () => {
-      if (!graph.isClipboardEmpty()) {
-        graph.paste({ offset: 32 })
-      }
-      return false
-    })
-
-    // undo redo
-    graph.bindKey(['meta+z', 'ctrl+z'], () => {
-      if (graph.canUndo()) {
-        graph.undo()
-      }
-      return false
-    })
-    graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
-      if (graph.canRedo()) {
-        graph.redo()
-      }
-      return false
-    })
-
-    // 鍒犻櫎鍏冪礌
-    graph.bindKey(['backspace', 'delete'], () => {
-      const cells = graph.getSelectedCells()
-      if (cells.length) {
-        graph.removeCells(cells)
-        this.selectNode = null
-        this.setState({node: null})
-      }
-    })
-
-    // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌
-    const showPorts = (ports, show) => {
-      for (let i = 0, len = ports.length; i < len; i += 1) {
-        ports[i].style.visibility = show ? 'visible' : 'hidden'
-      }
-    }
-    graph.on('node:mouseenter', () => {
-      const container = document.getElementById(card.uuid + 'container')
-      const ports = container.querySelectorAll('.x6-port-body')
-      showPorts(ports, true)
-    })
-    graph.on('node:mouseleave', () => {
-      const container = document.getElementById(card.uuid + 'container')
-      const ports = container.querySelectorAll('.x6-port-body')
-      showPorts(ports, false)
-    })
-
-    graph.on('node:click', ({ e, x, y, node, view }) => {
-      this.selectNode = node
-      
-      this.setState({node: node.store.data})
-    })
-    graph.on('edge:click', ({ e, x, y, edge, view }) => {
-      this.selectNode = edge
-      
-      this.setState({node: edge.store.data})
-
-      graph.clearTransformWidgets()
-    })
-    graph.on('blank:click', ({ e, x, y }) => {
-      this.selectNode = null
-      
-      this.setState({node: null})
-    })
-    
-    const r1 = graph.createNode({
-      shape: 'mk-rect',
-      label: '寮�濮�',
-      attrs: {
-        body: {
-          rx: 20,
-          ry: 26
+        anchor: 'center',
+        connectionPoint: 'anchor',
+        allowBlank: false,
+        snap: {
+          radius: 20
         }
       }
     })
-    const r2 = graph.createNode({
-      shape: 'mk-rect',
-      label: '杩囩▼'
-    })
-    const r3 = graph.createNode({
-      shape: 'mk-rect',
-      attrs: {
-        body: {
-          rx: 6,
-          ry: 6
-        }
-      },
-      label: '鍙�夎繃绋�'
-    })
-    const r4 = graph.createNode({
-      shape: 'mk-polygon',
-      attrs: {
-        body: {
-          refPoints: '0,10 10,0 20,10 10,20'
-        }
-      },
-      label: '鍐崇瓥'
-    })
-    const r5 = graph.createNode({
-      shape: 'mk-polygon',
-      attrs: {
-        body: {
-          refPoints: '10,0 40,0 30,20 0,20'
-        }
-      },
-      label: '鏁版嵁'
-    })
-    const r6 = graph.createNode({
-      shape: 'mk-circle',
-      label: '杩炴帴'
-    })
-    
-    stencil.load([r1, r2, r3, r4, r5, r6], 'group1')
-    
-    const p1 = graph.createNode({
-      shape: 'mk-ellipse',
-      label: 'ellipse'
-    })
-    const p2 = graph.createNode({
-      shape: 'mk-star',
-      label: ''
-    })
-    
-    stencil.load([p1, p2], 'group2')
-    
-    this.mkGraph = graph
-  }
-  
-  setTop = () => {
-    if (!this.selectNode) {
-      message.warning('璇烽�夋嫨鑺傜偣锛�')
-      return
-    }
-    this.selectNode.toFront()
-  }
 
-  setBottom = () => {
-    if (!this.selectNode) {
-      message.warning('璇烽�夋嫨鑺傜偣锛�')
-      return
-    }
-    // let cells = this.mkGraph.getCells()
-    this.selectNode.toBack()
-  }
-
-  // zoom() 鍙幏鍙栨垨鑰呰缃缉鏀炬瘮渚�
-  setZoomIn = () => {
-    this.mkGraph.zoom(0.1)
-  }
-
-  setZoomOut = () => {
-    this.mkGraph.zoom(-0.1)
-  }
-
-  setZoomInt = () => {
-    this.mkGraph.zoomTo(1)
-  }
-
-  save = () => {
-    // let nodes = this.mkGraph.toJSON()
-  }
-
-  changeProps = (value, key) => {
-    const { node } = this.state
-
-    if (node.shape === 'edge') {
-      if (key === 'title') {
-        this.selectNode.setLabels(value)
-      } else if (key === 'stroke') {
-        this.selectNode.attr('line/stroke', value)
-      } else if (key === 'strokeWidth') {
-        this.selectNode.attr('line/strokeWidth', value)
-      } else if (key === 'lineType') {
-        if (value === 'dash') {
-          this.selectNode.attr('line/strokeDasharray', 5)
-        } else {
-          this.selectNode.attr('line/strokeDasharray', 0)
-        }
-      } else if (key === 'fontSize') {
-        this.selectNode.attr('text/fontSize', value)
-      } else if (key === 'fontFill') {
-        this.selectNode.attr('text/fill', value)
+    let cells = []
+    lanes.forEach((item) => {
+      if (item.shape === 'edge') {
+        cells.push(graph.createEdge(item))
+      } else {
+        cells.push(graph.createNode(item))
       }
-    } else {
-      if (key === 'title') {
-        this.selectNode.attr('text/text', value)
-      } else if (key === 'fill') {
-        this.selectNode.attr('body/fill', value)
-      } else if (key === 'stroke') {
-        this.selectNode.attr('body/stroke', value)
-      } else if (key === 'fontSize') {
-        this.selectNode.attr('text/fontSize', value)
-      } else if (key === 'fontFill') {
-        this.selectNode.attr('text/fill', value)
-      }
-    }
+    })
+    graph.resetCells(cells)
+    graph.positionContent('top')
   }
 
   updateComponent = (card) => {
     card.width = card.plot.width
     card.name = card.plot.name
     card.subtype = card.plot.subtype
-    
-    card.$c_ds = true
-    card.errors = checkComponent(card)
-
-    if (card.errors.length === 0) {
-      card.$tables = getTables(card)
-    }
+    card.errors = []
+    card.$tables = []
 
     this.setState({
       card: card
@@ -710,74 +436,28 @@
   }
 
   render() {
-    const { card, toolunfold, nodeunfold, node } = this.state
+    const { card } = this.state
     let _style = resetStyle(card.style)
 
     return (
       <div className="menu-x6-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
         <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
-            <ChartCompileForm config={card} plotchange={this.updateComponent}/>
-            <CopyComponent type="antvG6" card={card}/>
+            <ChartCompileForm config={card} plotchange={this.plotchange}/>
+            <CopyComponent type="antvX6" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/>
-            <SettingComponent config={card} updateConfig={this.updateComponent}/>
           </div>
         } trigger="hover">
           <ToolOutlined/>
         </Popover>
         <NormalHeader config={card} updateComponent={this.updateComponent}/>
-        <div className="mk-toolbar">
-          <div className="left-tool">
-            <Tooltip title="缃墠">
-              <VerticalAlignTopOutlined onClick={this.setTop}/>
-            </Tooltip>
-            <Tooltip title="缃悗">
-              <VerticalAlignBottomOutlined onClick={this.setBottom}/>
-            </Tooltip>
-            <Tooltip title="淇濆瓨">
-              <SaveOutlined onClick={this.save}/>
-            </Tooltip>
-          </div>
-          <div className="right-tool">
-            <Tooltip title="鏀惧ぇ">
-              <ZoomInOutlined onClick={this.setZoomIn}/>
-            </Tooltip>
-            <Tooltip title="缂╁皬">
-              <ZoomOutOutlined onClick={this.setZoomOut}/>
-            </Tooltip>
-            <Tooltip title="1:1">
-              <OneToOneOutlined onClick={this.setZoomInt}/>
-            </Tooltip>
-          </div>
-        </div>
         <div className="canvas" style={{width: '100%', minHeight: card.plot.height, height: card.plot.height}} id={card.uuid + 'canvas'}>
-          <div id={card.uuid + 'stencil'} className={'mk-stencil ' + (toolunfold ? '' : 'merge')}>
-            <div className="tool-control" onClick={() => this.setState({toolunfold: !toolunfold})}>
-              <DoubleLeftOutlined />
-            </div>
-          </div>
           <div id={card.uuid + 'container'} className="mk-container"></div>
-          <div className={'mk-node-edit ' + (nodeunfold ? '' : 'merge')}>
-            <div className="tool-control" onClick={() => this.setState({nodeunfold: !nodeunfold})}>
-              <DoubleLeftOutlined />
-            </div>
-            <div className="header">璁剧疆</div>
-            {!node ? <div className="empty">鏈�変腑</div> : <NodeUpdate node={node} onChange={this.changeProps}/>}
-          </div>
         </div>
         <div className="component-name">
           <div className="center">
             <div className="title">{card.name}</div>
-            <div className="content">
-              {card.errors && card.errors.map((err, index) => {
-                if (err.level === 0) {
-                  return <span key={index} className="error">{err.detail}</span>
-                } else {
-                  return <span key={index} className="waring">{err.detail}锛�</span>
-                }
-              })}
-            </div>
           </div>
         </div>
       </div>
diff --git a/src/menu/components/chart/antv-X6/index.scss b/src/menu/components/chart/antv-X6/index.scss
index bb28fcb..edf4d88 100644
--- a/src/menu/components/chart/antv-X6/index.scss
+++ b/src/menu/components/chart/antv-X6/index.scss
@@ -5,194 +5,23 @@
   background-position: center center;
   background-repeat: no-repeat;
   background-size: cover;
-  
-  .mk-toolbar {
-    width: 100%;
-    height: 40px;
-    border: 1px solid #1890ff;
 
-    .left-tool {
-      float: left;
-      line-height: 40px;
-      .anticon {
-        margin: 0 10px;
-        font-size: 16px;
-        cursor: pointer;
-      }
-    }
-    .right-tool {
-      float: right;
-      line-height: 40px;
-      .anticon {
-        margin: 0 10px;
-        font-size: 16px;
-        cursor: pointer;
-      }
-    }
-  }
   .x6-graph-scroller::-webkit-scrollbar {
     display: none;
   }
   .x6-cell.x6-edge.x6-edge-selected path:nth-child(2) {
     stroke: #1890ff;
   }
+  .x6-cell[data-shape="lane"] {
+    cursor: default;
+  }
 
   .canvas {
     margin: 0px;
     letter-spacing: 0px;
-    display: flex;
-
-    .mk-stencil {
-      width: 180px;
-      min-width: 180px;
-      height: 100%;
-      position: relative;
-      z-index: 2;
-      border-right: 1px solid #dfe3e8;
-      transition: all 0.2s;
-
-      .x6-widget-stencil-title {
-        display: none;
-      }
-      .x6-widget-stencil-content {
-        overflow-y: auto;
-      }
-      .x6-widget-stencil-content::-webkit-scrollbar {
-        width: 7px;
-      }
-      .x6-widget-stencil-content::-webkit-scrollbar-thumb {
-        border-radius: 5px;
-        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-        background: rgba(0, 0, 0, 0.13);
-      }
-      .x6-widget-stencil-content::-webkit-scrollbar-track {
-        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-        border-radius: 3px;
-        border: 1px solid rgba(0, 0, 0, 0.07);
-        background: rgba(0, 0, 0, 0);
-      }
-      .tool-control {
-        position: absolute;
-        right: -13px;
-        top: 5px;
-        z-index: 3;
-        background: #ffffff;
-        width: 25px;
-        height: 25px;
-        border: 1px solid #d8d8d8;
-        border-radius: 30px;
-        text-align: center;
-        line-height: 25px;
-        cursor: pointer;
-      }
-    }
-    .mk-stencil.merge {
-      width: 0px;
-      min-width: 0px;
-
-      .tool-control {
-        right: -25px;
-        border-top-left-radius: 0px;
-        border-bottom-left-radius: 0px;
-        .anticon-double-left {
-          transform: rotate(180deg);
-        }
-      }
-    }
-
-    .mk-node-edit {
-      width: 180px;
-      min-width: 180px;
-      height: 100%;
-      position: relative;
-      z-index: 2;
-      border-left: 1px solid #dfe3e8;
-      transition: all 0.2s;
-
-      .header {
-        width: 100%;
-        height: 32px;
-        text-align: center;
-        line-height: 32px;
-        background-color: #f5f5f5!important;
-        overflow-x: hidden;
-        white-space: nowrap;
-      }
-      .empty {
-        width: 100%;
-        text-align: center;
-        padding-top: 20px;
-        overflow-x: hidden;
-        white-space: nowrap;
-      }
-
-      .tool-control {
-        position: absolute;
-        left: -13px;
-        top: 5px;
-        z-index: 3;
-        background: #ffffff;
-        width: 25px;
-        height: 25px;
-        border: 1px solid #d8d8d8;
-        border-radius: 30px;
-        text-align: center;
-        line-height: 25px;
-        cursor: pointer;
-        .anticon-double-left {
-          transform: rotate(180deg);
-        }
-      }
-    }
-    .mk-node-edit.merge {
-      width: 0px;
-      min-width: 0px;
-
-      .tool-control {
-        left: -25px;
-        border-top-right-radius: 0px;
-        border-bottom-right-radius: 0px;
-        .anticon-double-left {
-          transform: rotate(0deg);
-        }
-      }
-    }
 
     .mk-container {
-      width: calc(100% - 180px);
       height: 100%;
-    }
-    .x6-widget-stencil  {
-      background-color: #fff;
-    }
-    .x6-widget-stencil-title {
-      background-color: #fff;
-    }
-    .x6-widget-stencil-group-title {
-      background-color: #f5f5f5!important;
-    }
-    .x6-widget-transform {
-      margin: -1px 0 0 -1px;
-      padding: 0px;
-      border: 1px solid #239edd;
-    }
-    .x6-widget-transform > div {
-      border: 1px solid #239edd;
-    }
-    .x6-widget-transform > div:hover {
-      background-color: #3dafe4;
-    }
-    .x6-widget-transform-active-handle {
-      background-color: #3dafe4;
-    }
-    .x6-widget-transform-resize {
-      border-radius: 0;
-    }
-    .x6-widget-selection-inner {
-      border: 1px solid #239edd;
-    }
-    .x6-widget-selection-box {
-      opacity: 0;
     }
   }
 
diff --git a/src/menu/components/chart/antv-X6/lane.json b/src/menu/components/chart/antv-X6/lane.json
new file mode 100644
index 0000000..5029dce
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/lane.json
@@ -0,0 +1,1162 @@
+[{
+  "position": {
+    "x": 0,
+    "y": 0
+  },
+  "size": {
+    "width": 200,
+    "height": 500
+  },
+  "attrs": {
+    "text": {
+      "text": "闃舵1"
+    }
+  },
+  "visible": true,
+  "shape": "lane",
+  "id": "086eb967-7a70-4581-bb82-1dd87f6473e3",
+  "zIndex": 0
+}, {
+  "position": {
+    "x": 200,
+    "y": 0
+  },
+  "size": {
+    "width": 200,
+    "height": 500
+  },
+  "attrs": {
+    "text": {
+      "text": "闃舵2"
+    }
+  },
+  "visible": true,
+  "shape": "lane",
+  "id": "eab0b7c3-3eb4-45da-8b43-cc215047edd4",
+  "zIndex": 0
+}, {
+  "position": {
+    "x": 400,
+    "y": 0
+  },
+  "size": {
+    "width": 200,
+    "height": 500
+  },
+  "attrs": {
+    "text": {
+      "text": "闃舵3"
+    }
+  },
+  "visible": true,
+  "shape": "lane",
+  "id": "8666799f-c76c-4695-8804-0d3579caadc4",
+  "zIndex": 0
+}, {
+  "position": {
+    "x": 600,
+    "y": 0
+  },
+  "size": {
+    "width": 200,
+    "height": 500
+  },
+  "attrs": {
+    "text": {
+      "text": "闃舵4"
+    }
+  },
+  "visible": true,
+  "shape": "lane",
+  "id": "68e49c35-cf6f-46f0-bcde-754c2a2b0ffe",
+  "zIndex": 0
+}, {
+  "position": {
+    "x": 67,
+    "y": 70
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Start"
+    },
+    "body": {
+      "rx": 20,
+      "ry": 26
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "7af1dd51-e0c8-45e2-8f72-96777215e0da"
+    }, {
+      "group": "right",
+      "id": "d0576432-07e4-4f9e-bb0a-81fc7eabdbb3"
+    }, {
+      "group": "bottom",
+      "id": "6faa8816-930d-4356-9fbe-c18bbdfc99ab"
+    }, {
+      "group": "left",
+      "id": "161b1890-3c4a-4758-b444-7a249763ee3a"
+    }]
+  },
+  "id": "c6f49af2-3f6f-4b60-88e3-ea0f45223f34",
+  "zIndex": 1,
+  "parent": "086eb967-7a70-4581-bb82-1dd87f6473e3"
+}, {
+  "position": {
+    "x": 267,
+    "y": 70
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Process"
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+    }, {
+      "group": "right",
+      "id": "5c37a597-97e2-4f2e-a676-017f66060bbd"
+    }, {
+      "group": "bottom",
+      "id": "5573dafd-2958-410c-a4a0-e38bc6a24065"
+    }, {
+      "group": "left",
+      "id": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+    }]
+  },
+  "id": "26c76caa-ca35-4f72-abd3-9bdf348081b0",
+  "zIndex": 2,
+  "parent": "eab0b7c3-3eb4-45da-8b43-cc215047edd4"
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "78e0c6e9-a882-468e-91e1-f01399015440",
+  "zIndex": 2,
+  "source": {
+    "cell": "c6f49af2-3f6f-4b60-88e3-ea0f45223f34",
+    "port": "d0576432-07e4-4f9e-bb0a-81fc7eabdbb3"
+  },
+  "target": {
+    "cell": "26c76caa-ca35-4f72-abd3-9bdf348081b0",
+    "port": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "6418ad5a-f6af-486f-9068-0642c5c2fb1f",
+  "zIndex": 2,
+  "source": {
+    "cell": "26c76caa-ca35-4f72-abd3-9bdf348081b0",
+    "port": "5c37a597-97e2-4f2e-a676-017f66060bbd"
+  },
+  "target": {
+    "cell": "864acc4a-daa5-4fae-9b2a-c90c1eb7752e",
+    "port": "56c9c736-744a-48f3-84bb-706a0f15712f"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "458e8e95-f5e7-46a0-add3-e42c7b832178",
+  "zIndex": 2,
+  "source": {
+    "cell": "864acc4a-daa5-4fae-9b2a-c90c1eb7752e",
+    "port": "8e9111c6-83d2-44d5-b6be-2c5504d8ff72"
+  },
+  "target": {
+    "cell": "aae00f04-39b6-403d-98a2-057ea251376b",
+    "port": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+  },
+  "labels": ["Yes"]
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "3f9348e4-d2bd-4300-b873-8915fe7cc152",
+  "zIndex": 2,
+  "source": {
+    "cell": "864acc4a-daa5-4fae-9b2a-c90c1eb7752e",
+    "port": "23e59070-cc3f-4005-80b8-0d8eec0eba8f"
+  },
+  "target": {
+    "cell": "246493f4-865f-407e-9407-4df6f5dae340",
+    "port": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+  },
+  "labels": ["No"]
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "206575cf-9c23-4c95-8f98-e448f95b6bb3",
+  "zIndex": 2,
+  "source": {
+    "cell": "246493f4-865f-407e-9407-4df6f5dae340",
+    "port": "5573dafd-2958-410c-a4a0-e38bc6a24065"
+  },
+  "target": {
+    "cell": "54347093-ddd3-46c4-b2d5-b65352c10ac3",
+    "port": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "e88f16a4-393c-4572-9bf4-0775dff8b021",
+  "zIndex": 2,
+  "source": {
+    "cell": "54347093-ddd3-46c4-b2d5-b65352c10ac3",
+    "port": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+  },
+  "target": {
+    "cell": "d684e64f-6fac-4879-bd74-2749c9f2436f",
+    "port": "23e59070-cc3f-4005-80b8-0d8eec0eba8f"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "d5cc4a65-9209-422f-b971-7b0790938018",
+  "zIndex": 2,
+  "source": {
+    "cell": "d684e64f-6fac-4879-bd74-2749c9f2436f",
+    "port": "8e9111c6-83d2-44d5-b6be-2c5504d8ff72"
+  },
+  "target": {
+    "cell": "37ef7b6f-659d-4e10-812d-df7dc7c4d66e",
+    "port": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+  },
+  "labels": ["Yes"]
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "18aa70cc-a580-48b2-9b14-a2313ee3e69c",
+  "zIndex": 2,
+  "source": {
+    "cell": "37ef7b6f-659d-4e10-812d-df7dc7c4d66e",
+    "port": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+  },
+  "target": {
+    "cell": "1aa90d24-7fca-4298-a0e7-17b4bc88e33b",
+    "port": "d0576432-07e4-4f9e-bb0a-81fc7eabdbb3"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "30eff504-21f8-46ca-8809-28ce4aaadf03",
+  "zIndex": 2,
+  "source": {
+    "cell": "d684e64f-6fac-4879-bd74-2749c9f2436f",
+    "port": "56c9c736-744a-48f3-84bb-706a0f15712f"
+  },
+  "target": {
+    "cell": "1aa90d24-7fca-4298-a0e7-17b4bc88e33b",
+    "port": "7af1dd51-e0c8-45e2-8f72-96777215e0da"
+  },
+  "labels": ["No"]
+}, {
+  "position": {
+    "x": 467,
+    "y": 70
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Judge"
+    },
+    "body": {
+      "refPoints": "0,10 10,0 20,10 10,20"
+    }
+  },
+  "visible": true,
+  "shape": "mk-polygon",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "52a617c4-1c62-4bd6-b827-6215feac4495"
+    }, {
+      "group": "right",
+      "id": "23e59070-cc3f-4005-80b8-0d8eec0eba8f"
+    }, {
+      "group": "bottom",
+      "id": "8e9111c6-83d2-44d5-b6be-2c5504d8ff72"
+    }, {
+      "group": "left",
+      "id": "56c9c736-744a-48f3-84bb-706a0f15712f"
+    }]
+  },
+  "id": "864acc4a-daa5-4fae-9b2a-c90c1eb7752e",
+  "zIndex": 3,
+  "parent": "8666799f-c76c-4695-8804-0d3579caadc4"
+}, {
+  "position": {
+    "x": 467,
+    "y": 170
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Process"
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+    }, {
+      "group": "right",
+      "id": "5c37a597-97e2-4f2e-a676-017f66060bbd"
+    }, {
+      "group": "bottom",
+      "id": "5573dafd-2958-410c-a4a0-e38bc6a24065"
+    }, {
+      "group": "left",
+      "id": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+    }]
+  },
+  "id": "aae00f04-39b6-403d-98a2-057ea251376b",
+  "zIndex": 4,
+  "parent": "8666799f-c76c-4695-8804-0d3579caadc4"
+}, {
+  "position": {
+    "x": 670,
+    "y": 170
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Process"
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+    }, {
+      "group": "right",
+      "id": "5c37a597-97e2-4f2e-a676-017f66060bbd"
+    }, {
+      "group": "bottom",
+      "id": "5573dafd-2958-410c-a4a0-e38bc6a24065"
+    }, {
+      "group": "left",
+      "id": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+    }]
+  },
+  "id": "246493f4-865f-407e-9407-4df6f5dae340",
+  "zIndex": 5,
+  "parent": "68e49c35-cf6f-46f0-bcde-754c2a2b0ffe"
+}, {
+  "position": {
+    "x": 670,
+    "y": 260
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Process"
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+    }, {
+      "group": "right",
+      "id": "5c37a597-97e2-4f2e-a676-017f66060bbd"
+    }, {
+      "group": "bottom",
+      "id": "5573dafd-2958-410c-a4a0-e38bc6a24065"
+    }, {
+      "group": "left",
+      "id": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+    }]
+  },
+  "id": "54347093-ddd3-46c4-b2d5-b65352c10ac3",
+  "zIndex": 6,
+  "parent": "68e49c35-cf6f-46f0-bcde-754c2a2b0ffe"
+}, {
+  "position": {
+    "x": 467,
+    "y": 260
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Judge"
+    },
+    "body": {
+      "refPoints": "0,10 10,0 20,10 10,20"
+    }
+  },
+  "visible": true,
+  "shape": "mk-polygon",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "52a617c4-1c62-4bd6-b827-6215feac4495"
+    }, {
+      "group": "right",
+      "id": "23e59070-cc3f-4005-80b8-0d8eec0eba8f"
+    }, {
+      "group": "bottom",
+      "id": "8e9111c6-83d2-44d5-b6be-2c5504d8ff72"
+    }, {
+      "group": "left",
+      "id": "56c9c736-744a-48f3-84bb-706a0f15712f"
+    }]
+  },
+  "id": "d684e64f-6fac-4879-bd74-2749c9f2436f",
+  "zIndex": 7,
+  "parent": "8666799f-c76c-4695-8804-0d3579caadc4"
+}, {
+  "position": {
+    "x": 467,
+    "y": 370
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "Process"
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "c825ad9f-4b0a-4c6c-aee0-1c861955a794"
+    }, {
+      "group": "right",
+      "id": "5c37a597-97e2-4f2e-a676-017f66060bbd"
+    }, {
+      "group": "bottom",
+      "id": "5573dafd-2958-410c-a4a0-e38bc6a24065"
+    }, {
+      "group": "left",
+      "id": "7b15a915-f31a-4338-a68a-1fe5cf1f78da"
+    }]
+  },
+  "id": "37ef7b6f-659d-4e10-812d-df7dc7c4d66e",
+  "zIndex": 8,
+  "parent": "8666799f-c76c-4695-8804-0d3579caadc4"
+}, {
+  "position": {
+    "x": 270,
+    "y": 370
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "End"
+    },
+    "body": {
+      "rx": 20,
+      "ry": 26
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "7af1dd51-e0c8-45e2-8f72-96777215e0da"
+    }, {
+      "group": "right",
+      "id": "d0576432-07e4-4f9e-bb0a-81fc7eabdbb3"
+    }, {
+      "group": "bottom",
+      "id": "6faa8816-930d-4356-9fbe-c18bbdfc99ab"
+    }, {
+      "group": "left",
+      "id": "161b1890-3c4a-4758-b444-7a249763ee3a"
+    }]
+  },
+  "id": "1aa90d24-7fca-4298-a0e7-17b4bc88e33b",
+  "zIndex": 9,
+  "parent": "eab0b7c3-3eb4-45da-8b43-cc215047edd4"
+}]
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-X6/nodeupdate/index.jsx b/src/menu/components/chart/antv-X6/nodeupdate/index.jsx
deleted file mode 100644
index 5dcfb27..0000000
--- a/src/menu/components/chart/antv-X6/nodeupdate/index.jsx
+++ /dev/null
@@ -1,288 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, Radio, InputNumber } from 'antd'
-
-import ColorSketch from '@/mob/colorsketch'
-
-import './index.scss'
-
-class NodeUpdate extends Component {
-  static propTpyes = {
-    node: PropTypes.object
-  }
-
-  state = {
-    formlist: null
-  }
-
-  UNSAFE_componentWillMount () {
-    this.setState({
-      formlist: this.getFormList(this.props.node)
-    })
-  }
-
-  UNSAFE_componentWillReceiveProps(nextProps) {
-    if (!is(fromJS(this.props.node), fromJS(nextProps.node))) {
-      this.setState({
-        formlist: null
-      }, () => {
-        this.setState({
-          formlist: this.getFormList(nextProps.node)
-        })
-      })
-    }
-  }
-
-  getFormList = (node) => {
-    let roleList = sessionStorage.getItem('sysRoles')
-    if (roleList) {
-      try {
-        roleList = JSON.parse(roleList)
-      } catch (e) {
-        roleList = []
-      }
-    } else {
-      roleList = []
-    }
-
-    let title = ''
-    if (node.attrs && node.attrs.text) {
-      title = node.attrs.text.text || ''
-    }
-
-    if (node.shape === 'edge') {
-      // let fontSize = 14
-      // if (node.attrs && node.attrs.text) {
-      //   fontSize = node.attrs.text.fontSize || 14
-      // }
-      let stroke = ''
-
-      if (node.attrs && node.attrs.line) {
-        stroke = node.attrs.line.stroke || '#A2B1C3'
-      }
-
-      let strokeWidth = ''
-
-      if (node.attrs && node.attrs.line) {
-        strokeWidth = node.attrs.line.strokeWidth || 2
-      }
-
-      let lineType = 'solid'
-
-      if (node.attrs && node.attrs.line && node.attrs.line.strokeDasharray) {
-        lineType = 'dash'
-      }
-
-      return [
-        {
-          type: 'title',
-          label: '鍐呭'
-        },
-        {
-          type: 'text',
-          field: 'title',
-          label: '鏍囩',
-          initval: title
-        },
-        {
-          type: 'title',
-          label: '鏍峰紡'
-        },
-        {
-          type: 'color',
-          field: 'stroke',
-          label: '棰滆壊',
-          initval: stroke
-        },
-        {
-          type: 'number',
-          field: 'strokeWidth',
-          label: '绾垮',
-          initval: strokeWidth
-        },
-        {
-          type: 'radio',
-          field: 'lineType',
-          label: '绾垮瀷',
-          initval: lineType,
-          options: [
-            {value: 'solid', text: '瀹炵嚎'},
-            {value: 'dash', text: '铏氱嚎'}
-          ]
-        },
-        // {
-        //   type: 'number',
-        //   field: 'fontSize',
-        //   label: '瀛楀彿',
-        //   initval: fontSize
-        // },
-        // {
-        //   type: 'color',
-        //   field: 'fontFill',
-        //   label: '棰滆壊',
-        //   initval: fontFill
-        // }
-      ]
-    } else {
-      let fontFill = '#262626'
-      if (node.attrs && node.attrs.text) {
-        fontFill = node.attrs.text.fill || '#262626'
-      }
-      
-      let fill = ''
-
-      if (node.attrs && node.attrs.body) {
-        fill = node.attrs.body.fill || ''
-      }
-      let fontSize = 12
-      if (node.attrs && node.attrs.text) {
-        fontSize = node.attrs.text.fontSize || 12
-      }
-      let stroke = ''
-
-      if (node.attrs && node.attrs.body) {
-        stroke = node.attrs.body.stroke || ''
-      }
-      return [
-        {
-          type: 'title',
-          label: '鍐呭'
-        },
-        {
-          type: 'text',
-          field: 'title',
-          label: '鏍囩',
-          initval: title
-        },
-        {
-          type: 'title',
-          label: '鏍峰紡'
-        },
-        {
-          type: 'color',
-          field: 'fill',
-          label: '鑳屾櫙',
-          initval: fill
-        },
-        {
-          type: 'color',
-          field: 'stroke',
-          label: '杈规',
-          initval: stroke
-        },
-        {
-          type: 'title',
-          label: '鏍囩鏍峰紡'
-        },
-        {
-          type: 'number',
-          field: 'fontSize',
-          label: '瀛楀彿',
-          initval: fontSize
-        },
-        {
-          type: 'color',
-          field: 'fontFill',
-          label: '棰滆壊',
-          initval: fontFill
-        }
-      ]
-    }
-  }
-
-  change = (value, key) => {
-    if (key === 'fontSize') {
-      if (typeof(value) !== 'number' || value < 0) {
-        return
-      }
-    }
-
-    this.props.onChange(value, key)
-  }
-
-  getFields() {
-    const { formlist } = this.state
-    const fields = []
-
-    if (!formlist) return
-
-    formlist.forEach((item, index) => {
-      if (item.type === 'title') {
-        fields.push(
-          <Col span={24} key={index}>
-            <span className="split-line">{item.label}</span>
-          </Col>
-        )
-      } else if (item.type === 'text') {
-        fields.push(
-          <Col span={24} key={index}>
-            <Form.Item label={item.label}>
-              <Input defaultValue={item.initval} placeholder="" autoComplete="off" onChange={(e) => this.change(e.target.value, item.field)} />
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'number') {
-        fields.push(
-          <Col span={24} key={index}>
-            <Form.Item label={item.label}>
-              <InputNumber defaultValue={item.initval} precision={0} min={0} onChange={(value) => this.change(value, item.field)} />
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'select') {
-        fields.push(
-          <Col span={24} key={index}>
-            <Form.Item label={item.label}>
-              <Select
-                showSearch
-                defaultValue={item.initval}
-                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                onChange={(value) => {this.change(value, item.field)}}
-              >
-                {item.options.map(option =>
-                  <Select.Option key={option.value} value={option.value}>
-                    {option.text}
-                  </Select.Option>
-                )}
-              </Select>
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'radio') {
-        fields.push(
-          <Col span={24} key={index}>
-            <Form.Item label={item.label}>
-              <Radio.Group defaultValue={item.initval} style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.change(e.target.value, item.field)}}>
-                {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={24} key={index}>
-            <Form.Item label={item.label}>
-              <ColorSketch defaultValue={item.initval} onChange={(value) => this.change(value, item.field)}/>
-            </Form.Item>
-          </Col>
-        )
-      }
-    })
-    return fields
-  }
-
-  render() {
-    return (
-      <Form className="node-edit-form">
-        <Row>{this.getFields()}</Row>
-      </Form>
-    )
-  }
-}
-
-export default NodeUpdate
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-X6/nodeupdate/index.scss b/src/menu/components/chart/antv-X6/nodeupdate/index.scss
deleted file mode 100644
index 4434358..0000000
--- a/src/menu/components/chart/antv-X6/nodeupdate/index.scss
+++ /dev/null
@@ -1,67 +0,0 @@
-.node-edit-form {
-  padding-top: 10px;
-  .split-line {
-    display: block;
-    border-bottom: 1px solid #d9d9d9;
-    margin: 5px 12px 10px;
-    padding-bottom: 2px;
-    font-size: 13px;
-  }
-  .ant-form-item {
-    display: flex;
-    margin-bottom: 10px;
-
-    .ant-form-item-label {
-      width: 40px;
-      line-height: 24px;
-      label {
-        color: rgba(0,0,0,0.45);
-        font-size: 13px;
-      }
-      label::after {
-        display: none;
-      }
-    }
-    .ant-form-item-control-wrapper {
-      padding: 0 8px;
-      flex: 1;
-      .ant-form-item-control {
-        line-height: 24px;
-      }
-      .ant-input {
-        height: 24px;
-        padding: 0px 4px;
-        font-size: 13px;
-        line-height: 24px;
-        border-radius: 0px;
-      }
-      .ant-input-number {
-        height: 24px;
-        border-radius: 0px;
-        .ant-input-number-input {
-          height: 22px;
-          padding: 2px 4px;
-          font-size: 13px;
-        }
-      }
-      .ant-radio-wrapper {
-        margin-right: 0px;
-      }
-
-      .color-sketch-block {
-        height: 22px;
-        margin-top: 2px;
-        .color-sketch-block-box {
-          width: 22px;
-          height: 22px;
-        }
-        .color-sketch-value {
-          display: none;
-        }
-        .color-sketch-block-inner {
-          border-radius: 0px;
-        }
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-X6/xflow.json b/src/menu/components/chart/antv-X6/xflow.json
new file mode 100644
index 0000000..1062628
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/xflow.json
@@ -0,0 +1,986 @@
+[{
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "83fd4cbd-727e-4e99-b35a-854ea08a5a3e",
+  "zIndex": 0,
+  "source": {
+    "cell": "a464f73a-c12d-4612-ae76-55ae754618e2",
+    "port": "18cb49ca-e40a-4cb5-8a05-18c5ed7644fe"
+  },
+  "target": {
+    "cell": "310c8213-f07a-4d30-9d35-36f03a7ceb8e",
+    "port": "c6e8912a-e3a3-4765-9aad-0767b55eb976"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "31c3bf79-0ea5-46d1-acd0-028de2161075",
+  "zIndex": 0,
+  "source": {
+    "cell": "310c8213-f07a-4d30-9d35-36f03a7ceb8e",
+    "port": "95ae6a99-3024-4667-8c77-8b3e0404b07a"
+  },
+  "target": {
+    "cell": "ef3d1b04-c830-4146-89a4-23e330fce83d",
+    "port": "6c62d9ff-0d11-4d44-b234-76033f91b67d"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "79a4da44-2d8e-47fa-8449-fe3623805ffc",
+  "zIndex": 0,
+  "source": {
+    "cell": "ef3d1b04-c830-4146-89a4-23e330fce83d",
+    "port": "7024e8d6-df2f-4273-aadb-67ed01507bae"
+  },
+  "target": {
+    "cell": "dba4e54b-96e7-4bb8-9d2f-d76d47ce662e",
+    "port": "e1ad288c-6567-413f-b2c3-132d43a566c5"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "ffb2b76e-2d42-494a-a646-eb50fd410168",
+  "zIndex": 0,
+  "source": {
+    "cell": "ef3d1b04-c830-4146-89a4-23e330fce83d",
+    "port": "6a767960-f16e-4b71-93f8-82400370fe2c"
+  },
+  "target": {
+    "cell": "85e38883-641d-48ed-9701-15148be3cd7f",
+    "port": "e1ad288c-6567-413f-b2c3-132d43a566c5"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "ea73c7bb-645a-4198-a020-21b5df708e52",
+  "zIndex": 0,
+  "source": {
+    "cell": "ef3d1b04-c830-4146-89a4-23e330fce83d",
+    "port": "acd6bf40-8a98-481d-9280-a7df27da1743"
+  },
+  "target": {
+    "cell": "aef01570-a760-4b9b-ae64-fae758f3b1ca",
+    "port": "c493019f-b8a3-4ac2-b250-b92fcb5553ae"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "0e9ddb8a-8587-406c-b9c3-4876ea47ee36",
+  "zIndex": 0,
+  "source": {
+    "cell": "dba4e54b-96e7-4bb8-9d2f-d76d47ce662e",
+    "port": "037a3476-fa69-4253-87a5-a96834358056"
+  },
+  "target": {
+    "cell": "832fc8cc-140f-45c5-ada0-d58736d6e78c",
+    "port": "ec7d25b5-2c18-49ff-bfe7-37e77945b8b6"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "f3390158-6041-472e-b59e-c98b22a33926",
+  "zIndex": 0,
+  "source": {
+    "cell": "85e38883-641d-48ed-9701-15148be3cd7f",
+    "port": "037a3476-fa69-4253-87a5-a96834358056"
+  },
+  "target": {
+    "cell": "832fc8cc-140f-45c5-ada0-d58736d6e78c",
+    "port": "c6e8912a-e3a3-4765-9aad-0767b55eb976"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "7a6ecc86-505f-41c6-ad1a-3627ed46d930",
+  "zIndex": 0,
+  "source": {
+    "cell": "aef01570-a760-4b9b-ae64-fae758f3b1ca",
+    "port": "1532799f-dd72-441e-b753-c4356a9a6589"
+  },
+  "target": {
+    "cell": "832fc8cc-140f-45c5-ada0-d58736d6e78c",
+    "port": "f8b52aa8-fcf9-42c3-a573-badfec3097fb"
+  }
+}, {
+  "shape": "edge",
+  "attrs": {
+    "line": {
+      "stroke": "#000000",
+      "strokeWidth": 1,
+      "targetMarker": {
+        "name": "block",
+        "width": 12,
+        "height": 8
+      }
+    }
+  },
+  "id": "2106ab62-284c-4889-bffa-194d8eec02da",
+  "zIndex": 0,
+  "source": {
+    "cell": "832fc8cc-140f-45c5-ada0-d58736d6e78c",
+    "port": "95ae6a99-3024-4667-8c77-8b3e0404b07a"
+  },
+  "target": {
+    "cell": "66f14529-c53b-43be-be90-8408f6658b07",
+    "port": "748fb9f4-355c-4a6d-b8b2-f826c2dbbb42"
+  }
+}, {
+  "position": {
+    "x": 110,
+    "y": 150
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "寮�濮�"
+    },
+    "body": {
+      "rx": 20,
+      "ry": 26
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "dae0a153-31a7-4d9d-ae2b-7fce5b86eda3"
+    }, {
+      "group": "right",
+      "id": "18cb49ca-e40a-4cb5-8a05-18c5ed7644fe"
+    }, {
+      "group": "bottom",
+      "id": "f2667aa6-1f8b-485b-9de6-ed61b6abe815"
+    }, {
+      "group": "left",
+      "id": "748fb9f4-355c-4a6d-b8b2-f826c2dbbb42"
+    }]
+  },
+  "id": "a464f73a-c12d-4612-ae76-55ae754618e2",
+  "zIndex": 1
+}, {
+  "position": {
+    "x": 239,
+    "y": 150
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "杩囩▼"
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "ec7d25b5-2c18-49ff-bfe7-37e77945b8b6"
+    }, {
+      "group": "right",
+      "id": "95ae6a99-3024-4667-8c77-8b3e0404b07a"
+    }, {
+      "group": "bottom",
+      "id": "f8b52aa8-fcf9-42c3-a573-badfec3097fb"
+    }, {
+      "group": "left",
+      "id": "c6e8912a-e3a3-4765-9aad-0767b55eb976"
+    }]
+  },
+  "id": "310c8213-f07a-4d30-9d35-36f03a7ceb8e",
+  "zIndex": 2
+}, {
+  "position": {
+    "x": 470,
+    "y": 150
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "鍐崇瓥"
+    },
+    "body": {
+      "refPoints": "0,10 10,0 20,10 10,20"
+    }
+  },
+  "visible": true,
+  "shape": "mk-polygon",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "d4b5354c-82f3-4a4f-ae58-bf0085b514aa"
+    }, {
+      "group": "right",
+      "id": "037a3476-fa69-4253-87a5-a96834358056"
+    }, {
+      "group": "bottom",
+      "id": "3c1e94df-6424-4d63-b744-8f5f67c2e54a"
+    }, {
+      "group": "left",
+      "id": "e1ad288c-6567-413f-b2c3-132d43a566c5"
+    }]
+  },
+  "id": "85e38883-641d-48ed-9701-15148be3cd7f",
+  "zIndex": 3
+}, {
+  "position": {
+    "x": 470,
+    "y": 80
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "鍐崇瓥"
+    },
+    "body": {
+      "refPoints": "0,10 10,0 20,10 10,20"
+    }
+  },
+  "visible": true,
+  "shape": "mk-polygon",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "d4b5354c-82f3-4a4f-ae58-bf0085b514aa"
+    }, {
+      "group": "right",
+      "id": "037a3476-fa69-4253-87a5-a96834358056"
+    }, {
+      "group": "bottom",
+      "id": "3c1e94df-6424-4d63-b744-8f5f67c2e54a"
+    }, {
+      "group": "left",
+      "id": "e1ad288c-6567-413f-b2c3-132d43a566c5"
+    }]
+  },
+  "id": "dba4e54b-96e7-4bb8-9d2f-d76d47ce662e",
+  "zIndex": 4
+}, {
+  "position": {
+    "x": 470,
+    "y": 223
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "鍙�夎繃绋�"
+    },
+    "body": {
+      "rx": 6,
+      "ry": 6
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "9b1425a8-33db-4b10-a699-fb36fb452bb0"
+    }, {
+      "group": "right",
+      "id": "1532799f-dd72-441e-b753-c4356a9a6589"
+    }, {
+      "group": "bottom",
+      "id": "dfb1a762-247a-4056-8a8c-5f102eaebfac"
+    }, {
+      "group": "left",
+      "id": "c493019f-b8a3-4ac2-b250-b92fcb5553ae"
+    }]
+  },
+  "id": "aef01570-a760-4b9b-ae64-fae758f3b1ca",
+  "zIndex": 5
+}, {
+  "position": {
+    "x": 365,
+    "y": 150
+  },
+  "size": {
+    "width": 36,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "杩炴帴"
+    }
+  },
+  "visible": true,
+  "shape": "mk-circle",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "7024e8d6-df2f-4273-aadb-67ed01507bae"
+    }, {
+      "group": "right",
+      "id": "6a767960-f16e-4b71-93f8-82400370fe2c"
+    }, {
+      "group": "bottom",
+      "id": "acd6bf40-8a98-481d-9280-a7df27da1743"
+    }, {
+      "group": "left",
+      "id": "6c62d9ff-0d11-4d44-b234-76033f91b67d"
+    }]
+  },
+  "id": "ef3d1b04-c830-4146-89a4-23e330fce83d",
+  "zIndex": 6
+}, {
+  "position": {
+    "x": 590,
+    "y": 150
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "杩囩▼"
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "ec7d25b5-2c18-49ff-bfe7-37e77945b8b6"
+    }, {
+      "group": "right",
+      "id": "95ae6a99-3024-4667-8c77-8b3e0404b07a"
+    }, {
+      "group": "bottom",
+      "id": "f8b52aa8-fcf9-42c3-a573-badfec3097fb"
+    }, {
+      "group": "left",
+      "id": "c6e8912a-e3a3-4765-9aad-0767b55eb976"
+    }]
+  },
+  "id": "832fc8cc-140f-45c5-ada0-d58736d6e78c",
+  "zIndex": 7
+}, {
+  "position": {
+    "x": 729,
+    "y": 150
+  },
+  "size": {
+    "width": 66,
+    "height": 36
+  },
+  "attrs": {
+    "text": {
+      "text": "缁撴潫"
+    },
+    "body": {
+      "rx": 20,
+      "ry": 26
+    }
+  },
+  "visible": true,
+  "shape": "mk-rect",
+  "ports": {
+    "groups": {
+      "top": {
+        "position": "top",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "right": {
+        "position": "right",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "bottom": {
+        "position": "bottom",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      },
+      "left": {
+        "position": "left",
+        "attrs": {
+          "circle": {
+            "r": 4,
+            "magnet": true,
+            "stroke": "var(--mk-sys-color)",
+            "strokeWidth": 1,
+            "fill": "#fff",
+            "style": {
+              "visibility": "hidden"
+            }
+          }
+        }
+      }
+    },
+    "items": [{
+      "group": "top",
+      "id": "dae0a153-31a7-4d9d-ae2b-7fce5b86eda3"
+    }, {
+      "group": "right",
+      "id": "18cb49ca-e40a-4cb5-8a05-18c5ed7644fe"
+    }, {
+      "group": "bottom",
+      "id": "f2667aa6-1f8b-485b-9de6-ed61b6abe815"
+    }, {
+      "group": "left",
+      "id": "748fb9f4-355c-4a6d-b8b2-f826c2dbbb42"
+    }]
+  },
+  "id": "66f14529-c53b-43be-be90-8408f6658b07",
+  "zIndex": 8
+}]
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
index 2620f88..e5a0f18 100644
--- a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -90,6 +90,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      key: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initVal: card.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', text: '缁ф壙鑿滃崟'},
+        {value: 'false', text: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'select',
       key: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx
index 4000502..332e3ab 100644
--- a/src/menu/components/chart/antv-bar/index.jsx
+++ b/src/menu/components/chart/antv-bar/index.jsx
@@ -20,7 +20,6 @@
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 
 class antvBarLineChart extends Component {
@@ -84,27 +83,6 @@
         search: [],
         action: [],
         plot: _plot,
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.plot = config.plot
-        _card.plot.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.action = config.action.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
-        _card.search = config.search.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
       }
 
       this.updateComponent(_card, true)
@@ -1358,7 +1336,6 @@
             <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent}/>
           </div>
diff --git a/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
index f1d676e..1840ac9 100644
--- a/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
@@ -64,6 +64,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      key: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initVal: card.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', text: '缁ф壙鑿滃崟'},
+        {value: 'false', text: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'select',
       key: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/chart/antv-dashboard/index.jsx b/src/menu/components/chart/antv-dashboard/index.jsx
index f74d260..7ffc5c5 100644
--- a/src/menu/components/chart/antv-dashboard/index.jsx
+++ b/src/menu/components/chart/antv-dashboard/index.jsx
@@ -15,7 +15,6 @@
 const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 
 registerShape('point', 'pointer', {
@@ -127,19 +126,6 @@
         search: [],
         action: [],
         plot: _plot,
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.plot = config.plot
-        _card.plot.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
       }
 
       this.updateComponent(_card, true)
@@ -530,7 +516,6 @@
             <CopyComponent type="dashboard" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent}/>
           </div>
diff --git a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
index ce67f2a..f97f30f 100644
--- a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
@@ -122,6 +122,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      key: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initVal: card.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', text: '缁ф壙鑿滃崟'},
+        {value: 'false', text: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'select',
       key: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx
index 304484c..f5a70b1 100644
--- a/src/menu/components/chart/antv-pie/index.jsx
+++ b/src/menu/components/chart/antv-pie/index.jsx
@@ -17,7 +17,6 @@
 const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 
 class antvBarLineChart extends Component {
@@ -77,26 +76,6 @@
         search: [],
         action: [],
         plot: _plot,
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.plot = config.plot
-        _card.plot.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        if (appType !== 'mob') {
-          _card.search = config.search.map(col => {
-            col.uuid = Utils.getuuid()
-            return col
-          })
-        }
       }
 
       this.updateComponent(_card, true)
@@ -704,7 +683,6 @@
             <CopyComponent type="pie" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent}/>
           </div>
diff --git a/src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx
index 8b2f4f4..8957140 100644
--- a/src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx
@@ -64,6 +64,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      key: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initVal: card.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', text: '缁ф壙鑿滃崟'},
+        {value: 'false', text: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'select',
       key: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/chart/antv-scatter/index.jsx b/src/menu/components/chart/antv-scatter/index.jsx
index bf2a909..8c1a624 100644
--- a/src/menu/components/chart/antv-scatter/index.jsx
+++ b/src/menu/components/chart/antv-scatter/index.jsx
@@ -18,7 +18,6 @@
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 
 class antvScatterChart extends Component {
@@ -71,28 +70,6 @@
         search: [],
         action: [],
         plot: _plot,
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.plot = config.plot
-        _card.plot.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.action = config.action.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
-        _card.search = config.search.map(col => {
-          col.uuid = Utils.getuuid()
-          return col
-        })
       }
 
       this.updateComponent(_card, true)
@@ -377,7 +354,6 @@
             <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/>
             <SettingComponent config={card} updateConfig={this.updateComponent}/>
           </div>
diff --git a/src/menu/components/chart/chart-custom/chartcompile/formconfig.jsx b/src/menu/components/chart/chart-custom/chartcompile/formconfig.jsx
index 2434abd..9089580 100644
--- a/src/menu/components/chart/chart-custom/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/chart-custom/chartcompile/formconfig.jsx
@@ -75,6 +75,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      key: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initVal: card.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', text: '缁ф壙鑿滃崟'},
+        {value: 'false', text: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'select',
       key: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/code/sandbox/index.jsx b/src/menu/components/code/sandbox/index.jsx
index 1df42b8..62a1e35 100644
--- a/src/menu/components/code/sandbox/index.jsx
+++ b/src/menu/components/code/sandbox/index.jsx
@@ -15,7 +15,6 @@
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const EditorCode = asyncIconComponent(() => import('./editorcode'))
 const CodeContent = asyncComponent(() => import('./codecontent'))
 
@@ -52,21 +51,6 @@
         html: '',
         css: '',
         js: '',
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.html = config.html
-        _card.css = config.css
-        _card.js = config.js
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
       }
       
       this.updateComponent(_card)
@@ -162,7 +146,6 @@
             </NormalForm>
             <CopyComponent type="sandbox" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <EditorCode config={card} updateConfig={this.updateComponent}/>
             {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
diff --git a/src/menu/components/code/sandbox/options.jsx b/src/menu/components/code/sandbox/options.jsx
index f3a940b..db2f2ce 100644
--- a/src/menu/components/code/sandbox/options.jsx
+++ b/src/menu/components/code/sandbox/options.jsx
@@ -74,6 +74,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'multiselect',
       field: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/editor/braft-editor/index.jsx b/src/menu/components/editor/braft-editor/index.jsx
index 3dfb6b3..6557e9c 100644
--- a/src/menu/components/editor/braft-editor/index.jsx
+++ b/src/menu/components/editor/braft-editor/index.jsx
@@ -16,7 +16,6 @@
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const EditorContent = asyncIconComponent(() => import('./editorcontent'))
 const BraftContent = asyncComponent(() => import('@/tabviews/custom/components/share/braftContent'))
 
@@ -52,20 +51,6 @@
         columns: [],
         scripts: [],
         html: ''
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-        _card.html = config.html
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
       }
 
       this.updateComponent(_card)
@@ -197,7 +182,6 @@
             </NormalForm>
             <CopyComponent type="editor" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <EditorContent config={card} updateConfig={this.updateComponent}/>
             {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/>}
diff --git a/src/menu/components/form/formaction/actionform/index.jsx b/src/menu/components/form/formaction/actionform/index.jsx
index 266c700..b21638c 100644
--- a/src/menu/components/form/formaction/actionform/index.jsx
+++ b/src/menu/components/form/formaction/actionform/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-// import { fromJS } from 'immutable'
 import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import { formRule } from '@/utils/option.js'
@@ -17,89 +16,102 @@
   }
 
   state = {
-    formlist: null,  // 琛ㄥ崟淇℃伅
-    interType: null, // 鎺ュ彛绫诲瀷锛氬唴閮ㄣ�佸閮�
-    procMode: null,  // 鍙傛暟鏂瑰紡
-    linkmenu: null,
-    callbackType: null
+    formlist: null
   }
 
+  record = {}
   
   UNSAFE_componentWillMount () {
-    const { card } = this.props
+    this.props.formlist.forEach(item => {
+      this.record[item.key] = item.initVal
+    })
 
-    let _intertype = card.intertype || 'system'  // 鎺ュ彛绫诲瀷
-    let _procMode = card.procMode || 'system'    // 鍙傛暟璇锋眰鏂瑰紡
-    let _callbackType = card.callbackType || 'script'
-
-    let _options = this.getOptions(_intertype, _procMode, card.linkmenu, _callbackType)
+    let { shows, reRequired, reReadonly } = this.getMutilOptions()
 
     this.setState({
-      interType: _intertype,
-      procMode: _procMode,
-      callbackType: _callbackType,
-      linkmenu: card.linkmenu,
       formlist: this.props.formlist.map(item => {
-        if (item.key === 'innerFunc' && _procMode === 'inner') {
-          item.required = true
+        item.hidden = !shows.includes(item.key)
+        item.initVal = this.record[item.key]
+
+        if (reRequired[item.key] !== undefined) {
+          item.required = reRequired[item.key]
+        }
+        if (reReadonly[item.key] !== undefined) {
+          item.readonly = reReadonly[item.key]
         }
 
-        item.hidden = !_options.includes(item.key)
         return item
       })
     })
   }
 
-  getOptions = (_intertype, _procMode, linkmenu, _callbackType) => {
-    const { card } = this.props
+  getMutilOptions = () => {
+    let shows = []
+    let reRequired = {}
+    let reReadonly = {}
 
-    if (card.type === 'prev') {
-      return ['type', 'label', 'enable', 'actionType']
-    } else if (card.type === 'next') {
-      return ['type', 'label', 'enable', 'actionType']
-    } else if (card.type === 'close') {
-      return ['type', 'label', 'enable']
-    }
-    
-    let _options = ['type', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'enable', 'output', 'reload'] // 閫夐」鍒楄〃
-    
-    if (_intertype === 'custom') {
-      _options.pop()
-      _options.push('procMode', 'interface', 'callbackType', 'proInterface', 'method', 'cross', 'stringify')
-      if (_procMode === 'system') {
-        _options.push('sql', 'sqlType')
-      } else {
-        _options.push('innerFunc')
-      }
-      if (_callbackType === 'func') {
-        _options.push('callbackFunc')
-      } else if (_callbackType !== 'none') {
-        _options.push('cbTable')
-      }
-    } else if (_intertype === 'outer') {
-      _options.push('procMode', 'sysInterface', 'interface', 'proInterface', 'outerFunc', 'callbackType')
-      if (_procMode === 'system') {
-        _options.push('sql', 'sqlType')
-      } else if (_procMode === 'inner') {
-        _options.push('innerFunc')
-      }
-      if (_callbackType === 'func') {
-        _options.push('callbackFunc')
-      } else if (_callbackType !== 'none') {
-        _options.push('cbTable')
-      }
-
-    } else if (_intertype === 'inner') {
-      _options.push('innerFunc')
+    if (this.record.type === 'prev') {
+      shows = ['typeName', 'label', 'actionType']
+    } else if (this.record.type === 'next') {
+      shows = ['typeName', 'label', 'actionType']
+    } else if (this.record.type === 'close') {
+      shows = ['typeName', 'label']
     } else {
-      _options.push('sql', 'sqlType')
-    }
-    
-    if (linkmenu && linkmenu !== 'goback') {
-      _options.push('open')
+      shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload'] // 閫夐」鍒楄〃
+      
+      if (this.record.intertype === 'custom') {
+        shows.pop()
+        shows.push('procMode', 'interface', 'callbackType', 'proInterface', 'method', 'cross', 'stringify', 'ContentType', 'outerBlacklist')
+        if (this.record.procMode === 'system') {
+          shows.push('sql', 'sqlType')
+        } else if (this.record.procMode === 'inner') {
+          shows.push('innerFunc')
+        }
+        if (this.record.callbackType === 'func') {
+          shows.push('callbackFunc')
+        } else if (this.record.callbackType !== 'none') {
+          shows.push('cbTable')
+        }
+      } else if (this.record.intertype === 'outer') {
+        shows.push('procMode', 'sysInterface', 'interface', 'outerFunc', 'callbackType')
+        if (this.record.procMode === 'system') {
+          shows.push('sql', 'sqlType')
+        } else if (this.record.procMode === 'inner') {
+          shows.push('innerFunc')
+        }
+        if (this.record.callbackType === 'func') {
+          shows.push('callbackFunc')
+        } else if (this.record.callbackType !== 'none') {
+          shows.push('cbTable')
+        }
+
+        reRequired.outerFunc = false
+        if (this.record.sysInterface === 'false') {
+          reReadonly.interface = false
+          reRequired.interface = true
+
+          shows.push('proInterface')
+        } else if (this.record.sysInterface === 'true') {
+          reReadonly.interface = true
+          reRequired.interface = false
+          reRequired.outerFunc = true
+        }
+      } else if (this.record.intertype === 'inner') {
+        shows.push('innerFunc')
+      } else {
+        shows.push('sql', 'sqlType')
+      }
+      
+      if (this.record.linkmenu && this.record.linkmenu !== 'goback') {
+        shows.push('open')
+      }
     }
 
-    return _options
+    return {
+      shows,
+      reRequired,
+      reReadonly
+    }
   }
 
   /**
@@ -109,79 +121,35 @@
    * 3銆佸垏鎹㈡爣绛剧被鍨嬶紝閲嶇疆鍙�夋爣绛�
    */
   optionChange = (key, value) => {
-    const { procMode, linkmenu, callbackType } = this.state
+    this.record[key] = value
+    let _fieldval = {}
 
-    if (key === 'intertype') {
-      let _options = this.getOptions(value, procMode, linkmenu, callbackType)
-
-      this.setState({
-        interType: value,
-        formlist: this.state.formlist.map(item => {
-          item.hidden = !_options.includes(item.key)
-
-          if (item.key === 'interface') {
-            item.readonly = false
-          } else if (item.key === 'sysInterface') {
-            item.initVal = 'false'
-          }
-          return item
-        })
-      })
-    } else if (key === 'procMode') {
-      let _options = this.getOptions(this.state.interType, value, linkmenu, callbackType)
-
-      this.setState({
-        procMode: value,
-        formlist: this.state.formlist.map(item => {
-          item.hidden = !_options.includes(item.key)
-
-          if (item.key === 'procMode') {
-            item.initVal = value
-          }
-          return item
-        })
-      })
-    } else if (key === 'linkmenu') {
-      let _options = this.getOptions(this.state.interType, procMode, value, callbackType)
-
-      this.setState({
-        linkmenu: value,
-        formlist: this.state.formlist.map(item => {
-          item.hidden = !_options.includes(item.key)
-          return item
-        })
-      })
-    } else if (key === 'callbackType') {
-      let _options = this.getOptions(this.state.interType, procMode, linkmenu, value)
-
-      this.setState({
-        callbackType: value,
-        formlist: this.state.formlist.map(item => {
-          if (item.key === 'callbackType') {
-            item.initVal = value
-          }
-          item.hidden = !_options.includes(item.key)
-          return item
-        })
-      })
-    } else if (key === 'sysInterface') {
+    if (key === 'sysInterface') {
       if (value === 'true') {
-        this.props.form.setFieldsValue({
-          interface: window.GLOB.mainSystemApi || ''
-        })
+        _fieldval.interface = window.GLOB.mainSystemApi || ''
+        this.record.interface = window.GLOB.mainSystemApi || ''
       }
-      this.setState({
-        formlist: this.state.formlist.map(item => {
-          if (item.key === 'interface' && value === 'true') {
-            item.readonly = true
-          } else if (item.key === 'interface') {
-            item.readonly = false
-          }
-
-          return item
-        })
-      })
     }
+
+    let { shows, reRequired, reReadonly } = this.getMutilOptions()
+
+    this.setState({
+      formlist: this.state.formlist.map(item => {
+        item.hidden = !shows.includes(item.key)
+        item.initVal = this.record[item.key]
+
+        if (reRequired[item.key] !== undefined) {
+          item.required = reRequired[item.key]
+        }
+        if (reReadonly[item.key] !== undefined) {
+          item.readonly = reReadonly[item.key]
+        }
+
+        return item
+      })
+    }, () => {
+      this.props.form.setFieldsValue(_fieldval)
+    })
   }
 
   handleSubmit = (e) => {
@@ -394,7 +362,7 @@
                   }
                 ]
               })(
-                <Cascader options={item.options || []} expandTrigger="hover" placeholder=""/>
+                <Cascader onChange={(value) => {this.optionChange(item.key, value)}} options={item.options || []} expandTrigger="hover" placeholder=""/>
               )}
             </Form.Item>
           </Col>
@@ -409,6 +377,9 @@
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
+          if (values.outerBlacklist) {
+            values.outerBlacklist = values.outerBlacklist.replace(/\s/ig, '')
+          }
           resolve(values)
         } else {
           reject(err)
diff --git a/src/menu/components/form/formaction/formconfig.jsx b/src/menu/components/form/formaction/formconfig.jsx
index 823ad5f..2e98dbc 100644
--- a/src/menu/components/form/formaction/formconfig.jsx
+++ b/src/menu/components/form/formaction/formconfig.jsx
@@ -6,6 +6,7 @@
 
 export function getActionForm (card, functip, tableName, usefulFields, modules, anchors) {
   const appType = sessionStorage.getItem('appType')
+  let viewType = sessionStorage.getItem('editMenuType') // 寮圭獥 popview
   let _type = '鎻愪氦'
   if (card.type === 'prev') {
     _type = '涓婁竴姝�'
@@ -42,10 +43,29 @@
     }
   }
 
+  let refresh = []
+  if (viewType === 'popview') { // 寮圭獥鏍囩
+    refresh.push({
+      value: 'closepoptab', // 鍏抽棴寮圭獥鏍囩
+      text: '鍏抽棴寮圭獥'
+    })
+    refresh.push({
+      value: 'popclose',  // 鎵ц寮圭獥鍏抽棴鏃剁殑鍒锋柊
+      text: '鍒锋柊婧愮粍浠�'
+    })
+  }
+
   return [
     {
       type: 'tip',
       key: 'type',
+      label: '鎸夐挳绫诲瀷',
+      initVal: card.type,
+      forbid: true
+    },
+    {
+      type: 'tip',
+      key: 'typeName',
       label: '鎸夐挳绫诲瀷',
       initVal: _type
     },
@@ -97,7 +117,7 @@
       key: 'procMode',
       label: '鍙傛暟澶勭悊',
       initVal: card.procMode || 'system',
-      tooltip: '褰撹繑鍥炲�煎瓨鍦� mk_ex_invoke 涓斿�间负 false 鏃讹紝涓嶄細璋冪敤澶栭儴鎺ュ彛銆�',
+      tooltip: '褰撹繑鍥炲�煎瓨鍦� mk_ex_invoke 涓斿�间负 false 鏃讹紝涓嶄細璋冪敤澶栭儴鎺ュ彛锛涘綋杩斿洖鍊煎瓨鍦� mk_ex_data 鏃讹紝灏嗕互姝や负鍙傛暟鍒嗘壒璇锋眰鑷畾涔夋帴鍙c�傛敞锛氬綋閫夆�滄棤鈥濇椂锛屾寜閽�夎鏃朵細浼犻�掍富閿紝瀛樺湪琛ㄥ崟鏃朵細浼犻�掕〃鍗曞瓧娈碉紝瀛樺湪BID鏃朵細浼燘ID瀛楁銆�',
       required: true,
       options: [{
         value: 'system',
@@ -163,16 +183,16 @@
     {
       type: 'radio',
       key: 'sysInterface',
-      label: '绯荤粺鎺ュ彛',
+      label: '绯荤粺绫诲瀷',
       initVal: card.sysInterface || 'false',
-      tooltip: '鍗曠偣鐧诲綍绯荤粺',
+      tooltip: '涓氬姟绯荤粺鎸囧悓涓�sso涓嬬殑鍏朵粬涓氬姟绯荤粺',
       required: true,
       options: [{
         value: 'true',
-        text: '鏄�'
+        text: '鍗曠偣'
       }, {
         value: 'false',
-        text: '鍚�'
+        text: '涓氬姟'
       }]
     },
     {
@@ -282,6 +302,22 @@
       }]
     },
     {
+      type: 'text',
+      key: 'ContentType',
+      label: 'Content-Type',
+      initVal: card.ContentType || '',
+      tooltip: '榛樿鍊硷細application/x-www-form-urlencoded;charset=UTF-8',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'outerBlacklist',
+      label: '瀛楁榛戝悕鍗�',
+      initVal: card.outerBlacklist || '',
+      tooltip: '涓嶉渶瑕佸洖浼犵殑瀛楁鍙缃瓧娈甸粦鍚嶅崟锛屽涓�艰鐢ㄩ�楀彿鍒嗛殧銆�',
+      required: false
+    },
+    {
       type: 'radio',
       key: 'Ot',
       label: '琛岃缃�',
@@ -310,7 +346,7 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
-      }]
+      }, ...refresh]
     },
     {
       type: (appType === 'pc' || appType === 'mob') ? 'select' : 'cascader',
diff --git a/src/menu/components/form/formaction/index.scss b/src/menu/components/form/formaction/index.scss
index 79055ca..b980900 100644
--- a/src/menu/components/form/formaction/index.scss
+++ b/src/menu/components/form/formaction/index.scss
@@ -10,6 +10,7 @@
   .submit {
     border: none;
     height: auto;
+    border-style: solid;
   }
   .skip {
     color: rgba(0, 0, 0, 0.85);
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index 3f75c5d..bc66a55 100644
--- a/src/menu/components/form/simple-form/index.jsx
+++ b/src/menu/components/form/simple-form/index.jsx
@@ -24,7 +24,6 @@
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteForms = asyncIconComponent(() => import('@/menu/components/share/pasteforms'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 
 const { confirm } = Modal
@@ -69,33 +68,13 @@
         scripts: [],
         subcards: [{
           uuid: Utils.getuuid(),
-          setting: {title: '绌�', align: 'left_right', enable: 'true'},
+          setting: {title: '', align: 'left_right', enable: 'true'},
           style: {},
           fields: [],
           subButton: {label: '鎻愪氦', type: 'submit', intertype: 'system', reload: 'false', sqlType: 'update', sql: '', Ot: 'notRequired', execSuccess: 'never', enable: 'true', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px', paddingTop: '5px', paddingBottom: '5px'}},
         }]
       }
 
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.fields = scard.fields.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
-      }
       this.updateComponent(_card)
     } else {
       let _card = fromJS(card).toJS()
@@ -334,23 +313,22 @@
     let _linkableFields = []
     let _linksupFields = []
     let standardform = null
-
-    let uniq = new Map()
     let index = null
-    uniq.set(_form.field, true)
 
     card.subcards[0].fields.forEach((item, i) => {
       if (_form.uuid === item.uuid) {
         index = i
       }
 
-      if (['text', 'number', 'textarea', 'color'].includes(item.type) && _item.field !== item.field) {
+      if (!item.field || _form.field === item.field) return
+
+      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
         _inputfields.push({
           field: item.field,
           label: item.label
         })
       }
-      if (_form.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
+      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
         _tabfields.push({
           field: item.field,
           label: item.label
@@ -364,20 +342,19 @@
         })
       }
       
-      if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return
-      if (item.type === 'checkcard' && item.multiple === 'true') return // 閫夐」鍗″閫�
-      if (item.field && !uniq.has(item.field)) {
-        uniq.set(item.field, true)
+      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
 
-        _linkableFields.push({
-          field: item.field,
-          label: item.label + '-琛ㄥ崟'
-        })
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
+      _linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+
+      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
+
+      _linkableFields.push({
+        field: item.field,
+        label: item.label + '-琛ㄥ崟'
+      })
     })
 
     if (index !== null) {
@@ -388,10 +365,9 @@
       }
     }
 
+    let _fields = _linkableFields.map(cell => cell.field)
     card.columns.forEach(col => {
-      if (col.field && !uniq.has(col.field)) {
-        uniq.set(col.field, true)
-
+      if (col.field && !_fields.includes(col.field)) {
         _linkableFields.push({
           field: col.field,
           label: col.label + '-鏄剧ず鍒�'
@@ -624,7 +600,6 @@
             <CopyComponent type="simpleform" card={card}/>
             <PasteForms config={card.subcards[0]} update={this.pasteForm} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
             {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
@@ -683,6 +658,7 @@
         </div>
         <Modal
           title="缂栬緫"
+          wrapClassName="mk-scroll-modal"
           visible={this.state.visible}
           width={950}
           maskClosable={false}
diff --git a/src/menu/components/form/step-form/index.jsx b/src/menu/components/form/step-form/index.jsx
index c5624f9..1d81503 100644
--- a/src/menu/components/form/step-form/index.jsx
+++ b/src/menu/components/form/step-form/index.jsx
@@ -24,7 +24,6 @@
 const FormAction = asyncComponent(() => import('../formaction'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 
 const { confirm } = Modal
@@ -79,26 +78,6 @@
         }]
       }
 
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.fields = scard.fields.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
-      }
       this.setState({
         group: _card.subcards[0] || null
       })
@@ -435,24 +414,23 @@
     let _linkableFields = []
     let _linksupFields = []
     let standardform = null
-
-    let uniq = new Map()
     let index = null
-    uniq.set(_form.field, true)
 
     group.fields.forEach((item, i) => {
       if (_form.uuid === item.uuid) {
         index = i
       }
 
-      if (['text', 'number', 'textarea', 'color'].includes(item.type) && _item.field !== item.field) {
+      if (!item.field || _form.field === item.field) return
+
+      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
         _inputfields.push({
           field: item.field,
           label: item.label
         })
       }
 
-      if (_item.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
+      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
         _tabfields.push({
           field: item.field,
           label: item.label
@@ -466,20 +444,19 @@
         })
       }
       
-      if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return
-      if (item.type === 'checkcard' && item.multiple === 'true') return // 閫夐」鍗″閫�
-      if (item.field && !uniq.has(item.field)) {
-        uniq.set(item.field, true)
+      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
 
-        _linkableFields.push({
-          field: item.field,
-          label: item.label + '-琛ㄥ崟'
-        })
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
+      _linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+
+      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
+
+      _linkableFields.push({
+        field: item.field,
+        label: item.label + '-琛ㄥ崟'
+      })
     })
 
     if (index !== null) {
@@ -490,10 +467,9 @@
       }
     }
 
+    let _fields = _linkableFields.map(cell => cell.field)
     card.columns.forEach(col => {
-      if (col.field && !uniq.has(col.field)) {
-        uniq.set(col.field, true)
-
+      if (col.field && !_fields.includes(col.field)) {
         _linkableFields.push({
           field: col.field,
           label: col.label + '-鏄剧ず鍒�'
@@ -738,7 +714,6 @@
             <CopyComponent type="stepform" card={card}/>
             <PasteComponent config={card} options={['formgroup', 'simpleform']} updateConfig={this.pasteForm} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
             {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
@@ -807,6 +782,7 @@
         </div>
         <Modal
           title="缂栬緫"
+          wrapClassName="mk-scroll-modal"
           visible={this.state.visible}
           width={950}
           maskClosable={false}
diff --git a/src/menu/components/form/tab-form/index.jsx b/src/menu/components/form/tab-form/index.jsx
index ae873e0..18b4656 100644
--- a/src/menu/components/form/tab-form/index.jsx
+++ b/src/menu/components/form/tab-form/index.jsx
@@ -24,7 +24,6 @@
 const FormAction = asyncComponent(() => import('../formaction'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 
 const { confirm } = Modal
@@ -91,26 +90,6 @@
         }]
       }
 
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.fields = scard.fields.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
-      }
       this.setState({
         group: _card.subcards[0] || null
       })
@@ -441,23 +420,22 @@
     let _linkableFields = []
     let _linksupFields = []
     let standardform = null
-
-    let uniq = new Map()
     let index = null
-    uniq.set(_form.field, true)
 
     group.fields.forEach((item, i) => {
       if (_form.uuid === item.uuid) {
         index = i
       }
 
-      if (['text', 'number', 'textarea', 'color'].includes(item.type) && _item.field !== item.field) {
+      if (!item.field || _form.field === item.field) return
+
+      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
         _inputfields.push({
           field: item.field,
           label: item.label
         })
       }
-      if (_form.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
+      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
         _tabfields.push({
           field: item.field,
           label: item.label
@@ -471,20 +449,19 @@
         })
       }
       
-      if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return
-      if (item.type === 'checkcard' && item.multiple === 'true') return // 閫夐」鍗″閫�
-      if (item.field && !uniq.has(item.field)) {
-        uniq.set(item.field, true)
+      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
 
-        _linkableFields.push({
-          field: item.field,
-          label: item.label + '-琛ㄥ崟'
-        })
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
+      _linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+
+      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
+
+      _linkableFields.push({
+        field: item.field,
+        label: item.label + '-琛ㄥ崟'
+      })
     })
 
     if (index !== null) {
@@ -495,10 +472,9 @@
       }
     }
 
+    let _fields = _linkableFields.map(cell => cell.field)
     card.columns.forEach(col => {
-      if (col.field && !uniq.has(col.field)) {
-        uniq.set(col.field, true)
-
+      if (col.field && !_fields.includes(col.field)) {
         _linkableFields.push({
           field: col.field,
           label: col.label + '-鏄剧ず鍒�'
@@ -739,7 +715,6 @@
             <CopyComponent type="tabform" card={card}/>
             <PasteComponent config={card} options={['formgroup', 'simpleform']} updateConfig={this.pasteForm} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
             {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
@@ -809,6 +784,7 @@
         </div>
         <Modal
           title="缂栬緫"
+          wrapClassName="mk-scroll-modal"
           visible={this.state.visible}
           width={950}
           maskClosable={false}
diff --git a/src/menu/components/group/groupcomponents/card.jsx b/src/menu/components/group/groupcomponents/card.jsx
index 7dbdbb0..dd706fd 100644
--- a/src/menu/components/group/groupcomponents/card.jsx
+++ b/src/menu/components/group/groupcomponents/card.jsx
@@ -25,7 +25,9 @@
 const CustomChart = asyncComponent(() => import('@/menu/components/chart/chart-custom'))
 const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline'))
 const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
+const AntvX6 = asyncComponent(() => import('@/menu/components/chart/antv-X6'))
 const DoubleDataCard = asyncComponent(() => import('@/menu/components/card/double-data-card'))
+const Calendar = asyncComponent(() => import('@/menu/components/calendar'))
 
 const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
   const originalIndex = findCard(id).index
@@ -62,6 +64,8 @@
 
   if (card.style && card.style.clear === 'left') {
     style.clear = 'left'
+  } else if (card.style && card.style.clear === 'right') {
+    style.float = 'right'
   }
 
   const getCardComponent = () => {
@@ -109,6 +113,10 @@
       return (<CustomChart card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'antvG6') {
       return (<AntvG6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'antvX6') {
+      return (<AntvX6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'calendar') {
+      return (<Calendar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
 
diff --git a/src/menu/components/group/groupcomponents/index.jsx b/src/menu/components/group/groupcomponents/index.jsx
index 3d18434..5754e85 100644
--- a/src/menu/components/group/groupcomponents/index.jsx
+++ b/src/menu/components/group/groupcomponents/index.jsx
@@ -77,6 +77,7 @@
         balcony: '娴姩鍗�',
         timeline: '鏃堕棿杞�',
         antvG6: '鏍戝浘',
+        antvX6: '娴佺▼鍥�',
         card: '鍗$墖'
       }
       let i = 1
diff --git a/src/menu/components/group/paste/index.jsx b/src/menu/components/group/paste/index.jsx
index 8db0190..fb491f3 100644
--- a/src/menu/components/group/paste/index.jsx
+++ b/src/menu/components/group/paste/index.jsx
@@ -33,7 +33,7 @@
     }
 
     if (appType !== 'mob') {
-      options.push('editable', 'antvG6', 'tree', 'dashboard', 'chart')
+      options.push('editable', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
     }
 
     this.pasteFormRef.handleConfirm().then(res => {
diff --git a/src/menu/components/iframe/options.jsx b/src/menu/components/iframe/options.jsx
index b6e8ca6..2e74b01 100644
--- a/src/menu/components/iframe/options.jsx
+++ b/src/menu/components/iframe/options.jsx
@@ -63,7 +63,7 @@
       field: 'height',
       label: '楂樺害',
       initval: wrap.height || '',
-      tooltip: 'ifram楂樺害銆�',
+      tooltip: 'ifram楂樺害銆傛敞锛氶珮搴�100vh鏃朵細鏍规嵁鏍囩椤电獥鍙h繘琛岃皟鏁�',
       required: true,
       options: ['px', 'vh', 'vw']
     },
@@ -99,6 +99,7 @@
       field: 'linkUrl',
       label: '鍦板潃閾炬帴',
       initval: wrap.linkUrl || '',
+      tooltip: '鍦板潃涓殑@loginuid@浼氳嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨勭櫥褰曚俊鎭��',
       required: true,
       span: 24
     },
diff --git a/src/menu/components/module/voucher/options.jsx b/src/menu/components/module/voucher/options.jsx
index 2d78725..bdc8eb0 100644
--- a/src/menu/components/module/voucher/options.jsx
+++ b/src/menu/components/module/voucher/options.jsx
@@ -150,7 +150,7 @@
       field: 'linkmenu',
       label: '鍒锋柊鑿滃崟',
       initval: wrap.linkmenu || [],
-      tooltip: '鐐瑰嚮鍏抽棴鏃堕渶瑕佸埛鏂扮殑鑿滃崟銆�',
+      tooltip: '鐐瑰嚮淇濆瓨鏃堕渶瑕佸埛鏂扮殑鑿滃崟銆�',
       required: false,
       allowClear: true,
       options: menulist
diff --git a/src/menu/components/search/main-search/dragsearch/card.jsx b/src/menu/components/search/main-search/dragsearch/card.jsx
index 666ac3f..f439493 100644
--- a/src/menu/components/search/main-search/dragsearch/card.jsx
+++ b/src/menu/components/search/main-search/dragsearch/card.jsx
@@ -1,6 +1,6 @@
 import React from 'react'
 import { useDrag, useDrop } from 'react-dnd'
-import { Select, DatePicker, Input, Popover, Form, Switch, Checkbox } from 'antd'
+import { Select, Radio, DatePicker, Input, Popover, Form, Switch, Checkbox } from 'antd'
 import { CopyOutlined, EditOutlined, CloseOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -55,6 +55,8 @@
       _defaultValue = [moment().startOf('week'), moment().endOf('week')]
     } else if (card.initval === 'month') {
       _defaultValue = [moment().startOf('month'), moment().endOf('month')]
+    } else if (card.initval === 'lastMonth') {
+      _defaultValue = [moment().subtract(1, 'months').startOf('month'), moment().subtract(1, 'months').endOf('month')]
     } else if (card.initval) {
       try {
         let _initval = JSON.parse(card.initval)
@@ -111,6 +113,14 @@
     formItem = <CheckCard config={card} />
   } else if (card.type === 'switch') {
     formItem = (<Switch checkedChildren={card.openText || ''} unCheckedChildren={card.closeText || ''} style={{marginTop: '8px'}} checked={card.initval === card.openVal}/>)
+  } else if (card.type === 'radio') {
+    let options = card.options
+    if (options.length === 0) {
+      options = [{Value: '1', Text: '閫夐」1'}, {Value: '2', Text: '閫夐」2'}]
+    }
+    formItem = (<Radio.Group value={card.initval} style={{lineHeight: '36px'}}>
+      {options.map((item, i) => (<Radio key={i} value={item.Value}> {item.Text} </Radio>))}
+    </Radio.Group>)
   } else if (card.type === 'check') {
     formItem = <Checkbox style={{lineHeight: '36px'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
   }
diff --git a/src/menu/components/search/main-search/index.jsx b/src/menu/components/search/main-search/index.jsx
index 2708d3d..f526199 100644
--- a/src/menu/components/search/main-search/index.jsx
+++ b/src/menu/components/search/main-search/index.jsx
@@ -427,6 +427,7 @@
         {/* 缂栬緫鎼滅储鏉′欢 */}
         <Modal
           title="鎼滅储鏉′欢-缂栬緫"
+          wrapClassName="mk-scroll-modal"
           visible={visible}
           width={850}
           maskClosable={false}
diff --git a/src/menu/components/search/main-search/options.jsx b/src/menu/components/search/main-search/options.jsx
index f9324cf..c1cd29d 100644
--- a/src/menu/components/search/main-search/options.jsx
+++ b/src/menu/components/search/main-search/options.jsx
@@ -119,7 +119,8 @@
         {value: 'false', label: '闅愯棌'},
       ],
       controlFields: [
-        {field: 'borderRadius', values: ['true']}
+        {field: 'borderRadius', values: ['true']},
+        {field: 'resetContrl', values: ['true']}
       ]
     },
     {
@@ -132,6 +133,17 @@
     },
     {
       type: 'radio',
+      field: 'resetContrl',
+      label: '閲嶇疆鏃�',
+      initval: wrap.resetContrl || 'init',
+      required: false,
+      options: [
+        {value: 'init', label: '鎭㈠鍒濆鍊�'},
+        {value: 'clear', label: '娓呯┖'},
+      ],
+    },
+    {
+      type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
       initval: wrap.permission || 'false',
diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx
index ddeb8b0..c02a963 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -1,16 +1,16 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Checkbox, Typography } from 'antd'
+import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Checkbox } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import { formRule } from '@/utils/option.js'
 
 import asyncComponent from '@/utils/asyncComponent'
 import KeyInterface from '@/components/keyInterface'
+import MkPrintTemps from './mkPrintTemps'
 import './index.scss'
 
 const { TextArea } = Input
-const { Paragraph } = Typography
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
 const MKTable = asyncComponent(() => import('@/components/normalform/modalform/mkTable'))
 const acTyOptions = {
@@ -20,7 +20,7 @@
   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'],
-  tab: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'color', 'linkmenu', 'width', 'hidden'],
+  tab: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'color', 'linkmenu', 'width', 'hidden', 'openTab'],
   innerpage: ['label', 'Ot', 'OpenType', 'pageTemplate', 'show', 'swipe', 'icon', 'class', 'color', 'width', 'hidden'],
   funcbutton: ['label', 'OpenType', 'funcType', 'show', 'swipe', 'icon', 'class', 'color', 'width', 'hidden'],
   form: ['label', 'OpenType', 'formType', 'intertype', 'Ot', 'execSuccess', 'execError', 'syncComponent', 'width', 'refreshTab', 'title', 'hidden']
@@ -166,7 +166,7 @@
       reOptions.intertype = this.state.interTypeOptions
 
       if (intertype === 'custom') {
-        shows.push('procMode', 'interface', 'callbackType', 'proInterface', 'method', 'cross', 'stringify')
+        shows.push('procMode', 'interface', 'callbackType', 'proInterface', 'method', 'cross', 'stringify', 'ContentType', 'outerBlacklist')
         if (this.record.procMode === 'system') {
           shows.push('sql', 'sqlType')
         } else if (this.record.procMode === 'inner') {
@@ -174,14 +174,16 @@
           shows.push('innerFunc')
         }
         if (this.record.callbackType === 'func') {
-          shows.push('callbackFunc')
+          shows.push('callbackFunc', 'output')
+        } else if (this.record.callbackType === 'script') {
+          shows.push('cbTable', 'output')
         } else if (this.record.callbackType !== 'none') {
           shows.push('cbTable')
         }
         reReadonly.interface = false
         reRequired.interface = true
       } else if (intertype === 'outer') {
-        shows.push('procMode', 'sysInterface', 'outerFunc', 'callbackType', 'output')
+        shows.push('procMode', 'sysInterface', 'outerFunc', 'callbackType')
         if (this.record.procMode === 'system') {
           shows.push('sql', 'sqlType')
         } else if (this.record.procMode === 'inner') {
@@ -189,11 +191,14 @@
           shows.push('innerFunc')
         }
         if (this.record.callbackType === 'func') {
-          shows.push('callbackFunc')
+          shows.push('callbackFunc', 'output')
+        } else if (this.record.callbackType === 'script') {
+          shows.push('cbTable', 'output')
         } else if (this.record.callbackType !== 'none') {
           shows.push('cbTable')
         }
 
+        reRequired.outerFunc = false
         if (this.record.sysInterface === 'false') {
           reReadonly.interface = false
           reRequired.interface = true
@@ -202,13 +207,14 @@
         } else if (this.record.sysInterface === 'true') {
           reReadonly.interface = true
           reRequired.interface = false
+          reRequired.outerFunc = true
 
           shows.push('interface')
         } else if (this.record.sysInterface === 'external') {
           shows.push('exInterface', 'exProInterface')
         }
       } else if (intertype === 'inner') {
-        shows.push('innerFunc', 'output')
+        shows.push('innerFunc', 'output', 'recordUser')
         if (Ot === 'requiredOnce') { // 鍓嶇疆鍑芥暟
           shows.push('preFunc')
         }
@@ -249,7 +255,7 @@
 
       if (this.record.formType === 'switch') {
         shows.push('field', 'size', 'openVal', 'closeVal', 'openText', 'closeText')
-      } else if (this.record.formType === 'counter') {
+      } else if (this.record.formType === 'counter' || this.record.formType === 'count_line') {
         shows.push('field', 'size', 'min', 'max', 'decimal')
       } else if (this.record.formType === 'radio') {
         shows.push('field', 'checkType', 'openVal', 'closeVal')
@@ -273,6 +279,7 @@
           shows.push('cbTable')
         }
 
+        reRequired.outerFunc = false
         if (this.record.sysInterface === 'false') {
           reReadonly.interface = false
           reRequired.interface = true
@@ -281,13 +288,14 @@
         } else if (this.record.sysInterface === 'true') {
           reReadonly.interface = true
           reRequired.interface = false
+          reRequired.outerFunc = true
 
           shows.push('interface')
         } else if (this.record.sysInterface === 'external') {
           shows.push('exInterface', 'exProInterface')
         }
       } else if (intertype === 'inner') {
-        shows.push('innerFunc')
+        shows.push('innerFunc', 'recordUser')
         reRequired.innerFunc = true
       } else {
         shows.push('sql', 'sqlType')
@@ -308,6 +316,11 @@
         value: 'custom',
         text: '鑷畾涔�'
       }]
+
+      if (this.record.formType === 'count_line') {
+        reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
+        shows = shows.filter(op => ['label', 'OpenType', 'formType', 'Ot', 'width', 'title', 'hidden', 'field', 'size', 'min', 'max', 'decimal'].includes(op))
+      }
     } else if (openType === 'excelIn') {
       reOptions.intertype = this.state.interTypeOptions.filter(op => op.value !== 'custom')
       reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
@@ -316,6 +329,7 @@
         shows.push('innerFunc', 'sysInterface', 'outerFunc', 'callbackFunc')
         reRequired.innerFunc = false
         reRequired.callbackFunc = false
+        reRequired.outerFunc = false
 
         if (this.record.sysInterface === 'false') {
           reReadonly.interface = false
@@ -325,13 +339,14 @@
         } else if (this.record.sysInterface === 'true') {
           reReadonly.interface = true
           reRequired.interface = false
+          reRequired.outerFunc = true
 
           shows.push('interface')
         } else if (this.record.sysInterface === 'external') {
           shows.push('exInterface', 'exProInterface')
         }
       } else if (this.record.intertype === 'inner') {
-        shows.push('innerFunc')
+        shows.push('innerFunc', 'recordUser')
         reRequired.innerFunc = true
       }
       if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
@@ -339,11 +354,17 @@
       }
     } else if (openType === 'excelOut') {
       reOptions.intertype = this.state.interTypeOptions.filter(op => op.value !== 'custom')
-      reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredOnce'].includes(op.value))
+
+      if (appType === 'mob') {
+        reOptions.Ot = requireOptions.filter(op => ['notRequired'].includes(op.value))
+      } else {
+        reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredOnce'].includes(op.value))
+      }
 
       if (this.record.intertype === 'outer') {
         shows.push('innerFunc', 'sysInterface', 'outerFunc')
         reRequired.innerFunc = false
+        reRequired.outerFunc = false
 
         if (this.record.sysInterface === 'false') {
           reReadonly.interface = false
@@ -353,19 +374,22 @@
         } else if (this.record.sysInterface === 'true') {
           reReadonly.interface = true
           reRequired.interface = false
+          reRequired.outerFunc = true
 
           shows.push('interface')
         } else if (this.record.sysInterface === 'external') {
           shows.push('exInterface', 'exProInterface')
         }
       } else if (this.record.intertype === 'inner') {
-        shows.push('innerFunc')
+        shows.push('innerFunc', 'recordUser')
         reRequired.innerFunc = true
       }
       if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
         shows.push('resetPageIndex')
       }
-      if (this.record.Ot !== 'notRequired' && this.record.Ot !== 'requiredOnce') {
+      if (this.record.Ot !== 'notRequired' && appType === 'mob') {
+        this.record.Ot = 'notRequired'
+      } else if (this.record.Ot !== 'notRequired' && this.record.Ot !== 'requiredOnce') {
         this.record.Ot = 'notRequired'
       }
     } else if (openType === 'popview') {
@@ -375,6 +399,8 @@
         shows.push('placement')
       } else if (this.record.display === 'drawer') {
         shows.push('placement')
+      } else if (this.record.display === 'modal') {
+        shows.push('popshow')
       }
       if (this.record.popClose === 'grid') {
         shows.push('resetPageIndex')
@@ -388,7 +414,7 @@
       reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
 
       if (this.record.pageTemplate === 'custom') {
-        shows.push('url', 'joint', 'open')
+        shows.push('url', 'proUrl', 'joint', 'open')
       } else if (this.record.pageTemplate === 'linkpage') {
         shows.push('linkmenu', 'open')
 
@@ -400,7 +426,7 @@
         reTooltip.linkmenu = ''
       } else if (this.record.pageTemplate === 'billprint') {
         shows.push('printTemp')
-        reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredSgl', 'required'].includes(op.value))
+        reOptions.Ot = requireOptions
       } else if (this.record.pageTemplate === 'pay') {
         reOptions.Ot = requireOptions.filter(op => op.value === 'requiredSgl')
       }
@@ -416,6 +442,7 @@
           shows.push('innerFunc', 'sysInterface', 'outerFunc', 'callbackFunc')
           reRequired.innerFunc = false
           reRequired.callbackFunc = false
+          reRequired.outerFunc = false
 
           if (this.record.sysInterface === 'false') {
             reReadonly.interface = false
@@ -425,13 +452,14 @@
           } else if (this.record.sysInterface === 'true') {
             reReadonly.interface = true
             reRequired.interface = false
+            reRequired.outerFunc = true
   
             shows.push('interface')
           } else if (this.record.sysInterface === 'external') {
             shows.push('exInterface', 'exProInterface')
           }
         } else if (this.record.intertype === 'inner') {
-          shows.push('innerFunc')
+          shows.push('innerFunc', 'recordUser')
           reRequired.innerFunc = true
         }
         if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
@@ -481,7 +509,7 @@
     }
     
     if (appType === 'mob') {
-      if (Ot !== 'notRequired' && openType !== 'excelOut') {
+      if (openType !== 'excelOut') {
         shows.push('control')
         reOptions.control = [
           { value: '', text: '鏃�' },
@@ -496,7 +524,7 @@
         }
       }
     } else {
-      if (Ot !== 'notRequired' && openType !== 'excelOut') {
+      if (openType !== 'excelOut') {
         reOptions.control = [
           { value: '', text: '鏃�' },
           { value: 'disabled', text: '绂佺敤' },
@@ -618,6 +646,11 @@
       }
 
       this.props.updRecord && this.props.updRecord(this.record)
+    } else if (key === 'formType') {
+      if (value === 'count_line') {
+        _fieldval.Ot = 'requiredSgl'
+        this.record.Ot = 'requiredSgl'
+      }
     } else if (key === 'funcType') {
       if (value === 'print') {
         _fieldval.label = '鎵撳嵃'
@@ -778,6 +811,10 @@
             { pattern: formRule.func.pattern, message: formRule.func.message },
             { max: formRule.func.max, message: formRule.func.maxMessage }
           )
+        } else if (item.key === 'outerBlacklist') {
+          rules.push(
+            { max: 512, message: '鏈�澶�512涓瓧绗�' }
+          )
         } else if (item.key === 'output') {
           if (this.record.intertype === 'system' || ((this.record.intertype === 'outer' || this.record.intertype === 'custom') && this.record.callbackType === 'script')) {
             rules = [{
@@ -886,7 +923,20 @@
           { required: item.readonly ? false : item.required, message: '璇疯緭鍏�' + item.label + '!' }
         ]
 
+        if (item.key === 'url' || item.key === 'proUrl') {
+          rules.push({
+            pattern: /^[^\s]*$/,
+            message: '鍦板潃涓笉鍙娇鐢ㄧ┖鏍硷紒'
+          })
+        }
+
         content = <TextArea rows={2} readOnly={item.readonly}/>
+      } else if (item.type === 'printTemps') {
+        rules = [
+          { required: item.required, message: '璇烽�夋嫨' + item.label + '!' }
+        ]
+
+        content = <MkPrintTemps />
       } else if (item.type === 'keyinterface') {
         span = 24
         className = 'textarea'
@@ -900,7 +950,7 @@
       fields.push(
         <Col span={span} key={index}>
           <Form.Item className={className} help={item.help} label={item.tooltip ?
-            <Tooltip placement="topLeft" title={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}
             </Tooltip> : item.label
@@ -913,16 +963,6 @@
         </Col>
       )
     })
-
-    if (window.debugger && this.props.card.uuid) {
-      fields.push(
-        <Col span={12} key="uuid">
-          <Form.Item label="鎸夐挳ID">
-            <Paragraph copyable>{this.props.card.uuid}</Paragraph>
-          </Form.Item>
-        </Col>
-      )
-    }
 
     return fields
   }
@@ -937,13 +977,15 @@
           values.verify = card.verify || null
           values.modal = card.modal || null
           values.config = card.config || null
+          values.$fixed = card.$fixed || false
 
           if (card.OpenType === 'excelOut' && values.OpenType === 'excelIn') {
-            if (values.verify && values.verify.columns && values.verify.columns.length > 0) {
-              values.verify.columns = values.verify.columns.map(col => {
+            values.verify = {columns: [], scripts: [], sheet: 'Sheet1', default: 'true', range: 1, uniques: []}
+            if (card.verify && card.verify.columns) {
+              values.verify.columns = card.verify.columns.map(col => {
                 col.required = col.required || 'true'
                 col.type = col.type || 'Nvarchar(50)'
-                col.import = col.import || 'true'
+                col.import = 'true'
           
                 if (col.type === 'text' || col.type === 'image') {
                   col.type = 'Nvarchar(50)'
@@ -966,11 +1008,12 @@
                 return col
               })
 
-              values.verify.sheet = values.verify.sheet || 'Sheet1'
+              values.verify.sheet = card.verify.sheet || 'Sheet1'
             }
           } else if (card.OpenType === 'excelIn' && values.OpenType === 'excelOut') {
-            if (values.verify && values.verify.columns && values.verify.columns.length > 0) {
-              values.verify.columns = values.verify.columns.map(col => {
+            values.verify = {columns: [], scripts: [], dataType: 'default'}
+            if (card.verify && card.verify.columns) {
+              values.verify.columns = card.verify.columns.map(col => {
                 col.type = col.type || 'text'
                 col.output = col.output || 'true'
                 col.required = col.required || 'false'
@@ -1035,6 +1078,10 @@
               })
             }
           }
+          
+          if (values.outerBlacklist) {
+            values.outerBlacklist = values.outerBlacklist.replace(/\s/ig, '')
+          }
 
           if (values.openmenu && Array.isArray(values.openmenu) && values.openmenu.length > 0) {
             let list = null
diff --git a/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx b/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx
new file mode 100644
index 0000000..efc3032
--- /dev/null
+++ b/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx
@@ -0,0 +1,89 @@
+import React, {Component} from 'react'
+import { Select, notification } from 'antd'
+import moment from 'moment'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import { queryPrintSql } from '@/utils/option.js'
+
+class MKSelect extends Component {
+  constructor(props) {
+    super(props)
+    
+    this.state = {
+      options: window.GLOB.printTemps || []
+    }
+  }
+
+  componentDidMount () {
+    if (!window.GLOB.printTemps) {
+      this.getPrintTemp()
+    }
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  getPrintTemp = () => {
+    let param = {
+      func: 'sPC_Get_SelectedList',
+      LText: Utils.formatOptions(queryPrintSql),
+      obj_name: 'data',
+      arr_field: 'PN,ID,Images'
+    }
+
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
+
+    Api.getCloudConfig(param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+
+      let temps = (res.data || []).map(temp => {
+        return {
+          value: temp.ID,
+          text: temp.PN
+        }
+      })
+      window.GLOB.printTemps = temps
+
+      this.setState({options: temps})
+    })
+  }
+
+  selectChange = (val) => {
+    this.props.onChange(val)
+  }
+
+  render() {
+    const { value } = this.props
+    const { options } = this.state
+
+    return (
+      <Select
+        showSearch
+        allowClear
+        value={value}
+        filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+        onSelect={this.selectChange}
+        onChange={(val) => val === undefined && this.selectChange('')}
+      >
+        {options.map(option =>
+          <Select.Option key={option.value} value={option.value}>{option.text}</Select.Option>
+        )}
+      </Select>
+    )
+  }
+}
+
+export default MKSelect
\ No newline at end of file
diff --git a/src/menu/components/share/usercomponent/settingform/index.scss b/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.scss
similarity index 100%
rename from src/menu/components/share/usercomponent/settingform/index.scss
rename to src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.scss
diff --git a/src/menu/components/share/actioncomponent/dragaction/card.jsx b/src/menu/components/share/actioncomponent/dragaction/card.jsx
index 4735517..a90472c 100644
--- a/src/menu/components/share/actioncomponent/dragaction/card.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/card.jsx
@@ -106,9 +106,9 @@
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
       <div className="mk-popover-control">
         <EditOutlined className="edit" onClick={() => editCard(id)} />
-        <CopyOutlined className="copy" onClick={() => copyCard(id)} />
-        <CloseOutlined className="close" onClick={() => delCard(id)} />
-        {type !== 'datacard' && type !== 'basetable' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)}/> : ''}
+        {!card.$fixed ? <CopyOutlined className="copy" onClick={() => copyCard(id)} /> : null}
+        {!card.$fixed ? <CloseOutlined className="close" onClick={() => delCard(id)} /> : null}
+        {type !== 'datacard' && type !== 'basetable' && !card.$fixed ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)}/> : ''}
         {hasProfile ? <ProfileOutlined className="profile" title="楠岃瘉" onClick={() => profileCard(id)} /> : null}
         {updateTime}
       </div>
diff --git a/src/menu/components/share/actioncomponent/formconfig.jsx b/src/menu/components/share/actioncomponent/formconfig.jsx
index d8fa383..361a3a6 100644
--- a/src/menu/components/share/actioncomponent/formconfig.jsx
+++ b/src/menu/components/share/actioncomponent/formconfig.jsx
@@ -12,8 +12,6 @@
 export function getActionForm (card, functip, config, usefulFields, modules = [], anchors = [], side) {
   let appType = sessionStorage.getItem('appType')
   let viewType = sessionStorage.getItem('editMenuType') // 寮圭獥 popview
-  let printTemps = sessionStorage.getItem('printTemps')
-  printTemps = printTemps ? JSON.parse(printTemps) : []
   let setting = config.setting || {}
   let columns = side === 'sub' && config.subColumns ? config.subColumns : (config.columns || [])
   let appMenus = []
@@ -165,6 +163,10 @@
     }
   }
 
+  if (card.$fixed) {
+    opentypes = opentypes.filter(item => item.value === card.OpenType)
+  }
+
   if (card.funcType === 'changeuser') { // 鍘熺被鍨嬫敮鎸�
     funTypes.unshift({ value: 'changeuser', text: '鍒囨崲鐢ㄦ埛' })
   }
@@ -245,7 +247,7 @@
     {
       type: 'select',
       key: 'OpenType',
-      label: '鎵撳紑鏂瑰紡',
+      label: '鎸夐挳绫诲瀷',
       initVal: card.OpenType,
       required: true,
       options: opentypes
@@ -255,6 +257,7 @@
       key: 'label',
       label: '鎸夐挳鍚嶇О',
       initVal: card.label,
+      tooltip: card.uuid ? '鎸夐挳ID锛�' + card.uuid : '',
       required: true,
     },
     {
@@ -276,7 +279,7 @@
       ]
     },
     {
-      type: 'radio',
+      type: formTypes.length ? 'select' : 'radio',
       key: 'formType',
       label: '琛ㄥ崟绫诲瀷',
       initVal: card.formType || 'switch',
@@ -290,6 +293,9 @@
       }, {
         value: 'counter',
         text: '璁℃暟鍣�'
+      }, {
+        value: 'count_line',
+        text: '璁℃暟鍣�(鏈湴)'
       }, 
       ...formTypes]
     },
@@ -337,7 +343,7 @@
       key: 'procMode',
       label: '鍙傛暟澶勭悊',
       initVal: card.procMode || (card.innerFunc ? 'inner' : 'system'),
-      tooltip: '褰撹繑鍥炲�煎瓨鍦� mk_ex_invoke 涓斿�间负 false 鏃讹紝涓嶄細璋冪敤澶栭儴鎺ュ彛銆�',
+      tooltip: '褰撹繑鍥炲�煎瓨鍦� mk_ex_invoke 涓斿�间负 false 鏃讹紝涓嶄細璋冪敤澶栭儴鎺ュ彛锛涘綋杩斿洖鍊煎瓨鍦� mk_ex_data 鏃讹紝灏嗕互姝や负鍙傛暟鍒嗘壒璇锋眰鑷畾涔夋帴鍙c�傛敞锛氬綋閫夆�滄棤鈥濇椂锛屾寜閽�夎鏃朵細浼犻�掍富閿紝瀛樺湪琛ㄥ崟鏃朵細浼犻�掕〃鍗曞瓧娈碉紝瀛樺湪BID鏃朵細浼燘ID瀛楁銆�',
       required: true,
       options: [{
         value: 'system',
@@ -392,12 +398,11 @@
       options: pageTemps
     },
     {
-      type: 'select',
+      type: 'printTemps',
       key: 'printTemp',
       label: '鎵撳嵃妯℃澘',
       initVal: card.printTemp || '',
-      required: true,
-      options: printTemps
+      required: true
     },
     {
       type: isApp ? 'select' : 'cascader',
@@ -421,7 +426,16 @@
       key: 'url',
       label: '椤甸潰鍦板潃',
       initVal: card.url || '',
+      tooltip: appType === '' ? '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�' : '',
       required: true
+    },
+    {
+      type: 'textarea',
+      key: 'proUrl',
+      label: '姝e紡鍦板潃',
+      initVal: card.proUrl || '',
+      tooltip: appType === '' ? '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�' : '',
+      required: false
     },
     {
       type: 'radio',
@@ -561,6 +575,22 @@
       }]
     },
     {
+      type: 'text',
+      key: 'ContentType',
+      label: 'Content-Type',
+      initVal: card.ContentType || '',
+      tooltip: '榛樿鍊硷細application/x-www-form-urlencoded;charset=UTF-8',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'outerBlacklist',
+      label: '瀛楁榛戝悕鍗�',
+      initVal: card.outerBlacklist || '',
+      tooltip: '涓嶉渶瑕佸洖浼犵殑瀛楁鍙缃瓧娈甸粦鍚嶅崟锛屽涓�艰鐢ㄩ�楀彿鍒嗛殧銆�',
+      required: false
+    },
+    {
       type: 'select',
       key: 'Ot',
       label: '琛岃缃�',
@@ -573,7 +603,7 @@
       key: 'execSuccess',
       label: '鎴愬姛鍚�',
       initVal: card.execSuccess || 'grid',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�',
       required: true,
       options: [{
         value: 'never',
@@ -596,7 +626,7 @@
       key: 'execError',
       label: '澶辫触鍚�',
       initVal: card.execError || 'never',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�',
       required: true,
       options: [{
         value: 'never',
@@ -872,6 +902,19 @@
     },
     {
       type: 'radio',
+      key: 'openTab',
+      label: '鎵撳紑鏂瑰紡',
+      initVal: card.openTab || 'newtab',
+      tooltip: '鑿滃崟鎵撳紑鏂瑰紡銆�',
+      forbid: appType !== '',
+      options: [
+        {value: 'newtab', text: '鏍囩椤�'},
+        // {value: 'newpage', text: '鏂伴〉闈紙鏍囩椤碉級'},
+        {value: 'view', text: '鏂伴〉闈紙鍏ㄥ睆锛�'}
+      ]
+    },
+    {
+      type: 'radio',
       key: 'display',
       label: '鏄剧ず鏂瑰紡',
       initVal: card.display || 'modal',
@@ -929,6 +972,22 @@
         value: 'close',
         text: '鍏抽棴'
       }]
+    },
+    {
+      type: 'radio',
+      key: 'popshow',
+      label: '寮圭獥灞曠ず',
+      initVal: card.popshow || 'default',
+      tooltip: '灏忕獥鍙e睍绀哄皢闅愯棌鏍囬鍙婂簳閮ㄦ寜閽��',
+      required: false,
+      options: [{
+        value: 'default',
+        text: '榛樿'
+      }, {
+        value: 'miniview',
+        text: '灏忕獥鍙�'
+      }],
+      forbid: appType === 'mob'
     },
     {
       type: 'radio',
@@ -999,6 +1058,21 @@
       tooltip: '鍓嶇疆鍑芥暟鎵ц瀹屾垚鍚庯紝缁撴灉浼氫紶鍏ュ唴閮ㄥ嚱鏁颁腑锛屾鏃跺唴閮ㄥ嚱鏁颁細寮傛鎵ц锛涘綋鍓嶇疆鍑芥暟杩斿洖涓璄rrCode绛変簬-1鏃讹紝灏嗕笉鍐嶆墽琛屽唴閮ㄥ嚱鏁般��',
       required: false,
       forbid: appType === 'mob'
+    },
+    {
+      type: 'radio',
+      key: 'recordUser',
+      label: '璁板綍鐢ㄦ埛',
+      initVal: card.recordUser || 'false',
+      tooltip: '褰撻�夋嫨鈥滄槸鈥濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� username 涓� fullname銆�',
+      required: false,
+      options: [{
+        value: 'false',
+        text: '鍚�'
+      }, {
+        value: 'true',
+        text: '鏄�'
+      }]
     },
     {
       type: 'radio',
@@ -1221,8 +1295,6 @@
  */
 export function getBaseTableActionForm (card, functip, config, usefulFields, modules) {
   let viewType = sessionStorage.getItem('editMenuType') // 寮圭獥 popview
-  let printTemps = sessionStorage.getItem('printTemps')
-  printTemps = printTemps ? JSON.parse(printTemps) : []
   let setting = config.setting || {}
   let columns = config.columns || []
 
@@ -1314,7 +1386,7 @@
     {
       type: 'select',
       key: 'OpenType',
-      label: '鎵撳紑鏂瑰紡',
+      label: '鎸夐挳绫诲瀷',
       initVal: card.OpenType,
       required: true,
       options: opentypes
@@ -1324,6 +1396,7 @@
       key: 'label',
       label: '鎸夐挳鍚嶇О',
       initVal: card.label,
+      tooltip: card.uuid ? '鎸夐挳ID锛�' + card.uuid : '',
       required: true,
     },
     {
@@ -1388,7 +1461,7 @@
       key: 'procMode',
       label: '鍙傛暟澶勭悊',
       initVal: card.procMode || (card.innerFunc ? 'inner' : 'system'),
-      tooltip: '褰撹繑鍥炲�煎瓨鍦� mk_ex_invoke 涓斿�间负 false 鏃讹紝涓嶄細璋冪敤澶栭儴鎺ュ彛銆�',
+      tooltip: '褰撹繑鍥炲�煎瓨鍦� mk_ex_invoke 涓斿�间负 false 鏃讹紝涓嶄細璋冪敤澶栭儴鎺ュ彛锛涘綋杩斿洖鍊煎瓨鍦� mk_ex_data 鏃讹紝灏嗕互姝や负鍙傛暟鍒嗘壒璇锋眰鑷畾涔夋帴鍙c�傛敞锛氬綋閫夆�滄棤鈥濇椂锛屾寜閽�夎鏃朵細浼犻�掍富閿紝瀛樺湪琛ㄥ崟鏃朵細浼犻�掕〃鍗曞瓧娈碉紝瀛樺湪BID鏃朵細浼燘ID瀛楁銆�',
       required: true,
       options: [{
         value: 'system',
@@ -1443,12 +1516,11 @@
       options: pageTemps
     },
     {
-      type: 'select',
+      type: 'printTemps',
       key: 'printTemp',
       label: '鎵撳嵃妯℃澘',
       initVal: card.printTemp || '',
-      required: true,
-      options: printTemps
+      required: true
     },
     {
       type: 'cascader',
@@ -1464,7 +1536,16 @@
       key: 'url',
       label: '椤甸潰鍦板潃',
       initVal: card.url || '',
+      tooltip: '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�',
       required: true
+    },
+    {
+      type: 'textarea',
+      key: 'proUrl',
+      label: '姝e紡鍦板潃',
+      initVal: card.proUrl || '',
+      tooltip: '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�',
+      required: false
     },
     {
       type: 'radio',
@@ -1604,6 +1685,22 @@
       }]
     },
     {
+      type: 'text',
+      key: 'ContentType',
+      label: 'Content-Type',
+      initVal: card.ContentType || '',
+      tooltip: '榛樿鍊硷細application/x-www-form-urlencoded;charset=UTF-8',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'outerBlacklist',
+      label: '瀛楁榛戝悕鍗�',
+      initVal: card.outerBlacklist || '',
+      tooltip: '涓嶉渶瑕佸洖浼犵殑瀛楁鍙缃瓧娈甸粦鍚嶅崟锛屽涓�艰鐢ㄩ�楀彿鍒嗛殧銆�',
+      required: false
+    },
+    {
       type: 'select',
       key: 'Ot',
       label: '琛岃缃�',
@@ -1616,7 +1713,7 @@
       key: 'execSuccess',
       label: '鎴愬姛鍚�',
       initVal: card.execSuccess || 'grid',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�',
       required: true,
       options: [{
         value: 'never',
@@ -1638,7 +1735,7 @@
       key: 'execError',
       label: '澶辫触鍚�',
       initVal: card.execError || 'never',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊鍝竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊鍝竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�',
       required: true,
       options: [{
         value: 'never',
@@ -1831,6 +1928,18 @@
     },
     {
       type: 'radio',
+      key: 'openTab',
+      label: '鎵撳紑鏂瑰紡',
+      initVal: card.openTab || 'newtab',
+      tooltip: '鑿滃崟鎵撳紑鏂瑰紡銆�',
+      options: [
+        {value: 'newtab', text: '鏍囩椤�'},
+        // {value: 'newpage', text: '鏂伴〉闈紙鏍囩椤碉級'},
+        {value: 'view', text: '鏂伴〉闈紙鍏ㄥ睆锛�'}
+      ]
+    },
+    {
+      type: 'radio',
       key: 'display',
       label: '鏄剧ず鏂瑰紡',
       initVal: card.display || 'modal',
@@ -1889,6 +1998,21 @@
       }]
     },
     {
+      type: 'radio',
+      key: 'popshow',
+      label: '寮圭獥灞曠ず',
+      initVal: card.popshow || 'default',
+      tooltip: '灏忕獥鍙e睍绀哄皢闅愯棌鏍囬鍙婂簳閮ㄦ寜閽��',
+      required: false,
+      options: [{
+        value: 'default',
+        text: '榛樿'
+      }, {
+        value: 'miniview',
+        text: '灏忕獥鍙�'
+      }]
+    },
+    {
       type: 'text',
       key: 'preFunc',
       label: '鍓嶇疆鍑芥暟',
@@ -1898,6 +2022,21 @@
     },
     {
       type: 'radio',
+      key: 'recordUser',
+      label: '璁板綍鐢ㄦ埛',
+      initVal: card.recordUser || 'false',
+      tooltip: '褰撻�夋嫨鈥滄槸鈥濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� username 涓� fullname銆�',
+      required: false,
+      options: [{
+        value: 'false',
+        text: '鍚�'
+      }, {
+        value: 'true',
+        text: '鏄�'
+      }]
+    },
+    {
+      type: 'radio',
       key: 'control',
       label: '鎸夐挳鎺у埗',
       initVal: card.control || (card.controlField ? 'disabled' : ''),
diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx
index 5746ac8..3599e68 100644
--- a/src/menu/components/share/actioncomponent/index.jsx
+++ b/src/menu/components/share/actioncomponent/index.jsx
@@ -4,10 +4,9 @@
 import { Modal, notification, Button } from 'antd'
 import moment from 'moment'
 
-import Utils, { FuncUtils } from '@/utils/utils.js'
+import Utils from '@/utils/utils.js'
 import { getActionForm, getBaseTableActionForm } from './formconfig'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
-
 import MKEmitter from '@/utils/events.js'
 import ActionForm from './actionform'
 import MenuUtils from '@/utils/utils-custom.js'
@@ -527,55 +526,47 @@
    * @description 鍒涘缓鎸夐挳瀛樺偍杩囩▼
    */
   creatFunc = () => {
+    const { config } = this.props
     const menu = window.GLOB.customMenu
-    let _config = fromJS(this.props.config).toJS()
 
-    this.actionFormRef.handleConfirm().then(res => {
-      let btn = res         // 鎸夐挳淇℃伅
-      let newLText = ''     // 鍒涘缓瀛樺偍杩囩▼sql
-      let DelText = ''      // 鍒犻櫎瀛樺偍杩囩▼sql
+    return new Promise((resolve) => {
+      this.actionFormRef.handleConfirm().then(res => {
+        let btn = fromJS(res).toJS()
+        let _config = fromJS(config).toJS()
 
-      // 鍒涘缓瀛樺偍杩囩▼锛屽繀椤诲~鍐欏唴閮ㄥ嚱鏁板悕
-      if (btn.intertype !== 'inner') {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤鍐呴儴鍑芥暟鏃讹紝鎵嶅彲浠ュ垱寤哄瓨鍌ㄨ繃绋嬶紒',
-          duration: 5
-        })
-        return
-      }
+        if (btn.OpenType === 'excelIn') {
+          btn.func = btn.innerFunc
+          btn.menuNo = menu.MenuNo
+          btn.MenuName = menu.MenuName + _config.name
+          btn.$type = 'excelIn'
 
-      if (btn.OpenType === 'pop') {
-        let _param = {
-          funcName: btn.innerFunc,
-          name: _config.setting.tableName || '',
-          fields: btn.modal ? btn.modal.fields : [],
-          menuNo: menu.MenuNo
+          resolve(btn)
+        } else if (btn.OpenType === 'excelOut') {
+          _config.MenuName = menu.MenuName + '-' + _config.name
+          _config.menuNo = menu.MenuNo
+          _config.MenuID = menu.MenuID
+          _config.func = btn.innerFunc
+          _config.$type = 'table'
+          
+          resolve(_config)
+        } else {
+          btn.func = btn.innerFunc
+          btn.name = _config.setting.tableName || ''
+          btn.menuNo = menu.MenuNo
+          btn.MenuID = menu.MenuID
+          btn.MenuName = menu.MenuName + _config.name
+          btn.fields = []
+          btn.columns = _config.columns
+          btn.primaryKey = _config.setting.primaryKey || 'ID'
+          btn.$type = 'btn'
+
+          if (btn.OpenType === 'pop') {
+            btn.fields = btn.modal ? btn.modal.fields : []
+          }
+
+          resolve(btn)
         }
-        newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config))
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      } else if (btn.OpenType === 'excelIn') {
-        let _param = {
-          funcName: btn.innerFunc,
-          menuNo: menu.MenuNo
-        }
-        newLText = Utils.formatOptions(FuncUtils.getexcelInfunc(_param, btn, menu))
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      } else if (btn.OpenType === 'excelOut') {
-        newLText = Utils.formatOptions(FuncUtils.getTableFunc(btn.innerFunc, menu, _config)) // 鍒涘缓瀛樺偍杩囩▼sql
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      } else {
-        let _param = {
-          funcName: btn.innerFunc,
-          name: _config.setting.tableName || '',
-          fields: '',
-          menuNo: menu.MenuNo
-        }
-        newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config))
-        DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-      }
-
-      this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText)
+      })
     })
   }
 
@@ -705,12 +696,13 @@
         {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
         <Modal
           title="鎸夐挳路缂栬緫"
+          wrapClassName="mk-scroll-modal"
           visible={visible}
           width={920}
           maskClosable={false}
           onCancel={this.editModalCancel}
           footer={[
-            record && record.intertype === 'inner' ? <CreateFunc key="create" ref="btnCreatFunc" trigger={this.creatFunc}/> : null,
+            record && record.intertype === 'inner' ? <CreateFunc key="create" getMsg={this.creatFunc}/> : null,
             <Button key="cancel" onClick={this.editModalCancel}>鍙栨秷</Button>,
             <Button key="confirm" type="primary" onClick={this.handleSubmit}>纭畾</Button>
           ]}
diff --git a/src/menu/components/share/markcomponent/index.jsx b/src/menu/components/share/markcomponent/index.jsx
index c188601..246f2ea 100644
--- a/src/menu/components/share/markcomponent/index.jsx
+++ b/src/menu/components/share/markcomponent/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Modal, Col } from 'antd'
+import { Modal, Col, notification } from 'antd'
 import { AntDesignOutlined } from '@ant-design/icons'
 
 import Utils from '@/utils/utils.js'
@@ -32,6 +32,20 @@
         dataIndex: 'field',
         width: '16%',
         editable: true,
+        unique: true,
+        uniqueFunc: (data, item) => {
+          let index = data.findIndex(mark => mark.uuid !== item.uuid && mark.contrastValue === item.contrastValue && mark.match === item.match && mark.field.join('') === item.field.join(''))
+
+          if (index > -1) {
+            notification.warning({
+              top: 92,
+              message: '姝ゆ爣璁板凡瀛樺湪锛�',
+              duration: 5
+            })
+            return false
+          }
+          return true
+        },
         inputType: 'cascader',
         options: [],
         rules: [{
@@ -118,18 +132,24 @@
   markChange = (values) => {
     let _marks = fromJS(this.state.marks).toJS()
 
-    if (values.uuid) {
-      _marks = _marks.map(item => {
-        if (item.uuid === values.uuid) {
-          return values
-        } else {
-          return item
-        }
+    let has = false
+    _marks.forEach(mark => {
+      if (mark.contrastValue === values.contrastValue && mark.match === values.match && mark.field.join('') === values.field.join('')) {
+        has = true
+      }
+    })
+
+    if (has) {
+      notification.warning({
+        top: 92,
+        message: '姝ゆ爣璁板凡瀛樺湪锛�',
+        duration: 5
       })
-    } else {
-      values.uuid = Utils.getuuid()
-      _marks.push(values)
+      return
     }
+
+    values.uuid = Utils.getuuid()
+    _marks.push(values)
 
     this.setState({
       marks: _marks
@@ -319,6 +339,11 @@
           item.fontColor = ''
         }
       }
+
+      if (item.contrastValue) {
+        item.contrastValue = item.contrastValue.replace(/\t+|\v+|\s+/g, '')
+      }
+
       if (val && item.contrastValue === val) {
         save = true
       }
diff --git a/src/menu/components/share/markcomponent/markform/index.jsx b/src/menu/components/share/markcomponent/markform/index.jsx
index 0603b31..0fb88dc 100644
--- a/src/menu/components/share/markcomponent/markform/index.jsx
+++ b/src/menu/components/share/markcomponent/markform/index.jsx
@@ -18,6 +18,9 @@
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
+        if (values.contrastValue) {
+          values.contrastValue = values.contrastValue.replace(/\t+|\v+|\s+/g, '')
+        }
         this.props.markChange(values)
       }
     })
diff --git a/src/menu/components/share/searchcomponent/dragsearch/card.jsx b/src/menu/components/share/searchcomponent/dragsearch/card.jsx
index 7c6754f..07df0ae 100644
--- a/src/menu/components/share/searchcomponent/dragsearch/card.jsx
+++ b/src/menu/components/share/searchcomponent/dragsearch/card.jsx
@@ -54,6 +54,8 @@
       _defaultValue = [moment().startOf('week'), moment().endOf('week')]
     } else if (card.initval === 'month') {
       _defaultValue = [moment().startOf('month'), moment().endOf('month')]
+    } else if (card.initval === 'lastMonth') {
+      _defaultValue = [moment().subtract(1, 'months').startOf('month'), moment().subtract(1, 'months').endOf('month')]
     } else if (card.initval) {
       try {
         let _initval = JSON.parse(card.initval)
diff --git a/src/menu/components/share/sourcecomponent/index.jsx b/src/menu/components/share/sourcecomponent/index.jsx
index 2d197f7..bf42033 100644
--- a/src/menu/components/share/sourcecomponent/index.jsx
+++ b/src/menu/components/share/sourcecomponent/index.jsx
@@ -37,7 +37,7 @@
   }
 
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
+    return !is(fromJS(this.state), fromJS(nextState)) || nextProps.type !== this.props.type
   }
 
   deleteUrl = () => {
diff --git a/src/menu/components/share/sourcecomponent/inputform/index.jsx b/src/menu/components/share/sourcecomponent/inputform/index.jsx
index 7652431..5f552ce 100644
--- a/src/menu/components/share/sourcecomponent/inputform/index.jsx
+++ b/src/menu/components/share/sourcecomponent/inputform/index.jsx
@@ -36,7 +36,7 @@
 
   UNSAFE_componentWillMount () {
     if (this.props.keyword === 'system') {
-      this.init()
+      this.preInit()
     }
   }
 
@@ -54,26 +54,40 @@
     return !is(fromJS(this.state), fromJS(nextState))
   }
 
-  init = () => {
+  preInit = () => {
     const { type } = this.props
 
-    let originlist = []
-    if (type === 'video') {
-      let videos = sessionStorage.getItem('app_videos')
-      try {
-        originlist = JSON.parse(videos)
-      } catch (e) {
-        originlist = []
-      }
-    } else {
-      let pictures = sessionStorage.getItem('app_pictures')
-      try {
-        originlist = JSON.parse(pictures)
-      } catch (e) {
-        originlist = []
-      }
-    }
+    let _type = type === 'video' ? 'video' : 'image'
+    let _sname = type === 'video' ? 'app_videos' : 'app_pictures'
 
+    this.getSource(_type, _sname).then(res => {
+      this.init(res)
+    })
+  }
+
+  getSource = (type, sessionName) => {
+    return new Promise(resolve => {
+      if (window.GLOB[sessionName]) {
+        resolve(window.GLOB[sessionName])
+      } else {
+        let param = {
+          func: 's_url_db_adduptdel',
+          PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
+          PageSize: 0,   // 0 浠h〃鍏ㄩ儴
+          type: 'search',
+          typecharone: type
+        }
+        Api.getCloudConfig(param).then(res => {
+          let data = res.data || []
+          window.GLOB[sessionName] = data
+
+          resolve(data)
+        })
+      }
+    })
+  }
+
+  init = (originlist) => {
     let list = originlist
     let pagelist = list.filter((item, index) => index < this.state.pageSize)
 
@@ -124,7 +138,7 @@
         res.id = Utils.getuuid()
       }
 
-      Api.getSystemConfig({
+      Api.getCloudConfig({
         func: 's_url_db_adduptdel',
         id: res.id,
         PageIndex: 0, // 0 浠h〃鍏ㄩ儴
@@ -136,11 +150,11 @@
       }).then(result => {
         if (result.status) {
           if (card.typecharone === 'image') {
-            sessionStorage.setItem('app_pictures', JSON.stringify(result.data || []))
-            this.init()
+            window.GLOB.app_pictures = result.data || []
+            this.init(result.data || [])
           } else {
-            sessionStorage.setItem('app_videos', JSON.stringify(result.data || []))
-            this.init()
+            window.GLOB.app_videos = result.data || []
+            this.init(result.data || [])
           }
           this.setState({editvisible: false})
         } else {
diff --git a/src/menu/components/share/usercomponent/index.jsx b/src/menu/components/share/usercomponent/index.jsx
deleted file mode 100644
index 8862fa6..0000000
--- a/src/menu/components/share/usercomponent/index.jsx
+++ /dev/null
@@ -1,224 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Modal, notification } from 'antd'
-import { UserOutlined } from '@ant-design/icons'
-import html2canvas from 'html2canvas'
-
-import Api from '@/api'
-import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
-import UserForm from './settingform'
-import MKEmitter from '@/utils/events.js'
-import './index.scss'
-
-class UserComponent extends Component {
-  static propTpyes = {
-    config: PropTypes.object
-  }
-
-  state = {
-    visible: false,
-    loading: false,
-    name: '',
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  trigger = () => {
-    const { config } = this.props
-
-    this.setState({
-      visible: true,
-      loading: false,
-      name: window.GLOB.UserComponentMap.get(config.uuid) || config.name || ''
-    })
-  }
-
-  getUserComponent = () => {
-    let config = fromJS(this.props.config).toJS()
-    let _config = {}
-
-    _config.wrap = config.wrap || {}
-    _config.type = config.type || ''
-    _config.subtype = config.subtype || ''
-    _config.style = config.style || {}
-    _config.subcards = config.subcards || []
-    _config.headerStyle = config.headerStyle || {}
-    _config.action = config.action || []
-    _config.search = config.search || []
-    _config.cols = config.cols || []
-    _config.plot = config.plot || {}
-    _config.html = config.html || ''
-    _config.css = config.css || ''
-    _config.js = config.js || ''
-
-    _config.width = _config.wrap.width || _config.plot.width || config.width || 24
-
-    _config.subcards = _config.subcards.map(card => {
-      if (card.elements) {
-        card.elements = card.elements.map(item => this.resetElement(item))
-      }
-      if (card.backElements) {
-        card.backElements = card.backElements.map(item => this.resetElement(item))
-      }
-      return card
-    })
-    _config.action = _config.action.map(item => {
-      item.verify = null
-      return item
-    })
-    _config.search = _config.search.map(item => {
-      if (item.resourceType === '1') {
-        item.resourceType = '0'
-        item.dataSource = ''
-        item.valueText = ''
-        item.valueText = ''
-        item.options = ''
-      }
-      item.blacklist = []
-      return item
-    })
-
-    let loopCol = (cols) => {
-      return cols.map(col => {
-        col.uuid = Utils.getuuid()
-        col.marks = null
-
-        if (col.type === 'colspan' && col.subcols) {
-          col.subcols = loopCol(col.subcols)
-        } else if (col.type === 'custom' && col.elements) {
-          col.elements = col.elements.map(cell => {
-            if (cell.eleType === 'button') {
-              cell.verify = null
-            } else {
-              cell = this.resetElement(cell)
-            }
-            return cell
-          })
-        }
-        return col
-      })
-    }
-
-    _config.cols = loopCol(_config.cols)
-
-    return _config
-  }
-
-  resetElement = (item) => {
-    item.marks = null
-    item.verify = null
-
-    if (item.datatype === 'dynamic') {
-      if (item.eleType ===  'icon') {
-        item.tooltip = item.field
-      } else if (item.eleType === 'slider') {
-        item.value = 50
-      } else {
-        item.value = item.field
-      }
-      
-      item.datatype = 'static'
-      item.field = ''
-    }
-    if (item.link === 'dynamic') {
-      item.link = 'static'
-    }
-    return item
-  }
-
-  submit = () => {
-    const { config } = this.props
-
-    this.verifyRef.handleConfirm().then(res => {
-      document.getElementsByClassName('menu-view')[0].classList.add('saving')
-      this.setState({loading: true})
-      setTimeout(() => {
-        // let template = this.getUserComponent()
-        let template = fromJS(config).toJS()
-        html2canvas(document.getElementById(config.uuid)).then(canvas => {
-          let param = {
-            Base64Img: canvas.toDataURL('image/png') // 鑾峰彇鐢熸垚鐨勫浘鐗�
-          }
-
-          if (options.cloudServiceApi) {
-            param.rduri = options.cloudServiceApi
-            param.userid = sessionStorage.getItem('CloudUserID') || ''
-            param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
-          }
-
-          Api.fileuploadbase64(param).then(result => {
-            if (result.status) {
-              Api.getSystemConfig({
-                func: 's_custom_components_adduptdel',
-                c_id: config.uuid,
-                images: Utils.getcloudurl(result.Images),
-                typename: sessionStorage.getItem('appType') || '',
-                c_name: res.name,
-                long_param: window.btoa(window.encodeURIComponent(JSON.stringify(template))),
-                del_type: ''
-              }).then(response => {
-                if (response.status) {
-                  this.setState({loading: false, visible: false})
-                  notification.success({
-                    top: 92,
-                    message: '淇濆瓨鎴愬姛',
-                    duration: 2
-                  })
-                  document.getElementsByClassName('menu-view')[0].classList.remove('saving')
-                  MKEmitter.emit('updateCustomComponent')
-                } else {
-                  this.setState({loading: false})
-                  notification.warning({
-                    top: 92,
-                    message: response.message,
-                    duration: 5
-                  })
-                }
-              })
-            } else {
-              this.setState({loading: false})
-              notification.warning({
-                top: 92,
-                message: result.ErrMesg,
-                duration: 5
-              })
-            }
-          })
-        })
-      }, 300)
-    })
-  }
-
-  cancel = () => {
-    this.setState({ visible: false })
-    document.getElementsByClassName('menu-view')[0].classList.remove('saving')
-  }
-
-  render () {
-    const { visible, loading, name } = this.state
-
-    return (
-      <div className="user-component-wrap">
-        <UserOutlined title="鐢熸垚鑷畾涔夌粍浠�" onClick={this.trigger} />
-        <Modal
-          title="鑷畾涔夌粍浠�"
-          visible={visible}
-          width={500}
-          maskClosable={false}
-          confirmLoading={loading}
-          onOk={this.submit}
-          onCancel={this.cancel}
-          destroyOnClose
-        >
-          <UserForm name={name} inputSubmit={this.submit} wrappedComponentRef={(inst) => this.verifyRef = inst}/>
-        </Modal>
-      </div>
-    )
-  }
-}
-
-export default UserComponent
\ No newline at end of file
diff --git a/src/menu/components/share/usercomponent/index.scss b/src/menu/components/share/usercomponent/index.scss
deleted file mode 100644
index cdfe23d..0000000
--- a/src/menu/components/share/usercomponent/index.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.user-component-wrap {
-  display: inline-block;
-
-  >.anticon-user {
-    color: purple;
-  }
-}
\ No newline at end of file
diff --git a/src/menu/components/share/usercomponent/settingform/index.jsx b/src/menu/components/share/usercomponent/settingform/index.jsx
deleted file mode 100644
index cd66103..0000000
--- a/src/menu/components/share/usercomponent/settingform/index.jsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Tooltip } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-
-// import './index.scss'
-
-class SettingForm extends Component {
-  static propTpyes = {
-    name: PropTypes.string,       // 缁勪欢鍚嶇О
-    inputSubmit: PropTypes.func   // 鍥炶溅浜嬩欢
-  }
-
-  state = {}
-
-  UNSAFE_componentWillMount () {
-
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  render() {
-    const { getFieldDecorator } = this.props.form
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <Form {...formItemLayout}>
-        <Row gutter={24}>
-          <Col span={22}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                缁勪欢鍚嶇О
-              </Tooltip>
-            }>
-              {getFieldDecorator('name', {
-                initialValue: this.props.name || '',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ョ粍浠跺悕绉�!'
-                  },
-                  {
-                    max: 15,
-                    message: '缁勪欢鍚嶇О鏈�澶�15涓瓧绗�!'
-                  }
-                ]
-              })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit}/>)}
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
index e139d76..0ebdd54 100644
--- a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -164,14 +164,20 @@
     {
       type: 'radio',
       key: 'eval',
-      label: '瑙f瀽',
+      label: '瑙f瀽鏂瑰紡',
       initVal: card.eval || 'false',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滆绠椻�濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃瓧娈垫浛鎹⑩�濓紝浣跨敤鍑芥暟鏃跺叆鍙備负data锛堟暟缁勶級銆�',
       required: false,
-      options: [
-        { value: 'true', text: '鏄�' },
-        { value: 'false', text: '鍚�' }
-      ]
+      options: [{
+        value: 'false',
+        text: '瀛楁鏇挎崲'
+      }, {
+        value: 'true',
+        text: '璁$畻'
+      }, {
+        value: 'func',
+        text: '鍑芥暟'
+      }]
     },
     {
       type: 'radio',
@@ -239,7 +245,7 @@
         value: 'false',
         text: '鍚�'
       }],
-      forbid: card.isSub
+      forbid: card.isSub || card.sum !== 'true'
     },
     {
       type: 'number',
diff --git a/src/menu/components/table/base-table/columns/editColumn/index.jsx b/src/menu/components/table/base-table/columns/editColumn/index.jsx
index 16ae1ca..7318054 100644
--- a/src/menu/components/table/base-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -416,7 +416,7 @@
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
         // eslint-disable-next-line
-        if (values.type === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
+        if (values.type === 'formula' && values.eval === 'true' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
           let cols = []
           fields.forEach(col => {
             if (/^(Int|Decimal)/ig.test(col.datatype)) {
@@ -459,6 +459,7 @@
       <div style={{display: 'inline-block'}}>
         <Modal
           title="鏄剧ず鍒楃紪杈�"
+          wrapClassName="mk-scroll-modal"
           visible={visible}
           width={850}
           maskClosable={false}
diff --git a/src/menu/components/table/base-table/columns/index.jsx b/src/menu/components/table/base-table/columns/index.jsx
index d1da3b4..5b6a30a 100644
--- a/src/menu/components/table/base-table/columns/index.jsx
+++ b/src/menu/components/table/base-table/columns/index.jsx
@@ -324,9 +324,17 @@
       col.subcols = []
     } else if (col.type === 'index') {
       col.label = '搴忓彿'
+    } else if (col.type === 'number') {
+      col.Width = 80
     }
 
-    _columns.splice(hoverIndex, 0, col)
+    let hIndex = +hoverIndex
+
+    if (_columns.length > 0 && hIndex + 1 === _columns.length) {
+      _columns.push(col)
+    } else {
+      _columns.splice(hIndex, 0, col)
+    }
 
     this.setState({
       columns: _columns
diff --git a/src/menu/components/table/base-table/index.jsx b/src/menu/components/table/base-table/index.jsx
index e301f10..653881d 100644
--- a/src/menu/components/table/base-table/index.jsx
+++ b/src/menu/components/table/base-table/index.jsx
@@ -247,6 +247,8 @@
     res.drawerPlacement = card.wrap.drawerPlacement || 'right'
     res.searchRatio = card.wrap.searchRatio || 6
     res.searchLwidth = card.wrap.searchLwidth !== undefined ? card.wrap.searchLwidth : 33.3
+    res.borderRadius = card.wrap.borderRadius || 0
+    res.resetContrl = card.wrap.resetContrl || 'init'
 
     this.updateComponent({...card, wrap: res})
   }
@@ -306,6 +308,14 @@
       config.absFields = null
     }
 
+    if (!config.setting.primaryKey && config.columns.length > 0) {
+      config.columns.forEach(col => {
+        if (col.field.toLowerCase() === 'id') {
+          config.setting.primaryKey = col.field
+        }
+      })
+    }
+
     this.updateComponent(config)
   }
 
diff --git a/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
index 263da80..9b72d05 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -146,14 +146,20 @@
     {
       type: 'radio',
       key: 'eval',
-      label: '瑙f瀽',
+      label: '瑙f瀽鏂瑰紡',
       initVal: card.eval || 'false',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滆绠椻�濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃瓧娈垫浛鎹⑩�濓紝浣跨敤鍑芥暟鏃跺叆鍙備负data锛堟暟缁勶級銆�',
       required: false,
-      options: [
-        { value: 'true', text: '鏄�' },
-        { value: 'false', text: '鍚�' }
-      ]
+      options: [{
+        value: 'false',
+        text: '瀛楁鏇挎崲'
+      }, {
+        value: 'true',
+        text: '璁$畻'
+      }, {
+        value: 'func',
+        text: '鍑芥暟'
+      }]
     },
     {
       type: 'radio',
@@ -265,7 +271,7 @@
       key: 'dataSource',
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
-      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆�',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�粿BID@銆�',
       required: true,
     },
     {
diff --git a/src/menu/components/table/edit-table/columns/editColumn/index.jsx b/src/menu/components/table/edit-table/columns/editColumn/index.jsx
index 06b4348..14f0606 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -421,7 +421,7 @@
             return
           }
           // eslint-disable-next-line
-        } else if (values.type === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
+        } else if (values.type === 'formula' && values.eval === 'true' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
           let cols = []
           fields.forEach(col => {
             if (/^(Int|Decimal)/ig.test(col.datatype)) {
@@ -512,6 +512,7 @@
       <div style={{display: 'inline-block'}}>
         <Modal
           title="鏄剧ず鍒楃紪杈�"
+          wrapClassName="mk-scroll-modal"
           visible={visible}
           width={900}
           maskClosable={false}
diff --git a/src/menu/components/table/edit-table/columns/index.jsx b/src/menu/components/table/edit-table/columns/index.jsx
index ba13cb7..4897eff 100644
--- a/src/menu/components/table/edit-table/columns/index.jsx
+++ b/src/menu/components/table/edit-table/columns/index.jsx
@@ -722,7 +722,7 @@
         <Modal
           wrapClassName="mk-pop-modal"
           visible={visible}
-          width={'75vw'}
+          width={'90vw'}
           maskClosable={false}
           onOk={this.verifySubmit}
           onCancel={() => { this.setState({ visible: false }) }}
diff --git a/src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx b/src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx
index a4a7025..9aab9bf 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx
+++ b/src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select } from 'antd'
+import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select, Switch } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -22,6 +22,7 @@
     editItem: null,
     usefulfields: null,
     loading: false,
+    skip: false,
     verifySql: ''
   }
 
@@ -35,7 +36,8 @@
 
     fields.push('jskey')
 
-    let _sql = `Declare @${btn.sheet} table (${usefulfields.map(item => item.field + ' ' + item.type).join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50))
+    let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
+    let _sql = `create table #${sheet} (${usefulfields.map(item => item.field + ' ' + item.type).join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50))
       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),@tbid Nvarchar(512)
       Select @ErrorCode='', @retmsg=''
     `
@@ -66,8 +68,8 @@
   }
 
   handleConfirm = () => {
-    const { type } = this.props
-    const { editItem } = this.state
+    const { type, btn } = this.props
+    const { editItem, skip } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (type === 'fullscreen' && err) {
@@ -143,8 +145,10 @@
           return
         }
 
+        let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
         let tail = `
-          aaa:
+          drop table #${sheet}
+          aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg
         `
 
         let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
@@ -208,27 +212,39 @@
 
         param.LText = Utils.formatOptions(param.LText)
         param.secretkey = Utils.encrypt('', param.timestamp)
-        
-        this.setState({loading: true})
-        Api.genericInterface(param).then(res => {
-          if (res.status) {
-            this.setState({
-              loading: false,
-              editItem: null
-            }, () => {
-              this.props.scriptsChange(values)
-            })
-            this.props.form.setFieldsValue({
-              sql: ' '
-            })
-          } else {
-            this.setState({loading: false})
 
-            Modal.error({
-              title: res.message
-            })
-          }
-        })
+        if (skip) {
+          this.setState({
+            editItem: null,
+            skip: false
+          }, () => {
+            this.props.scriptsChange(values)
+          })
+          this.props.form.setFieldsValue({
+            sql: ' '
+          })
+        } else {
+          this.setState({loading: true})
+          Api.genericInterface(param).then(res => {
+            if (res.status) {
+              this.setState({
+                loading: false,
+                editItem: null
+              }, () => {
+                this.props.scriptsChange(values)
+              })
+              this.props.form.setFieldsValue({
+                sql: ' '
+              })
+            } else {
+              this.setState({loading: false})
+  
+              Modal.error({
+                title: res.message
+              })
+            }
+          })
+        }
       }
     })
   }
@@ -259,7 +275,7 @@
 
       database = database ? (database[0] || '') : ''
 
-      _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From @${sheet}`
+      _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From #${sheet}`
     } else {
       _value = value
     }
@@ -287,7 +303,7 @@
 
   render() {
     const { systemScripts, btn, type } = this.props
-    const { usefulfields, editItem } = this.state
+    const { usefulfields, editItem, skip } = this.state
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
       labelCol: {
@@ -304,17 +320,17 @@
       <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
         <Row gutter={24}>
           {!type && btn.sheet ? <Col span={8}>
-            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
-              {btn.sheet}
+            <Form.Item label="琛ㄥ悕" style={{whiteSpace: 'nowrap', margin: 0}}>
+              {btn.sheet}锛堣〃鍙橀噺璇蜂娇鐢�#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')}锛�
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={10}>
-            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
+            <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
               ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={24} className="sqlfield">
-            <Form.Item label={'鍙敤瀛楁'}>
+            <Form.Item label="鍙敤瀛楁">
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id</span></Tooltip>,&nbsp;
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
               {usefulfields},data_type锛堟敞锛歫skey涓轰富閿�硷紝鏂板鏃跺墠绔敓鎴愶紱data_type涓烘搷浣滅被鍨嬶紝鏂板 - add銆佷慨鏀� - upt銆佸垹闄� - del锛�
@@ -322,7 +338,7 @@
           </Col> : null}
           {!type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
             <Form.Item style={{marginBottom: 0}} label={
-              <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}>
+              <Tooltip placement="bottomLeft" title="鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
                 鎵ц浣嶇疆
               </Tooltip>
@@ -338,8 +354,8 @@
               )}
             </Form.Item>
           </Col> : null}
-          {!type ? <Col span={10}>
-            <Form.Item style={{marginBottom: 0}} label={'蹇嵎娣诲姞'}>
+          {!type ? <Col span={8}>
+            <Form.Item style={{marginBottom: 0}} label="蹇嵎娣诲姞">
               <Select
                 showSearch
                 filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
@@ -360,16 +376,20 @@
               </Select>
             </Form.Item>
           </Col> : null}
-          <Col span={6} className="add">
-            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
+          <Col span={5} style={{paddingTop: '3px', whiteSpace: 'nowrap'}}>
+            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 15}}>
               {type === 'fullscreen' && !editItem ? '娣诲姞' : '淇濆瓨'}
             </Button>
             <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
               鍙栨秷
             </Button>
           </Col>
+          <Col span={3} style={{paddingTop: '12px', fontSize: '12px', whiteSpace: 'nowrap'}}>
+            寮哄埗淇濆瓨锛�
+            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
+          </Col>
           <Col span={24} className="sql">
-            <Form.Item label={'sql'}>
+            <Form.Item label="sql">
               {getFieldDecorator('sql', {
                 initialValue: '',
                 rules: [
diff --git a/src/menu/components/table/edit-table/columns/tableIn/index.jsx b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
index 8d5c18e..ec97661 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -237,7 +237,7 @@
 
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
-    Api.getSystemConfig(_sParam).then(res => {
+    Api.getCloudConfig(_sParam).then(res => {
       if (res.status) {
         let _scripts = res.data.map(item => {
           return {
@@ -535,8 +535,16 @@
                     <Input value={verify.innerFunc} placeholder="" autoComplete="off" onChange={(e) => this.onOptionChange(e.target.value, 'innerFunc')}/>
                   </Form.Item>
                 </Col> : null}
+                {verify.intertype === 'inner' ? <Col span={8}>
+                  <Form.Item required label="璁板綍鐢ㄦ埛">
+                    <Radio.Group value={verify.recordUser || 'false'} onChange={(e) => this.onOptionChange(e.target.value, 'recordUser')}>
+                      <Radio value="false">鍚�</Radio>
+                      <Radio value="true">鏄�</Radio>
+                    </Radio.Group>
+                  </Form.Item>
+                </Col> : null}
                 {verify.intertype === 'system' ? <Col span={8}>
-                  <Form.Item required label={'榛樿sql'}>
+                  <Form.Item required label="榛樿sql">
                     <Radio.Group value={verify.default} onChange={(e) => this.onOptionChange(e.target.value, 'default')}>
                       <Radio value="true">鎵ц</Radio>
                       <Radio value="false">涓嶆墽琛�</Radio>
diff --git a/src/menu/components/table/edit-table/index.jsx b/src/menu/components/table/edit-table/index.jsx
index 6c0dc8d..9aed6ca 100644
--- a/src/menu/components/table/edit-table/index.jsx
+++ b/src/menu/components/table/edit-table/index.jsx
@@ -19,7 +19,6 @@
 const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const ColumnComponent = asyncComponent(() => import('./columns'))
 
@@ -64,41 +63,6 @@
         scripts: [],
         submit: {intertype: 'system', default: 'true', innerFunc: '', execSuccess: 'grid', execError: 'never', scripts: [], uniques: []},
         isNew: true
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        let oriUids = {}
-        _card.action = config.action.map(item => {
-          let _uuid = Utils.getuuid()
-          oriUids[item.uuid] = _uuid
-          item.uuid = _uuid
-          return item
-        })
-        _card.search = config.search.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
-        _card.cols = config.cols.map(col => {
-          col.uuid = Utils.getuuid()
-          if (col.type === 'custom' && col.elements) {
-            col.elements = col.elements.map(cell => {
-              cell.uuid = Utils.getuuid()
-              return cell
-            })
-          }
-          return col
-        })
       }
 
       this.updateComponent(_card)
@@ -292,6 +256,8 @@
     res.drawerPlacement = card.wrap.drawerPlacement || 'right'
     res.searchRatio = card.wrap.searchRatio || 6
     res.searchLwidth = card.wrap.searchLwidth !== undefined ? card.wrap.searchLwidth : 33.3
+    res.borderRadius = card.wrap.borderRadius || 0
+    res.resetContrl = card.wrap.resetContrl || 'init'
 
     let _card = {...card, wrap: res}
 
@@ -363,7 +329,6 @@
             <CopyComponent type="editable" card={card}/>
             <PasteComponent config={card} options={['action', 'search', 'form', 'cols']} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent} />
           </div>
diff --git a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
index e4c73d2..f915309 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -156,14 +156,20 @@
     {
       type: 'radio',
       key: 'eval',
-      label: '瑙f瀽',
+      label: '瑙f瀽鏂瑰紡',
       initVal: card.eval || 'false',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滆绠椻�濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃瓧娈垫浛鎹⑩�濓紝浣跨敤鍑芥暟鏃跺叆鍙備负data锛堟暟缁勶級銆�',
       required: false,
-      options: [
-        { value: 'true', text: '鏄�' },
-        { value: 'false', text: '鍚�' }
-      ]
+      options: [{
+        value: 'false',
+        text: '瀛楁鏇挎崲'
+      }, {
+        value: 'true',
+        text: '璁$畻'
+      }, {
+        value: 'func',
+        text: '鍑芥暟'
+      }]
     },
     {
       type: 'radio',
@@ -216,22 +222,6 @@
         value: 'false',
         text: '鍚�'
       }]
-    },
-    {
-      type: 'radio',
-      key: 'sum',
-      label: '鏄剧ず鍚堣',
-      initVal: card.sum || 'false',
-      tooltip: '鍚堣淇℃伅鍙湪浣跨敤绯荤粺鏁版嵁婧愭椂鏈夋晥銆�',
-      required: false,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
-      }],
-      forbid: card.isSub
     },
     {
       type: 'number',
diff --git a/src/menu/components/table/normal-table/columns/editColumn/index.jsx b/src/menu/components/table/normal-table/columns/editColumn/index.jsx
index df3913f..6f51d09 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/index.jsx
@@ -424,7 +424,7 @@
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
         // eslint-disable-next-line
-        if (values.type === 'formula' && values.eval !== 'false' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
+        if (values.type === 'formula' && values.eval === 'true' && /^[\u4E00-\u9FA50-9a-zA-Z_\s@\+\-\*\/]*$/ig.test(values.formula) && /[\+\-\*\/]/ig.test(values.formula)) {
           let cols = []
           fields.forEach(col => {
             if (/^(Int|Decimal)/ig.test(col.datatype)) {
@@ -465,6 +465,7 @@
       <div style={{display: 'inline-block'}}>
         <Modal
           title="鏄剧ず鍒楃紪杈�"
+          wrapClassName="mk-scroll-modal"
           visible={visible}
           width={850}
           maskClosable={false}
diff --git a/src/menu/components/table/normal-table/columns/index.jsx b/src/menu/components/table/normal-table/columns/index.jsx
index 1713c3c..00f61c5 100644
--- a/src/menu/components/table/normal-table/columns/index.jsx
+++ b/src/menu/components/table/normal-table/columns/index.jsx
@@ -563,7 +563,6 @@
       } else {
         cell.type = 'number'
         cell.format = 'none'
-        cell.sum = 'false'
         cell.decimal = item.decimal || 0
         cell.Width = 80
       }
diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx
index 2934bd9..613f54c 100644
--- a/src/menu/components/table/normal-table/index.jsx
+++ b/src/menu/components/table/normal-table/index.jsx
@@ -19,7 +19,6 @@
 const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 const ColumnComponent = asyncComponent(() => import('./columns'))
@@ -72,47 +71,6 @@
         ],
         scripts: [],
         isNew: true
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        let oriUids = {}
-        _card.action = config.action.map(item => {
-          let _uuid = Utils.getuuid()
-          oriUids[item.uuid] = _uuid
-          item.uuid = _uuid
-          return item
-        })
-        _card.search = config.search.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
-        _card.cols = config.cols.map(col => {
-          col.uuid = Utils.getuuid()
-          if (col.type === 'colspan' && col.subcols) {
-            col = this.loopCol(col)
-          } else if (col.type === 'custom' && col.elements) {
-            col.elements = col.elements.map(cell => {
-              cell.uuid = Utils.getuuid()
-              return cell
-            })
-          }
-          return col
-        })
-        
-        if (_card.wrap.doubleClick) {
-          _card.wrap.doubleClick = oriUids[_card.wrap.doubleClick] || ''
-        }
       }
 
       if (appType === 'mob') {
@@ -344,6 +302,8 @@
     res.drawerPlacement = card.wrap.drawerPlacement || 'right'
     res.searchRatio = card.wrap.searchRatio || 6
     res.searchLwidth = card.wrap.searchLwidth !== undefined ? card.wrap.searchLwidth : 33.3
+    res.borderRadius = card.wrap.borderRadius || 0
+    res.resetContrl = card.wrap.resetContrl || 'init'
 
     this.updateComponent({...card, wrap: res})
   }
@@ -415,7 +375,6 @@
             <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent} />
           </div>
diff --git a/src/menu/components/table/normal-table/options.jsx b/src/menu/components/table/normal-table/options.jsx
index 688c674..0a6329b 100644
--- a/src/menu/components/table/normal-table/options.jsx
+++ b/src/menu/components/table/normal-table/options.jsx
@@ -272,7 +272,19 @@
       initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
         {value: 'false', label: '绂佺敤'},
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
diff --git a/src/menu/components/tabs/antv-tabs/index.jsx b/src/menu/components/tabs/antv-tabs/index.jsx
index 523c8b2..9f1a261 100644
--- a/src/menu/components/tabs/antv-tabs/index.jsx
+++ b/src/menu/components/tabs/antv-tabs/index.jsx
@@ -195,8 +195,6 @@
   }
 
   getTabForms = (tab) => {
-    const { tabs } = this.state
-
     if (!tab) {
       tab = {
         uuid: '',
@@ -210,7 +208,7 @@
       editab: tab
     })
 
-    return getTabForm(tab, tabs.setting)
+    return getTabForm(tab)
   }
 
   updateTab = (res) => {
@@ -221,7 +219,7 @@
     editab.icon = res.icon
     editab.hide = res.hide || 'false'
     editab.backgroundColor = res.backgroundColor
-    editab.controlVal = res.controlVal || ''
+    // editab.controlVal = res.controlVal || ''
     editab.selectVal = res.selectVal || ''
     editab.blacklist = res.blacklist
 
@@ -249,11 +247,27 @@
   getTabsForms = () => {
     const { tabs } = this.state
 
-    return getTabsSetForm(tabs.setting, tabs.uuid)
+    return getTabsSetForm(tabs.setting, tabs.uuid, tabs.subtabs)
   }
 
   updateTabs = (res) => {
-    this.updateComponent({...this.state.tabs, setting: res})
+    let tabs = fromJS(this.state.tabs).toJS()
+
+    if (res.controlVals) {
+      let values = {}
+      res.controlVals.forEach(item => {
+        values[item.uuid] = item.value
+      })
+      tabs.subtabs.forEach(tab => {
+        tab.controlVal = values[tab.uuid]
+      })
+
+      delete res.controlVals
+    }
+
+    tabs.setting = res
+
+    this.updateComponent(tabs)
   }
 
   onChange = (key) => {
diff --git a/src/menu/components/tabs/antv-tabs/options.jsx b/src/menu/components/tabs/antv-tabs/options.jsx
index 798a655..df84fdf 100644
--- a/src/menu/components/tabs/antv-tabs/options.jsx
+++ b/src/menu/components/tabs/antv-tabs/options.jsx
@@ -3,7 +3,7 @@
 /**
  * @description tab琛ㄥ崟閰嶇疆淇℃伅
  */
-export function getTabForm(tab, setting) {
+export function getTabForm(tab) {
   let appType = sessionStorage.getItem('appType')
   let roleList = sessionStorage.getItem('sysRoles')
 
@@ -34,14 +34,14 @@
       required: false,
       allowClear: true,
     },
-    {
-      type: 'text',
-      field: 'controlVal',
-      label: '闅愯棌鏍囪',
-      initval: tab.controlVal || '',
-      tooltip: '褰撶鐢ㄥ瓧娈靛�间笌闅愯棌鏍囪鐩哥瓑鏃讹紝鏍囩椤典細闅愯棌銆傛敞锛氬涓�艰鐢ㄩ�楀彿鍒嗛殧銆�',
-      required: false,
-    },
+    // {
+    //   type: 'text',
+    //   field: 'controlVal',
+    //   label: '闅愯棌鏍囪',
+    //   initval: tab.controlVal || '',
+    //   tooltip: '褰撶鐢ㄥ瓧娈靛�间笌闅愯棌鏍囪鐩哥瓑鏃讹紝鏍囩椤典細闅愯棌銆傛敞锛�1銆佸涓�艰鐢ㄩ�楀彿鍒嗛殧锛�2銆丂pass@鍊艰〃绀哄拷鐣ユ璁剧疆锛堝缁堟樉绀猴級锛�2銆丂pass_empty@鍊艰〃绀哄拷鐣ョ┖鍊硷紝鍗虫湭鑾峰彇涓婄骇缁勪欢淇℃伅鏃舵樉绀猴紙鍙笌鍏朵粬鍊兼嫾鎺ワ級銆�',
+    //   required: false,
+    // },
     {
       type: 'text',
       field: 'selectVal',
@@ -85,7 +85,7 @@
 /**
  * @description tabs琛ㄥ崟閰嶇疆淇℃伅
  */
-export function getTabsSetForm(setting, uuid) {
+export function getTabsSetForm(setting, uuid, subtabs) {
   let appType = sessionStorage.getItem('appType')
   let roleList = sessionStorage.getItem('sysRoles')
 
@@ -104,6 +104,8 @@
   } else {
     roleList = []
   }
+
+  let controlVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.controlVal}))
 
   const tabForm = [
     {
@@ -202,6 +204,7 @@
       options: modules,
       controlFields: [
         {field: 'controlField', notNull: true},
+        {field: 'controlVals', notNull: true},
       ],
     },
     {
@@ -209,7 +212,7 @@
       field: 'controlField',
       label: '绂佺敤瀛楁',
       initval: setting.controlField || '',
-      tooltip: '鐢ㄤ簬鎺у埗鏍囩闅愯棌鐨勫瓧娈碉紝鍦ㄦ爣绛句腑濉叆闅愯棌鏍囪銆�',
+      tooltip: '鐢ㄤ簬鎺у埗鏍囩闅愯棌鐨勫瓧娈点�傛敞锛氭爲褰㈢粍浠朵腑涓嶅悓灞傜骇浼氳嚜鍔ㄧ敓鎴恗k_floor锛堝眰绾у瓧娈�1銆�2銆�3...锛夈��',
       required: true,
     },
     {
@@ -217,7 +220,7 @@
       field: 'selectField',
       label: '閫変腑瀛楁',
       initval: setting.selectField || '',
-      tooltip: '鐢ㄤ簬鎺у埗鏍囩椤靛垵濮嬪寲閫変腑锛屽湪鏍囩涓~鍏ラ�変腑鏍囪锛屾敞锛氭暟鎹簮浜巙rl鍙傛暟銆�',
+      tooltip: '鐢ㄤ簬鎺у埗鏍囩椤靛垵濮嬪寲閫変腑锛屽湪鏍囩涓~鍏ラ�変腑鏍囪锛屾敞锛氭暟鎹潵婧愪簬url鍙傛暟銆�',
       required: false
     },
     {
@@ -248,6 +251,33 @@
       options: roleList,
       forbid: !!appType
     },
+    {
+      type: 'table',
+      field: 'controlVals',
+      label: '鏍囩缁�',
+      initval: controlVals,
+      tooltip: '褰撶鐢ㄥ瓧娈靛�间笌闅愯棌鏍囪鐩哥瓑鏃讹紝鏍囩椤典細闅愯棌銆傛敞锛�1銆佸涓�艰鐢ㄩ�楀彿鍒嗛殧锛�2銆丂pass@鍊艰〃绀哄拷鐣ユ璁剧疆锛堝缁堟樉绀猴級锛�2銆丂pass_empty@鍊艰〃绀哄拷鐣ョ┖鍊硷紝鍗虫湭鑾峰彇涓婄骇缁勪欢淇℃伅鏃舵樉绀猴紙鍙笌鍏朵粬鍊兼嫾鎺ワ級銆�',
+      required: false,
+      fixed: true,
+      span: 24,
+      columns: [
+        {
+          title: '鏍囩鍚嶇О',
+          dataIndex: 'label',
+          editable: false,
+          required: false,
+          width: '30%'
+        },
+        {
+          title: '闅愯棌鏍囪',
+          dataIndex: 'value',
+          inputType: 'input',
+          editable: true,
+          required: false,
+          width: '50%'
+        }
+      ]
+    }
   ]
 
   return tabForm
diff --git a/src/menu/components/tabs/paste/index.jsx b/src/menu/components/tabs/paste/index.jsx
index 9391b7c..733653d 100644
--- a/src/menu/components/tabs/paste/index.jsx
+++ b/src/menu/components/tabs/paste/index.jsx
@@ -63,7 +63,7 @@
     if (appType === 'mob') {
       options.push('menubar')
     } else {
-      options.push('editable', 'antvG6', 'tree', 'dashboard', 'chart')
+      options.push('editable', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
     }
 
     this.pasteFormRef.handleConfirm().then(res => {
diff --git a/src/menu/components/tabs/tabcomponents/card.jsx b/src/menu/components/tabs/tabcomponents/card.jsx
index cf77eba..6552008 100644
--- a/src/menu/components/tabs/tabcomponents/card.jsx
+++ b/src/menu/components/tabs/tabcomponents/card.jsx
@@ -28,7 +28,9 @@
 const CustomChart = asyncComponent(() => import('@/menu/components/chart/chart-custom'))
 const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline'))
 const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
+const AntvX6 = asyncComponent(() => import('@/menu/components/chart/antv-X6'))
 const DoubleDataCard = asyncComponent(() => import('@/menu/components/card/double-data-card'))
+const Calendar = asyncComponent(() => import('@/menu/components/calendar'))
 
 const Card = ({ id, card, moveCard, findCard, delCard, unGroup, updateConfig }) => {
   const originalIndex = findCard(id).index
@@ -65,6 +67,8 @@
 
   if (card.style && card.style.clear === 'left') {
     style.clear = 'left'
+  } else if (card.style && card.style.clear === 'right') {
+    style.float = 'right'
   }
 
   const getCardComponent = () => {
@@ -118,6 +122,10 @@
       return (<CustomChart card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'antvG6') {
       return (<AntvG6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'antvX6') {
+      return (<AntvX6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'calendar') {
+      return (<Calendar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
 
diff --git a/src/menu/components/tabs/tabcomponents/index.jsx b/src/menu/components/tabs/tabcomponents/index.jsx
index bda63dd..8f345f6 100644
--- a/src/menu/components/tabs/tabcomponents/index.jsx
+++ b/src/menu/components/tabs/tabcomponents/index.jsx
@@ -117,6 +117,8 @@
         balcony: '娴姩鍗�',
         timeline: '鏃堕棿杞�',
         antvG6: '鏍戝浘',
+        antvX6: '娴佺▼鍥�',
+        calendar: '鏃ュ巻',
         card: '鍗$墖'
       }
       let i = 1
diff --git a/src/menu/components/timeline/normal-timeline/index.jsx b/src/menu/components/timeline/normal-timeline/index.jsx
index cb58209..22d2344 100644
--- a/src/menu/components/timeline/normal-timeline/index.jsx
+++ b/src/menu/components/timeline/normal-timeline/index.jsx
@@ -17,7 +17,6 @@
 const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 
 class NormalTimelineComponent extends Component {
@@ -58,27 +57,6 @@
         }],
         columns: [],
         scripts: [],
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
-
-        _card.subcards = config.subcards.map(scard => {
-          scard.uuid = Utils.getuuid()
-          scard.elements = scard.elements.map(elem => {
-            elem.uuid = Utils.getuuid()
-            return elem
-          })
-          return scard
-        })
       }
 
       this.updateComponent(_card)
@@ -181,7 +159,6 @@
             <CopyComponent type="timeline" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent} />
           </div>
diff --git a/src/menu/components/timeline/normal-timeline/options.jsx b/src/menu/components/timeline/normal-timeline/options.jsx
index f9537e1..e07e25d 100644
--- a/src/menu/components/timeline/normal-timeline/options.jsx
+++ b/src/menu/components/timeline/normal-timeline/options.jsx
@@ -168,7 +168,19 @@
       initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
         {value: 'false', label: '绂佺敤'},
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
diff --git a/src/menu/components/tree/antd-tree/index.jsx b/src/menu/components/tree/antd-tree/index.jsx
index c7afa92..b093ad7 100644
--- a/src/menu/components/tree/antd-tree/index.jsx
+++ b/src/menu/components/tree/antd-tree/index.jsx
@@ -17,7 +17,6 @@
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
 
@@ -55,19 +54,6 @@
         columns: [],
         scripts: [],
         action: [],
-      }
-
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.setting = config.setting
-        _card.columns = config.columns
-        _card.scripts = config.scripts
       }
       
       this.updateComponent(_card)
@@ -233,7 +219,6 @@
             <CopyComponent type="tree" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent} />
           </div>
diff --git a/src/menu/components/tree/antd-tree/options.jsx b/src/menu/components/tree/antd-tree/options.jsx
index 54e81d2..eb10a2a 100644
--- a/src/menu/components/tree/antd-tree/options.jsx
+++ b/src/menu/components/tree/antd-tree/options.jsx
@@ -134,6 +134,18 @@
       forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
+      type: 'radio',
+      field: 'cacheLocal',
+      label: '鏈湴缂撳瓨',
+      initval: wrap.cacheLocal || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '缁ф壙鑿滃崟'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'multiselect',
       field: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/datasource/index.jsx b/src/menu/datasource/index.jsx
index 27d9a81..4076942 100644
--- a/src/menu/datasource/index.jsx
+++ b/src/menu/datasource/index.jsx
@@ -1,10 +1,11 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Modal } from 'antd'
+import { Modal, Button } from 'antd'
 import { SettingOutlined } from '@ant-design/icons'
 
 import VerifyCard from './verifycard'
+import CreateFunc from '@/templates/zshare/createfunc'
 import './index.scss'
 
 class DataSource extends Component {
@@ -19,7 +20,8 @@
     mainSearch: [],
     visible: false,
     loading: false,
-    setting: null
+    setting: null,
+    record: {}
   }
 
   UNSAFE_componentWillMount () {
@@ -100,44 +102,42 @@
         })
       }
     } else {
-      let _search = null
-      let filterComponent = (box) => {
+      let filterComponent = (box, mainSearch) => {
         box.components.forEach(item => {
-          if (_search) return
-
-          if (item.type === 'search') {
-            box.slist = [...box.slist, item.search]
-          } else if (item.uuid === config.uuid) {
-            _search = box.slist.pop()
+          if (item.type !== 'search') return
+          mainSearch = item.search
+        })
+        let has = false
+        box.components.forEach(item => {
+          if (item.uuid === config.uuid) {
+            has = true
           } else if (item.type === 'group') {
             item.components.forEach(m => {
               if (m.uuid !== config.uuid) return
-              _search = box.slist.pop()
-            })
-          } else if (item.type === 'tabs') {
-            item.subtabs.forEach(tab => {
-              tab.slist = [...box.slist]
-              filterComponent(tab)
+              has = true
             })
           }
         })
-      }
-      menu.slist = []
-      filterComponent(menu)
 
-      if (_search) {
-        search = _search
-      } else {
-        menu.components.forEach(item => {
-          if (item.type !== 'search') return
-          search = item.search
-        })
+        if (has) {
+          search = mainSearch || []
+        } else {
+          box.components.forEach(item => {
+            if (item.type !== 'tabs') return
+
+            item.subtabs.forEach(tab => {
+              filterComponent(tab, mainSearch)
+            })
+          })
+        }
       }
+      filterComponent(menu, null)
     }
 
     this.setState({
       visible: true,
-      mainSearch: search
+      mainSearch: search,
+      record: {...config.setting}
     })
   }
 
@@ -212,6 +212,14 @@
         delete res.setting.debugId
       }
 
+      if (res.setting.interType === 'system' && res.setting.sync === 'true') {
+        res.scripts && res.scripts.forEach(script => {
+          if (script.status === 'false' || script.position !== 'back') return
+
+          res.setting.sync = 'false'
+        })
+      }
+
       this.setState({loading: false, visible: false})
       this.props.updateConfig({...config, ...res})
     }, () => {
@@ -219,9 +227,34 @@
     })
   }
 
+  creatFunc = () => {
+    const { config } = this.props
+    const { mainSearch } = this.state
+    const menu = window.GLOB.customMenu
+
+    return new Promise((resolve) => {
+      this.verifyRef.submitDataSource().then(res => {
+        let _config = fromJS(config).toJS()
+        _config.MenuName = menu.MenuName + '-' + _config.name
+        _config.menuNo = menu.MenuNo
+        _config.MenuID = menu.MenuID
+        _config.setting = res.setting
+        _config.columns = res.columns
+        _config.func = res.setting.innerFunc
+        _config.$type = 'table'
+  
+        if (res.setting.useMSearch === 'true') { // 浣跨敤涓绘悳绱㈡潯浠�
+          _config.search = [..._config.search, ...mainSearch]
+        }
+  
+        resolve(_config)
+      })
+    })
+  }
+
   render () {
     const { config } = this.props
-    const { visible, loading, mainSearch } = this.state
+    const { visible, loading, mainSearch, record } = this.state
 
     return (
       <div className="model-datasource">
@@ -233,14 +266,18 @@
           width={'75vw'}
           maskClosable={false}
           okText="鎻愪氦"
-          onOk={this.verifySubmit}
-          confirmLoading={loading}
-          onCancel={() => {this.setState({ visible: false }) }}
+          onCancel={() => {this.setState({ visible: false, loading: false }) }}
+          footer={[
+            config.subtype !== 'dualdatacard' && record.interType === 'inner' ? <CreateFunc key="create" getMsg={this.creatFunc}/> : null,
+            <Button key="cancel" onClick={() => { this.setState({ visible: false, loading: false }) }}>鍙栨秷</Button>,
+            <Button key="confirm" type="primary" loading={loading} onClick={this.verifySubmit}>纭畾</Button>
+          ]}
           destroyOnClose
         >
           <VerifyCard
             mainSearch={mainSearch}
             config={config}
+            updRecord={(record) => this.setState({record: record})}
             wrappedComponentRef={(inst) => this.verifyRef = inst}
           />
         </Modal>
diff --git a/src/menu/datasource/verifycard/customscript/index.jsx b/src/menu/datasource/verifycard/customscript/index.jsx
index bca6509..63146d0 100644
--- a/src/menu/datasource/verifycard/customscript/index.jsx
+++ b/src/menu/datasource/verifycard/customscript/index.jsx
@@ -1,7 +1,10 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Button, notification, Select, Tooltip } from 'antd'
+import { Form, Row, Col, Button, notification, Select, Tooltip, Modal, Switch, Radio } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
+import Toast from 'antd-mobile/es/components/toast'
+import Dialog from 'antd-mobile/es/components/dialog'
 
 import Utils from '@/utils/utils.js'
 import CodeMirror from '@/templates/zshare/codemirror'
@@ -10,6 +13,7 @@
 
 class CustomForm extends Component {
   static propTpyes = {
+    type: PropTypes.string,         // 缁勪欢绫诲瀷
     defaultsql: PropTypes.string,   // 榛樿sql
     setting: PropTypes.object,      // 璁剧疆
     searches: PropTypes.array,      // 鎼滅储鏉′欢
@@ -19,6 +23,7 @@
   }
 
   state = {
+    skip: false,
     editItem: null,
     loading: false,
     usefulFields: ''
@@ -83,7 +88,8 @@
     })
 
     this.props.form.setFieldsValue({
-      sql: record.sql
+      sql: record.sql,
+      position: record.position || 'front'
     })
   }
 
@@ -92,11 +98,13 @@
       editItem: null
     })
     this.props.form.setFieldsValue({
-      sql: ' '
+      sql: ' ',
+      position: 'front'
     })
   }
 
   handleConfirm = () => {
+    const { skip } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
@@ -160,11 +168,10 @@
           return
         }
 
-        this.setState({loading: true})
-        this.props.scriptsChange(values).then(() => {
+        if (skip) {
           this.setState({
             editItem: null,
-            loading: false
+            skip: false
           })
 
           if (values.uuid) {
@@ -175,11 +182,28 @@
             sql: ' '
           })
           this.props.scriptSubmit(values)
-        }, () => {
-          this.setState({
-            loading: false
+        } else {
+          this.setState({loading: true})
+          this.props.scriptsChange(values).then(() => {
+            this.setState({
+              editItem: null,
+              loading: false
+            })
+  
+            if (values.uuid) {
+              MKEmitter.emit('editLineId', values.uuid)
+            }
+  
+            this.props.form.setFieldsValue({
+              sql: ' '
+            })
+            this.props.scriptSubmit(values)
+          }, () => {
+            this.setState({
+              loading: false
+            })
           })
-        })
+        }
       }
     })
   }
@@ -209,46 +233,108 @@
     })
   }
 
-  render() {
-    const { systemScripts, setting } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { usefulFields } = this.state
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
+  showError = (type) => {
+    let appType = sessionStorage.getItem('appType')
+
+    if (type === 'S') {
+      if (appType === 'mob') {
+        Toast.show({ icon: 'success', content: '鎵ц鎴愬姛锛�', duration: 3000 })
+      } else {
+        notification.success({
+          top: 92,
+          message: '鎵ц鎴愬姛锛�',
+          duration: 2
+        })
+      }
+      
+    } else if (type === 'Y') {
+      if (appType === 'mob') {
+        Dialog.alert({content: '鎵ц鎴愬姛锛�', confirmText: '鐭ラ亾浜�'})
+      } else {
+        Modal.success({
+          title: '鎵ц鎴愬姛锛�'
+        })
+      }
+    } else if (type === 'N') {
+      if (appType === 'mob') {
+        Dialog.alert({content: '鎵ц澶辫触锛�', confirmText: '鐭ラ亾浜�'})
+      } else {
+        Modal.error({
+          title: '鎵ц澶辫触锛�'
+        })
+      }
+    } else {
+      if (appType === 'mob') {
+        Toast.show({ icon: 'fail', content: '鎵ц澶辫触锛�', duration: 3000 })
+      } else {
+        notification.error({
+          top: 92,
+          message: '鎵ц澶辫触锛�',
+          duration: 10
+        })
       }
     }
+  }
+
+  render() {
+    const { systemScripts, setting, type } = this.props
+    const { getFieldDecorator } = this.props.form
+    const { usefulFields, skip } = this.state
 
     let urlFields = window.GLOB.urlFields ? window.GLOB.urlFields.join(', ') : ''
 
     return (
-      <Form {...formItemLayout} className="modal-menu-setting-script">
+      <Form className="modal-source-setting-script">
         <Row gutter={24}>
-          {setting.tableName ? <Col span={8}>
-            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
+          {setting.tableName ? <Col span={6}>
+            <Form.Item label="琛ㄥ悕" style={{whiteSpace: 'nowrap', margin: 0}}>
               {setting.tableName}
             </Form.Item>
           </Col> : null}
-          <Col span={8}>
-            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
+          <Col span={18}>
+            <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0}}>
               ErrorCode, retmsg
+              <span style={{marginLeft: 25}}>
+                鎴愬姛锛�
+                <span className="error-val" onClick={() => {this.showError('S')}}> S </span>銆�
+                <span className="error-val" onClick={() => {this.showError('Y')}}> Y </span>銆�
+                -1锛堜笉鎻愮ず锛�
+              </span>
+              <span style={{marginLeft: 20}}>
+                澶辫触锛�
+                <span className="error-val" onClick={() => {this.showError('N')}}> N </span>銆�
+                -2锛堜笉鎻愮ず锛夈��
+                <span className="error-val" onClick={() => {this.showError('')}}> 鍏朵粬 </span>
+              </span>
             </Form.Item>
           </Col>
-          <Col span={24} className="sqlfield">
-            <Form.Item label={'鍙敤瀛楁'}>
+          <Col span={24}>
+            <Form.Item label="鍙敤瀛楁" className="field-able">
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, LoginUID, SessionUid, UserID, Appkey, time_id, typename</span></Tooltip>,&nbsp;
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
-              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎺掑簭銆佸垎椤典互鍙婃悳绱㈡潯浠跺彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}</Tooltip>
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎺掑簭銆佸垎椤典互鍙婃悳绱㈡潯浠跺彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆備娇鐢ˊpageSize@鎴朄orderBy@浠h〃鑷畾涔夊垎椤碉紝鎬绘暟璇蜂互mk_total杩斿洖銆�'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{type === 'calendar' ? ', mk_year' : ''}</Tooltip>
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'url鍙橀噺锛岃鎸夌収@xxx@鏍煎紡浣跨敤銆�'}>{urlFields ? ', ' : ''}<span style={{color: '#13c2c2'}}>{urlFields}</span></Tooltip>
             </Form.Item>
           </Col>
-          <Col span={10} style={{width: '43%'}}>
-            <Form.Item label={'蹇嵎娣诲姞'} labelCol={{xs: { span: 24 }, sm: { span: 6 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 18 }} } style={{marginBottom: 0}}>
+          <Col span={8} style={{whiteSpace: 'nowrap'}}>
+            <Form.Item style={{marginBottom: 0}} label={
+              <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌鏁版嵁婧愪綅缃叧绯汇��'}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鎵ц浣嶇疆
+              </Tooltip>
+            }>
+              {getFieldDecorator('position', {
+                initialValue: 'front'
+              })(
+                <Radio.Group>
+                  <Radio value="front">鍓嶇疆</Radio>
+                  <Radio value="back">鍚庣疆</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={8}>
+            <Form.Item label="蹇嵎娣诲姞" labelCol={{xs: { span: 24 }, sm: { span: 6 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 18 }} } style={{marginBottom: 0}}>
               <Select
                 showSearch
                 filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
@@ -264,7 +350,7 @@
               </Select>
             </Form.Item>
           </Col>
-          <Col span={6} className="add">
+          <Col span={5} style={{whiteSpace: 'nowrap'}}>
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginTop: 5, marginBottom: 15, marginLeft: 30}}>
               淇濆瓨
             </Button>
@@ -272,6 +358,10 @@
               鍙栨秷
             </Button>
           </Col>
+          <Col span={3} style={{paddingTop: '15px', fontSize: '12px', whiteSpace: 'nowrap'}}>
+            寮哄埗淇濆瓨锛�
+            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
+          </Col>
           <Col span={24} className="sql">
             <Form.Item label="sql">
               {getFieldDecorator('sql', {
diff --git a/src/menu/datasource/verifycard/customscript/index.scss b/src/menu/datasource/verifycard/customscript/index.scss
index 2a1d2d8..d1c3a10 100644
--- a/src/menu/datasource/verifycard/customscript/index.scss
+++ b/src/menu/datasource/verifycard/customscript/index.scss
@@ -1,34 +1,45 @@
-.modal-menu-setting-script {
-  .sqlfield {
-    .ant-form-item {
-      margin-bottom: 5px;
-    }
+.modal-source-setting-script {
+  .ant-form-item {
+    display: flex;
+    margin-bottom: 5px;
+  }
+  .ant-form-item-label {
+    width: 110px;
+    min-width: 110px;
+  }
+  .field-able {
     .ant-form-item-control {
-      line-height: 24px;
-    }
-    .ant-form-item-label {
       line-height: 25px;
-    }
-    .ant-form-item-children {
-      line-height: 22px;
-    }
-    .ant-col-sm-8 {
-      width: 10.5%;
-    }
-    .ant-col-sm-16 {
-      width: 89.5%;
+      padding-top: 7px;
     }
   }
-  .sql {
-    .ant-col-sm-8 {
-      width: 10.5%;
-    }
-    .ant-col-sm-16 {
-      width: 89.5%;
-      padding-top: 4px;
-    }
-    .CodeMirror {
-      height: 350px;
-    }
+  .ant-form-item-control-wrapper {
+    flex: auto;
+    max-width: calc(100% - 110px);
+  }
+  .CodeMirror {
+    height: 350px;
+  }
+  .error-val {
+    display: inline-block;
+    margin-right: 5px;
+    color: #1890ff;
+    cursor: pointer;
+  }
+}
+.adm-mask {
+  z-index: 2000!important;
+}
+.adm-dialog {
+  z-index: 2000!important;
+  .adm-center-popup-body {
+    background-color: #ffffff;
+  }
+  .adm-center-popup-wrap {
+    z-index: 2000;
+  }
+  .adm-button {
+    color: #1890ff;
+    border-top: 1px solid #e9e9e9;
   }
 }
\ No newline at end of file
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index ddd14c0..9d84902 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -29,7 +29,8 @@
 
 class VerifyCard extends Component {
   static propTpyes = {
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
+    config: PropTypes.object,
+    updRecord: PropTypes.func
   }
 
   state = {
@@ -117,7 +118,7 @@
       {
         title: 'SQL',
         dataIndex: 'sql',
-        width: '72%',
+        width: '65%',
         render: (text) => {
           let title = text.match(/^\s*\/\*.+\*\//)
           title = title && title[0] ? title[0] : ''
@@ -132,9 +133,21 @@
         }
       },
       {
+        title: '鎵ц浣嶇疆',
+        dataIndex: 'position',
+        width: '10%',
+        render: (text, record) => {
+          if (record.position === 'back') {
+            return <span style={{color: '#1890ff'}}>鍚庣疆</span>
+          } else {
+            return <span style={{color: '#26C281'}}>鍓嶇疆</span>
+          }
+        }
+      },
+      {
         title: '鐘舵��',
         dataIndex: 'status',
-        width: '13%',
+        width: '10%',
         render: (text, record) => record.status === 'false' ?
           (
             <div style={{color: '#ff4d4f'}}>
@@ -244,7 +257,7 @@
 
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
-    Api.getSystemConfig(_sParam).then(res => {
+    Api.getCloudConfig(_sParam).then(res => {
       if (res.status) {
         let _scripts = res.data.map(item => {
           return {
@@ -657,6 +670,7 @@
   }
 
   sqlverify = (resolve, reject, change = false, testScripts) => {
+    const { config } = this.props
     const { columns, setting, scripts, searches, defaultSearch, debugId } = this.state
 
     let _scripts = scripts.filter(item => item.status !== 'false')
@@ -681,7 +695,7 @@
 
     if ((setting.interType === 'system' && setting.execute !== 'false') || _scripts.length > 0) {
       let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      let r = SettingUtils.getDebugSql(setting, _scripts, columns, searches, defaultSearch, '2023-04-20 15:29:37')
+      let r = SettingUtils.getDebugSql(setting, _scripts, columns, searches, defaultSearch, config.type, '2023-04-20 15:29:37')
 
       let _debugId = md5(r.sql)
 
@@ -898,7 +912,14 @@
           this.setState({reload: false})
         })
       }
+
+      this.props.updRecord({...res.data.setting})
     })
+  }
+
+  updateStatus = (res) => {
+    this.setState({median: {...res}})
+    this.props.updRecord({...res})
   }
 
   copyColumns = () => {
@@ -972,7 +993,7 @@
               subColumns={subColumns}
               setting={setting}
               scripts={scripts}
-              updateStatus={(res) => this.setState({median: {...res}})}
+              updateStatus={this.updateStatus}
               wrappedComponentRef={(inst) => this.settingForm = inst}
             /> : null}
           </TabPane>
@@ -1027,6 +1048,7 @@
               this.setState({visible: true, script: null, scriptValue: ''})
             }}/> : null}
             <CustomScriptsForm
+              type={config.type}
               setting={setting}
               searches={searches}
               defaultsql={defaultsql}
diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx
index 235cd21..3c256d0 100644
--- a/src/menu/datasource/verifycard/settingform/index.jsx
+++ b/src/menu/datasource/verifycard/settingform/index.jsx
@@ -27,16 +27,24 @@
     modules: [],
     innerRules: [],
     innertip: '',
+    MenuType: '',
     ismain: false
   }
 
   UNSAFE_componentWillMount () {
     const { config, setting } = this.props
 
-    let modules = MenuUtils.getSupModules(window.GLOB.customMenu.components, config.uuid, window.GLOB.customMenu.interfaces)
+    let menu = window.GLOB.customMenu
+    let MenuType = ''
+  
+    if (menu.parentId === 'BillPrintTemp') {
+      MenuType = 'billPrint'
+    }
+
+    let modules = MenuUtils.getSupModules(menu.components, config.uuid, menu.interfaces)
     let ismain = false
 
-    if (window.GLOB.customMenu.Template === 'BaseTable') {
+    if (menu.Template === 'BaseTable') {
       ismain = config.name === '涓昏〃'
     }
 
@@ -82,7 +90,7 @@
       }
     }
 
-    this.setState({modules, innerRules, innertip, setting: _setting, ismain})
+    this.setState({modules, innerRules, innertip, setting: _setting, ismain, MenuType})
   }
 
   handleConfirm = () => {
@@ -181,7 +189,7 @@
   render() {
     const { columns, config } = this.props
     const { getFieldDecorator } = this.props.form
-    const { setting, modules, innerRules, innertip } = this.state
+    const { setting, modules, innerRules, innertip, MenuType } = this.state
 
     const formItemLayout = {
       labelCol: {
@@ -349,7 +357,7 @@
             </Col> : null}
             {setting.interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
               <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={
-                <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''锛涙煡璇㈡浛鎹㈢ $select@ -> /* 鎴� ''銆� @select$ -> */ 鎴� ''锛涚粺璁℃浛鎹㈢ $sum@ -> /* 鎴� ''銆� @sum$ -> */ 鎴� ''銆俙}>
+                <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''銆俙}>
                   <QuestionCircleOutlined className="mk-form-tip" />
                   鏁版嵁婧�
                 </Tooltip>
@@ -398,7 +406,12 @@
             </Col>
             {/* 鏁扮粍鏁版嵁锛岄渶璁剧疆鎺掑簭瑙勫垯 */}
             {config.format === 'array' ? <Col span={8}>
-              <Form.Item label="榛樿鎺掑簭">
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="濡傛灉鍦ㄨ嚜瀹氫箟鑴氭湰涓娇鐢ㄤ簡@pageSize@鎴朄orderBy@锛岃鍦ㄦ暟鎹簮涓崟鐙啓鎺掑簭璇彞銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  榛樿鎺掑簭
+                </Tooltip>
+              }>
                 {getFieldDecorator('order', {
                   initialValue: setting.order || 'ID desc',
                   rules: [
@@ -421,7 +434,7 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            {!['navbar', 'balcony', 'menubar'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') ? <Col span={8}>
+            {!['navbar', 'balcony', 'menubar'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') && MenuType !== 'billPrint' ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'璇ョ粍浠跺鏋滃彈鍏朵粬缁勪欢鎺у埗锛岃閫夐」鐩稿簲鐨勭粍浠讹紝娌℃湁鏃堕�夆�滄棤鈥濄��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -471,8 +484,24 @@
                 })(<InputNumber min={1} max={500} precision={0} />)}
               </Form.Item>
             </Col> : null}
+            {setting.interType === 'inner' ? <Col span={8}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="褰撻�夋嫨鈥滄槸鈥濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� username 涓� fullname銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  璁板綍鐢ㄦ埛
+                </Tooltip>
+              }>
+                {getFieldDecorator('recordUser', {
+                  initialValue: setting.recordUser || 'false'
+                })(
+                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'recordUser')}}>
+                  <Radio value="false">鍚�</Radio>
+                  <Radio value="true">鏄�</Radio>
+                </Radio.Group>)}
+              </Form.Item>
+            </Col> : null}
             {/* 1銆佷笉鍒嗛〉涓斾笉瀛樺湪涓婄骇妯″潡 */}
-            {!['navbar', 'interface'].includes(config.type) && !['editable', 'basetable', 'dualdatacard'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') && setting.interType === 'system' && setting.onload !== 'false' ? <Col span={8}>
+            {!['navbar', 'interface', 'calendar'].includes(config.type) && !['editable', 'basetable', 'dualdatacard'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') && setting.interType === 'system' && setting.onload !== 'false' ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹紝娉細濡傝彍鍗曟湭浣跨敤鍚庣缂撳瓨锛屽垯鏌ヨ璇彞澶т簬8000瀛楃鏃舵棤鏁堛��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -535,7 +564,7 @@
                 )}
               </Form.Item>
             </Col> : null}
-            {config.type === 'interface' && setting.supModule && setting.supModule[0] === 'empty' ? <Col span={8}>
+            {config.type === 'interface' && ((setting.supModule && setting.supModule[0] === 'empty') || MenuType === 'billPrint') ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title="鍒濆鍖栧姞杞藉皢鍦ㄩ〉闈㈠姞杞藉墠鎵ц銆�">
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -552,7 +581,7 @@
                 )}
               </Form.Item>
             </Col> : null}
-            {config.type === 'interface' ? <Col span={8}>
+            {config.type === 'interface' && MenuType !== 'billPrint' ? <Col span={8}>
               <Form.Item label="瀹氭椂鍣�">
                 {getFieldDecorator('timer', {
                   initialValue: setting.timer || ''
diff --git a/src/menu/datasource/verifycard/utils.jsx b/src/menu/datasource/verifycard/utils.jsx
index 93f129b..71bb2b5 100644
--- a/src/menu/datasource/verifycard/utils.jsx
+++ b/src/menu/datasource/verifycard/utils.jsx
@@ -7,17 +7,24 @@
    * @return {Object}  setting       椤甸潰璁剧疆
    * @return {Array}   columns       鏄剧ず瀛楁
    */
-  static getDebugSql (setting, scripts, columns, searches = [], defSearch, timestamp) {
+  static getDebugSql (setting, scripts, columns, searches = [], defSearch, type, timestamp) {
     let sql = ''
     let error = ''
     let _dataresource = ''
-    let _customScript = ''
     let arr_field = columns.map(item => item.field).join(',')
-
-    scripts.forEach(item => {
-      _customScript += `
-        ${item.sql}
-      `
+    let _customScript = ''
+    let _tailScript = ''
+    scripts && scripts.forEach(script => {
+      if (script.status === 'false') return
+      if (script.position !== 'back') {
+        _customScript += `
+        ${script.sql}
+        `
+      } else {
+        _tailScript += `
+        ${script.sql}
+        `
+      }
     })
 
     if (!arr_field) {
@@ -26,6 +33,10 @@
 
     if (setting.interType === 'system' && setting.execute !== 'false') {
       _dataresource = setting.dataresource || ''
+    }
+
+    if (/\s/.test(_dataresource)) {
+      _dataresource = '(' + _dataresource + ') tb'
     }
     
     if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
@@ -36,24 +47,24 @@
       })
     }
 
-    // if (/\$ex@.{1,50}@ex\$/.test(_dataresource)) {
-    //   error = '绯荤粺鍑芥暟' + _dataresource.match(/\$ex@.{1,50}@ex\$/g)[0].replace(/\$ex@|@ex\$/g, '') + '鏈畾涔�'
-    // } else if (/\$ex@.{1,50}@ex\$/.test(_customScript)) {
-    //   error = '绯荤粺鍑芥暟' + _customScript.match(/\$ex@.{1,50}@ex\$/g)[0].replace(/\$ex@|@ex\$/g, '') + '鏈畾涔�'
-    // }
-
     _dataresource = _dataresource.replace(/@(BID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|upid|typename)@/ig, `'${timestamp}'`)
     _customScript = _customScript.replace(/@(BID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|upid|typename)@/ig, `'${timestamp}'`)
+    _tailScript = _tailScript.replace(/@(BID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|upid|typename)@/ig, `'${timestamp}'`)
 
     _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
     _customScript = _customScript.replace(/@\$|\$@/ig, '')
+    _tailScript = _tailScript.replace(/@\$|\$@/ig, '')
+
     _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
     _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
-    // _dataresource = _dataresource.replace(/@sum\$|\$sum@/ig, '')
     _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '')
+    _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
+    _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
 
-    _dataresource = _dataresource.replace(/\$sum@/ig, '/*$sum@')
-    _dataresource = _dataresource.replace(/@sum\$/ig, '@sum$*/')
+    if (type === 'calendar') {
+      _dataresource = _dataresource.replace(/@mk_year@/ig, '')
+      _customScript = _customScript.replace(/@mk_year@/ig, '')
+    }
 
     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 =''
@@ -65,6 +76,7 @@
     if (window.GLOB.externalDatabase !== null) {
       _dataresource = _dataresource.replace(/@db@/ig, window.GLOB.externalDatabase)
       _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase)
+      _tailScript = _tailScript.replace(/@db@/ig, window.GLOB.externalDatabase)
     }
 
     if (window.GLOB.urlFields) {
@@ -72,12 +84,14 @@
         let reg = new RegExp('@' + field + '@', 'ig')
         _dataresource = _dataresource.replace(reg, `'0'`)
         _customScript = _customScript.replace(reg, `'0'`)
+        _tailScript = _tailScript.replace(reg, `'0'`)
       })
     }
 
     // 姝e垯鏇挎崲
     let _regoptions = []
     let _fields = []
+    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
 
     searches.forEach(item => {
       if (!item.field) return
@@ -128,69 +142,38 @@
       }
     })
 
+    _regoptions.push({
+      reg: new RegExp('@orderBy@', 'ig'),
+    }, {
+      reg: new RegExp('@UserName@', 'ig'),
+    }, {
+      reg: new RegExp('@FullName@', 'ig'),
+    }, {
+      reg: new RegExp('@pageSize@', 'ig'),
+    }, {
+      reg: new RegExp('@pageIndex@', 'ig'),
+    })
+
+    _regoptions.forEach(item => {
+      _dataresource = _dataresource.replace(item.reg, '0')
+      _customScript = _customScript.replace(item.reg, '0')
+      _tailScript = _tailScript.replace(item.reg, '0')
+    })
+
     let _search = defSearch
 
-    if (_dataresource) {
-      _regoptions.forEach(item => {
-        _dataresource = _dataresource.replace(item.reg, '0')
-      })
-
+    if (setting.queryType === 'statistics') {
       _search = ''
-    }
-
-    let originscript = _customScript
-
-    if (_customScript) {
-      _regoptions.push({
-        reg: new RegExp('@orderBy@', 'ig'),
-      }, {
-        reg: new RegExp('@UserName@', 'ig'),
-      }, {
-        reg: new RegExp('@FullName@', 'ig'),
-      })
-      if (setting.laypage === 'true') {
-        _regoptions.push({
-          reg: new RegExp('@pageSize@', 'ig'),
-        }, {
-          reg: new RegExp('@pageIndex@', 'ig'),
-        })
-      }
-      _regoptions.forEach(item => {
-        _customScript = _customScript.replace(item.reg, '0')
-        originscript = originscript.replace(item.reg, '0')
-      })
-    }
-
-    let sumSql = ''
-
-    if (_dataresource && /\/\*\$sum@/ig.test(_dataresource)) {
-      let _sql = _dataresource.replace(/\/\*\$sum@|@sum\$\*\//ig, '')
-      _sql = `/*system_query*/${_sql} ${_search}`
-      if (_customScript) {
-        sumSql = `/* sql sum楠岃瘉 */
-          ${_customScript}
-          ${_sql}
-          aaa:
-          if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select '${timestamp}',@ErrorCode, @retmsg,'${timestamp}'
-        `
-      } else {
-        sumSql = `/* sql sum楠岃瘉 */
-          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}`
-      }
     }
 
     // 鏁版嵁婧愬鐞�, 瀛樺湪鏄剧ず鍒楁椂 
     if (_dataresource) {
-      if (/\s/.test(_dataresource)) {
-        _dataresource = '(' + _dataresource + ') tb'
-      }
-
-      if (setting.order) {
+      if (custompage) {
+        _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search}`
+      } else if (setting.order) {
         _dataresource = `/*system_query*/select${setting.laypage === 'true' ?  ' top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage === 'true' ?  'where rows > 0' : ''} order by tmptable.rows`
       } else {
-        _dataresource = `/*system_query*/select${setting.laypage === 'true' ?  ' top 10' : ''} ${arr_field} from ${_dataresource} ${_search}`
+        _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search}`
       }
     }
 
@@ -198,9 +181,19 @@
       sql = `/* sql 楠岃瘉 */
         ${_customScript}
         ${_dataresource}
+        ${_tailScript}
         aaa:
         if @ErrorCode!=''
           insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select '${timestamp}',@ErrorCode, @retmsg,'${timestamp}'
+      `
+    } else if (_tailScript) {
+      sql = `/* 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 =''
+        ${_dataresource}
+        ${_tailScript}
+        aaa:
+        if @ErrorCode!=''
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select '${timestamp}',@ErrorCode, @retmsg,'${timestamp}' 
       `
     } else {
       sql = `/* sql 楠岃瘉 */
@@ -243,7 +236,7 @@
       })
 
       arr.forEach(item => {
-        let reg = new RegExp(item, 'ig')
+        let reg = new RegExp(item, 'i')
         if (reg.test(_dataresource)) {
           errors.push(`鏁版嵁婧愪腑瀛樺湪鏈浛鎹㈠��${item}`)
         }
@@ -255,14 +248,8 @@
       })
     }
 
-    if (sumSql) {
-      sumSql = sumSql.replace(/\n\s{10}/ig, '\n')
-
-      console.info(sumSql)
-      sumSql = sumSql.replace(/\n/g, ' ')
-    }
     sql = sql.replace(/\n/g, ' ')
 
-    return { error, sql, sumSql, errors: errors.join('锛�') }
+    return { error, sql, errors: errors.join('锛�') }
   }
 }
\ No newline at end of file
diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx
index 1719f71..b56942a 100644
--- a/src/menu/menushell/card.jsx
+++ b/src/menu/menushell/card.jsx
@@ -33,6 +33,7 @@
 const Iframe = asyncComponent(() => import('@/menu/components/iframe'))
 const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
 const AntvX6 = asyncComponent(() => import('@/menu/components/chart/antv-X6'))
+const Calendar = asyncComponent(() => import('@/menu/components/calendar'))
 
 const Card = ({ id, card, moveCard, findCard, delCard, unGroup, updateConfig }) => {
   const originalIndex = findCard(id).index
@@ -69,6 +70,8 @@
 
   if (card.style && card.style.clear === 'left') {
     style.clear = 'left'
+  } else if (card.style && card.style.clear === 'right') {
+    style.float = 'right'
   }
 
   const getCardComponent = () => {
@@ -126,20 +129,14 @@
       return (<AntvG6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'antvX6') {
       return (<AntvX6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'calendar') {
+      return (<Calendar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'module' && card.subtype === 'voucher') {
       return (<Voucher card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'module' && card.subtype === 'account') {
       return (<Account card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
-
-  // if (card.type === 'antvX6') { // 娴嬭瘯
-  //   return (
-  //     <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} style={style}>
-  //       <AntvX6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>
-  //     </div>
-  //   )
-  // }
 
   return (
     <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}>
diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx
index 06b1c59..77c601f 100644
--- a/src/menu/menushell/index.jsx
+++ b/src/menu/menushell/index.jsx
@@ -121,6 +121,7 @@
         antvX6: '娴佺▼鍥�',
         iframe: 'iframe',
         module: '妯″潡',
+        calendar: '鏃ュ巻',
         card: '鍗$墖'
       }
       let i = 1
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index a6741f2..9791220 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -115,23 +115,22 @@
     let _linkableFields = []
     let _linksupFields = []
     let standardform = null
-
-    let uniq = new Map()
     let index = null
-    uniq.set(card.field, true)
 
     config.fields.forEach((item, i) => {
       if (card.uuid === item.uuid) {
         index = i
       }
 
-      if (['text', 'number', 'textarea', 'color'].includes(item.type) && card.field !== item.field) {
+      if (!item.field || card.field === item.field) return
+
+      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
         _inputfields.push({
           field: item.field,
           label: item.label
         })
       }
-      if (card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
+      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
         _tabfields.push({
           field: item.field,
           label: item.label
@@ -145,20 +144,19 @@
         })
       }
 
-      if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return
-      if (item.type === 'checkcard' && item.multiple === 'true') return // 閫夐」鍗″閫�
-      if (item.field && !uniq.has(item.field)) {
-        uniq.set(item.field, true)
+      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
 
-        _linkableFields.push({
-          field: item.field,
-          label: item.label + '-琛ㄥ崟'
-        })
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
+      _linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+
+      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
+
+      _linkableFields.push({
+        field: item.field,
+        label: item.label + '-琛ㄥ崟'
+      })
     })
     if (index !== null) {
       if (index === 0) {
@@ -173,10 +171,9 @@
       columns = componentConfig.subColumns || []
     }
 
+    let _fields = _linkableFields.map(cell => cell.field)
     columns.forEach(col => {
-      if (col.field && !uniq.has(col.field)) {
-        uniq.set(col.field, true)
-
+      if (col.field && !_fields.includes(col.field)) {
         _linkableFields.push({
           field: col.field,
           label: col.label + '-鏄剧ず鍒�'
@@ -588,6 +585,7 @@
         </DndProvider>
         <Modal
           title={card && card.$copy ? '澶嶅埗' : '缂栬緫'}
+          wrapClassName="mk-scroll-modal"
           visible={this.state.visible}
           width={950}
           maskClosable={false}
diff --git a/src/menu/modalconfig/tablecomponent/index.jsx b/src/menu/modalconfig/tablecomponent/index.jsx
index 01fd0f2..37e9cba 100644
--- a/src/menu/modalconfig/tablecomponent/index.jsx
+++ b/src/menu/modalconfig/tablecomponent/index.jsx
@@ -5,7 +5,6 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import { queryTableSql } from '@/utils/option.js'
@@ -49,8 +48,8 @@
     param.secretkey = Utils.encrypt(param.LText, param.timestamp)
     param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
 
-    if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
-      param.rduri = options.cloudServiceApi
+    if (window.GLOB.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
+      param.rduri = window.GLOB.cloudServiceApi
       param.userid = sessionStorage.getItem('CloudUserID') || ''
       param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
     }
diff --git a/src/menu/modulesource/dragsource/index.jsx b/src/menu/modulesource/dragsource/index.jsx
index 7b5a6ea..290d9b2 100644
--- a/src/menu/modulesource/dragsource/index.jsx
+++ b/src/menu/modulesource/dragsource/index.jsx
@@ -1,13 +1,12 @@
 import React from 'react'
 import { useDrag } from 'react-dnd'
-import { CloseCircleOutlined } from '@ant-design/icons'
 import './index.scss'
 
-const MobSourceElement = ({item, triggerDel}) => {
+const MobSourceElement = ({item}) => {
   const [, drag] = useDrag({ item })
   return (
     <div className="menu-source-item">
-      <div className="property"><span>{item.title}</span>{item.config ? <CloseCircleOutlined onClick={() => triggerDel(item)}/> : null}</div>
+      <div className="property"><span>{item.title}</span></div>
       <img ref={drag} src={item.url} alt=""/>
     </div>
   )
diff --git a/src/menu/modulesource/index.jsx b/src/menu/modulesource/index.jsx
index 2233f75..a5e0a7e 100644
--- a/src/menu/modulesource/index.jsx
+++ b/src/menu/modulesource/index.jsx
@@ -1,14 +1,9 @@
 import React, {Component} from 'react'
 import { is, fromJS } from 'immutable'
-import { Modal, notification } from 'antd'
 
-import Api from '@/api'
 import { menuOptions } from './option'
 import SourceWrap from './dragsource'
-import MKEmitter from '@/utils/events.js'
 import './index.scss'
-
-const { confirm } = Modal
 
 class ModelSource extends Component {
   state = {
@@ -32,54 +27,8 @@
     })
   }
 
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (nextProps.components && !is(fromJS(this.props.components), fromJS(nextProps.components))) {
-      this.setState({
-        menuOptions: fromJS(nextProps.components).toJS()
-      })
-    }
-  }
-
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  triggerDel = (item) => {
-    confirm({
-      title: `纭畾鍒犻櫎<${item.title}>鍚楋紵`,
-      content: '',
-      onOk() {
-        return new Promise(resolve => {
-          Api.getSystemConfig({
-            func: 's_custom_components_adduptdel',
-            c_id: item.uuid,
-            images: '',
-            c_name: item.title,
-            typename: sessionStorage.getItem('appType') || '',
-            long_param: '',
-            del_type: 'Y'
-          }).then(result => {
-            if (result.status) {
-              notification.success({
-                top: 92,
-                message: '鍒犻櫎鎴愬姛锛�',
-                duration: 5
-              })
-
-              MKEmitter.emit('updateCustomComponent')
-            } else {
-              notification.warning({
-                top: 92,
-                message: result.message,
-                duration: 5
-              })
-            }
-            resolve()
-          })
-        })
-      },
-      onCancel() {}
-    })
   }
 
   render() {
@@ -87,7 +36,7 @@
 
     return (
       <div className="mob-card-source-box">
-        {menuOptions.map((item, index) => (<SourceWrap key={index} item={item} triggerDel={this.triggerDel} />))}
+        {menuOptions.map((item, index) => (<SourceWrap key={index} item={item}/>))}
       </div>
     )
   }
diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx
index 50d70b5..f077659 100644
--- a/src/menu/modulesource/option.jsx
+++ b/src/menu/modulesource/option.jsx
@@ -29,7 +29,7 @@
 import mindmap from '@/assets/mobimg/mindmap.png'
 import indent from '@/assets/mobimg/indent.jfif'
 import kapmap from '@/assets/mobimg/kapmap.jfif'
-// import xflow from '@/assets/mobimg/xflow.png'
+import xflow from '@/assets/mobimg/xflow.png'
 import Voucher from '@/assets/mobimg/voucher.png'
 import Account from '@/assets/mobimg/account.png'
 
@@ -50,6 +50,7 @@
   { type: 'menu', url: NormalTable, component: 'table', subtype: 'normaltable', title: '甯哥敤琛�', width: 24 },
   { type: 'menu', url: NormalTable, component: 'table', subtype: 'editable', title: '琛ㄦ牸锛堝彲缂栬緫锛�', width: 24, forbid: ['billPrint'] },
   { type: 'menu', url: timeline, component: 'timeline', subtype: 'timeline', title: '鏃堕棿杞�', width: 12 },
+  { type: 'menu', url: timeline, component: 'calendar', subtype: 'calendar', title: '鏃ュ巻', width: 24 },
   { type: 'menu', url: tree, component: 'tree', subtype: 'normaltree', title: '鏍戝舰鍒楄〃', width: 12, forbid: ['billPrint'] },
   { type: 'menu', url: line, component: 'line', subtype: 'line', title: '鎶樼嚎鍥�', width: 24 },
   { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '鏌辩姸鍥�', width: 24 },
@@ -64,7 +65,7 @@
   { type: 'menu', url: mindmap, component: 'antvG6', subtype: 'mindmap', title: '鎬濈淮瀵煎浘', width: 24 },
   { type: 'menu', url: indent, component: 'antvG6', subtype: 'indentTree', title: '缂╄繘鏂囦欢鏍�', width: 24 },
   { type: 'menu', url: kapmap, component: 'antvG6', subtype: 'kapmap', title: '鐭ヨ瘑鍥捐氨鏍�', width: 24 },
-  // { type: 'menu', url: xflow, component: 'antvX6', subtype: 'xflow', title: '娴佺▼鍥�', width: 24 },
+  { type: 'menu', url: xflow, component: 'antvX6', subtype: 'xflow', title: '娴佺▼鍥�', width: 24 },
   { type: 'menu', url: chart, component: 'chart', subtype: 'custom', title: '鑷畾涔夊浘琛�', width: 24, forbid: ['billPrint'] },
   { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '瀵屾枃鏈�', width: 24 },
   { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx
index 5179037..652a0f0 100644
--- a/src/menu/pastecontroller/index.jsx
+++ b/src/menu/pastecontroller/index.jsx
@@ -21,7 +21,7 @@
   resetconfig = (item, appType) => {
     if (item.type === 'tabs') {
       item.uuid = MenuUtils.getuuid()
-      item.setting.name = item.setting.name + MenuUtils.getSignName()
+      item.setting.name = (item.setting.name || '') + MenuUtils.getSignName()
       item.name = item.setting.name
 
       item.subtabs.forEach(tab => {
@@ -38,7 +38,7 @@
       })
     } else if (item.type === 'group') {
       item.uuid = MenuUtils.getuuid()
-      item.setting.name = item.setting.name + MenuUtils.getSignName()
+      item.setting.name = (item.setting.name || '') + MenuUtils.getSignName()
       item.name = item.setting.name
 
       item.components = item.components.map(cell => {
@@ -63,10 +63,14 @@
         options.push('menubar', 'singleSearch')
       }
     } else {
-      options.push('editable', 'mainsearch', 'antvG6', 'tree', 'dashboard', 'chart')
+      options.push('editable', 'mainsearch', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
     }
 
     this.pasteFormRef.handleConfirm().then(res => {
+      if (res.copyType === 'basetable') {
+        res.copyType = 'normaltable'
+        res.subtype = 'normaltable'
+      }
       if (!options.includes(res.copyType)) {
         notification.warning({
           top: 92,
diff --git a/src/menu/picturecontroller/index.jsx b/src/menu/picturecontroller/index.jsx
index e51d89f..f91da59 100644
--- a/src/menu/picturecontroller/index.jsx
+++ b/src/menu/picturecontroller/index.jsx
@@ -18,7 +18,7 @@
 const Video = asyncComponent(() => import('./video'))
 const Image = asyncComponent(() => import('@/components/Image'))
 
-class PasteController extends Component {
+class SourceController extends Component {
   state = {
     visible: false,
     editvisible: false,
@@ -39,29 +39,42 @@
   }
 
   trigger = () => {
-    let pictures = sessionStorage.getItem('app_pictures')
-    let videos = sessionStorage.getItem('app_videos')
-    let colorlist = sessionStorage.getItem('app_colors')
+    let deffers = []
 
-    if (!pictures) {
-      notification.warning({
-        top: 92,
-        message: '鏈幏鍙栧埌璧勬簮淇℃伅锛岃绋嶅悗鎴栧埛鏂伴噸璇曘��',
-        duration: 5
-      })
-      return
-    }
+    deffers.push(this.getSource('image', 'app_pictures', 0))
+    deffers.push(this.getSource('video', 'app_videos', 50))
+    deffers.push(this.getSource('color', 'app_colors', 100))
+    
+    Promise.all(deffers).then(result => {
+      this.open(...result)
+    })
+  }
 
-    try {
-      pictures = JSON.parse(pictures)
-      videos = JSON.parse(videos)
-      colorlist = JSON.parse(colorlist)
-    } catch (e) {
-      pictures = []
-      videos = []
-      colorlist = []
-    }
+  getSource = (type, sessionName, delay) => {
+    return new Promise(resolve => {
+      if (window.GLOB[sessionName]) {
+        resolve(window.GLOB[sessionName])
+      } else {
+        let param = {
+          func: 's_url_db_adduptdel',
+          PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
+          PageSize: 0,   // 0 浠h〃鍏ㄩ儴
+          type: 'search',
+          typecharone: type
+        }
+        setTimeout(() => {
+          Api.getCloudConfig(param).then(res => {
+            let data = res.data || []
+            window.GLOB[sessionName] = data
+  
+            resolve(data)
+          })
+        }, delay)
+      }
+    })
+  }
 
+  open = (pictures, videos, colorlist) => {
     let filpictures = pictures
     let filvideos = videos
 
@@ -100,7 +113,7 @@
         res.id = Utils.getuuid()
       }
 
-      Api.getSystemConfig({
+      Api.getCloudConfig({
         func: 's_url_db_adduptdel',
         id: res.id,
         PageIndex: 0, // 0 浠h〃鍏ㄩ儴
@@ -112,13 +125,13 @@
       }).then(result => {
         if (result.status) {
           if (card.typecharone === 'image') {
-            sessionStorage.setItem('app_pictures', JSON.stringify(result.data || []))
+            window.GLOB.app_pictures = result.data || []
             this.resetPicture(result.data || [])
           } else if (card.typecharone === 'video') {
-            sessionStorage.setItem('app_videos', JSON.stringify(result.data || []))
+            window.GLOB.app_videos = result.data || []
             this.resetVideo(result.data || [])
           } else if (card.typecharone === 'color') {
-            sessionStorage.setItem('app_colors', JSON.stringify(result.data || []))
+            window.GLOB.app_colors = result.data || []
             this.resetColor(result.data || [])
           }
           this.setState({editvisible: false})
@@ -154,7 +167,7 @@
       content: '',
       onOk() {
         return new Promise((resolve) => {
-          Api.getSystemConfig({
+          Api.getCloudConfig({
             func: 's_url_db_adduptdel',
             id: item.id,
             PageIndex: 0, // 0 浠h〃鍏ㄩ儴
@@ -166,13 +179,13 @@
           }).then(res => {
             if (res.status) {
               if (item.typecharone === 'image') {
-                sessionStorage.setItem('app_pictures', JSON.stringify(res.data || []))
+                window.GLOB.app_pictures = res.data || []
                 _this.resetPicture(res.data || [])
               } else if (item.typecharone === 'video') {
-                sessionStorage.setItem('app_videos', JSON.stringify(res.data || []))
+                window.GLOB.app_videos = res.data || []
                 _this.resetVideo(res.data || [])
               } else if (item.typecharone === 'color') {
-                sessionStorage.setItem('app_colors', JSON.stringify(res.data || []))
+                window.GLOB.app_colors = res.data || []
                 _this.resetColor(res.data || [])
               }
             } else {
@@ -381,4 +394,4 @@
   }
 }
 
-export default PasteController
\ No newline at end of file
+export default SourceController
\ No newline at end of file
diff --git a/src/menu/replaceField/index.jsx b/src/menu/replaceField/index.jsx
index df1506a..11289e7 100644
--- a/src/menu/replaceField/index.jsx
+++ b/src/menu/replaceField/index.jsx
@@ -5,7 +5,6 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import SettingForm from './settingform'
 import { queryTableSql } from '@/utils/option.js'
@@ -45,8 +44,8 @@
       param.secretkey = Utils.encrypt(param.LText, param.timestamp)
       param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
   
-      if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
-        param.rduri = options.cloudServiceApi
+      if (window.GLOB.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
+        param.rduri = window.GLOB.cloudServiceApi
         param.userid = sessionStorage.getItem('CloudUserID') || ''
         param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
       }
@@ -107,8 +106,8 @@
         }
       } else {
         let param = {func: 'sPC_Get_FieldName', TBName: res.table}
-        if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
-          param.rduri = options.cloudServiceApi
+        if (window.GLOB.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
+          param.rduri = window.GLOB.cloudServiceApi
           param.userid = sessionStorage.getItem('CloudUserID') || ''
           param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         }
diff --git a/src/menu/stylecontroller/index.jsx b/src/menu/stylecontroller/index.jsx
index 6acd6cc..163a7c6 100644
--- a/src/menu/stylecontroller/index.jsx
+++ b/src/menu/stylecontroller/index.jsx
@@ -1,5 +1,4 @@
 import React, {Component} from 'react'
-import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Collapse, Form, Col, InputNumber, Input, Select, Radio, Drawer, Button, message } from 'antd'
 import {
@@ -29,7 +28,8 @@
   ArrowLeftOutlined,
   ArrowRightOutlined,
   SwapOutlined,
-  EnterOutlined
+  EnterOutlined,
+  DragOutlined
 } from '@ant-design/icons'
 
 import MKEmitter from '@/utils/events.js'
@@ -46,11 +46,6 @@
 const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
 
 class MobController extends Component {
-  static propTpyes = {
-    editElem: PropTypes.any,
-    updateStyle: PropTypes.func,
-  }
-
   state = {
     card: null,
     fonts: null,
@@ -168,7 +163,7 @@
     this.callback = null
   }
 
-  updateStyle = (style, prop) => {
+  updateStyle = (style) => {
     const { card } = this.state
 
     let _style = {
@@ -176,8 +171,20 @@
       ...style
     }
 
-    if (prop && !_style[prop]) {
-      delete _style[prop]
+    Object.keys(style).forEach(key => {
+      if (!_style[key] && _style[key] !== 0) {
+        delete _style[key]
+      }
+    })
+
+    if (_style.position === 'relative') {
+      _style.zIndex = 1
+    } else if (_style.position === 'absolute') {
+      _style.zIndex = 2
+    } else if (_style.position === 'fixed') {
+      _style.zIndex = 3
+    } else {
+      delete _style.zIndex
     }
 
     this.setState({
@@ -237,55 +244,6 @@
     this.updateStyle({textIndent: `${value}px`})
   }
 
-  /**
-   * @description 淇敼瀛椾綋绮楃粏
-   */
-  boldChange = (val) => {
-    this.updateStyle({fontWeight: val})
-  }
-
-  /**
-   * @description 鑷姩鎹㈣
-   */
-  wordBreakChange = (val) => {
-    this.updateStyle({wordBreak: val})
-  }
-
-  /**
-   * @description 淇敼瀛椾綋棰滆壊 锛岄鑹叉帶浠�
-   */
-  changeFontColor = (val) => {
-    this.updateStyle({color: val})
-  }
-
-  /**
-   * @description 瀛椾綋瀵归綈
-   */
-  changeTextAlign = (e) => {
-    this.updateStyle({textAlign: e.target.value})
-  }
-
-  /**
-   * @description 瀛椾綋鏍峰紡锛屽�炬枩
-   */
-  changeFontStyle = (e) => {
-    this.updateStyle({fontStyle: e.target.value})
-  }
-
-  /**
-   * @description 瀛椾綋瑁呴グ锛屼笅鍒掔嚎銆佽疮绌跨嚎銆佷笂鍒掔嚎
-   */
-  changeTextDecoration = (e) => {
-    this.updateStyle({textDecoration: e.target.value})
-  }
-
-  /**
-   * @description 淇敼鑳屾櫙棰滆壊 锛岄鑹叉帶浠�
-   */
-  changeBackgroundColor = (val) => {
-    this.updateStyle({backgroundColor: val}, 'backgroundColor')
-  }
-
   changeBackground = (val) => {
     const { card } = this.state
 
@@ -307,27 +265,6 @@
     if (!val || /(^linear-gradient|^radial-gradient)\(.*\)$/.test(val)) {
       this.callback && this.callback(_style)
     }
-  }
-
-  /**
-   * @description 淇敼鑳屾櫙澶у皬
-   */
-  changeBackgroundSize = (val) => {
-    this.updateStyle({backgroundSize: val})
-  }
-
-  /**
-   * @description 淇敼鑳屾櫙浣嶇疆
-   */
-  changeBackgroundPositon= (val) => {
-    this.updateStyle({backgroundPosition: val})
-  }
-
-  /**
-   * @description 淇敼鑳屾櫙閲嶅璁剧疆
-   */
-  changeBackgroundRepeat = (val) => {
-    this.updateStyle({backgroundRepeat: val})
   }
 
   /**
@@ -440,14 +377,6 @@
     }
     
     this.updateStyle(_style)
-  }
-
-  changeWidth = (val) => {
-    this.updateStyle({width: val === '0px' ? '' : val}, 'width')
-  }
-
-  changeHeight = (val) => {
-    this.updateStyle({height: val === '0px' ? '' : val}, 'height')
   }
 
   changeNormalStyle = (val, type) => {
@@ -564,7 +493,7 @@
                     label={<ColumnWidthOutlined title="瀹藉害"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.width || ''} options={['px', 'vh', 'vw', '%', 'auto']} onChange={this.changeWidth}/>
+                    <StyleInput clear={true} defaultValue={card.width || ''} options={['px', 'vh', 'vw', '%', 'auto']} onChange={(val) => this.changeNormalStyle(val, 'width')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -575,7 +504,7 @@
                     label={<ColumnHeightOutlined title="楂樺害"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.height || ''} options={['px', 'vh', 'vw']} onChange={this.changeHeight}/>
+                    <StyleInput clear={true} defaultValue={card.height || ''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'height')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -587,7 +516,7 @@
                 </Col> : null}
                 {fonts.includes('fontWeight') ? <Col span={12}>
                   <Form.Item colon={false} label={<BoldOutlined title="瀛椾綋绮楃粏"/>}>
-                    <Select defaultValue={card.fontWeight || 'normal'} onChange={this.boldChange}>
+                    <Select defaultValue={card.fontWeight || 'normal'} onChange={(val) => this.changeNormalStyle(val, 'fontWeight')}>
                       <Option value="normal">normal</Option>
                       <Option value="bold">bold</Option>
                       <Option value="bolder">bolder</Option>
@@ -621,7 +550,7 @@
                 </Col> : null}
                 {fonts.includes('wordBreak') ? <Col span={12}>
                   <Form.Item colon={false} label={<EnterOutlined title="鑷姩鎹㈣"/>}>
-                    <Select defaultValue={card.wordBreak || 'normal'} onChange={this.wordBreakChange}>
+                    <Select defaultValue={card.wordBreak || 'normal'} onChange={(val) => this.changeNormalStyle(val, 'wordBreak')}>
                       <Option value="normal">normal</Option>
                       <Option value="break-all">break-all</Option>
                     </Select>
@@ -633,14 +562,14 @@
                     label={<FontColorsOutlined title="瀛椾綋棰滆壊"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <ColorSketch value={card.color || ''} onChange={this.changeFontColor} />
+                    <ColorSketch value={card.color || ''} onChange={(val) => this.changeNormalStyle(val, 'color')} />
                   </Form.Item>
                   <Form.Item
                     colon={false}
                     label={<BgColorsOutlined title="绯荤粺鑹�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <SysColorSketch onChange={this.changeFontColor} />
+                    <SysColorSketch onChange={(val) => this.changeNormalStyle(val, 'color')} />
                   </Form.Item>
                 </Col> : null}
                 {fonts.includes('fontStyle') ? <Col span={24}>
@@ -649,7 +578,7 @@
                     label={' '}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <Radio.Group defaultValue={card.fontStyle || 'normal'} onChange={this.changeFontStyle}>
+                    <Radio.Group defaultValue={card.fontStyle || 'normal'} onChange={(e) => this.changeNormalStyle(e.target.value, 'fontStyle')}>
                       <Radio.Button value="normal"><span title="鏍囧噯">N</span></Radio.Button>
                       <Radio.Button value="italic"><ItalicOutlined title="鏂滀綋"/></Radio.Button>
                       <Radio.Button value="oblique" style={{fontStyle: 'oblique'}}><span title="鍊炬枩">B</span></Radio.Button>
@@ -662,7 +591,7 @@
                     label={' '}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <Radio.Group className="text-align" defaultValue={card.textAlign || 'left'} onChange={this.changeTextAlign}>
+                    <Radio.Group className="text-align" defaultValue={card.textAlign || 'left'} onChange={(e) => this.changeNormalStyle(e.target.value, 'textAlign')}>
                       <Radio.Button value="left"><AlignLeftOutlined title="宸﹀榻�"/></Radio.Button>
                       <Radio.Button value="center"><AlignCenterOutlined title="灞呬腑瀵归綈"/></Radio.Button>
                       <Radio.Button value="right"><AlignRightOutlined title="鍙冲榻�"/></Radio.Button>
@@ -675,7 +604,7 @@
                     label={' '}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <Radio.Group className="text-decoration" defaultValue={card.textDecoration || 'none'} onChange={this.changeTextDecoration}>
+                    <Radio.Group className="text-decoration" defaultValue={card.textDecoration || 'none'} onChange={(e) => this.changeNormalStyle(e.target.value, 'textDecoration')}>
                       <Radio.Button value="none"><span title="鏍囧噯">N</span></Radio.Button>
                       <Radio.Button value="underline"><UnderlineOutlined title="涓嬪垝绾�"/></Radio.Button>
                       <Radio.Button value="line-through"><StrikethroughOutlined title="涓垝绾�"/></Radio.Button>
@@ -691,14 +620,14 @@
                     label={<BgColorsOutlined title="鑳屾櫙棰滆壊"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <ColorSketch allowClear={true} value={card.backgroundColor || ''} onChange={this.changeBackgroundColor} />
+                    <ColorSketch allowClear={true} value={card.backgroundColor || ''} onChange={(val) => this.changeNormalStyle(val, 'backgroundColor')} />
                   </Form.Item>
                   <Form.Item
                     colon={false}
                     label={<BgColorsOutlined title="绯荤粺鑹�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <SysColorSketch onChange={this.changeBackgroundColor} />
+                    <SysColorSketch onChange={(val) => this.changeNormalStyle(val, 'backgroundColor')} />
                   </Form.Item>
                 </Col>
                 {window.develop === true ? <Col span={24}>
@@ -725,7 +654,7 @@
                     label="姣斾緥"
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <Select defaultValue={card.backgroundSize || 'cover'} onChange={this.changeBackgroundSize}>
+                    <Select defaultValue={card.backgroundSize || 'cover'} onChange={(val) => this.changeNormalStyle(val, 'backgroundSize')}>
                       <Option value="100%">100%</Option>
                       <Option value="100% 100%">100% 100%</Option>
                       <Option value="auto 100%">auto 100%</Option>
@@ -742,7 +671,7 @@
                     label="閲嶅"
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <Select defaultValue={card.backgroundRepeat || 'no-repeat'} onChange={this.changeBackgroundRepeat}>
+                    <Select defaultValue={card.backgroundRepeat || 'no-repeat'} onChange={(val) => this.changeNormalStyle(val, 'backgroundRepeat')}>
                       <Option value="repeat">repeat</Option>
                       <Option value="no-repeat">no-repeat</Option>
                       <Option value="repeat-x">repeat-x</Option>
@@ -756,7 +685,7 @@
                     label="浣嶇疆"
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <Select defaultValue={card.backgroundPosition || 'center'} onChange={this.changeBackgroundPositon}>
+                    <Select defaultValue={card.backgroundPosition || 'center'} onChange={(val) => this.changeNormalStyle(val, 'backgroundPosition')}>
                       <Option value="center">center</Option>
                       <Option value="center top">center top</Option>
                       <Option value="center bottom">center bottom</Option>
@@ -863,7 +792,7 @@
                     label={<RadiusSettingOutlined title="鍦嗚"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.borderRadius || '0px'} options={['px', '%']} onChange={(val) => this.changeNormalStyle(val, 'borderRadius')}/>
+                    <StyleInput clear={true} defaultValue={card.borderRadius || ''} options={['px', '%']} onChange={(val) => this.changeNormalStyle(val, 'borderRadius')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -919,7 +848,7 @@
                     label={<ArrowUpOutlined title="涓婅竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/>
+                    <StyleInput clear={true} defaultValue={card.marginTop || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -928,7 +857,7 @@
                     label={<ArrowDownOutlined title="涓嬭竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/>
+                    <StyleInput clear={true} defaultValue={card.marginBottom || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -937,7 +866,7 @@
                     label={<ArrowLeftOutlined title="宸﹁竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/>
+                    <StyleInput clear={true} defaultValue={card.marginLeft || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -946,7 +875,7 @@
                     label={<ArrowRightOutlined title="鍙宠竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.marginRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/>
+                    <StyleInput clear={true} defaultValue={card.marginRight || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -957,7 +886,7 @@
                     label={<ArrowUpOutlined title="涓婅竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/>
+                    <StyleInput clear={true} defaultValue={card.paddingTop || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -966,7 +895,7 @@
                     label={<ArrowDownOutlined title="涓嬭竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/>
+                    <StyleInput clear={true} defaultValue={card.paddingBottom || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -975,7 +904,7 @@
                     label={<ArrowLeftOutlined title="宸﹁竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/>
+                    <StyleInput clear={true} defaultValue={card.paddingLeft || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/>
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -984,7 +913,7 @@
                     label={<ArrowRightOutlined title="鍙宠竟璺�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.paddingRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/>
+                    <StyleInput clear={true} defaultValue={card.paddingRight || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -1010,7 +939,7 @@
                     label={<ColumnHeightOutlined title="鏈�灏忛珮搴�"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <StyleInput defaultValue={card.minHeight || ''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'minHeight')}/>
+                    <StyleInput clear={true} defaultValue={card.minHeight || ''} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'minHeight')}/>
                   </Form.Item>
                 </Col>
               </Panel> : null}
@@ -1024,6 +953,7 @@
                     <Radio.Group style={{whiteSpace: 'nowrap'}} defaultValue={card.clear || 'none'} onChange={(e) => this.changeNormalStyle(e.target.value, 'clear')}>
                       <Radio value="none">宸︽诞鍔�</Radio>
                       <Radio value="left">涓嶆诞鍔�</Radio>
+                      <Radio value="right">鍙虫诞鍔�</Radio>
                     </Radio.Group>
                   </Form.Item>
                 </Col>
@@ -1042,6 +972,81 @@
                   </Form.Item>
                 </Col>
               </Panel> : null}
+              {options.includes('position') ? <Panel header="瀹氫綅" key="position">
+                <div style={{paddingLeft: '35px', fontSize: '12px'}}>娉細瀹氫綅鏁堟灉璇峰湪杩愯鐜涓煡鐪嬨��</div>
+                <Col span={24}>
+                  <Form.Item
+                    colon={false}
+                    label={<SwapOutlined title="瀹氫綅"/>}
+                    labelCol={{xs: { span: 24 }, sm: { span: 3 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 21 }} }
+                  >
+                    <Radio.Group style={{whiteSpace: 'nowrap'}} defaultValue={card.position || 'unset'} onChange={(e) => this.changeNormalStyle(e.target.value, 'position')}>
+                      <Radio value="unset">鏃�</Radio>
+                      <Radio value="relative">鐩稿</Radio>
+                      <Radio value="absolute">缁濆</Radio>
+                      <Radio value="fixed">鍥哄畾</Radio>
+                    </Radio.Group>
+                  </Form.Item>
+                </Col>
+                <Col span={24}>
+                  <Form.Item
+                    colon={false}
+                    label={<ArrowUpOutlined title="涓�"/>}
+                    labelCol={{xs: { span: 24 }, sm: { span: 3 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 21 }} }
+                  >
+                    <StyleInput clear={true} defaultValue={card.top || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'top')}/>
+                  </Form.Item>
+                </Col>
+                <Col span={24}>
+                  <Form.Item
+                    colon={false}
+                    label={<ArrowDownOutlined title="涓�"/>}
+                    labelCol={{xs: { span: 24 }, sm: { span: 3 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 21 }} }
+                  >
+                    <StyleInput clear={true} defaultValue={card.bottom || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'bottom')}/>
+                  </Form.Item>
+                </Col>
+                <Col span={24}>
+                  <Form.Item
+                    colon={false}
+                    label={<ArrowLeftOutlined title="宸�"/>}
+                    labelCol={{xs: { span: 24 }, sm: { span: 3 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 21 }} }
+                  >
+                    <StyleInput clear={true} defaultValue={card.left || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'left')}/>
+                  </Form.Item>
+                </Col>
+                <Col span={24}>
+                  <Form.Item
+                    colon={false}
+                    label={<ArrowRightOutlined title="鍙�"/>}
+                    labelCol={{xs: { span: 24 }, sm: { span: 3 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 21 }} }
+                  >
+                    <StyleInput clear={true} defaultValue={card.right || ''} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'right')}/>
+                  </Form.Item>
+                </Col>
+              </Panel> : null}
+              {options.includes('transform') ? <Panel header="浣嶇疆鍙樻崲" key="transform">
+                <div style={{paddingLeft: '50px', fontSize: '12px'}}>娉細鍙樻崲鏁堟灉璇峰湪杩愯鐜涓煡鐪嬨��</div>
+                <Col span={24}>
+                  <Form.Item
+                    colon={false}
+                    label={<DragOutlined title="鍙樻崲"/>}
+                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
+                  >
+                    <Select defaultValue={card.transform || ''} onChange={(val) => this.changeNormalStyle(val, 'transform')}>
+                      <Option value="">鏃�</Option>
+                      <Option value="translateY(-50%)">涓婄Щ50%</Option>
+                      <Option value="translateY(50%)">涓嬬Щ50%</Option>
+                      <Option value="translateX(-50%)">宸︾Щ50%</Option>
+                      <Option value="translateX(50%)">鍙崇Щ50%</Option>
+                      <Option value="translate(-50%, -50%)">宸︿笂绉�50%</Option>
+                      <Option value="translate(-50%, 50%)">宸︿笅绉�50%</Option>
+                      <Option value="translate(50%, -50%)">鍙充笂绉�50%</Option>
+                      <Option value="translate(50%, 50%)">鍙充笅绉�50%</Option>
+                    </Select>
+                  </Form.Item>
+                </Col>
+              </Panel> : null}
             </Collapse> : null}
           </Form>
           <div style={{textAlign: 'right', lineHeight: '60px', marginBottom: '30px'}}>
diff --git a/src/menu/stylecontroller/styleInput/index.jsx b/src/menu/stylecontroller/styleInput/index.jsx
index d7661d0..52b9c1c 100644
--- a/src/menu/stylecontroller/styleInput/index.jsx
+++ b/src/menu/stylecontroller/styleInput/index.jsx
@@ -21,6 +21,8 @@
     options: null
   }
 
+  timer = null
+
   UNSAFE_componentWillMount () {
     const { defaultValue, value, options } = this.props
     let val = ''
@@ -105,6 +107,7 @@
   }
 
   changeValue = (e) => {
+    const { clear } = this.props
     const { unit } = this.state
     let val = e.target.value
 
@@ -124,28 +127,34 @@
       value: _val,
     })
 
-    if (this.props.onChange) {
-      if (!_val) {
-        this.props.onChange('0px')
-      } else {
-        this.props.onChange(`${_val}${unit}`)
+    clearTimeout(this.timer)
+
+    this.timer = setTimeout(() => {
+      if (this.props.onChange) {
+        if (_val === '') {
+          this.props.onChange(clear ? '' : '0px')
+        } else {
+          this.props.onChange(`${_val}${unit}`)
+        }
       }
-    }
+    }, 100)
   }
 
   changeUnit = (val) => {
     const { value } = this.state
 
-    this.setState({unit: val})
-
-    if (val === 'auto') {
-      this.setState({value: ''})
-      this.props.onChange('auto')
-    } else {
-      if (value && this.props.onChange) {
-        this.props.onChange(`${value}${val}`)
+    this.setState({unit: val}, () => {
+      if (val === 'auto') {
+        this.setState({value: ''})
+        this.props.onChange('auto')
+      } else {
+        if (value && this.props.onChange) {
+          this.props.onChange(`${value}${val}`)
+        } else {
+          this.props.onChange('')
+        }
       }
-    }
+    })
   }
 
   render () {
diff --git a/src/menu/tablenodes/index.jsx b/src/menu/tablenodes/index.jsx
index e903da7..26fb797 100644
--- a/src/menu/tablenodes/index.jsx
+++ b/src/menu/tablenodes/index.jsx
@@ -122,7 +122,7 @@
         MenuID: config.uuid
       }
 
-      Api.getSystemConfig(param).then(result => {
+      Api.getCloudConfig(param).then(result => {
         if (!result.status) {
           notification.warning({
             top: 92,
diff --git a/src/menu/transfer/index.jsx b/src/menu/transfer/index.jsx
index 6eeecbf..04223ca 100644
--- a/src/menu/transfer/index.jsx
+++ b/src/menu/transfer/index.jsx
@@ -29,6 +29,22 @@
     const _this = this
 
     if (!config.enabled) {
+      let tb = config.components[0]
+      if (config.components.length === 1 && tb.setting.interType === 'system' && !tb.setting.dataresource) {
+        confirm({
+          title: '褰撳墠椤甸潰灏嗘竻绌猴紝纭畾鍒囨崲涓鸿嚜瀹氫箟椤甸潰鍚楋紵',
+          content: '',
+          onOk() {
+            return new Promise(resolve => {
+              _this.execUpdate(resolve, true)
+            })
+          },
+          onCancel() {}
+        })
+
+        return
+      }
+
       notification.warning({
         top: 92,
         message: '鏈惎鐢ㄨ彍鍗曚笉鍙崌绾э紒',
@@ -49,7 +65,7 @@
     })
   }
 
-  execUpdate = (_resolve) => {
+  execUpdate = (_resolve, clear) => {
     let _config = fromJS(this.props.config).toJS()
     _config.permission = 'true'
     _config.Template = 'CustomPage'
@@ -59,23 +75,53 @@
     delete _config.autoMatic
 
     let useMSearch = false
-    _config.components.forEach((item, i) => {
-      if (item.type === 'tabs') {
-        item.name = '鏍囩缁�' + i
-        item.width = 24
-        item.subtype = 'tabs'
-        item.setting = {autoSwitch: 'false', blacklist: [], name: item.name, position: 'top', supModule: [], tabStyle: 'line', width: 24}
 
-        item.subtabs.forEach(tab => {
-          tab.components[0].subtype = 'normaltable'
-          tab.components[0].width = 24
-          tab.components[0].wrap.width = 24
-          tab.components[0].wrap.name = tab.components[0].name
-          if (tab.components[0].setting.useMSearch === 'true') {
-            useMSearch = true
-          }
-
-          tab.components[0].action.forEach(btn => {
+    if (clear) {
+      _config.components = []
+    } else {
+      _config.components.forEach((item, i) => {
+        if (item.type === 'tabs') {
+          item.name = '鏍囩缁�' + i
+          item.width = 24
+          item.subtype = 'tabs'
+          item.setting = {autoSwitch: 'false', blacklist: [], name: item.name, position: 'top', supModule: [], tabStyle: 'line', width: 24}
+  
+          item.subtabs.forEach(tab => {
+            tab.components[0].subtype = 'normaltable'
+            tab.components[0].width = 24
+            tab.components[0].wrap.width = 24
+            tab.components[0].wrap.name = tab.components[0].name
+            if (tab.components[0].setting.useMSearch === 'true') {
+              useMSearch = true
+            }
+  
+            tab.components[0].action.forEach(btn => {
+              if (btn.OpenType === 'popview' && btn.config) {
+                btn.config.Template = 'CustomPage'
+                if (btn.config.components[0]) {
+                  btn.config.components[0].subtype = 'normaltable'
+                }
+              }
+            })
+            tab.components[0].cols = tab.components[0].cols.filter(col => !(col.field && col.Hide === 'true'))
+            tab.components[0].cols.forEach(col => {
+              if (col.type !== 'custom') return
+              col.elements.forEach(btn => {
+                if (btn.OpenType === 'popview' && btn.config) {
+                  btn.config.Template = 'CustomPage'
+                  if (btn.config.components[0]) {
+                    btn.config.components[0].subtype = 'normaltable'
+                  }
+                }
+              })
+            })
+          })
+        } else {
+          item.subtype = 'normaltable'
+          item.width = 24
+          item.wrap.width = 24
+          item.wrap.name = item.name
+          item.action.forEach(btn => {
             if (btn.OpenType === 'popview' && btn.config) {
               btn.config.Template = 'CustomPage'
               if (btn.config.components[0]) {
@@ -83,8 +129,8 @@
               }
             }
           })
-          tab.components[0].cols = tab.components[0].cols.filter(col => !(col.field && col.Hide === 'true'))
-          tab.components[0].cols.forEach(col => {
+          item.cols = item.cols.filter(col => !(col.field && col.Hide === 'true'))
+          item.cols.forEach(col => {
             if (col.type !== 'custom') return
             col.elements.forEach(btn => {
               if (btn.OpenType === 'popview' && btn.config) {
@@ -95,34 +141,9 @@
               }
             })
           })
-        })
-      } else {
-        item.subtype = 'normaltable'
-        item.width = 24
-        item.wrap.width = 24
-        item.wrap.name = item.name
-        item.action.forEach(btn => {
-          if (btn.OpenType === 'popview' && btn.config) {
-            btn.config.Template = 'CustomPage'
-            if (btn.config.components[0]) {
-              btn.config.components[0].subtype = 'normaltable'
-            }
-          }
-        })
-        item.cols = item.cols.filter(col => !(col.field && col.Hide === 'true'))
-        item.cols.forEach(col => {
-          if (col.type !== 'custom') return
-          col.elements.forEach(btn => {
-            if (btn.OpenType === 'popview' && btn.config) {
-              btn.config.Template = 'CustomPage'
-              if (btn.config.components[0]) {
-                btn.config.components[0].subtype = 'normaltable'
-              }
-            }
-          })
-        })
-      }
-    })
+        }
+      })
+    }
 
     if (useMSearch) {
       let cell = {
@@ -140,6 +161,7 @@
       cell.wrap.advanceWidth = _config.components[0].wrap.advanceWidth || 1000
       cell.wrap.searchLwidth = _config.components[0].wrap.searchLwidth || 33.3
       cell.wrap.searchRatio = _config.components[0].wrap.searchRatio || 6
+      cell.wrap.resetContrl = _config.components[0].wrap.resetContrl || 'init'
       cell.wrap.show = _config.components[0].wrap.show || 'true'
       
       if (cell.wrap.advanceType === 'drawer') {
@@ -224,7 +246,7 @@
     param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     param.secretkey = Utils.encrypt(param.LText, param.timestamp)
 
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       _resolve()
       if (!res.status) {
         Modal.warning({
diff --git a/src/menu/viewnodes/index.jsx b/src/menu/viewnodes/index.jsx
index ec0fd77..d69598b 100644
--- a/src/menu/viewnodes/index.jsx
+++ b/src/menu/viewnodes/index.jsx
@@ -36,7 +36,7 @@
         par_menuid: MenuId
       }
 
-      Api.getSystemConfig(param).then(result => {
+      Api.getCloudConfig(param).then(result => {
         if (!result.status) {
           notification.warning({
             top: 92,
diff --git a/src/mob/colorsketch/index.jsx b/src/mob/colorsketch/index.jsx
index 63abecf..35822cb 100644
--- a/src/mob/colorsketch/index.jsx
+++ b/src/mob/colorsketch/index.jsx
@@ -4,6 +4,7 @@
 import { Popover } from 'antd'
 import { CloseCircleFilled } from '@ant-design/icons'
 
+import Api from '@/api'
 import './index.scss'
 
 const presetColors = [
@@ -12,6 +13,7 @@
   '#adc6ff', '#EBE9E9', '#d9d9d9', 'rgba(0, 0, 0, 0.65)', 'rgba(0, 0, 0, 0.85)', '#000000', '#ffffff', 'transparent'
 ]
 const _href = window.location.href.split('#')[0]
+let loading = false
 
 class ColorSketch extends Component {
   static propTpyes = {
@@ -38,7 +40,39 @@
       initVal = value
     }
 
-    let _colors = sessionStorage.getItem('app_colors')
+    this.setState({color: initVal, initVal, allowClear: allowClear === true}, () => {
+      this.checkcolors()
+    })
+  }
+
+  checkcolors = () => {
+    let app_colors = window.GLOB.app_colors
+
+    if (app_colors) {
+      this.getColors(app_colors)
+    } else {
+      if (loading) {
+        this.getColors([])
+      } else {
+        loading = true
+        let param = {
+          func: 's_url_db_adduptdel',
+          PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
+          PageSize: 0,   // 0 浠h〃鍏ㄩ儴
+          typecharone: 'color',
+          type: 'search'
+        }
+  
+        Api.getCloudConfig(param).then(res => {
+          loading = false
+          window.GLOB.app_colors = res.data || []
+          this.getColors(res.data || [])
+        })
+      }
+    }
+  }
+
+  getColors = (appColors) => {
     let colors = JSON.parse(JSON.stringify(presetColors))
     let normal_colors = localStorage.getItem(_href + 'normal_colors')
 
@@ -56,19 +90,11 @@
       normal_colors = []
     }
 
-    if (_colors) {
-      try {
-        _colors = JSON.parse(_colors)
-      } catch (e) {
-        _colors = []
-      }
+    appColors.forEach(item => {
+      if (normal_colors.includes(item.linkurl)) return
       
-      _colors.forEach(item => {
-        if (normal_colors.includes(item.linkurl)) return
-        
-        colors.push({color: item.linkurl, title: '绯荤粺鑹诧細' + item.linkurl})
-      })
-    }
+      colors.push({color: item.linkurl, title: '绯荤粺鑹诧細' + item.linkurl})
+    })
 
     if (colors.length < 40) {
       for (let i = colors.length; i < 40; i++) {
@@ -76,7 +102,7 @@
       }
     }
 
-    this.setState({color: initVal, initVal, allowClear: allowClear === true, colors})
+    this.setState({colors})
   }
 
   handleChange = (color) => {
@@ -126,8 +152,6 @@
       localStorage.setItem(_href + 'normal_colors', JSON.stringify(normal_colors))
     }
   }
-
-  
 
   render() {
     const { color, allowClear, colors } = this.state
diff --git a/src/mob/components/formdragelement/index.scss b/src/mob/components/formdragelement/index.scss
index 5aeda26..2798a34 100644
--- a/src/mob/components/formdragelement/index.scss
+++ b/src/mob/components/formdragelement/index.scss
@@ -8,8 +8,10 @@
     padding-left: 0px;
     padding-right: 0px;
   }
-  >.ant-col:not(.ant-col-24) {
+  >.ant-col {
     padding-right: 10px;
+  }
+  >.ant-col:not(.ant-col-24) {
     .am-list-line .am-input-label {
       width: auto;
       padding-right: 10px;
diff --git a/src/mob/components/menubar/normal-menubar/index.jsx b/src/mob/components/menubar/normal-menubar/index.jsx
index df95f23..016fd2f 100644
--- a/src/mob/components/menubar/normal-menubar/index.jsx
+++ b/src/mob/components/menubar/normal-menubar/index.jsx
@@ -16,7 +16,6 @@
 const MenuComponent = asyncComponent(() => import('./menucomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
-const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
 
@@ -60,20 +59,6 @@
         }]
       }
 
-      if (card.config) {
-        let config = fromJS(card.config).toJS()
-
-        _card.wrap = config.wrap
-        _card.wrap.name = card.name
-        _card.style = config.style
-        _card.headerStyle = config.headerStyle
-
-        _card.subMenus = config.subMenus.map(item => {
-          item.uuid = Utils.getuuid()
-          
-          return item
-        })
-      }
       this.setState({
         card: _card
       })
@@ -298,7 +283,6 @@
             <CopyComponent type="menubar" card={card}/>
             <PasteComponent config={card} options={['menucell']} updateConfig={this.filterComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} />
-            <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
             {card.wrap.datatype !== 'dynamic' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
diff --git a/src/mob/components/tabs/antv-tabs/index.jsx b/src/mob/components/tabs/antv-tabs/index.jsx
index 45181e1..fdd6b21 100644
--- a/src/mob/components/tabs/antv-tabs/index.jsx
+++ b/src/mob/components/tabs/antv-tabs/index.jsx
@@ -226,8 +226,6 @@
   }
 
   getTabForms = (tab) => {
-    const { tabs } = this.state
-
     if (!tab) {
       tab = {
         uuid: '',
@@ -241,7 +239,7 @@
       editab: tab
     })
 
-    return getTabForm(tab, tabs.setting)
+    return getTabForm(tab)
   }
 
   updateTab = (res) => {
@@ -252,7 +250,7 @@
     editab.icon = res.icon
     editab.hide = res.hide || 'false'
     editab.backgroundColor = res.backgroundColor
-    editab.controlVal = res.controlVal || ''
+    // editab.controlVal = res.controlVal || ''
     editab.selectVal = res.selectVal || ''
     editab.blacklist = res.blacklist
 
@@ -280,11 +278,27 @@
   getTabsForms = () => {
     const { tabs } = this.state
 
-    return getTabsSetForm(tabs.setting, tabs.uuid)
+    return getTabsSetForm(tabs.setting, tabs.uuid, tabs.subtabs)
   }
 
   updateTabs = (res) => {
-    this.updateComponent({...this.state.tabs, setting: res})
+    let tabs = fromJS(this.state.tabs).toJS()
+
+    if (res.controlVals) {
+      let values = {}
+      res.controlVals.forEach(item => {
+        values[item.uuid] = item.value
+      })
+      tabs.subtabs.forEach(tab => {
+        tab.controlVal = values[tab.uuid]
+      })
+
+      delete res.controlVals
+    }
+
+    tabs.setting = res
+
+    this.updateComponent(tabs)
   }
 
   onChange = (key) => {
diff --git a/src/mob/components/tabs/antv-tabs/options.jsx b/src/mob/components/tabs/antv-tabs/options.jsx
index 9c4ddc7..3fe37fb 100644
--- a/src/mob/components/tabs/antv-tabs/options.jsx
+++ b/src/mob/components/tabs/antv-tabs/options.jsx
@@ -3,8 +3,7 @@
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
  */
-export function getTabForm(tab, setting) {
-  // let appType = sessionStorage.getItem('appType')
+export function getTabForm(tab) {
   let roleList = sessionStorage.getItem('sysRoles')
 
   if (roleList) {
@@ -34,14 +33,14 @@
       required: false,
       allowClear: true,
     },
-    {
-      type: 'text',
-      field: 'controlVal',
-      label: '闅愯棌鏍囪',
-      initval: tab.controlVal || '',
-      tooltip: '褰撶鐢ㄥ瓧娈靛�间笌闅愯棌鏍囪鐩哥瓑鏃讹紝鏍囩椤典細闅愯棌銆傛敞锛氬涓�艰鐢ㄩ�楀彿鍒嗛殧銆�',
-      required: false
-    },
+    // {
+    //   type: 'text',
+    //   field: 'controlVal',
+    //   label: '闅愯棌鏍囪',
+    //   initval: tab.controlVal || '',
+    //   tooltip: '褰撶鐢ㄥ瓧娈靛�间笌闅愯棌鏍囪鐩哥瓑鏃讹紝鏍囩椤典細闅愯棌銆傛敞锛氬涓�艰鐢ㄩ�楀彿鍒嗛殧銆�',
+    //   required: false
+    // },
     {
       type: 'text',
       field: 'selectVal',
@@ -67,16 +66,7 @@
         {value: 'false', label: '鍚�'},
         {value: 'true', label: '鏄�'},
       ],
-    },
-    // {
-    //   type: 'multiselect',
-    //   field: 'blacklist',
-    //   label: '榛戝悕鍗�',
-    //   initval: tab.blacklist || [],
-    //   required: false,
-    //   options: roleList,
-    //   forbid: !!appType,
-    // },
+    }
   ]
 
   return tabForm
@@ -85,12 +75,14 @@
 /**
  * @description tabs琛ㄥ崟閰嶇疆淇℃伅
  */
-export function getTabsSetForm(setting, uuid) {
+export function getTabsSetForm(setting, uuid, subtabs) {
   let modules = MenuUtils.getSupModules(window.GLOB.customMenu.components, uuid, window.GLOB.customMenu.interfaces)
   modules.push({
     value: 'preview',
     label: '涓婁竴椤碉紙url鍙傛暟锛�'
   })
+
+  let controlVals = subtabs.map(item => ({uuid: item.uuid, label: item.label, value: item.controlVal}))
 
   const tabForm = [
     {
@@ -112,22 +104,6 @@
       precision: 0,
       required: true
     },
-    // {
-    //   type: 'select',
-    //   field: 'position',
-    //   label: '鏍囩浣嶇疆',
-    //   initval: setting.position || 'top',
-    //   required: true,
-    //   options: [
-    //     {value: 'top', label: 'top'},
-    //     {value: 'bottom', label: 'bottom'},
-    //     {value: 'left', label: 'left'},
-    //     {value: 'right', label: 'right'},
-    //   ],
-    //   controlFields: [
-    //     {field: 'display', values: ['top', 'bottom']},
-    //   ]
-    // },
     {
       type: 'radio',
       field: 'display',
@@ -151,6 +127,7 @@
       options: modules,
       controlFields: [
         {field: 'controlField', notNull: true},
+        {field: 'controlVals', notNull: true},
         {field: 'swiper', values: ['']},
       ],
     },
@@ -200,6 +177,33 @@
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
     },
+    {
+      type: 'table',
+      field: 'controlVals',
+      label: '鏍囩缁�',
+      initval: controlVals,
+      tooltip: '褰撶鐢ㄥ瓧娈靛�间笌闅愯棌鏍囪鐩哥瓑鏃讹紝鏍囩椤典細闅愯棌銆傛敞锛�1銆佸涓�艰鐢ㄩ�楀彿鍒嗛殧锛�2銆丂pass@鍊艰〃绀哄拷鐣ユ璁剧疆锛堝缁堟樉绀猴級锛�2銆丂pass_empty@鍊艰〃绀哄拷鐣ョ┖鍊硷紝鍗虫湭鑾峰彇涓婄骇缁勪欢淇℃伅鏃舵樉绀猴紙鍙笌鍏朵粬鍊兼嫾鎺ワ級銆�',
+      required: false,
+      fixed: true,
+      span: 24,
+      columns: [
+        {
+          title: '鏍囩鍚嶇О',
+          dataIndex: 'label',
+          editable: false,
+          required: false,
+          width: '30%'
+        },
+        {
+          title: '闅愯棌鏍囪',
+          dataIndex: 'value',
+          inputType: 'input',
+          editable: true,
+          required: false,
+          width: '50%'
+        }
+      ]
+    }
   ]
 
   return tabForm
diff --git a/src/mob/components/tabs/tabcomponents/card.jsx b/src/mob/components/tabs/tabcomponents/card.jsx
index 24dc025..f150bd4 100644
--- a/src/mob/components/tabs/tabcomponents/card.jsx
+++ b/src/mob/components/tabs/tabcomponents/card.jsx
@@ -63,6 +63,8 @@
 
   if (card.style && card.style.clear === 'left') {
     style.clear = 'left'
+  } else if (card.style && card.style.clear === 'right') {
+    style.float = 'right'
   }
 
   const getCardComponent = () => {
diff --git a/src/mob/mobshell/card.jsx b/src/mob/mobshell/card.jsx
index fdca2fd..ca91322 100644
--- a/src/mob/mobshell/card.jsx
+++ b/src/mob/mobshell/card.jsx
@@ -70,6 +70,8 @@
 
   if (card.style && card.style.clear === 'left') {
     style.clear = 'left'
+  } else if (card.style && card.style.clear === 'right') {
+    style.float = 'right'
   }
 
   let col = 'ant-col-' + (card.width || 24)
diff --git a/src/mob/modalconfig/index.jsx b/src/mob/modalconfig/index.jsx
index 285307a..c33da82 100644
--- a/src/mob/modalconfig/index.jsx
+++ b/src/mob/modalconfig/index.jsx
@@ -137,23 +137,22 @@
     let _linkableFields = []
     let _linksupFields = []
     let standardform = null
-
-    let uniq = new Map()
     let index = null
-    uniq.set(card.field, true)
 
     config.fields.forEach((item, i) => {
       if (card.uuid === item.uuid) {
         index = i
       }
 
-      if (['text', 'number', 'textarea', 'color'].includes(item.type) && card.field !== item.field) {
+      if (!item.field || card.field === item.field) return
+
+      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
         _inputfields.push({
           field: item.field,
           label: item.label
         })
       }
-      if (card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
+      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
         _tabfields.push({
           field: item.field,
           label: item.label
@@ -168,19 +167,18 @@
       }
 
       if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return
-      if (item.type === 'checkcard' && item.multiple === 'true') return // 閫夐」鍗″閫�
-      if (item.field && !uniq.has(item.field)) {
-        uniq.set(item.field, true)
 
-        _linkableFields.push({
-          field: item.field,
-          label: item.label + '-琛ㄥ崟'
-        })
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
+      _linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+
+      if (item.type === 'checkcard' && item.multiple === 'true') return
+
+      _linkableFields.push({
+        field: item.field,
+        label: item.label + '-琛ㄥ崟'
+      })
     })
 
     if (index !== null) {
@@ -196,10 +194,9 @@
       columns = componentConfig.subColumns || []
     }
 
+    let _fields = _linkableFields.map(cell => cell.field)
     columns.forEach(col => {
-      if (col.field && !uniq.has(col.field)) {
-        uniq.set(col.field, true)
-
+      if (col.field && !_fields.includes(col.field)) {
         _linkableFields.push({
           field: col.field,
           label: col.label + '-鏄剧ず鍒�'
@@ -525,6 +522,7 @@
         </DndProvider>
         <Modal
           title={card && card.$copy ? '澶嶅埗' : '缂栬緫'}
+          wrapClassName="mk-scroll-modal"
           visible={this.state.visible}
           width={950}
           maskClosable={false}
diff --git a/src/mob/modulesource/dragsource/index.jsx b/src/mob/modulesource/dragsource/index.jsx
index 5e00912..8e60670 100644
--- a/src/mob/modulesource/dragsource/index.jsx
+++ b/src/mob/modulesource/dragsource/index.jsx
@@ -1,13 +1,12 @@
 import React from 'react'
 import { useDrag } from 'react-dnd'
-import { CloseCircleOutlined } from '@ant-design/icons'
 import './index.scss'
 
-const MobSourceElement = ({item, triggerDel}) => {
+const MobSourceElement = ({item}) => {
   const [, drag] = useDrag({ item })
   return (
     <div className={'menu-source-item ' + item.component + '-' + item.subtype}>
-      <div className="property"><span>{item.title}</span>{item.config ? <CloseCircleOutlined onClick={() => triggerDel(item)}/> : null}</div>
+      <div className="property"><span>{item.title}</span></div>
       <img ref={drag} src={item.url} alt=""/>
     </div>
   )
diff --git a/src/mob/modulesource/index.jsx b/src/mob/modulesource/index.jsx
index debf9c8..3e9ecbc 100644
--- a/src/mob/modulesource/index.jsx
+++ b/src/mob/modulesource/index.jsx
@@ -1,14 +1,9 @@
 import React, {Component} from 'react'
 import { is, fromJS } from 'immutable'
-import { Modal, notification } from 'antd'
 
-import Api from '@/api'
 import { menuOptions } from './option'
 import SourceWrap from './dragsource'
-import MKEmitter from '@/utils/events.js'
 import './index.scss'
-
-const { confirm } = Modal
 
 class ModelSource extends Component {
   state = {
@@ -38,54 +33,8 @@
     })
   }
 
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (nextProps.components && !is(fromJS(this.props.components), fromJS(nextProps.components))) {
-      this.setState({
-        menuOptions: fromJS(nextProps.components).toJS()
-      })
-    }
-  }
-
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  triggerDel = (item) => {
-    confirm({
-      title: `纭畾鍒犻櫎<${item.title}>鍚楋紵`,
-      content: '',
-      onOk() {
-        return new Promise(resolve => {
-          Api.getSystemConfig({
-            func: 's_custom_components_adduptdel',
-            c_id: item.uuid,
-            images: '',
-            c_name: item.title,
-            typename: sessionStorage.getItem('appType') || '',
-            long_param: '',
-            del_type: 'Y'
-          }).then(result => {
-            if (result.status) {
-              notification.success({
-                top: 92,
-                message: '鍒犻櫎鎴愬姛锛�',
-                duration: 5
-              })
-
-              MKEmitter.emit('updateCustomComponent')
-            } else {
-              notification.warning({
-                top: 92,
-                message: result.message,
-                duration: 5
-              })
-            }
-            resolve()
-          })
-        })
-      },
-      onCancel() {}
-    })
   }
 
   render() {
@@ -93,7 +42,7 @@
 
     return (
       <div className="mob-card-source-box">
-        {menuOptions.map((item, index) => (<SourceWrap key={index} item={item} triggerDel={this.triggerDel} />))}
+        {menuOptions.map((item, index) => (<SourceWrap key={index} item={item}/>))}
       </div>
     )
   }
diff --git a/src/mob/searchconfig/searchdragelement/card.jsx b/src/mob/searchconfig/searchdragelement/card.jsx
index 13080ed..1a469a8 100644
--- a/src/mob/searchconfig/searchdragelement/card.jsx
+++ b/src/mob/searchconfig/searchdragelement/card.jsx
@@ -91,27 +91,6 @@
         </div>
       </div>
     </div>)
-  // } else if (card.type === 'daterange') {
-  //   let value = '璇烽�夋嫨'
-  //   if (card.initval === 'week') {
-  //     value = [moment().startOf('week').format('YYYY-MM-DD'), moment().endOf('week').format('YYYY-MM-DD')].join(' ~ ')
-  //   } else if (card.initval === 'month') {
-  //     value = [moment().startOf('month').format('YYYY-MM-DD'), moment().endOf('month').format('YYYY-MM-DD')].join(' ~ ')
-  //   } else if (card.initval) {
-  //     try {
-  //       let _initval = JSON.parse(card.initval)
-  //       value = [moment().subtract(_initval[0], 'days').format('YYYY-MM-DD'), moment().subtract(_initval[1], 'days').format('YYYY-MM-DD')].join(' ~ ')
-  //     } catch (e) {
-  //       value = '璇烽�夋嫨'
-  //     }
-  //   }
-  //   formItem = (<div className="am-list-item">
-  //     <div className="am-list-line">
-  //       {card.labelShow !== 'false' ? <div className="am-input-label">{card.label}</div> : null}
-  //       <div className="am-input-control">{value}</div>
-  //       <div className="am-list-extra"><RightOutlined /></div>
-  //     </div>
-  //   </div>)
   } else if (card.type === 'checkcard') {
     formItem = (<div className="am-list-item check-card">
       <div className="am-list-line">
diff --git a/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.scss b/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.scss
index 120837c..d0c38eb 100644
--- a/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.scss
+++ b/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.scss
@@ -31,8 +31,8 @@
   tr:not(.classify) + .ant-table-expanded-row {
     display: none;
   }
-  td[colspan="6"] {
-    padding: 5px 0px 5px 5px!important;
+  td[colspan="5"] {
+    padding: 5px 0px 5px 0px!important;
   }
   .ant-table-body {
     margin: 0!important;
diff --git a/src/pc/createview/index.jsx b/src/pc/createview/index.jsx
index be5bdec..856e54c 100644
--- a/src/pc/createview/index.jsx
+++ b/src/pc/createview/index.jsx
@@ -97,7 +97,7 @@
       if (!res.copymenuId) {
         param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
 
-        Api.getSystemConfig(param).then(result => {
+        Api.getCloudConfig(param).then(result => {
           if (!result.status) {
             notification.warning({
               top: 92,
@@ -120,7 +120,7 @@
           this.props.resetmenu()
         })
       } else {
-        Api.getSystemConfig({
+        Api.getCloudConfig({
           func: 'sPC_Get_LongParam',
           TypeCharOne: sessionStorage.getItem('kei_no'),
           typename: sessionStorage.getItem('typename') || 'pc',
@@ -179,7 +179,7 @@
   
           param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
 
-          Api.getSystemConfig(param).then(result => {
+          Api.getCloudConfig(param).then(result => {
             if (!result.status) {
               notification.warning({
                 top: 92,
diff --git a/src/pc/menushell/card.jsx b/src/pc/menushell/card.jsx
index 7cdc671..037187a 100644
--- a/src/pc/menushell/card.jsx
+++ b/src/pc/menushell/card.jsx
@@ -69,6 +69,8 @@
 
   if (card.style && card.style.clear === 'left') {
     style.clear = 'left'
+  } else if (card.style && card.style.clear === 'right') {
+    style.float = 'right'
   }
   
   let col = ' ant-col ant-col-' + (card.width || 24)
diff --git a/src/pc/modulesource/dragsource/index.jsx b/src/pc/modulesource/dragsource/index.jsx
index 7b5a6ea..290d9b2 100644
--- a/src/pc/modulesource/dragsource/index.jsx
+++ b/src/pc/modulesource/dragsource/index.jsx
@@ -1,13 +1,12 @@
 import React from 'react'
 import { useDrag } from 'react-dnd'
-import { CloseCircleOutlined } from '@ant-design/icons'
 import './index.scss'
 
-const MobSourceElement = ({item, triggerDel}) => {
+const MobSourceElement = ({item}) => {
   const [, drag] = useDrag({ item })
   return (
     <div className="menu-source-item">
-      <div className="property"><span>{item.title}</span>{item.config ? <CloseCircleOutlined onClick={() => triggerDel(item)}/> : null}</div>
+      <div className="property"><span>{item.title}</span></div>
       <img ref={drag} src={item.url} alt=""/>
     </div>
   )
diff --git a/src/pc/modulesource/index.jsx b/src/pc/modulesource/index.jsx
index f84cdd7..feabed5 100644
--- a/src/pc/modulesource/index.jsx
+++ b/src/pc/modulesource/index.jsx
@@ -1,14 +1,9 @@
 import React, {Component} from 'react'
 import { is, fromJS } from 'immutable'
-import { Modal, notification } from 'antd'
 
-import Api from '@/api'
 import { menuOptions } from './option'
 import SourceWrap from './dragsource'
-import MKEmitter from '@/utils/events.js'
 import './index.scss'
-
-const { confirm } = Modal
 
 class ModelSource extends Component {
   state = {
@@ -30,54 +25,8 @@
     })
   }
 
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (nextProps.components && !is(fromJS(this.props.components), fromJS(nextProps.components))) {
-      this.setState({
-        menuOptions: fromJS(nextProps.components).toJS()
-      })
-    }
-  }
-
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  triggerDel = (item) => {
-    confirm({
-      title: `纭畾鍒犻櫎<${item.title}>鍚楋紵`,
-      content: '',
-      onOk() {
-        return new Promise(resolve => {
-          Api.getSystemConfig({
-            func: 's_custom_components_adduptdel',
-            c_id: item.uuid,
-            images: '',
-            c_name: item.title,
-            typename: sessionStorage.getItem('appType') || '',
-            long_param: '',
-            del_type: 'Y'
-          }).then(result => {
-            if (result.status) {
-              notification.success({
-                top: 92,
-                message: '鍒犻櫎鎴愬姛锛�',
-                duration: 5
-              })
-
-              MKEmitter.emit('updateCustomComponent')
-            } else {
-              notification.warning({
-                top: 92,
-                message: result.message,
-                duration: 5
-              })
-            }
-            resolve()
-          })
-        })
-      },
-      onCancel() {}
-    })
   }
 
   render() {
@@ -85,7 +34,7 @@
 
     return (
       <div className="mob-card-source-box">
-        {menuOptions.map((item, index) => (<SourceWrap key={index} item={item} triggerDel={this.triggerDel} />))}
+        {menuOptions.map((item, index) => (<SourceWrap key={index} item={item}/>))}
       </div>
     )
   }
diff --git a/src/pc/quotecomponent/index.jsx b/src/pc/quotecomponent/index.jsx
index 11a7a0e..271fc60 100644
--- a/src/pc/quotecomponent/index.jsx
+++ b/src/pc/quotecomponent/index.jsx
@@ -45,7 +45,7 @@
         return
       }
 
-      Api.getSystemConfig({
+      Api.getCloudConfig({
         func: 'sPC_Get_LongParam',
         TypeCharOne: sessionStorage.getItem('kei_no'),
         typename: sessionStorage.getItem('typename') || 'pc',
diff --git a/src/router/index.js b/src/router/index.js
index 5a7b168..b66adb6 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -24,6 +24,7 @@
 const RoleManage = asyncLoadComponent(() => import('@/views/rolemanage'))
 const SystemFunc = asyncLoadComponent(() => import('@/views/systemfunc'))
 const SystemProc = asyncLoadComponent(() => import('@/views/systemproc'))
+const MkIframe = asyncLoadComponent(() => import('@/views/mkiframe'))
 
 const routers = [
   {path: '/login', name: 'login', component: Login},
@@ -47,6 +48,11 @@
   {path: '/role/:param', name: 'role', component: RoleManage},
   {path: '/hs', name: 'hs', component: SystemFunc},
   {path: '/proc', name: 'proc', component: SystemProc},
+  {path: '/proc/:func', name: 'proc', component: SystemProc},
+  {path: '/iframe/:menuId/:loginUid', name: 'iframe', component: MkIframe},
+  {path: '/iframe/:menuId/:loginUid/:bid', name: 'iframe', component: MkIframe},
+  {path: '/view/:menuId', name: 'iframe', component: MkIframe},
+  {path: '/view/:menuId/:bid', name: 'iframe', component: MkIframe},
   {path: '/interface', name: 'interface', component: Interface}
 ]
 
diff --git a/src/store/action-type.js b/src/store/action-type.js
deleted file mode 100644
index 9443fa6..0000000
--- a/src/store/action-type.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// 鍒濆鍖栬彍鍗曚俊鎭�
-export const MODIFY_MENUTREE = 'MODIFY_MENUTREE'
-
-// 鍒囨崲涓昏彍鍗�
-export const MODIFY_MAINMENU = 'MODIFY_MAINMENU'
-
-// 灞曞紑鍚堝苟鑿滃崟鏍�
-export const Toggle_COLLAPSE = 'Toggle_COLLAPSE'
-
-// 鍒锋柊tab椤甸潰
-export const REFRESH_TABVIEW = 'REFRESH_TABVIEW'
-
-// 閲嶇疆缂栬緫绾у埆
-export const RESET_EDITLEVEL = 'RESET_EDITLEVEL'
-
-// 閫�鍑�
-export const LOGOUT = 'LOGOUT'
\ No newline at end of file
diff --git a/src/store/action.js b/src/store/action.js
deleted file mode 100644
index c0115e7..0000000
--- a/src/store/action.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import * as user from './action-type'
-
-// 灞曞紑鍚堝苟鑿滃崟鏍�
-export const toggleCollapse = (collapse) => {
-  return {
-    type: user.Toggle_COLLAPSE,
-    collapse
-  }
-}
-
-// 鍒濆鍖栬彍鍗曚俊鎭�
-export const modifyMenuTree = (menuTree) => {
-  return {
-    type: user.MODIFY_MENUTREE,
-    menuTree
-  }
-}
-
-// 鍒囨崲涓昏彍鍗�
-export const modifyMainMenu = (mainMenu) => {
-  return {
-    type: user.MODIFY_MAINMENU,
-    mainMenu
-  }
-}
-
-// 閲嶇疆缂栬緫绾у埆
-export const resetEditLevel = (editLevel) => {
-  return {
-    type: user.RESET_EDITLEVEL,
-    editLevel
-  }
-}
-
-// 閫�鍑洪噸缃�
-export const logout = () => {
-  return {
-    type: user.LOGOUT
-  }
-}
\ No newline at end of file
diff --git a/src/store/index.js b/src/store/index.js
deleted file mode 100644
index 4407580..0000000
--- a/src/store/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import {createStore, applyMiddleware} from 'redux'
-import userReducer from './reducer'
-import thunk from 'redux-thunk'
-
-let store = createStore(
-  userReducer,
-  applyMiddleware(thunk)
-)
-
-export default store
\ No newline at end of file
diff --git a/src/store/options.js b/src/store/options.js
index 1b159bc..8f3ebd5 100644
--- a/src/store/options.js
+++ b/src/store/options.js
@@ -2,14 +2,13 @@
  * @description 绯荤粺淇℃伅
  * 1銆亂un ( Y2xv$mkdWQ= ) 銆� dandian ( U1$mkNP ) 銆� yewu ( bG9j$mkYWw= )
  * 2銆亀indow.btoa('') 鍩熷悕 涓嶅甫 /
- * 3銆乥aoshide old ( aHR0cDovL2Nsb3VkLnBv$mkc2l0ZWNncm91cC5jb206ODA4MA== )
- * 4銆乸ositecgroup ( aHR0cHM6Ly9jbG91ZC5$mkwb3NpdGVjZ3JvdXAuY29t )
+ * 3銆乸ositecgroup ( aHR0cHM6Ly9jbG91ZC5$mkwb3NpdGVjZ3JvdXAuY29t )
  */
 export default {
-  sysType: 'bG9j$mkYWw=',
-  caId: 'MjAyMDAxMTYxMjMzMzU1MDd$mkGQzkyMzI1Rjk4MDY0QUNGQjQ2Mg==',
-  cakey: 'MjAyMDAxMTYxMjQwMDQ2NDM$mk2N0QzODE2MjExNUI0MTc4OTVDMQ==',
-  cdomain: 'aHR0cHM6Ly9jbG91ZC5$mkwb3NpdGVjZ3JvdXAuY29t'
+  sysType: window.atob('bG9j$mkYWw='.replace('$mk', '')),
+  caId: window.atob('MjAyMDAxMTYxMjMzMzU1MDd$mkGQzkyMzI1Rjk4MDY0QUNGQjQ2Mg=='.replace('$mk', '')),
+  cakey: window.atob('MjAyMDAxMTYxMjQwMDQ2NDM$mk2N0QzODE2MjExNUI0MTc4OTVDMQ=='.replace('$mk', '')),
+  cdomain: window.atob('aHR0cHM6Ly9jbG91ZC5$mkwb3NpdGVjZ3JvdXAuY29t'.replace('$mk', ''))
 }
 
 /**
diff --git a/src/store/reducer.js b/src/store/reducer.js
deleted file mode 100644
index b33716d..0000000
--- a/src/store/reducer.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import * as Type from './action-type'
-
-let _mainMenu = null
-let _collapse = localStorage.getItem('collapse') === 'true'
-
-let defaultState = {
-  menuTree: null,       // 鑿滃崟缁撴瀯鏍�
-  mainMenu: _mainMenu,  // 宸查�変富鑿滃崟
-  collapse: _collapse,  // 鏄惁鏀惰捣渚ц竟鏍忓鑸�
-  editLevel: null,      // 缂栬緫鑿滃崟绾у埆锛屽�间负level1銆乴evel2銆乴evel3銆丠S
-}
-
-// 鐢ㄦ埛娑堟伅
-export default (state = defaultState, action = {}) => {
-  switch (action.type) {
-    case Type.Toggle_COLLAPSE:
-    // 鍒囨崲鑿滃崟鏍忓睍寮�鍚堝苟鐘舵��
-      return {
-        ...state,
-        collapse: action.collapse
-      }
-    case Type.MODIFY_MENUTREE:
-    // 鍒濆鍖栬彍鍗曚俊鎭�
-      return {
-        ...state,
-        menuTree: action.menuTree
-      }
-    case Type.MODIFY_MAINMENU:
-    // 鍒囨崲涓昏彍鍗�
-      return {
-        ...state,
-        mainMenu: action.mainMenu
-      }
-    case Type.RESET_EDITLEVEL:
-    // 閲嶇疆缂栬緫绾у埆
-      return {
-        ...state,
-        editLevel: action.editLevel
-      }
-    case Type.LOGOUT:
-      return {
-        menuTree: null,
-        mainMenu: null,
-        collapse: localStorage.getItem('collapse') === 'true',
-        editLevel: null
-      }
-    default:
-      return state
-  }
-}
diff --git a/src/tabviews/basetable/index.jsx b/src/tabviews/basetable/index.jsx
index 59932b9..4f0028e 100644
--- a/src/tabviews/basetable/index.jsx
+++ b/src/tabviews/basetable/index.jsx
@@ -4,8 +4,6 @@
 import { notification, Spin, Row, Col } from 'antd'
 
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import Utils from '@/utils/utils.js'
 import asyncComponent from '@/utils/asyncComponent'
 import MKEmitter from '@/utils/events.js'
@@ -25,22 +23,18 @@
     param: PropTypes.any,        // 鍏朵粬椤甸潰浼犻�掔殑鍙傛暟
     Tab: PropTypes.string,       // 寮圭獥鏍囩
     MenuID: PropTypes.string,    // 鑿滃崟Id
-    MenuNo: PropTypes.string,    // 鑿滃崟鍙傛暟
     MenuName: PropTypes.string,  // 鑿滃崟鍚嶇О
     changeTemp: PropTypes.func
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id
     BID: '',              // 椤甸潰璺宠浆鏃舵惡甯D
     loadingview: true,    // 椤甸潰鍔犺浇涓�
     viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
     lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
     config: null,         // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷粍浠剁瓑
-    mainSearch: null,     // 涓绘悳绱�
     userConfig: null,     // 鐢ㄦ埛鑷畾涔夎缃�
-    data: null,           // 鍒楄〃鏁版嵁闆�
     loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
     visible: false,       // 鏍囩椤垫帶鍒�
     shortcuts: null,      // 蹇嵎閿�
@@ -51,12 +45,13 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { MenuID } = this.props
+    const { MenuID, MenuName } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
       MenuID: MenuID
     }
+    
     let result = await Api.getCacheConfig(_param)
 
     if (result.status) {
@@ -67,6 +62,8 @@
         config = window.decodeURIComponent(window.atob(result.LongParam))
         config = config.replace(/@mywebsite@\//ig, window.GLOB.baseurl)
         config = JSON.parse(config)
+        config.MenuID = MenuID
+        config.MenuName = MenuName || config.MenuName
       } catch (e) {
         console.warn('Parse Failure')
         config = ''
@@ -86,7 +83,7 @@
         this.setState({
           viewlost: true,
           loadingview: false,
-          lostmsg: this.state.dict['main.view.unenabled']
+          lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
         })
         return
       }
@@ -130,11 +127,6 @@
       let userName = sessionStorage.getItem('User_Name') || ''
       let fullName = sessionStorage.getItem('Full_Name') || ''
 
-      if (sessionStorage.getItem('isEditState') === 'true') {
-        userName = sessionStorage.getItem('CloudUserName') || ''
-        fullName = sessionStorage.getItem('CloudFullName') || ''
-      }
-
       let regs = [
         { reg: /@userName@/ig, value: `'${userName}'` },
         { reg: /@fullName@/ig, value: `'${fullName}'` }
@@ -156,7 +148,7 @@
         })
       }
 
-      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, skip, param, MenuID)
+      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, skip, param, MenuID, config.MenuName)
 
       let autoMatic = null
       if (config.autoMatic && config.autoMatic.enable === 'true') {
@@ -173,32 +165,41 @@
       }
       
       // 鑾峰彇涓绘悳绱㈡潯浠�
-      let mainSearch = []
       config.components.forEach(component => {
         if (component.type === 'tabs') return
 
-        component.search = component.search.map(item => {
-          item.oriInitval = item.initval
-          if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
-            item.initval = param.$searchval
+        if (param.$searchkey) {
+          component.search = component.search.map(item => {
+            if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
+              item.initval = param.$searchval
+            }
+  
+            return item
+          })
+
+          component.$searches = Utils.initMainSearch(component.search)
+        }
+
+        if (component.$searches.length) {
+          component.$main = true
+          
+          window.GLOB.SearchBox.set(MenuID, component.$searches)
+  
+          if (component.$s_req) {
+            window.GLOB.SearchBox.set(MenuID + 'required', true)
           }
-
-          return item
-        })
-
-        mainSearch = Utils.initMainSearch(component.search)
+        }
       })
 
       let BID = param.$BID || ''
 
-      config.components = this.formatSetting(config.components, mainSearch, regs)
+      config.components = this.formatSetting(config.components, regs)
 
       this.setState({
         BID: BID,
         shortcuts: shortcuts.length > 0 ? shortcuts : null,
         config,
-        autoMatic,
-        mainSearch
+        autoMatic
       }, () => {
         setTimeout(() => { // 寤舵椂鍔犺浇鐘舵��
           this.setState({
@@ -244,7 +245,6 @@
       let _shortcut = `${preKey}+${keyCode}`
 
       if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
-        window.debugger = false
         window.GLOB.breakpoint = false
         sessionStorage.removeItem('breakpoint')
         
@@ -263,11 +263,12 @@
     }
   }
 
-  filterComponent = (components, roleId, permAction, skip, urlparam, pageId) => {
+  filterComponent = (components, roleId, permAction, skip, urlparam, pageId, MenuName) => {
     return components.filter(item => {
       item.$pageId = pageId
+      item.$searchId = pageId
 
-      item.$menuname = (this.props.MenuName || '') + '-' + (item.name || '涓昏〃')
+      item.$menuname = (MenuName || '') + '-' + (item.name || '涓昏〃')
 
       if (item.type === 'tabs') {
         item.subtabs = item.subtabs.filter(tab => {
@@ -286,19 +287,19 @@
           if (tab.permission !== 'true') { // 鏉冮檺鏈紑鍚笉鍋氭潈闄愭帶鍒�
             skip = true
           }
-          tab.components = this.filterComponent(tab.components, roleId, permAction, skip, urlparam, pageId)
+          tab.components = this.filterComponent(tab.components, roleId, permAction, skip, urlparam, pageId, MenuName)
           return tab
         })
 
         return true
       } else {
-        item.name = (this.props.MenuName || '')
+        item.name = (MenuName || '')
       }
 
       // 鎼滅储鏉′欢鍒濆鍖�
-      if (item.search && item.search.length > 0) {
-        item.search = Utils.initSearchVal(item.search)
-      }
+      Utils.initSearchVal(item)
+
+      item.$searches = Utils.initMainSearch(item.search)
 
       if (item.setting.supModule) {
         let pid = item.setting.supModule.pop()
@@ -340,50 +341,10 @@
               if (cell.eleType === 'button') {
                 if (cell.hidden === 'true') return false
           
-                cell.logLabel = item.$menuname + '-' + cell.label
-                cell.Ot = cell.Ot || 'requiredSgl'
-                cell.ContainerId = this.state.ContainerId
-                cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
-                cell.$menuId = item.uuid
-                cell.$MenuID = this.props.MenuID
-                cell.$view = 'popview'
-
-                if (cell.syncComponentId) {
-                  if (cell.syncComponentId === item.setting.supModule) {
-                    cell.syncComponentId = ''
-                    if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                      cell.execSuccess = 'mainline'
-                    }
-                  } else if (cell.syncComponentId === 'multiComponent') {
-                    let ids = cell.syncComponents.map(m => {
-                      return m.syncComId.pop() || ''
-                    })
-            
-                    if (item.setting.supModule && ids.includes(item.setting.supModule)) {
-                      if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                        cell.execSuccess = 'mainline'
-                      }
-                      ids = ids.filter(id => id !== item.setting.supModule)
-                    }
-                    
-                    if (ids.length === 0) {
-                      cell.syncComponentId = ''
-                    } else {
-                      cell.syncComponentIds = ids
-                    }
-                  }
-                }
+                cell = this.resetButton(item, cell)
 
                 if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
                   cell = this.getPrinter(cell, item.uuid)
-                }
-
-                if (cell.controlField) {
-                  if (/,/ig.test(cell.controlVal)) {
-                    cell.controlVals = cell.controlVal.split(',')
-                  } else {
-                    cell.controlVals = [(cell.controlVal || '')]
-                  }
                 }
 
                 return skip || permAction[cell.uuid]
@@ -425,50 +386,12 @@
         item.action = item.action.filter(cell => {
           if (cell.hidden === 'true') return false
 
-          cell.logLabel = item.$menuname + '-' + cell.label
-          cell.ContainerId = this.state.ContainerId
-          cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
-          cell.$menuId = item.uuid
-          cell.$MenuID = this.props.MenuID
-          cell.$view = 'popview'
-          cell.$toolbtn = true
+          cell = this.resetButton(item, cell)
 
-          if (cell.syncComponentId) {
-            if (cell.syncComponentId === item.setting.supModule) {
-              cell.syncComponentId = ''
-              if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                cell.execSuccess = 'mainline'
-              }
-            } else if (cell.syncComponentId === 'multiComponent') {
-              let ids = cell.syncComponents.map(m => {
-                return m.syncComId.pop() || ''
-              })
-      
-              if (item.setting.supModule && ids.includes(item.setting.supModule)) {
-                if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                  cell.execSuccess = 'mainline'
-                }
-                ids = ids.filter(id => id !== item.setting.supModule)
-              }
-              
-              if (ids.length === 0) {
-                cell.syncComponentId = ''
-              } else {
-                cell.syncComponentIds = ids
-              }
-            }
-          }
+          cell.$toolbtn = true
 
           if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
             cell = this.getPrinter(cell, item.uuid)
-          }
-
-          if (cell.controlField) {
-            if (/,/ig.test(cell.controlVal)) {
-              cell.controlVals = cell.controlVal.split(',')
-            } else {
-              cell.controlVals = [(cell.controlVal || '')]
-            }
           }
 
           return skip || permAction[cell.uuid]
@@ -477,6 +400,62 @@
       
       return true
     })
+  }
+
+  resetButton = (item, cell) => {
+    cell.logLabel = item.$menuname + '-' + cell.label
+    cell.Ot = cell.Ot || 'requiredSgl'
+    cell.ContainerId = this.state.ContainerId
+    cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
+    cell.$menuId = item.uuid
+    cell.$MenuID = this.props.MenuID
+    cell.$view = 'popview'
+
+    if (cell.controlField) {
+      if (/,/ig.test(cell.controlVal)) {
+        cell.controlVals = cell.controlVal.split(',')
+      } else {
+        cell.controlVals = [(cell.controlVal || '')]
+      }
+    }
+
+    if (cell.OpenType === 'excelOut') { // 瀵煎嚭
+      cell.$menuName = item.name
+
+      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
+        cell.errorType = 'error1'
+      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom' && item.setting.interType !== 'system') {
+        cell.errorType = 'error2'
+      }
+    }
+
+    if (cell.syncComponentId) {
+      if (cell.syncComponentId === item.setting.supModule) {
+        cell.syncComponentId = ''
+        if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
+          cell.execSuccess = 'mainline'
+        }
+      } else if (cell.syncComponentId === 'multiComponent') {
+        let ids = cell.syncComponents.map(m => {
+          return m.syncComId.pop() || ''
+        })
+
+        if (item.setting.supModule && ids.includes(item.setting.supModule)) {
+          if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
+            cell.execSuccess = 'mainline'
+          }
+          ids = ids.filter(id => id !== item.setting.supModule)
+        }
+        
+        if (ids.length === 0) {
+          cell.syncComponentId = ''
+        } else {
+          cell.syncComponentIds = ids
+        }
+      }
+    }
+
+    return cell
   }
 
   getPrinter = (item, parentId) => {
@@ -509,7 +488,15 @@
         return component
       }
 
+      component.setting.arr_field = component.columns.map(col => col.field).join(',')
       component.setting.useMSearch = component.setting.useMSearch === 'true'
+      if (component.setting.useMSearch) {
+        if (!window.GLOB.SearchBox.has(component.$searchId)) {
+          component.setting.useMSearch = false
+        } else if (window.GLOB.SearchBox.has(component.$searchId + 'required')) {
+          component.$s_req = true
+        }
+      }
 
       if (component.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
         component.setting.sync = 'false'
@@ -518,9 +505,15 @@
       }
 
       let _customScript = ''
+      let _tailScript = ''
       component.scripts && component.scripts.forEach(script => {
-        if (script.status !== 'false') {
+        if (script.status === 'false') return
+        if (script.position !== 'back') {
           _customScript += `
+          ${script.sql}
+          `
+        } else {
+          _tailScript += `
           ${script.sql}
           `
         }
@@ -538,22 +531,30 @@
       }
   
       if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        component.setting.dataresource = component.setting.dataresource.replace(/@\$/ig, '*/')
-        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        _customScript = _customScript.replace(/@\$/ig, '*/')
+        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
       } else {
         component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
         _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
       }
 
       regs.forEach(cell => {
         component.setting.dataresource = component.setting.dataresource.replace(cell.reg, cell.value)
         _customScript = _customScript.replace(cell.reg, cell.value)
+        _tailScript = _tailScript.replace(cell.reg, cell.value)
       })
 
       component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+      component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
+      component.setting.custompage = /@pageSize@|@orderBy@/i.test(component.setting.dataresource + component.setting.customScript)
+
+      if (!component.setting.execute || component.setting.custompage) {
+        component.forbidLine = true
+      }
+      
       component.setting.delay = delay
       delay += 20
 
@@ -622,6 +623,9 @@
       } else {
         window.GLOB.CacheData.delete(item.uuid)
       }
+      if (item.type !== 'tabs' && item.$main) {
+        window.GLOB.SearchBox.delete(item.$searchId)
+      }
     })
   }
 
@@ -638,20 +642,13 @@
       config: null,         // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷粍浠剁瓑
       loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
       shortcuts: null,
-      data: ''
     }, () => {
       this.loadconfig()
     })
   }
 
-  resetSearch = (search) => {
-    this.setState({mainSearch: null}, () => {
-      this.setState({mainSearch: search})
-    })
-  }
-
   getComponents = () => {
-    const { config, data, mainSearch } = this.state
+    const { config } = this.state
 
     if (!config || !config.components) return
 
@@ -659,13 +656,13 @@
       if (item.type === 'tabs') {
         return (
           <Col span={item.width} key={item.uuid}>
-            <AntvTabs config={item} mainSearch={mainSearch} />
+            <AntvTabs config={item}/>
           </Col>
         )
       } else {
         return (
           <Col span={item.width} key={item.uuid}>
-            <MkBaseTable config={item} data={data}/>
+            <MkBaseTable config={item}/>
           </Col>
         )
       }
@@ -680,9 +677,9 @@
         {(loadingview || loading) ? <Spin className="view-spin" size="large" /> : null}
         <Row className="component-wrap">{this.getComponents()}</Row>
         {config && window.GLOB.breakpoint ? <DebugTable /> : null}
-        {!window.GLOB.mkHS && config && autoMatic ? <AutoMatic autoMatic={autoMatic} config={config.components[0]} /> : null}
+        {!window.GLOB.mkHS && config && autoMatic ? <AutoMatic autoMatic={autoMatic} tabId={config.MenuID} config={config.components[0]} /> : null}
         {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <TableNodes config={config} /> : null}
-        {!window.GLOB.mkHS && config ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts || []}/> : null}
+        {!window.GLOB.mkHS && config ? <SettingComponent config={config} shortcuts={shortcuts || []}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
     )
diff --git a/src/tabviews/calendar/index.jsx b/src/tabviews/calendar/index.jsx
deleted file mode 100644
index 7ed4d3f..0000000
--- a/src/tabviews/calendar/index.jsx
+++ /dev/null
@@ -1,590 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { notification, Spin, Modal, Button } from 'antd'
-import moment from 'moment'
-
-import Api from '@/api'
-import options from '@/store/options.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
-import Utils from '@/utils/utils.js'
-import asyncComponent from '@/utils/asyncComponent'
-import asyncSpinComponent from '@/utils/asyncSpinComponent'
-import MKEmitter from '@/utils/events.js'
-import NotFount from '@/components/404'
-import './index.scss'
-
-// 閫氱敤缁勪欢
-const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
-const CalendarComponent = asyncSpinComponent(() => import('@/tabviews/zshare/calendar'))
-const SubTabTable = asyncSpinComponent(() => import('@/tabviews/subtabtable'))
-const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
-
-class MkCalendar extends Component {
-  static propTpyes = {
-    param: PropTypes.any,        // 鍏朵粬椤甸潰浼犻�掔殑鍙傛暟
-    MenuID: PropTypes.string,    // 鑿滃崟Id
-    MenuNo: PropTypes.string,    // 鑿滃崟鍙傛暟
-    MenuName: PropTypes.string   // 鑿滃崟鍚嶇О
-  }
-
-  state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    BID: null,            // 椤甸潰璺宠浆鏃舵惡甯D
-    loadingview: true,    // 椤甸潰鍔犺浇涓�
-    viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
-    lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
-    config: {},           // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佹悳绱€�佹樉绀哄垪銆佹爣绛剧瓑
-    userConfig: null,     // 鐢ㄦ埛鑷畾涔夎缃�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
-    setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
-    data: null,           // 鍒楄〃鏁版嵁闆�
-    loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
-    search: '',           // 鎼滅储鏉′欢鏁扮粍锛屼娇鐢ㄦ椂闇�鍒嗗満鏅鐞�
-    visible: false,       // 鏍囩椤垫帶鍒�
-    triggerTime: '',      // 鐐瑰嚮鏃堕棿
-    calendarYear: moment().format('YYYY'), // 鏃ュ巻骞翠唤
-    hasReqFields: false
-  }
-
-  /**
-   * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
-   */
-  async loadconfig () {
-    const { param } = this.props
-
-    let _param = {
-      func: 'sPC_Get_LongParam',
-      MenuID: this.props.MenuID
-    }
-    let result = await Api.getCacheConfig(_param)
-
-    if (result.status) {
-      let config = ''
-      let userConfig = null
-      let _curUserConfig = ''
-
-      try { // 閰嶇疆淇℃伅瑙f瀽
-        config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-      } catch (e) {
-        console.warn('Parse Failure')
-        config = ''
-      }
-      
-      // HS涓嶄娇鐢ㄨ嚜瀹氫箟璁剧疆
-      if (result.LongParamUser && !window.GLOB.mkHS) {
-        try { // 閰嶇疆淇℃伅瑙f瀽
-          userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
-          _curUserConfig = userConfig[this.props.MenuID]
-        } catch (e) {
-          console.warn('Parse Failure')
-          userConfig = null
-        }
-      }
-
-      // 椤甸潰閰嶇疆瑙f瀽閿欒鏃舵彁绀�
-      if (!config) {
-        this.setState({
-          loadingview: false,
-          viewlost: true
-        })
-        return
-      }
-
-      // 椤甸潰鏈惎鐢ㄦ椂锛屾樉绀烘湭鍚敤椤甸潰
-      if (!config.enabled) {
-        this.setState({
-          loadingview: false,
-          viewlost: true,
-          lostmsg: this.state.dict['main.view.unenabled']
-        })
-        return
-      }
-
-      // 鏉冮檺杩囨护
-      if (config.tab) {
-        config.tab.uuid = Utils.getuuid()
-      }
-
-      if (_curUserConfig) {
-        config.setting = {...config.setting, ..._curUserConfig.setting}
-        config.easyCode = _curUserConfig.easyCode || config.easyCode || ''
-      }
-
-      config.search = Utils.initSearchVal(config.search)
-
-      // 瀛楁閫忚
-      let hasReqFields = false
-      config.search = config.search.map(item => {
-        if (param && ['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
-          item.initval = param.$searchval
-        }
-
-        if (item.required) {
-          hasReqFields = true
-        }
-
-        return item
-      })
-
-      // 鏁版嵁婧�
-      if (config.setting.interType === 'inner' && !config.setting.innerFunc) {
-        config.setting.interType = 'system'
-      }
-
-      if (config.setting.interType === 'system') {
-        // 鏁寸悊鏁版嵁婧愯嚜瀹氫箟鑴氭湰
-        let _customScript = ''
-        config.scripts && config.scripts.forEach(script => {
-          if (script.status !== 'false') {
-            _customScript += `
-            ${script.sql}
-            `
-          }
-        })
-
-        if (/\s/.test(config.setting.dataresource)) {
-          config.setting.dataresource = '(' + config.setting.dataresource + ') tb'
-        }
-    
-        if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-          _customScript = _customScript.replace(/\$@/ig, '/*')
-          _customScript = _customScript.replace(/@\$/ig, '*/')
-        } else {
-          config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
-          _customScript = _customScript.replace(/@\$|\$@/ig, '')
-        }
-
-        let userName = sessionStorage.getItem('User_Name') || ''
-        let fullName = sessionStorage.getItem('Full_Name') || ''
-
-        if (sessionStorage.getItem('isEditState') === 'true') {
-          userName = sessionStorage.getItem('CloudUserName') || ''
-          fullName = sessionStorage.getItem('CloudFullName') || ''
-        }
-
-        let regs = [
-          { reg: /@userName@/ig, value: `'${userName}'` },
-          { reg: /@fullName@/ig, value: `'${fullName}'` }
-        ]
-
-        regs.forEach(cell => {
-          config.setting.dataresource = config.setting.dataresource.replace(cell.reg, cell.value)
-          _customScript = _customScript.replace(cell.reg, cell.value)
-        })
-
-        if (config.urlFields) {
-          let _param = param || {}
-          config.urlFields.forEach(field => {
-            let reg = new RegExp('@' + field + '@', 'ig')
-            let val = `'${_param[field] || ''}'`
-            config.setting.dataresource = config.setting.dataresource.replace(reg, val)
-            _customScript = _customScript.replace(reg, val)
-          })
-        }
-
-        config.setting.customScript = _customScript
-      }
-
-      config.type = 'table'
-      config.wrap = {
-        show: config.setting.show || '',
-        float: config.setting.float || '',
-        advanceType: config.setting.advanceType || '',
-        advanceWidth: config.setting.advanceWidth || '',
-        drawerPlacement: config.setting.drawerPlacement || '',
-        searchRatio: config.setting.searchRatio || '',
-        searchLwidth: config.setting.searchLwidth,
-        borderRadius: config.setting.borderRadius,
-      }
-
-      this.setState({
-        hasReqFields,
-        BID: param && param.$BID ? param.$BID : '',
-        loadingview: false,
-        config: config,
-        userConfig: userConfig,
-        setting: config.setting,
-        arr_field: config.columns.map(item => item.field).join(','),
-        search: Utils.initMainSearch(config.search)
-      }, () => {
-        if (config.setting.onload !== 'false') {
-          this.loadmaindata()
-        }
-      })
-    } else {
-      this.setState({
-        loadingview: false,
-        viewlost: true
-      })
-      notification.warning({
-        top: 92,
-        message: result.message,
-        duration: 5
-      })
-    }
-  }
-
-  /**
-   * @description 涓昏〃鏁版嵁鍔犺浇
-   */ 
-  async loadmaindata () {
-    const { setting, search, BID, hasReqFields } = this.state
-    let param = ''
-
-    if (hasReqFields) {
-      let requireFields = search.filter(item => item.required && item.value === '')
-  
-      if (requireFields.length > 0) {
-        return
-      }
-    }
-
-    this.setState({
-      loading: true
-    })
-
-    if (setting.interType === 'system') {
-      param = this.getDefaultParam()
-    } else {
-      param = this.getCustomParam()
-    }
-
-    if (BID) {
-      param.BID = BID
-    }
-    // 鏁版嵁绠$悊鏉冮檺
-    if (sessionStorage.getItem('dataM') === 'true') {
-      param.dataM = 'Y'
-    }
-
-    let result = await Api.genericInterface(param)
-    if (result.status) {
-      this.setState({
-        data: result.data.map((item, index) => {
-          item.key = index
-          return item
-        }),
-        loading: false
-      })
-    } else {
-      this.setState({
-        loading: false
-      })
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
-    }
-  }
-
-  /**
-   * @description 鑾峰彇鐢ㄦ埛鑷畾涔夊瓨鍌ㄨ繃绋嬩紶鍙�
-   */
-  getCustomParam = () => {
-    const { search, setting, calendarYear, config } = this.state
-
-    let _search = Utils.formatCustomMainSearch(search)
-
-    let param = {
-      ..._search
-    }
-
-    if (config.calendar.refresh === 'true') {
-      param.calendarDate = calendarYear
-    }
-
-    if (setting.interType === 'inner') {
-      param.func = setting.innerFunc
-    } else {
-      if (window.GLOB.mkHS) {
-        if (setting.sysInterface === 'true' && options.cloudServiceApi) {
-          param.rduri = options.cloudServiceApi
-          param.userid = sessionStorage.getItem('CloudUserID') || ''
-          param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
-        } else if (setting.sysInterface !== 'true') {
-          param.rduri = setting.interface
-        }
-      } else {
-        if (setting.sysInterface === 'true' && window.GLOB.mainSystemApi) {
-          param.rduri = window.GLOB.mainSystemApi
-        } else if (setting.sysInterface !== 'true') {
-          param.rduri = setting.interface
-        }
-      }
-
-      if (setting.outerFunc) {
-        param.func = setting.outerFunc
-      }
-    }
-
-    return param
-  }
-
-  /**
-   * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼鐨勫弬鏁�
-   */
-  getDefaultParam = () => {
-    const { arr_field, search, setting, config, calendarYear } = this.state
-
-    let _search = Utils.joinMainSearchkey(search)
-    _search = _search ? 'where ' + _search : ''
-
-    let param = {
-      func: 'sPC_Get_TableData',
-      obj_name: 'data',
-      arr_field: arr_field,
-      custom_script: setting.customScript,
-      default_sql: setting.execute || 'true',
-      menuname: this.props.MenuName || ''
-    }
-    
-    let _dataresource = setting.dataresource
-    let regoptions = []
-    let userName = sessionStorage.getItem('User_Name') || ''
-    let fullName = sessionStorage.getItem('Full_Name') || ''
-    let RoleID = sessionStorage.getItem('role_id') || ''
-    let departmentcode = sessionStorage.getItem('departmentcode') || ''
-    let organization = sessionStorage.getItem('organization') || ''
-    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
-    let nation = sessionStorage.getItem('nation') || ''
-    let province = sessionStorage.getItem('province') || ''
-    let city = sessionStorage.getItem('city') || ''
-    let district = sessionStorage.getItem('district') || ''
-    let address = sessionStorage.getItem('address') || ''
-
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
-
-    if (setting.queryType === 'statistics' || param.custom_script) {
-      let allSearch = Utils.getAllSearchOptions(search)
-      regoptions = allSearch.map(item => {
-        return {
-          reg: new RegExp('@' + item.key + '@', 'ig'),
-          value: `'${item.value}'`
-        }
-      })
-      regoptions.push({
-        reg: new RegExp('@userName@', 'ig'),
-        value: userName
-      }, {
-        reg: new RegExp('@fullName@', 'ig'),
-        value: fullName
-      })
-    }
-
-    if (config.calendar.refresh === 'true') {
-      regoptions.push({
-        reg: new RegExp('@calendarDate@', 'ig'),
-        value: `'${calendarYear}-01-01 00:00:00.000'`
-      })
-      regoptions.push({
-        reg: new RegExp('@calendarDate1@', 'ig'),
-        value: `'${calendarYear}-12-31 23:59:59.999'`
-      })
-    }
-
-    if ((setting.queryType === 'statistics' || config.calendar.refresh === 'true') && setting.execute !== 'false') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲
-      regoptions.forEach(item => {
-        _dataresource = _dataresource.replace(item.reg, item.value)
-      })
-      _search = ''
-    }
-
-    let LText = ''
-
-    if (setting.execute !== 'false') {
-      LText = `select ${arr_field} from ${_dataresource} ${_search}`
-    }
-
-    if (param.custom_script) {
-      regoptions.forEach(item => {
-        param.custom_script = param.custom_script.replace(item.reg, item.value)
-      })
-      
-      param.custom_script = `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='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
-        ${param.custom_script}
-      `
-
-      if (LText) {
-        LText += `
-          aaa:
-          if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
-        `
-      } else {
-        param.custom_script += `
-          aaa:
-          if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
-        `
-      }
-    }
-
-    // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
-      param.custom_script &&  console.info(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`)
-      LText &&  console.info(LText)
-    }
-    
-    param.custom_script = Utils.formatOptions(param.custom_script)
-    param.LText = Utils.formatOptions(LText)
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-    param.DateCount = ''
-
-    if (window.GLOB.probation) {
-      param.s_debug_type = 'Y'
-    }
-    
-    if (window.GLOB.mkHS) { // 浜戠鏁版嵁楠岃瘉
-      param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
-    }
-
-    return param
-  }
-
-  /**
-   * @description 鎼滅储鏉′欢鏀瑰彉鏃讹紝閲嶇疆琛ㄦ牸鏁版嵁
-   * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
-   */
-  refreshbysearch = (searches) => {
-    const { setting } = this.state
-
-    if (setting.onload === 'false') {
-      this.setState({
-        search: searches,
-        setting: {...setting, onload: 'true'}
-      }, () => {
-        this.loadmaindata()
-      })
-    } else {
-      this.setState({
-        search: searches
-      }, () => {
-        this.loadmaindata()
-      })
-    }
-  }
-
-
-  /**
-   * @description 椤甸潰鍒锋柊锛岄噸鏂拌幏鍙栭厤缃�
-   */
-  reloadview = () => {
-    this.setState({ loadingview: true, viewlost: false, lostmsg: '', data: null, loading: false, search: ''
-    }, () => {
-      this.loadconfig()
-    })
-  }
-
-  reloadMenuView = (menuId) => {
-    const { MenuID } = this.props
-
-    if (MenuID !== menuId) return
-
-    this.reloadview()
-  }
-
-  UNSAFE_componentWillMount () {
-    // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
-    this.loadconfig()
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  componentDidMount () {
-    MKEmitter.addListener('openNewTab', this.closeTab)
-    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
-    MKEmitter.addListener('refreshPopButton', this.refreshPopButton)
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    MKEmitter.removeListener('openNewTab', this.closeTab)
-    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
-    MKEmitter.removeListener('refreshPopButton', this.refreshPopButton)
-  }
-
-  refreshPopButton = (tabId) => {
-    const { config } = this.props
-
-    if (!config.tab || config.tab.uuid !== tabId) return
-
-    this.loadmaindata()
-  }
-
-  triggerDate = (item) => {
-    const { config } = this.state
-
-    if (!config.tab) return
-    
-    this.setState({
-      visible: true,
-      triggerTime: item.time.substr(0, 4) + '-' + item.time.substr(4, 2) + '-' + item.time.substr(6, 2)
-    })
-  }
-
-  closeTab = () => {
-    this.setState({
-      visible: false,
-      triggerTime: ''
-    })
-  }
-
-  render() {
-    const { BID, loadingview, viewlost, config, loading, data, triggerTime } = this.state
-
-    return (
-      <div className="calendar-page">
-        {loadingview && <Spin size="large" />}
-        {config.search && config.search.length > 0 ?
-          <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
-        }
-        {config && config.calendar ? <CalendarComponent calendar={config.calendar} loading={loading} data={data} triggerDate={this.triggerDate} changeDate={this.changeDate}/> : null}
-        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
-        <Modal
-          title={config.tab ? config.tab.label : ''}
-          width={'80vw'}
-          maskClosable={false}
-          visible={this.state.visible}
-          onCancel={this.closeTab}
-          footer={[
-            <Button key="close" onClick={this.closeTab}>{this.state.dict['main.close']}</Button>
-          ]}
-          destroyOnClose
-        >
-          {config.tab ? <SubTabTable
-            BID={triggerTime}
-            Tab={config.tab}
-            MenuID={config.tab.linkTab}
-            SupMenuID={this.props.MenuID}
-          /> : null}
-        </Modal>
-        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
-      </div>
-    )
-  }
-}
-
-export default MkCalendar
\ No newline at end of file
diff --git a/src/tabviews/calendar/index.scss b/src/tabviews/calendar/index.scss
deleted file mode 100644
index 23d25cf..0000000
--- a/src/tabviews/calendar/index.scss
+++ /dev/null
@@ -1,44 +0,0 @@
-.calendar-page {
-  position: relative;
-  min-height: calc(100vh - 94px);
-  padding-top: 16px;
-  padding-bottom: 80px;
-  .box404 {
-    padding-top: 30px;
-  }
-  >.mk-search-wrap {
-    padding: 0px 24px 5px;
-    border-bottom: 1px solid #efefef;
-  }
-
-  .ant-modal-mask {
-    position: absolute;
-  }
-  .ant-modal-wrap {
-    position: absolute;
-  }
-  .action-modal .ant-modal {
-    top: 40px;
-    max-width: 95%;
-    .ant-modal-body {
-      max-height: calc(100vh - 265px);
-    }
-  }
-  > .ant-spin {
-    position: absolute;
-    z-index: 10;
-    left: calc(50% - 22px);
-    top: calc(50vh - 70px);
-  }
-  
-  .common-table-copy {
-    position: fixed;
-    z-index: 2;
-    bottom: 65px;
-    right: 30px;
-    width: 40px;
-    height: 40px;
-  }
-}
-
-
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index f9887fb..ab15b41 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -22,8 +22,6 @@
 const SubTable = asyncSpinComponent(() => import('@/tabviews/subtable'))
 const CardComponent = asyncSpinComponent(() => import('@/tabviews/zshare/cardcomponent'))
 const ChartComponent = asyncSpinComponent(() => import('@/tabviews/zshare/chartcomponent'))
-const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
-const AutoMatic = asyncComponent(() => import('@/tabviews/zshare/automatic'))
 const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
 
 const { TabPane } = Tabs
@@ -47,7 +45,6 @@
     shortcuts: null,      // 蹇嵎閿�
     actions: null,        // 鎸夐挳闆�
     columns: null,        // 鏄剧ず鍒�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
     setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
     data: [],             // 鍒楄〃鏁版嵁闆�
     selectedData: [],     // 宸查�夎〃鏍兼暟鎹�
@@ -63,7 +60,6 @@
     statFields: [],       // 鍚堣瀛楁
     statFValue: [],       // 鍚堣鍊�
     absFields: [],        // 缁濆鍊煎瓧娈�
-    hasReqFields: false,
     autoMatic: null,
     visible: false
   }
@@ -117,7 +113,7 @@
       }
       
       // HS涓嶄娇鐢ㄨ嚜瀹氫箟璁剧疆
-      if (result.LongParamUser && !window.GLOB.mkHS) {
+      if (result.LongParamUser) {
         try { // 閰嶇疆淇℃伅瑙f瀽
           let userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
           if (userConfig && !userConfig.version) {
@@ -209,19 +205,13 @@
         chartId = config.charts[0] ? config.charts[0].uuid : ''
       }
 
-      config.search = Utils.initSearchVal(config.search)
+      Utils.initSearchVal(config)
 
       // 瀛楁閫忚鍙婂繀濉爣蹇�
-      let hasReqFields = false
       config.search = config.search.map(item => {
         if (['text', 'select', 'link'].includes(item.type) && param && param.$searchkey === item.field) {
           item.initval = param.$searchval
         }
-
-        if (item.required) {
-          hasReqFields = true
-        }
-
         return item
       })
 
@@ -263,10 +253,8 @@
         }
   
         if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
-          config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
+          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
+          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
         } else {
           config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
           config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
@@ -274,11 +262,6 @@
 
         let userName = sessionStorage.getItem('User_Name') || ''
         let fullName = sessionStorage.getItem('Full_Name') || ''
-
-        if (sessionStorage.getItem('isEditState') === 'true') {
-          userName = sessionStorage.getItem('CloudUserName') || ''
-          fullName = sessionStorage.getItem('CloudFullName') || ''
-        }
 
         let regs = [
           { reg: /@userName@/ig, value: `'${userName}'` },
@@ -316,6 +299,16 @@
         item.$menuId = this.props.MenuID
         item.$old = true
         item.ContainerId = this.state.ContainerId
+
+        if (item.OpenType === 'excelOut') { // 瀵煎嚭
+          item.$menuName = MenuName
+    
+          if (!item.verify || !item.verify.columns || item.verify.columns.length === 0) {
+            item.errorType = 'error1'
+          } else if (item.intertype === 'system' && item.verify.dataType !== 'custom' && config.setting.interType !== 'system') {
+            item.errorType = 'error2'
+          }
+        }
 
         if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify) { // 鎵撳嵃鏈鸿缃�
           let _item = window.GLOB.UserCacheMap.get(this.props.MenuID + item.uuid)
@@ -454,7 +447,10 @@
         searchRatio: config.setting.searchRatio || '',
         searchLwidth: config.setting.searchLwidth,
         borderRadius: config.setting.borderRadius,
+        resetContrl: config.setting.resetContrl,
       }
+
+      config.setting.arr_field = _arrField.join(',')
 
       this.setState({
         pageSize: config.setting.pageSize || 10,
@@ -468,10 +464,8 @@
         setting: config.setting,
         actions: _actions,
         columns: _columns,
-        arr_field: _arrField.join(','),
         BID: param && param.$BID ? param.$BID : '',
-        search: Utils.initMainSearch(config.search),
-        hasReqFields
+        search: Utils.initMainSearch(config.search)
       }, () => {
         if (config.setting.onload !== 'false') { // 鍒濆鍖栧彲鍔犺浇
           this.loadData()
@@ -512,7 +506,6 @@
       let _shortcut = `${preKey}+${keyCode}`
 
       if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
-        window.debugger = false
         window.GLOB.breakpoint = false
         sessionStorage.removeItem('breakpoint')
         
@@ -539,14 +532,14 @@
 
   loadData = (id) => {
     const { MenuID } = this.props
-    const { setting, search, hasReqFields, ContainerId } = this.state
+    const { setting, search, config, ContainerId } = this.state
 
     this.setState({
       selectedData: []
     })
     MKEmitter.emit('changeTableLine', ContainerId, MenuID, '', '')
 
-    if (hasReqFields) {
+    if (config.$s_req) {
       let requireFields = search.filter(item => item.required && item.value === '')
 
       if (requireFields.length > 0) {
@@ -573,14 +566,14 @@
    * @description 涓昏〃鏁版嵁鍔犺浇
    */ 
   async loadmaindata (id) {
-    const { setting, arr_field, search, orderBy, BID, pageIndex, pageSize, absFields, autoMatic } = this.state
+    const { setting, search, orderBy, BID, pageIndex, pageSize, absFields, autoMatic } = this.state
 
     this.setState({
       loading: true
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, search, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(setting, search, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
 
@@ -664,14 +657,14 @@
    * @description 鑾峰彇鍗曡鏁版嵁
    */ 
   async loadmainLinedata (id) {
-    const { setting, arr_field, search, orderBy, BID, pageIndex, pageSize, absFields } = this.state
+    const { setting, search, orderBy, BID, pageIndex, pageSize, absFields } = this.state
 
     this.setState({
       loading: true
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, search, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(setting, search, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -863,16 +856,14 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { MenuName, MenuID } = this.props
-    const { arr_field, orderBy, search, setting} = this.state
+    const { MenuID } = this.props
+    const { orderBy, search, setting } = this.state
 
     if (MenuID !== menuId) return
 
     callback({
-      arr_field: arr_field,
       orderBy: orderBy || setting.order,
-      search: search,
-      menuName: MenuName
+      search: search
     })
   }
 
@@ -1005,12 +996,12 @@
 
   render() {
     const { MenuID } = this.props
-    const { BID, setting, pageSize, actions, columns, loadingview, viewlost, pickup, config, chartId, search, selectedData, shortcuts, autoMatic } = this.state
+    const { BID, setting, pageSize, actions, columns, loadingview, viewlost, pickup, config, chartId, search, selectedData, shortcuts } = this.state
 
     return (
       <div className="commontable" id={this.state.ContainerId}>
         {loadingview ? <Spin size="large" /> : null}
-        {config.search && config.search.length ?
+        {config && config.search && config.search.length ?
           <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
         }
         {setting && config.charts ? <Row className="chart-view" gutter={16}>
@@ -1143,8 +1134,6 @@
           </Tabs>))
         }
         {setting && window.GLOB.breakpoint ? <DebugTable /> : null}
-        {!window.GLOB.mkHS && autoMatic ? <AutoMatic autoMatic={autoMatic} config={config} /> : null}
-        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config}/> : null}
         {!window.GLOB.mkHS && setting ? <SettingComponent config={config} shortcuts={shortcuts || []}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
diff --git a/src/tabviews/custom/components/calendar/board/index.jsx b/src/tabviews/custom/components/calendar/board/index.jsx
new file mode 100644
index 0000000..77727e6
--- /dev/null
+++ b/src/tabviews/custom/components/calendar/board/index.jsx
@@ -0,0 +1,660 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Select, Radio, Row, Col, Popover, Badge } from 'antd'
+import moment from 'moment'
+import 'moment/locale/zh-cn'
+
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+const { Option } = Select
+
+moment.locale('zh-cn')
+
+class CalendarBoard extends Component {
+  static propTpyes = {
+    data: PropTypes.any,            // 浜嬩欢鏁版嵁
+    config: PropTypes.any
+  }
+
+  state = {
+    level: 'day',
+    levels: null,
+    yearlist: null,
+    selectYear: moment().format('YYYY'),
+    selectMonth: moment().format('MM'),
+    datelist: null,
+    monthlist: null
+  }
+
+  UNSAFE_componentWillMount() {
+    const { config } = this.props
+
+    let yearlist = []
+    let _selectYear = +this.state.selectYear
+    yearlist.push(`${_selectYear}`)
+    
+    for (let i = 1; i <= 10; i++) {
+      yearlist.unshift(`${_selectYear - i}`)
+      yearlist.push(`${_selectYear + i}`)
+    }
+
+    let datelist = this.getDateList(this.state.selectYear)
+
+    let _levels = config.wrap.levels
+    let level = _levels[0]
+    let monthlist = datelist.filter(item => item.month === moment().format('MM'))[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
+
+    this.setState({
+      yearlist,
+      datelist,
+      monthlist,
+      level,
+      levels: _levels
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    const { datelist } = this.state
+    if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
+      this.setState({
+        datelist: this.mountdata(datelist, nextProps.data)
+      })
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  mountdata = (datelist, data) => {
+    return fromJS(datelist).toJS().map(month => {
+      month.subData = []
+      data.forEach(item => {
+        if (item.$startM <= month.time && item.$endM >= month.time) {
+          month.subData.push(item)
+        }
+      })
+
+      month.children = month.children.map(week => {
+        week.children = week.children.map(day => {
+          if (day.$disable) return day
+
+          day.subData = []
+          day.style = null
+          day.$level = 100
+          data.forEach(item => {
+            if (item.$start <= day.time && item.$end >= day.time) {
+              day.subData.push(item)
+
+              if (!day.style) {
+                day.style = item.$style
+                day.$level = item.$level
+              } else if (item.$level < day.$level) {
+                day.style = item.$style
+                day.$level = item.$level
+              }
+            }
+          })
+          return day
+        })
+        return week
+      })
+      return month
+    })
+  }
+
+  getNongLi = (nyear, nmonth, nday, week) => {
+    let lmonth;
+    let lday;
+    let lleap; //鍐滃巻鍙傛暟
+    
+    //闃村巻鍑芥暟寮�濮�
+    // eslint-disable-next-line
+    let lunarInfo = new Array(0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0,
+      0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63)
+    let lYearDays = (y) => {
+      let i, sum = 348;
+      for (i = 0x8000; i > 0x8; i >>= 1) {
+        sum += (lunarInfo[y - 1900] & i) ? 1 : 0
+      }
+      return (sum + leapDays(y))
+    }
+    let leapDays = (y) => {
+      if (leapMonth(y)) return ((lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
+      return 0
+    }
+    let leapMonth = (y) => {
+      return (lunarInfo[y - 1900] & 0xf)
+    }
+    let monthDays = (y, m) => {
+      return ((lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
+    }
+    let Lunar = (y, m, d) => {
+      let i, leap = 0, temp = 0;
+      let offset = (Date.UTC(y, m, d) - Date.UTC(1900, 0, 31)) / 86400000;
+      for (i = 1900; i < 2050 && offset > 0; i++) {
+        temp = lYearDays(i)
+        offset -= temp
+      }
+      if (offset < 0) {
+        offset += temp
+        i--
+      }
+
+      let year = i
+      leap = leapMonth(i)
+      let isLeap = false
+
+      for (i = 1; i < 13 && offset > 0; i++) {
+        if (leap > 0 && i === (leap + 1) && isLeap === false) {
+          --i
+          isLeap = true
+          temp = leapDays(year)
+        } else {
+          temp = monthDays(year, i)
+        }
+        if (isLeap === true && i === (leap + 1)) {
+          isLeap = false
+        }
+        offset -= temp
+      }
+      if (offset === 0 && leap > 0 && i === leap + 1) {
+        if (isLeap) {
+          isLeap = false
+        } else {
+          isLeap = true
+          --i
+        }
+      }
+      if (offset < 0) {
+        offset += temp
+        --i
+      }
+
+      return {
+        month: i,
+        day: offset + 1,
+        isLeap: isLeap
+      }
+    }
+
+    let nStr1 = ['', '涓�', '浜�', '涓�', '鍥�', '浜�', '鍏�', '涓�', '鍏�', '涔�', '鍗�', '鍗佷竴', '鍗佷簩']
+    let nStr2 = ['鍒�', '鍗�', '寤�', '鍗�']
+    let GetcDay = (d) => {
+      let s
+      switch (d) {
+        case 10:
+          s = '鍒濆崄'
+          break
+        case 20:
+          s = '浜屽崄'
+          break
+        case 30:
+          s = '涓夊崄'
+          break
+        default:
+          s = nStr2[Math.floor(d / 10)]
+          s += nStr1[d % 10]
+          break
+      }
+      return s
+    }
+    let GetcMon = (m) => {
+      if (m === 1) return '姝�'
+      return nStr1[m]
+    }
+    
+    let lObj = Lunar(nyear, nmonth - 1, nday)
+    lmonth = GetcMon(lObj.month)
+    lday = GetcDay(lObj.day)
+    lleap = lObj.isLeap
+    if (lleap === 1) {
+      lmonth = '闂�' + lmonth
+    }
+
+    lmonth = lmonth + '鏈�'
+
+    if (!week) {
+      return lmonth + lday
+    }
+
+    let jq = this.getjq(nyear, nmonth, nday)
+
+    let nl = lday
+
+    if (lday === '鍒濅竴') {
+      nl = lmonth
+    }
+    if (jq) {
+      nl = jq
+    }
+
+    let sign = '鐝�'
+    if (week > 5) {
+      sign = '浼�'
+    }
+
+    let jr = ''
+    let gr = '' + nmonth + '-' + nday
+    let nr = lmonth + lday
+    if (gr === '1-1') {
+      jr = '鍏冩棪'
+      sign = '浼�'
+    } else if (nr === '姝f湀鍒濅竴') {
+      jr = '鏄ヨ妭'
+      sign = '浼�'
+    } else if (nr === '姝f湀鍗佷簲') {
+      jr = '鍏冨鑺�'
+    } else if (jq === '娓呮槑') {
+      sign = '浼�'
+    } else if (gr === '3-8') {
+      jr = '濡囧コ鑺�'
+    } else if (gr === '5-1') {
+      jr = '鍔冲姩鑺�'
+      sign = '浼�'
+    } else if (nr === '浜旀湀鍒濅簲') {
+      jr = '绔崍鑺�'
+      sign = '浼�'
+    } else if (nr === '涓冩湀鍒濅竷') {
+      jr = '涓冨鑺�'
+    } else if (nr === '涓冩湀鍗佷簲') {
+      jr = '涓厓鑺�'
+    } else if (nr === '鍏湀鍗佷簲') {
+      jr = '涓鑺�'
+      sign = '浼�'
+    } else if (gr === '7-1') {
+      jr = '寤哄厷鑺�'
+    } else if (gr === '8-1') {
+      jr = '寤哄啗鑺�'
+    } else if (gr === '9-10') {
+      jr = '鏁欏笀鑺�'
+    } else if (gr === '10-1') {
+      jr = '鍥藉簡鑺�'
+      sign = '浼�'
+    } else if (nr === '涔濇湀鍒濅節') {
+      jr = '閲嶉槼鑺�'
+    } else if (nr === '鍗佷簩鏈堜笁鍗�') {
+      jr = '闄ゅ'
+      sign = '浼�'
+    } else if (['姝f湀鍒濅簩', '姝f湀鍒濅笁', '姝f湀鍒濆洓', '姝f湀鍒濅簲', '姝f湀鍒濆叚'].includes(nr)) {
+      sign = '浼�'
+    } else if (['10-2', '10-3'].includes(gr)) {
+      sign = '浼�'
+    } else if (nr === '鍗佷簩鏈堝豢涔�') {
+      let tis = moment(`${nyear}${nmonth < 10 ? '0' + nmonth : nmonth}${nday < 10 ?  '0' + nday : nday}`, 'YYYYMMDD').add(1, 'days').format('YYYY-MM-DD').split('-')
+      let nd = this.getNongLi(+tis[0], +tis[1], +tis[2])
+
+      if (nd === '姝f湀鍒濅竴') {
+        jr = '闄ゅ'
+        sign = '浼�'
+      }
+    }
+
+    return {
+      nlday: lday,
+      nlmonth: lmonth,
+      nljq: jq,
+      nl: nl,
+      jr: jr,
+      week: week,
+      sign: sign
+    }
+  }
+
+  getjq = (yyyy, mm, dd) => {
+    mm = mm - 1
+    // eslint-disable-next-line
+    let sTermInfo = new Array(0,21208,42467,63836,85337,107014,128867,150921,173149,195551,218072,240693,263343,285989,308563,331033,353350,375494,397447,419210,440795,462224,483532,504758)
+    let solarTerm = ['灏忓瘨', '澶у瘨', '绔嬫槬', '闆ㄦ按', '鎯婅洶', '鏄ュ垎', '娓呮槑', '璋烽洦', '绔嬪', '灏忔弧', '鑺掔', '澶忚嚦', '灏忔殤', '澶ф殤', '绔嬬', '澶勬殤', '鐧介湶', '绉嬪垎', '瀵掗湶', '闇滈檷', '绔嬪啲', '灏忛洩', '澶ч洩', '鍐嚦']
+    let tmp1 = new Date((31556925974.7 * (yyyy - 1900) + sTermInfo[mm * 2 + 1] * 60000) + Date.UTC(1900, 0, 6, 2, 5))
+    let tmp2 = tmp1.getUTCDate()
+    let solarTerms = ''
+    if (tmp2 === dd) {
+      solarTerms = solarTerm[mm * 2 + 1]
+    }
+    tmp1 = new Date((31556925974.7 * (yyyy - 1900) + sTermInfo[mm * 2] * 60000) + Date.UTC(1900, 0, 6, 2, 5))
+    tmp2= tmp1.getUTCDate()
+    if (tmp2 === dd) {
+      solarTerms = solarTerm[mm * 2]
+    }
+
+    return solarTerms
+  }
+
+  getDateList = (selectYear) => {
+    let datelist = []
+    let months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
+    let monthName = {
+      '01': '涓�鏈�', '02': '浜屾湀', '03': '涓夋湀', '04': '鍥涙湀', '05': '浜旀湀', '06': '鍏湀',
+      '07': '涓冩湀', '08': '鍏湀', '09': '涔濇湀', '10': '鍗佹湀', '11': '鍗佷竴鏈�', '12': '鍗佷簩鏈�'
+    }
+
+    months.forEach(month => {
+      let _weeklist = []
+      let weekday = moment(`${selectYear}${month}01`, 'YYYYMMDD').weekday()
+      let end = +moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').format('DD')
+
+      let children = []
+      if (weekday > 0) {
+        let times = moment(`${selectYear}${month}01`, 'YYYYMMDD').subtract(1, 'days').format('YYYY-MM-DD').split('-')
+        for (let i = 0; i < weekday; i++) {
+          let _day = times[2] - i
+          let nl = this.getNongLi(+times[0], +times[1], +_day, weekday - i)
+  
+          let item = {
+            day: _day,
+            time: +(times[0] + times[1] + _day),
+            label: _day,
+            subData: [],
+            $disable: true,
+            ...nl
+          }
+          children.unshift(item)
+        }
+      }
+
+      for (let i = 1; i <= end; i++) {
+        let _day = i < 10 ? `0${i}` : `${i}`
+        let nl = this.getNongLi(+selectYear, +month, +_day, children.length + 1)
+
+        let item = {
+          day: _day,
+          time: +(selectYear + month + _day),
+          label: i,
+          subData: [],
+          ...nl
+        }
+
+        children.push(item)
+
+        if (children.length === 7) {
+          _weeklist.push({
+            children: [...children]
+          })
+          children = []
+        }
+      }
+
+      let times = moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').add(1, 'days').format('YYYY-MM-DD').split('-')
+      let tick = 42 - _weeklist.length * 7 - children.length
+
+      for (let i = 1; i <= tick; i++) {
+        let _day = i < 10 ? '0' + i : i
+        let nl = this.getNongLi(+times[0], +times[1], +_day, children.length + 1)
+  
+        let item = {
+          day: _day,
+          time: +(times[0] + times[1] + _day),
+          label: i,
+          subData: [],
+          $disable: true,
+          ...nl
+        }
+        children.push(item)
+
+        if (children.length === 7) {
+          _weeklist.push({
+            children: [...children]
+          })
+          children = []
+        }
+      }
+
+      datelist.push({
+        month: month,
+        time: +(selectYear + month),
+        label: monthName[month],
+        children: _weeklist,
+        subData: []
+      })
+    })
+
+    return datelist
+  }
+
+  levelChange = (e) => {
+    this.setState({ level: e.target.value })
+  }
+
+  yearChange = (value) => {
+    const { data } = this.props
+    const { selectMonth } = this.state
+    let datelist = this.getDateList(value)
+
+    if (data.length > 0) {
+      datelist = this.mountdata(datelist, data)
+    }
+
+    let monthlist = datelist.filter(item => item.month === selectMonth)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
+
+    this.setState({ selectYear: value, datelist, monthlist })
+
+    this.props.yearChange(value)
+  }
+
+  monthChange = (value) => {
+    const { datelist, levels } = this.state
+
+    if (!levels.includes('month')) {
+      return
+    }
+
+    this.setState({
+      level: 'month',
+      selectMonth: value,
+      monthlist: datelist.filter(item => item.month === value)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
+    })
+  }
+
+  triggerDay = (d) => {
+    const { config } = this.props
+
+    if (!config.setting.linkbtn) return
+
+    let id = d.time + ''
+    id = id.substr(0, 4) + '-' + id.substr(4, 2) + '-' + id.substr(6)
+
+    MKEmitter.emit('triggerBtnId', config.setting.linkbtn, [{$$uuid: id}])
+  }
+
+  openView = (data, e) => {
+    const { config } = this.props
+
+    if (!config.wrap.click) return
+
+    e && e.stopPropagation()
+
+    if (config.wrap.click === 'menus') {
+      let menu = null
+      
+      if (config.wrap.menus && config.wrap.menus.length > 0) {
+        let s = data[config.wrap.menuType] + ''
+        config.wrap.menus.forEach(m => {
+          if (s !== m.sign) return
+          menu = m
+        })
+      }
+      if (!menu) return
+
+      let newtab = {
+        MenuID: menu.MenuID,
+        MenuName: menu.MenuName,
+        MenuNo: menu.MenuNo || '',
+        type: menu.tabType,
+        param: {$BID: data.$$uuid || ''}
+      }
+
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        newtab.param[key] = data[key]
+      })
+
+      MKEmitter.emit('modifyTabs', newtab, true)
+    } else if (config.wrap.click === 'menu') {
+      let menuId = config.wrap.MenuID || config.wrap.menu.slice(-1)[0]
+      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
+
+      if (!menu && config.wrap.MenuName && config.wrap.tabType) {
+        menu = {
+          MenuID: menuId,
+          MenuName: config.wrap.MenuName,
+          MenuNo: config.wrap.MenuNo || '',
+          type: config.wrap.tabType
+        }
+      }
+
+      if (!menu) return
+
+      let newtab = {
+        ...menu,
+        param: {$BID: data.$$uuid || ''}
+      }
+
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        newtab.param[key] = data[key]
+      })
+
+      MKEmitter.emit('modifyTabs', newtab, true)
+    }
+  }
+
+  render() {
+    const { config } = this.props
+    const { level, selectYear, selectMonth, yearlist, levels, datelist, monthlist } = this.state
+    const _levelName = {day: '鏃�', month: '鏈�', year: '骞�'}
+
+    return (
+      <div className={'mk-calendar' + (config.setting.linkbtn ? ' open-pop' : '') + (config.wrap.click ? ' open-menu' : '')}>
+        <div className="mk-calendar-control">
+          <Select value={selectYear} onChange={this.yearChange}>
+            {yearlist.map(item => (<Option key={item} value={item}>{item}骞�</Option>))}
+          </Select>
+          {level === 'month' ? <Select value={selectMonth} onChange={this.monthChange}>
+            <Option value="01">1鏈�</Option>
+            <Option value="02">2鏈�</Option>
+            <Option value="03">3鏈�</Option>
+            <Option value="04">4鏈�</Option>
+            <Option value="05">5鏈�</Option>
+            <Option value="06">6鏈�</Option>
+            <Option value="07">7鏈�</Option>
+            <Option value="08">8鏈�</Option>
+            <Option value="09">9鏈�</Option>
+            <Option value="10">10鏈�</Option>
+            <Option value="11">11鏈�</Option>
+            <Option value="12">12鏈�</Option>
+          </Select> : null}
+          {levels.length > 1 ? <Radio.Group value={level} onChange={this.levelChange}>
+            {levels.map(item => (<Radio.Button key={item} value={item}>{_levelName[item]}</Radio.Button>))}
+          </Radio.Group> : null}
+        </div>
+        <div className="mk-calendar-content">
+          {level === 'day' ? <Row className="day-calendar" gutter={16}>
+            {datelist.map(item => (
+              <Col span={4} key={item.month}>
+                <table>
+                  <thead>
+                    <tr>
+                      <th colSpan="7">{item.label}</th>
+                    </tr>
+                    <tr>
+                      <th>涓�</th><th>浜�</th><th>涓�</th><th>鍥�</th><th>浜�</th><th>鍏�</th><th>鏃�</th>
+                    </tr>
+                  </thead>
+                  <tbody>
+                    {item.children.map((cell, m) => (
+                      <tr key={m}>
+                        {cell.children.map((d, i) => (
+                          <td key={i}>
+                            <div style={d.style} className={'day-wrap' + (d.$disable ? ' disabled' : '')} onClick={() => !d.$disable && this.triggerDay(d)}>
+                              {d.subData.length > 0 ? <Popover mouseEnterDelay={0.3} overlayClassName={'calendar-day-pop' + (config.wrap.click ? ' open-menu' : '')} content={
+                                <div onClick={(e) => e.stopPropagation()}>
+                                  {d.subData.map((data, index) => (
+                                    <div key={index} className="message" onClick={() => this.openView(data)}>
+                                      <Badge color={data.$color} text={
+                                        <span>
+                                          {data.$message}
+                                          <span style={{color: 'rgba(0,0,0,.45)'}}>({data.$startTime + ' ~ ' + data.$endTime})</span>
+                                        </span>}
+                                      />
+                                    </div>
+                                  ))}
+                                </div>
+                              } trigger="hover">
+                                {d.label}
+                              </Popover> : d.label}
+                            </div>
+                          </td>
+                        ))}
+                      </tr>
+                    ))}
+                  </tbody>
+                </table>
+              </Col>
+            ))}
+          </Row> : null}
+          {level === 'month' && monthlist ? <div className="month-calendar">
+            <table>
+              <thead>
+                <tr>
+                  <th>鏄熸湡涓�</th><th>鏄熸湡浜�</th><th>鏄熸湡涓�</th><th>鏄熸湡鍥�</th><th>鏄熸湡浜�</th><th>鏄熸湡鍏�</th><th>鏄熸湡鏃�</th>
+                </tr>
+              </thead>
+              <tbody>
+                {monthlist.map((cell, m) => (
+                  <tr key={m}>
+                    {cell.children.map((d, i) => (
+                      <td key={i}>
+                        <div className={'month-wrap' + (d.$disable ? ' disabled' : '')} onClick={() => !d.$disable && this.triggerDay(d)}>
+                          <div className="header">
+                            <div className="message">
+                              {d.label}
+                              <span className={'right' + (d.sign === '浼�' ? ' danger' : '')}>{d.sign}</span>
+                            </div>
+                            <div className="message">
+                              {d.nl}
+                              <span className="right">{d.jr}</span>
+                            </div>
+                          </div>
+                          <ul className="content">
+                            {d.subData.map((data, index) => (
+                              <li key={index} className="message" onClick={(e) => this.openView(data, e)}>
+                                <Badge color={data.$color} text={data.$message} />
+                              </li>
+                            ))}
+                          </ul>
+                        </div>
+                      </td>
+                    ))}
+                  </tr>
+                ))}
+              </tbody>
+            </table>
+          </div>: null}
+          {level === 'year' ? <Row className="year-calendar">
+            {datelist.map(item => (
+              <Col span={8} key={item.month}>
+                <div className="year-wrap">
+                  <div className="header">
+                    {item.label}
+                  </div>
+                  <ul className="content">
+                    {item.subData.map((data, index) => (
+                      <li key={index} className="message" onClick={() => this.openView(data)}>
+                        <Badge color={data.$color} text={`${data.$message} (${data.$startTime} ~ ${data.$endTime})`}/>
+                      </li>
+                    ))}
+                  </ul>
+                </div>
+              </Col>
+            ))}
+          </Row>: null}
+        </div>
+      </div>
+    )
+  }
+}
+
+export default CalendarBoard
\ No newline at end of file
diff --git a/src/tabviews/zshare/calendar/index.scss b/src/tabviews/custom/components/calendar/board/index.scss
similarity index 63%
copy from src/tabviews/zshare/calendar/index.scss
copy to src/tabviews/custom/components/calendar/board/index.scss
index 52faea5..3957fc3 100644
--- a/src/tabviews/zshare/calendar/index.scss
+++ b/src/tabviews/custom/components/calendar/board/index.scss
@@ -2,6 +2,7 @@
   position: relative;
   width: 100%;
   padding: 20px;
+  color: rgba(0, 0, 0, 0.85);
 
   .loading-data {
     position: absolute;
@@ -24,6 +25,9 @@
       width: 90px;
       margin-right: 15px;
     }
+    .ant-select + .ant-select {
+      width: 80px;
+    }
   }
   .mk-calendar-content {
     margin-top: 10px;
@@ -33,7 +37,7 @@
         width: 100%;
         thead {
           text-align: center;
-          color: #1890ff;
+          color: var(--mk-sys-color);
           tr {
             height: 30px;
           }
@@ -58,8 +62,12 @@
                   height: 100%;
                 }
               }
-              .day-wrap:hover {
-                background: #bae7ff;
+              .day-wrap.disabled {
+                cursor: default;
+                color: rgba(0, 0, 0, 0.35);
+              }
+              .day-wrap:not(.disabled):hover {
+                background: var(--mk-sys-color2);
               }
             }
           }
@@ -71,7 +79,6 @@
         width: 100%;
         thead {
           text-align: center;
-          color: #1890ff;
           font-size: 16px;
           tr {
             height: 35px;
@@ -88,22 +95,44 @@
                 width: calc(100% - 2px);
                 transition: background 0.1s;
                 margin-bottom: 2px;
-                box-shadow: 0px 0px 3px #bae7ff;
+                box-shadow: 0px 0px 3px var(--mk-sys-color2);
                 .header {
-                  text-align: center;
                   font-size: 16px;
+                  padding: 5px 10px;
+
+                  .message {
+                    .right {
+                      float: right;
+                    }
+                    .right.danger {
+                      color: #ff4d4f;
+                    }
+                  }
                 }
                 .content {
                   padding: 0 10px 10px;
-                  height: 90px;
+                  height: 55px;
                   overflow-y: auto;
                   position: absolute;
                   left: 0;
                   right: 0;
                   .message {
                     width: 100%;
+                    white-space: nowrap;
+                    overflow: hidden;
+                    .ant-badge {
+                      width: 100%;
+                    }
                     .ant-badge-status-text {
-                      color: inherit;
+                      font-size: 13px;
+                      width: calc(100% - 15px);
+                      overflow: hidden;
+                      word-break: break-word;
+                      white-space: nowrap;
+                      text-overflow: ellipsis;
+                      height: 21px;
+                      display: inline-block;
+                      vertical-align: top;
                     }
                   } 
                 }
@@ -122,8 +151,21 @@
                   background: rgba(0, 0, 0, 0);
                 }
               }
-              .month-wrap:hover {
-                background: #e6f7ff;
+
+              .month-wrap.disabled {
+                cursor: default;
+                color: rgba(0, 0, 0, 0.35);
+                .header {
+                  .message {
+                    .right.danger {
+                      color: rgba(0, 0, 0, 0.35);
+                    }
+                  }
+                }
+              }
+
+              .month-wrap:not(.disabled):hover {
+                background: var(--mk-sys-color1);
               }
             }
           }
@@ -133,12 +175,12 @@
     .year-calendar {
       .year-wrap {
         width: calc(100% - 2px);
-        box-shadow: 0px 0px 3px #bae7ff;
-        cursor: pointer;
+        box-shadow: 0px 0px 3px var(--mk-sys-color2);
         transition: background 0.1s;
         .header {
           text-align: center;
           font-size: 16px;
+          color: var(--mk-sys-color);
         }
         .content {
           padding: 5px 15px 10px;
@@ -150,10 +192,22 @@
           }
           .message {
             width: 100%;
-            // white-space: nowrap;
             overflow: hidden;
             margin-bottom: 5px;
-            text-overflow: ellipsis;
+            .ant-badge {
+              width: 100%;
+            }
+            .ant-badge-status-text {
+              font-size: 13px;
+              width: calc(100% - 15px);
+              overflow: hidden;
+              word-break: break-word;
+              white-space: nowrap;
+              text-overflow: ellipsis;
+              height: 21px;
+              display: inline-block;
+              vertical-align: top;
+            }
           } 
         }
         .content::-webkit-scrollbar {
@@ -172,9 +226,31 @@
         }
       }
       .year-wrap:hover {
-        background: #e6f7ff;
+        background: var(--mk-sys-color1);
       }
     }
+  }
+}
+.mk-calendar:not(.open-pop) {
+  .day-wrap {
+    cursor: default!important;
+  }
+  .month-wrap {
+    cursor: default!important;
+  }
+}
+.mk-calendar.open-menu {
+  .month-wrap, .year-wrap {
+    .content {
+      .message {
+        cursor: pointer;
+      }
+    }
+  }
+}
+.calendar-day-pop.open-menu {
+  .message {
+    cursor: pointer;
   }
 }
 .calendar-day-pop {
@@ -186,10 +262,17 @@
       vertical-align: middle;
     }
   }
+  .ant-popover-inner {
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
+  }
   .ant-popover-inner-content {
-    min-height: 100px;
+    padding: 0px;
+    min-height: 45px;
     max-height: 200px;
     overflow-y: auto;
+    >div {
+      padding: 12px 16px;
+    }
   }
   .ant-popover-inner-content::-webkit-scrollbar {
     width: 5px;
diff --git a/src/tabviews/custom/components/calendar/index.jsx b/src/tabviews/custom/components/calendar/index.jsx
new file mode 100644
index 0000000..764dd9b
--- /dev/null
+++ b/src/tabviews/custom/components/calendar/index.jsx
@@ -0,0 +1,380 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Spin, notification, Modal } from 'antd'
+
+import Api from '@/api'
+import asyncComponent from '@/utils/asyncComponent'
+import UtilsDM from '@/utils/utils-datamanage.js'
+import MKEmitter from '@/utils/events.js'
+import CalendarBoard from './board'
+import './index.scss'
+
+const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
+const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
+const PopupButton = asyncComponent(() => import('@/tabviews/zshare/actionList/popupbutton'))
+
+class NormalCalendar extends Component {
+  static propTpyes = {
+    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
+  }
+
+  state = {
+    BID: '',                   // 涓婄骇ID
+    config: null,              // 鍥捐〃閰嶇疆淇℃伅
+    loading: false,            // 鏁版嵁鍔犺浇鐘舵��
+    data: [],                // 鏁版嵁
+    search: '',
+    year: new Date().getFullYear(),
+    BData: ''
+  }
+
+  loaded = false
+
+  /**
+   * @description 鍒濆鍖栧鐞�
+   */
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+    let _config = fromJS(config).toJS()
+    let BData = ''
+
+    if (_config.setting.supModule) {
+      BData = window.GLOB.CacheData.get(_config.setting.supModule)
+    } else {
+      BData = window.GLOB.CacheData.get(_config.$pageId)
+    }
+
+    if (_config.setting.interType === 'system') {
+      if (/@mk_year@/ig.test(_config.setting.dataresource) || /@mk_year@/ig.test(_config.setting.customScript)) {
+        _config.setting.$re_year = true
+      }
+    } else {
+      _config.setting.$re_year = true
+    }
+
+    if (_config.wrap.colorField && (!_config.wrap.signs || _config.wrap.signs.length === 0)) {
+      _config.wrap.colorField = ''
+    }
+
+    if (_config.action[0] && _config.action[0].config && _config.action[0].config.enabled) {
+      _config.setting.linkbtn = _config.action[0].uuid
+    } else {
+      _config.action = []
+    }
+
+    this.setState({
+      BID: BData ? (BData.$BID || '') : '',
+      BData: BData,
+      config: _config,
+      search: _config.$searches
+    })
+  }
+
+  componentDidMount () {
+    const { config } = this.state
+
+    MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    this.initExec()
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+          if (!res.valid && config.setting.onload === 'true') {
+            setTimeout(() => {
+              this.loadData('init')
+            }, config.setting.delay || 0)
+          }
+
+          if (!res.data) return
+
+          let _data = []
+          res.data.forEach((item, index) => {
+            item.key = index
+            item.$$uuid = item[config.setting.primaryKey] || ''
+
+            let pass = this.resetLine(item)
+
+            if (pass) {
+              _data.push(item)
+            }
+          })
+  
+          this.setState({data: _data})
+        })
+      } else {
+        Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+          if (!res.data || this.loaded) return
+  
+          let _data = []
+          res.data.forEach((item, index) => {
+            item.key = index
+            item.$$uuid = item[config.setting.primaryKey] || ''
+
+            let pass = this.resetLine(item)
+
+            if (pass) {
+              _data.push(item)
+            }
+          })
+  
+          this.setState({data: _data})
+        })
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    }
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
+  }
+
+  /**
+   * @description 鎸夐挳鎵ц瀹屾垚鍚庨〉闈㈠埛鏂�
+   * @param {*} menuId     // 鑿滃崟Id
+   * @param {*} position   // 鍒锋柊浣嶇疆
+   * @param {*} btn        // 鎵ц鐨勬寜閽�
+   */
+  refreshByButtonResult = (menuId, position, btn) => {
+    const { config, BID } = this.state
+
+    if (config.uuid !== menuId) return
+
+    if (position === 'mainline' && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
+      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    } else {
+      this.loadData()
+    }
+  }
+
+  resetParentParam = (MenuID, id, data) => {
+    const { config } = this.state
+
+    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
+    if (id !== this.state.BID || id !== '') {
+      this.setState({ BID: id, BData: data }, () => {
+        this.loadData()
+      })
+    }
+  }
+
+  reloadData = (menuId) => {
+    const { config } = this.state
+
+    if (config.uuid !== menuId) return
+
+    this.loadData()
+  }
+
+  async loadData (type) {
+    const { config, BID, search, year } = this.state
+    
+    if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
+      this.setState({
+        data: [],
+      })
+      this.loaded = true
+      return
+    }
+
+    let searches = fromJS(search).toJS()
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
+      mainSearch.forEach(item => {
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
+      })
+    }
+
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
+      return
+    }
+
+    this.setState({
+      loading: true
+    })
+
+    let _orderBy = config.setting.order || ''
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 99999, BID, '', year)
+
+    let result = await Api.genericInterface(param)
+    if (result.status) {
+      this.loaded = true
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
+      }
+
+      let data = []
+      result.data.forEach((item, index) => {
+        item.key = index
+        item.$$uuid = item[config.setting.primaryKey] || ''
+        item.$$BID = BID || ''
+
+        let pass = this.resetLine(item)
+
+        if (pass) {
+          data.push(item)
+        }
+      })
+
+      this.setState({
+        data: data,
+        loading: false
+      })
+      
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
+    } else {
+      this.setState({
+        loading: false
+      })
+      
+      if (!result.message) return
+      if (result.ErrCode === 'N') {
+        Modal.error({
+          title: result.message,
+        })
+      } else if (result.ErrCode !== '-2') {
+        notification.error({
+          top: 92,
+          message: result.message,
+          duration: 10
+        })
+      }
+    }
+  }
+
+  resetLine = (item) => {
+    const { config: { wrap } } = this.state
+
+    let startTime = item[wrap.timeField] || ''
+    let endTime = item[wrap.endField || wrap.timeField] || ''
+
+    item.$message = item[wrap.remarkField]
+
+    if (!/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(startTime)) return false
+    if (!/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(endTime)) return false
+    if (!item.$message) return false
+
+    if (wrap.colorField) {
+      let sign = item[wrap.colorField] || ''
+
+      wrap.signs.forEach(cell => {
+        if (cell.sign !== sign) return
+
+        item.$style = cell.style
+        item.$color = cell.background
+        item.$level = cell.$index
+      })
+    }
+
+    let equal = endTime.substr(0, 4) === startTime.substr(0, 4)
+
+    item.$startM = +(startTime.substr(0, 4) + startTime.substr(5, 2))
+    item.$endM = +(endTime.substr(0, 4) + endTime.substr(5, 2))
+    item.$start = +(startTime.substr(0, 4) + startTime.substr(5, 2) + startTime.substr(8, 2))
+    item.$end = +(endTime.substr(0, 4) + endTime.substr(5, 2) + endTime.substr(8, 2))
+    item.$startTime = equal ? `${startTime.substr(5, 2)}-${startTime.substr(8, 2)}` : `${startTime.substr(0, 4)}-${startTime.substr(5, 2)}-${startTime.substr(8, 2)}`
+    item.$endTime = equal ?  `${endTime.substr(5, 2)}-${endTime.substr(8, 2)}` : `${endTime.substr(0, 4)}-${endTime.substr(5, 2)}-${endTime.substr(8, 2)}`
+    
+    return true
+  }
+
+  refreshbysearch = (searches) => {
+    this.setState({
+      search: searches
+    }, () => {
+      this.loadData()
+    })
+  }
+
+  yearChange = (value) => {
+    const { config } = this.state
+
+    if (!config.setting.$re_year) return
+
+    this.setState({
+      year: value
+    }, () => {
+      this.loadData()
+    })
+  }
+
+  render() {
+    const { config, loading, data, BID, BData } = this.state
+
+    return (
+      <div className="normal-calendar-box" id={'anchor' + config.uuid} style={{...config.style}}>
+        {loading ?
+          <div className="loading-mask">
+            <div className="ant-spin-blur"></div>
+            <Spin />
+          </div> : null
+        }
+        <NormalHeader config={config} />
+        {config.search.length ?
+          <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
+        }
+        {config.action[0] ? 
+          <PopupButton disabled={false} BID={BID} btn={config.action[0]} BData={BData} setting={config.setting} selectedData={[]}/> : null
+        }
+        <CalendarBoard config={config} data={data} yearChange={this.yearChange}/>
+      </div>
+    )
+  }
+}
+
+export default NormalCalendar
\ No newline at end of file
diff --git a/src/tabviews/custom/components/calendar/index.scss b/src/tabviews/custom/components/calendar/index.scss
new file mode 100644
index 0000000..d06f8c6
--- /dev/null
+++ b/src/tabviews/custom/components/calendar/index.scss
@@ -0,0 +1,38 @@
+.normal-calendar-box {
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  min-height: 100px;
+  position: relative;
+
+  >.ant-btn {
+    display: none;
+  }
+  .loading-mask {
+    position: absolute;
+    left: 0px;
+    top: 0;
+    right: 0px;
+    bottom: 0px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    text-align: justify;
+    z-index: 1;
+
+    .ant-spin-blur {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      opacity: 0.5;
+      background: #ffffff;
+    }
+  }
+}
+
+.normal-calendar-box::after {
+  content: ' ';
+  display: block;
+  clear: both;
+}
diff --git a/src/tabviews/custom/components/card/balcony/index.jsx b/src/tabviews/custom/components/card/balcony/index.jsx
index 1697e66..8378215 100644
--- a/src/tabviews/custom/components/card/balcony/index.jsx
+++ b/src/tabviews/custom/components/card/balcony/index.jsx
@@ -14,8 +14,7 @@
 
 class BalconyComponent extends Component {
   static propTpyes = {
-    data: PropTypes.array,
-    config: PropTypes.object,
+    config: PropTypes.object
   }
 
   state = {
@@ -23,7 +22,6 @@
     config: null,
     syncConfig: null,
     loading: false,
-    sync: false,
     data: {},
     BData: null,
     syncData: [],
@@ -34,12 +32,9 @@
   loaded = false
 
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
-    let _data = { $$empty: true }
-    let _sync = false
-
+    let _config = fromJS(config).toJS()
     let BID = ''
     let BData = ''
 
@@ -52,30 +47,30 @@
       BID = BData.$BID || ''
     }
     
+    let _data = { $$empty: true }
     if (_config.wrap.datatype === 'dynamic') {
-      _sync = _config.setting.sync === 'true'
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[_config.dataName] || {$$empty: true}
-        if (_data && Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
         }
-        _sync = false
+
+        _config.setting.sync = 'false'
+
+        _data = _data[0] || {$$empty: true}
+
         this.loaded = true
-      } else if (_sync && initdata) {
-        _data = initdata
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
-        this.loaded = true
+
+        window.GLOB.SyncData.delete(_config.dataName)
       }
-    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.get(_config.wrap.publicId)) {
-      _data = window.GLOB.CacheData.get(_config.wrap.publicId)
-      _data = fromJS(_data).toJS()
-      this.loaded = true
-    } else if (_config.wrap.datatype === 'static') {
-      this.loaded = true
+    } else if (_config.wrap.datatype === 'public') {
+      if (window.GLOB.CacheData.has(_config.wrap.publicId)) {
+        _data = window.GLOB.CacheData.get(_config.wrap.publicId)
+        _data = fromJS(_data).toJS()
+      }
     }
 
     _data.$$BID = BID || ''
@@ -84,21 +79,23 @@
       _data.$$uuid = _data[_config.setting.primaryKey] || ''
     }
 
-    if (_config.wrap.position === 'fixed' || _config.wrap.position === 'absolute') {
-      _config.style.position = _config.wrap.position
-      _config.style.zIndex = _config.wrap.position === 'fixed' ? 3 : 2
-      _config.style.left = _config.wrap.left || ''
-      _config.style.right = _config.wrap.right || ''
-      _config.style.top = _config.wrap.top || ''
-      _config.style.bottom = _config.wrap.bottom || ''
-      _config.style.transform = _config.wrap.transform || ''
-      _config.style.width = _config.wrap.realwidth || ''
-    } else {
-      _config.style.zIndex = 1
-      _config.style.left = _config.wrap.left || ''
-      _config.style.right = _config.wrap.right || ''
-      _config.style.top = _config.wrap.top || ''
-      _config.style.bottom = _config.wrap.bottom || ''
+    if (!_config.style.position) {
+      if (_config.wrap.position === 'fixed' || _config.wrap.position === 'absolute') {
+        _config.style.position = _config.wrap.position
+        _config.style.zIndex = _config.wrap.position === 'fixed' ? 3 : 2
+        _config.style.left = _config.wrap.left || ''
+        _config.style.right = _config.wrap.right || ''
+        _config.style.top = _config.wrap.top || ''
+        _config.style.bottom = _config.wrap.bottom || ''
+        _config.style.transform = _config.wrap.transform || ''
+        _config.style.width = _config.wrap.realwidth || ''
+      } else {
+        _config.style.zIndex = 1
+        _config.style.left = _config.wrap.left || ''
+        _config.style.right = _config.wrap.right || ''
+        _config.style.top = _config.wrap.top || ''
+        _config.style.bottom = _config.wrap.bottom || ''
+      }
     }
 
     let show = true
@@ -119,17 +116,9 @@
     this.setState({
       show,
       syncConfig,
-      sync: _sync,
       data: _data,
       BID: BID || '',
-      config: _config,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.wrap.datatype === 'dynamic' && _config.setting && _config.setting.sync !== 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      config: _config
     })
   }
 
@@ -137,29 +126,27 @@
     const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
     MKEmitter.addListener('syncBalconyData', this.syncBalconyData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
 
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.wrap.datatype === 'public') {
       MKEmitter.addListener('mkPublicData', this.mkPublicData)
     }
     
-    if (config.timer && config.wrap.datatype === 'dynamic') {
-      this.timer = new TimerTask()
-      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData(true)})
-    }
+    if (config.wrap.datatype === 'dynamic') {
+      if (config.timer) {
+        this.timer = new TimerTask()
+        this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData('timer')})
+      }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        let _data = res[0]
-        _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-        this.setState({data: _data})
-      })
+      this.initExec()
     }
   }
 
@@ -173,37 +160,88 @@
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('mkPublicData', this.mkPublicData)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
     MKEmitter.removeListener('syncBalconyData', this.syncBalconyData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID, BData } = this.state
+  initExec = () => {
+    const { config, BID } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = {$$empty: true}
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (_data && Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            let _data = res.data[0] || {$$empty: true}
+            _data.$$uuid = _data[config.setting.primaryKey] || ''
+    
+            this.setState({data: _data})
+          })
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            let _data = res.data[0] || {$$empty: true}
+            _data.$$uuid = _data[config.setting.primaryKey] || ''
+    
+            this.setState({data: _data})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
         }
       }
-
-      _data.$$BID = BID || ''
-      _data.$$BData = BData || ''
-      _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data})
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { BID, BData } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data[0] || {$$empty: true}
+
+    _data.$$BID = BID || ''
+    _data.$$BData = BData || ''
+    _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+    this.loaded = true
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
   }
 
   mkPublicData = (publicId, data) => {
@@ -215,8 +253,6 @@
       _data.$$BID = BID || ''
       _data.$$BData = BData || ''
       _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-      this.loaded = true
 
       this.setState({data: _data})
     }
@@ -243,11 +279,20 @@
       } else {
         this.loadData()
       }
-      
-      if (position === 'popclose') {                                      // 鏍囩鍏抽棴鍒锋柊
-        btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-      }
     }
+  }
+
+  refreshLineData = (menuId, btn, uuid, count) => {
+    const { config, data } = this.state
+
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(data).toJS()
+    _data[btn.field] = count
+
+    this.setState({
+      data: _data
+    })
   }
 
   syncBalconyData = (menuId, data, checked) => {
@@ -293,10 +338,8 @@
     if (config.uuid !== menuId) return
 
     callback({
-      arr_field: '',
       orderBy: '',
       search: [],
-      menuName: config.name
     })
   }
 
@@ -308,8 +351,8 @@
     this.loadData()
   }
 
-  async loadData (hastimer) {
-    const { config, arr_field, BID, BData } = this.state
+  async loadData (type) {
+    const { config, BID, BData } = this.state
 
     if (config.wrap.datatype === 'public') {
       MKEmitter.emit('reloadData', config.wrap.publicId)
@@ -331,22 +374,22 @@
 
     let searches = []
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let _data = {}
 
       this.loaded = true
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       if (!result.data || !result.data[0]) {
@@ -370,16 +413,32 @@
           this.timer && this.timer.stop()
         }
       }
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
+      
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/card/cardItem/index.jsx b/src/tabviews/custom/components/card/cardItem/index.jsx
index c378930..d7d8a72 100644
--- a/src/tabviews/custom/components/card/cardItem/index.jsx
+++ b/src/tabviews/custom/components/card/cardItem/index.jsx
@@ -16,19 +16,10 @@
     data: PropTypes.object,
   }
 
-  state = {
-    card: null,            // 鍗$墖淇℃伅锛屽寘鎷鍙嶉潰
-  }
-
-  /**
-   * @description 鎼滅储鏉′欢鍒濆鍖�
-   */
-  UNSAFE_componentWillMount () {
-
-  }
+  state = {}
 
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props), fromJS(nextProps))
+    return !is(fromJS(this.props.data), fromJS(nextProps.data))
   }
 
   /**
@@ -164,7 +155,6 @@
   render() {
     const { card, data, cards, children } = this.props
     let style = {...card.style}
-
     let bg = null
 
     if (card.setting.bgField) {
diff --git a/src/tabviews/custom/components/card/cardcellList/asyncButtonComponent.jsx b/src/tabviews/custom/components/card/cardcellList/asyncButtonComponent.jsx
deleted file mode 100644
index aa0307b..0000000
--- a/src/tabviews/custom/components/card/cardcellList/asyncButtonComponent.jsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import React, {Component} from 'react'
-/**
- * @description 寮傛鍔犺浇妯″潡
- * @param {*} importComponent
- */
-export default function asyncComponent(importComponent) {
-  return class extends Component {
-    constructor(props) {
-      super(props)
-
-      this.state = {
-        component: null
-      }
-    }
-
-    async componentDidMount() {
-      const {default: component} = await importComponent()
-
-      this.setState({component})
-    }
-
-    componentWillUnmount () {
-      this.setState = () => {
-        return
-      }
-    }
-    
-    // <Button className="loading-skeleton" disabled={true}></Button> // 楠ㄦ灦鎸夐挳
-    render() {
-      const C = this.state.component
-
-      return C ? <C {...this.props} /> : null
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index 030841b..fae11ad 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -5,8 +5,7 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import asyncComponent from './asyncButtonComponent'
-import asyncElementComponent from '@/utils/asyncComponent'
+import asyncComponent from '@/utils/asyncComponent'
 import { getMark } from '@/utils/utils.js'
 import MkIcon from '@/components/mk-icon'
 import Encrypts from '@/components/encrypts'
@@ -25,9 +24,9 @@
 const FuncMegvii = asyncComponent(() => import('@/tabviews/zshare/actionList/funcMegvii'))
 const FuncZip = asyncComponent(() => import('@/tabviews/zshare/actionList/funczip'))
 const EditLine = asyncComponent(() => import('@/tabviews/zshare/actionList/editLine'))
-const BarCode = asyncElementComponent(() => import('@/components/barcode'))
-const QrCode = asyncElementComponent(() => import('@/components/qrcode'))
-const MkProgress = asyncElementComponent(() => import('@/components/mkProgress'))
+const BarCode = asyncComponent(() => import('@/components/barcode'))
+const QrCode = asyncComponent(() => import('@/components/qrcode'))
+const MkProgress = asyncComponent(() => import('@/components/mkProgress'))
 const Video = asyncComponent(() => import('@/components/video'))
 const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
 const PicRadio = {
@@ -77,7 +76,7 @@
   }
 
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps))
+    return !is(fromJS(this.props.data), fromJS(nextProps.data)) || (nextProps.syncData && !is(fromJS(this.props.syncData), fromJS(nextProps.syncData)))
   }
 
   /**
@@ -200,11 +199,6 @@
     }
 
     let Id = ''
-    let con = '?'
-
-    if (/\?/ig.test(url)) {
-      con = '&'
-    }
 
     if (cards.subtype === 'propcard' && cardCell) {
       Id = cardCell.setting.primaryId || ''
@@ -213,6 +207,12 @@
     }
     
     if (card.joint === 'true') {
+      let con = '?'
+
+      if (/\?/ig.test(url)) {
+        con = '&'
+      }
+
       url = url + `${con}id=${Id}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
     }
 
@@ -265,6 +265,8 @@
 
       if (card.style && card.style.clear === 'left') {
         _style_ = {clear: 'left'}
+      } else if (card.style && card.style.clear === 'right') {
+        _style_ = {float: 'right'}
       }
 
       if (card.eleType === 'sequence') {
@@ -524,6 +526,8 @@
 
         if (card.datatype === 'dynamic') {
           icon = data[card.field] || ''
+        } else if (card.tipType === 'text') {
+          icon = card.value
         } else {
           icon = card.icon
         }
@@ -537,16 +541,38 @@
         } else {
           val = card.tooltip
         }
-  
-        contents.push(
-          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
-            <div style={card.style}>
-              {val ? <Tooltip title={val}>
-                <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>
-              </Tooltip> : <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>}
+
+        if (/\\n|\n/.test(val)) {
+          val = val.replace(/(\\n|\n)$/, '')
+        
+          if (val) {
+            val = val.split(/\\n|\n/)
+        
+            val = <div>{val.map((cell, i) => <div style={{marginBottom: 2}} key={i}>{cell}</div>)}</div>
+          }
+        }
+
+        if (card.tipType === 'text') {
+          contents.push(
+            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+              <div style={card.style}>
+                {val ? <Tooltip title={val}>
+                  <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}}>{icon}</div>
+                </Tooltip> : <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}}>{icon}</div>}
+              </div>
             </div>
-          </div>
-        )
+          )
+        } else {
+          contents.push(
+            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+              <div style={card.style}>
+                {val ? <Tooltip title={val}>
+                  <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>
+                </Tooltip> : <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>}
+              </div>
+            </div>
+          )
+        }
       } else if (card.eleType === 'slider') {
         let val = 0
         let color = card.color
@@ -734,8 +760,26 @@
       } else if (card.eleType === 'formula') {
         let val = 0
         let _style = {...card.style}
+        
+        if (card.eval === 'func') {
+          let _data = []
+          if (card.$sync) {
+            _data = this.props.syncData
+          } else if (data && !data.$$empty) {
+            _data = [data]
+          }
 
-        if (card.$sync) {
+          try {
+            // eslint-disable-next-line
+            let func = new Function('data', card.formula)
+            val = func(_data)
+          } catch (e) {
+            if (window.GLOB.debugger === true) {
+              console.warn(e)
+            }
+            val = ''
+          }
+        } else if (card.$sync) {
           if (card.eval === 'false') {
             val = ''
           }
@@ -750,7 +794,7 @@
                 // eslint-disable-next-line
                 _val = eval(_val)
               } catch (e) {
-                if (window.debugger) {
+                if (window.GLOB.debugger === true) {
                   console.info(_val)
                   console.warn(e)
                 }
@@ -776,7 +820,7 @@
               // eslint-disable-next-line
               _val = eval(_val)
             } catch (e) {
-              if (window.debugger) {
+              if (window.GLOB.debugger === true) {
                 console.info(_val)
                 console.warn(e)
               }
@@ -789,6 +833,15 @@
 
         if (!val && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
+        } else if (card.eval === 'func') {
+          contents.push(
+            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+              <div style={_style}>
+                <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}} dangerouslySetInnerHTML={{__html: val}}></div>
+              </div>
+            </div>
+          )
+          return
         }
 
         if (card.round && typeof(val) === 'number') {
@@ -892,6 +945,9 @@
   
         if (data.$$type === 'extendCard') {
           _data = data.$$selectedData || []
+          if (card.Ot === 'notRequired' && _data.length === 0) {
+            _data = [data]
+          }
         } else if (card.$sync) {
           _data = this.props.syncData || []
         } else if (data.$$empty) {
@@ -973,6 +1029,7 @@
             <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}
diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss
index 4fc1ddf..07ac844 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.scss
+++ b/src/tabviews/custom/components/card/cardcellList/index.scss
@@ -194,6 +194,9 @@
     height: 26px;
   }
 
+  .ant-col {
+    min-height: 0px;
+  }
   .ant-col[class*="x"] {
     float: left;
     box-sizing: border-box;
diff --git a/src/tabviews/custom/components/card/data-card/index.jsx b/src/tabviews/custom/components/card/data-card/index.jsx
index 9b84661..96e55f2 100644
--- a/src/tabviews/custom/components/card/data-card/index.jsx
+++ b/src/tabviews/custom/components/card/data-card/index.jsx
@@ -5,7 +5,6 @@
 import { DownOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
-import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import preImg from '@/assets/img/prev.png'
 import nextImg from '@/assets/img/next.png'
@@ -21,9 +20,7 @@
 
 class DataCard extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -35,13 +32,12 @@
     pageSize: 10,
     orderBy: '',
     pageOptions: [],
-    activeKey: '',             // 閫変腑鍗�
-    selectKeys: [],            // 澶氶�夋椂閫変腑鍗$墖
-    selectedData: [],          // 閫変腑鏁版嵁锛岀敤浜庡伐鍏锋爮鎸夐挳
-    loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
-    card: null,                // 鍗$墖璁剧疆
-    data: null,                // 鏁版嵁
+    activeKey: '',
+    selectKeys: [],
+    selectedData: [],
+    loading: false,
+    card: null,
+    data: null,
     total: null,
     precards: [],
     nextcards: [],
@@ -53,9 +49,9 @@
   loaded = false
 
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let BID = ''
     let BData = ''
 
@@ -95,6 +91,14 @@
         }
       }
 
+      if (item.style.clear === 'left') {
+        item.wStyle = {clear: 'left'}
+      } else if (item.style.clear === 'right') {
+        item.wStyle = {float: 'right'}
+      }
+
+      delete item.style.clear
+
       if (item.$cardType !== 'extendCard') {
         _card = item
       } else if (!_card) {
@@ -111,49 +115,12 @@
     })
 
     _config.subcards = null
-    
-    let _data = null
-    let _sync = _config.setting.sync === 'true'
-
-    if (_sync && data) {
-      _data = data[_config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      _data = initdata || []
-      _sync = false
-    }
 
     let selected = 'false'
     if (_config.wrap.selected === 'always' || _config.wrap.selected === 'init' || _config.wrap.selected === 'sign') {
       selected = _config.wrap.selected
     } else {
       _config.wrap.selected = 'false'
-    }
-
-    if (_data) {
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[_config.setting.primaryKey] || ''
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1 + ''
-
-        if (_config.wrap.controlField) {
-          if (_config.wrap.controlVal.includes(item[_config.wrap.controlField] + '')) {
-            item.$disabled = true
-          }
-        }
-        return item
-      })
-
-      if (selected !== 'false') {
-        setTimeout(() => {
-          this.checkTopLine()
-        }, 200)
-        if (selected === 'init') {
-          selected = 'false'
-        }
-      }
     }
 
     let supComs = null
@@ -167,8 +134,6 @@
     _config.wrap.layout = (_config.wrap.layout || 'grid') + '-layout float-' + (_config.wrap.cardFloat || 'left')
 
     _config.wrap.wrapClass =  `${_config.wrap.selStyle} ${_config.wrap.cardType || ''} ${_config.wrap.scale}`
-
-    this.loaded = _data !== null
 
     let pageOptions = ['10', '25', '50', '100', '500', '1000']
 
@@ -184,6 +149,40 @@
       }
     }
 
+    let _data = null
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        _data = _data.map((item, index) => {
+          item.key = index
+          item.$$uuid = item[_config.setting.primaryKey] || ''
+          item.$$BID = BID || ''
+          item.$$BData = BData || ''
+          item.$Index = index + 1 + ''
+  
+          if (_config.wrap.controlField) {
+            if (_config.wrap.controlVal.includes(item[_config.wrap.controlField] + '')) {
+              item.$disabled = true
+            }
+          }
+          return item
+        })
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
+    }
+
     this.setState({
       pageSize: _config.setting.pageSize || 10,
       pageOptions,
@@ -191,20 +190,12 @@
       selected,
       precards,
       nextcards,
-      sync: _sync,
       data: _data,
       BID: BID || '',
       BData: BData || '',
       config: _config,
       card: _card,
-      search: Utils.initMainSearch(_config.search),
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      search: _config.$searches
     })
   }
 
@@ -213,9 +204,18 @@
 
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('mkCheckAll', this.mkCheckAll)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
     
     if (config.timer) {
       this.timer = new TimerTask()
@@ -228,73 +228,11 @@
       })
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-        let _data = res.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[config.setting.primaryKey] || ''
-          item.$Index = index + 1 + ''
-
-          if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
-              item.$disabled = true
-            }
-          }
-
-          return item
-        })
-
-        this.setState({data: _data})
-      })
-    }
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID, BData, selected } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-        _data = _data.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[config.setting.primaryKey] || ''
-          item.$$BID = BID || ''
-          item.$$BData = BData || ''
-          item.$Index = index + 1 + ''
-
-          if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
-              item.$disabled = true
-            }
-          }
-
-          return item
-        })
-
-        if (selected !== 'false') {
-          setTimeout(() => {
-            this.checkTopLine()
-          }, 200)
-          if (selected === 'init') {
-            this.setState({selected: 'false'})
-          }
-        }
-      }
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({pageIndex: 1}, () => {
-        this.loadData()
-      })
-    }
   }
 
   componentWillUnmount () {
@@ -303,11 +241,136 @@
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('mkCheckAll', this.mkCheckAll)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    this.loaded && this.prevCheck()
+
+    if (config.$cache) {
+      if (config.$time && !config.setting.laypage) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('', 'init')
+              }, config.setting.delay || 0)
+            }
+
+            if (!res.data || this.loaded) return
+
+            let _data = res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+    
+              if (config.wrap.controlField) {
+                if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
+                  item.$disabled = true
+                }
+              }
+    
+              return item
+            })
+    
+            this.setState({data: _data}, () => {
+              this.prevCheck()
+            })
+          })
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            let _data = res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+    
+              if (config.wrap.controlField) {
+                if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
+                  item.$disabled = true
+                }
+              }
+    
+              return item
+            })
+    
+            this.setState({data: _data})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('', 'init')
+          }, config.setting.delay || 0)
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { BID, BData } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data.map((item, index) => {
+      item.key = index
+      item.$$uuid = item[config.setting.primaryKey] || ''
+      item.$$BID = BID || ''
+      item.$$BData = BData || ''
+      item.$Index = index + 1 + ''
+
+      if (config.wrap.controlField) {
+        if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
+          item.$disabled = true
+        }
+      }
+
+      return item
+    })
+
+    this.prevCheck()
+
+    this.loaded = true
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({pageIndex: 1}, () => {
+      this.loadData()
+    })
   }
 
   /**
@@ -371,9 +434,36 @@
         this.loadData(id)
       }
     }
+  }
 
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
+  refreshLineData = (menuId, btn, uuid, count) => {
+    const { config, data } = this.state
+
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(data).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
+      }
+      return item
+    })
+
+    this.setState({
+      data: _data
+    })
+  }
+
+  prevCheck = (id) => {
+    const { selected } = this.state
+
+    if (selected === 'false' && !id) return
+
+    setTimeout(() => {
+      this.checkTopLine(id)
+    }, 10)
+
+    if (selected === 'init') {
+      this.setState({selected: 'false'})
     }
   }
 
@@ -593,32 +683,29 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, search, orderBy } = this.state
+    const { config, search, orderBy } = this.state
 
     if (config.uuid !== menuId) return
 
-    let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    let searches = fromJS(search).toJS()
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
-      orderBy: orderBy ||config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      orderBy: orderBy || config.setting.order || '',
+      search: searches
     })
   }
 
   async loadData (id, type) {
-    const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, pageSize, search, BID, BData, selected, orderBy } = this.state
+    const { config, pageIndex, pageSize, search, BID, BData, selected, orderBy } = this.state
 
     if (config.setting.supModule && !BID && config.wrap.supKey !== 'false') { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.loaded = true
@@ -634,12 +721,7 @@
       })
       
       if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
-        setTimeout(() => {
-          this.checkTopLine(id)
-        }, 200)
-        if (selected === 'init') {
-          this.setState({selected: 'false'})
-        }
+        this.prevCheck(id)
       } else {
         MKEmitter.emit('resetSelectLine', config.uuid, '', '')
         if (config.setting.$hasSyncModule) {
@@ -650,17 +732,17 @@
     }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -671,7 +753,7 @@
     }
 
     let _orderBy = orderBy || config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -681,17 +763,12 @@
       }
 
       this.loaded = true
-      if (config.$cache && pageIndex === 1 && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
-        setTimeout(() => {
-          this.checkTopLine(id)
-        }, 200)
-        if (selected === 'init') {
-          this.setState({selected: 'false'})
-        }
+        this.prevCheck(id)
       } else {
         MKEmitter.emit('resetSelectLine', config.uuid, '', '')
         if (config.setting.$hasSyncModule) {
@@ -734,12 +811,17 @@
         })
       }
 
+      let total = result.total || 0
+      if (config.setting.custompage && data.length) {
+        total = data[data.length - 1].mk_total || 0
+      }
+
       this.setState({
         activeKey: '',
         selectKeys: [],
         selectedData: [],
         data: data,
-        total: result.total,
+        total: total,
         loading: false
       })
 
@@ -749,16 +831,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
+
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -772,16 +869,25 @@
    * @description 鑾峰彇鍗曡鏁版嵁
    */ 
   async loadLinedata (id) {
-    const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
+    const { config, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
+
+    if (config.forbidLine) {
+      this.setState({
+        pageIndex: 1
+      }, () => {
+        this.loadData()
+      })
+      return
+    }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
@@ -790,38 +896,104 @@
     })
 
     let _orderBy = orderBy || config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let data = fromJS(this.state.data).toJS()
+      let selectedData = fromJS(this.state.selectedData).toJS()
+      let selectKeys = fromJS(this.state.selectKeys).toJS()
+      let activeKey = this.state.activeKey
+
       if (result.data && result.data[0]) {
         let _data = result.data[0]
+        _data.$$uuid = _data[config.setting.primaryKey] || ''
+        _data.$$BID = BID || ''
+        _data.$$BData = BData || ''
 
-        try {
-          data = data.map(item => {
-            if (item[config.setting.primaryKey] === _data[config.setting.primaryKey]) {
-              _data.key = item.key
-              _data.$$uuid = _data[config.setting.primaryKey] || ''
-              _data.$$BID = BID || ''
-              _data.$$BData = BData || ''
-              _data.$Index = item.$Index
-              return _data
-            } else {
-              return item
-            }
+        data = data.map(item => {
+          if (item.$$uuid === _data.$$uuid) {
+            _data.key = item.key
+            _data.$Index = item.$Index
+            return _data
+          }
+          return item
+        })
+
+        if (!_data.$Index) {
+          this.setState({
+            loading: false
           })
-        } catch (e) {
-          console.warn('鏁版嵁鏌ヨ閿欒')
+          return
         }
 
-        MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
-      }
+        selectedData = selectedData.map(item => {
+          if (item.$$uuid === _data.$$uuid) {
+            return _data
+          }
+          return item
+        })
 
-      this.setState({
-        data: data,
-        loading: false
-      })
+        this.setState({
+          data: data,
+          selectedData: selectedData,
+          loading: false
+        })
+
+        if (_data.key === activeKey) {
+          MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
+        }
+        if (config.setting.$hasSyncModule) {
+          MKEmitter.emit('syncBalconyData', config.uuid, selectedData, data.length === selectedData.length)
+        }
+      } else {
+        let index = data.findIndex(item => item.$$uuid === id)
+
+        if (index === -1) {
+          this.setState({
+            loading: false
+          })
+          return
+        }
+
+        data = data.filter(item => item.$$uuid !== id)
+        data = data.map((item, i) => {
+          item.key = i
+          return item
+        })
+        
+        let trans = activeKey === index
+        let _item = null
+        
+        if (config.wrap.cardType) {
+          selectKeys = selectKeys.filter(key => key !== index)
+          selectKeys = selectKeys.map(key => key > index ? key - 1 : key)
+
+          selectedData = selectKeys.map(key => data[key]).filter(Boolean)
+
+          activeKey = selectKeys.length ? selectKeys[selectKeys.length - 1] : ''
+
+          if (trans && selectedData.length) {
+            _item = selectedData[selectedData.length - 1]
+          }
+        }
+
+        this.setState({
+          data: data,
+          activeKey: activeKey,
+          selectKeys: selectKeys,
+          selectedData: selectedData,
+          loading: false
+        })
+
+        if (trans) {
+          MKEmitter.emit('resetSelectLine', config.uuid, (_item ? _item.$$uuid : ''), _item)
+        }
+
+        if (config.setting.$hasSyncModule) {
+          MKEmitter.emit('syncBalconyData', config.uuid, selectedData, data.length === selectedData.length)
+        }
+      }
     } else {
       this.setState({
         loading: false
@@ -929,6 +1101,7 @@
       if (activeKey === index) return
 
       _selectedData = [item]
+      _selectKeys = [index]
       _activeKey = index
     }
 
@@ -1008,7 +1181,7 @@
           {switchable ? <div className={'prev-page ' + (pageIndex === 1 ? 'disabled' : '')} onClick={this.prevPage}><div><div><img src={preImg} alt=""/></div></div></div> : null}
           <Row className={'card-row-list ' + config.wrap.layout}>
             {precards.map((item, index) => (
-              <Col key={'pre' + index} className="extend-card" span={item.setting.width || 6}>
+              <Col key={'pre' + index} className="extend-card" style={item.wStyle} span={item.setting.width || 6}>
                 {item.setting.cardRole === 'header' ? <TableHeader card={item} data={extendData} refresh={this.refreshByHeader}>
                   {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
                 </TableHeader> : <CardItem card={item} cards={config} data={extendData}>
@@ -1032,7 +1205,7 @@
               }
 
               return (
-                <Col className={className} key={index} span={card.setting.width}>
+                <Col className={className} key={index} style={card.wStyle} span={card.setting.width}>
                   <CardItem card={card} cards={config} data={item} onClick={() => {this.changeCard(index, item)}}>
                     <span className="circle-select"></span>
                   </CardItem>
@@ -1040,7 +1213,7 @@
               )
             })}
             {nextcards.map((item, index) => (
-              <Col key={'next' + index} className="extend-card" span={item.setting.width || 6}>
+              <Col key={'next' + index} className="extend-card" style={item.wStyle} span={item.setting.width || 6}>
                 {item.setting.cardRole === 'header' ? <TableHeader card={item} data={extendData} refresh={this.refreshByHeader}>
                   {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
                 </TableHeader> : <CardItem card={item} cards={config} data={extendData}>
diff --git a/src/tabviews/custom/components/card/data-card/index.scss b/src/tabviews/custom/components/card/data-card/index.scss
index bb71f96..ea3ac4a 100644
--- a/src/tabviews/custom/components/card/data-card/index.scss
+++ b/src/tabviews/custom/components/card/data-card/index.scss
@@ -39,6 +39,7 @@
   }
   .card-row-list {
     flex: 10;
+    max-width: 100%;
   }
   .card-row-list.flex-layout {
     display: flex;
@@ -158,6 +159,7 @@
     display: none;
     width: 16px;
     height: 16px;
+    min-width: 16px;
     border: 1px solid #cccccc;
     border-radius: 50%;
     box-sizing: content-box;
diff --git a/src/tabviews/custom/components/card/double-data-card/index.jsx b/src/tabviews/custom/components/card/double-data-card/index.jsx
index ddf5d2d..53048cb 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.jsx
+++ b/src/tabviews/custom/components/card/double-data-card/index.jsx
@@ -5,7 +5,6 @@
 import { DownOutlined, UpOutlined, PlusSquareOutlined, MinusSquareOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
-import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import MKEmitter from '@/utils/events.js'
 import TimerTask from '@/utils/timer-task.js'
@@ -20,7 +19,6 @@
 class DoubleDataCard extends Component {
   static propTpyes = {
     config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
   }
 
   state = {
@@ -93,6 +91,14 @@
         }
       }
 
+      if (item.style.clear === 'left') {
+        item.wStyle = {clear: 'left'}
+      } else if (item.style.clear === 'right') {
+        item.wStyle = {float: 'right'}
+      }
+
+      delete item.style.clear
+
       if (item.$cardType !== 'extendCard') {
         _card = item
       } else if (!_card) {
@@ -110,8 +116,6 @@
 
     _config.subcards = null
     
-    let _data = null
-
     let selected = 'false'
     if (_config.wrap.selected === 'always' || _config.wrap.selected === 'init' || _config.wrap.selected === 'sign') {
       selected = _config.wrap.selected
@@ -123,8 +127,6 @@
     _config.wrap.pagestyle = _config.wrap.pagestyle || 'page'
 
     _config.wrap.wrapClass =  `${_config.wrap.selStyle} ${_config.wrap.cardType || ''}`
-
-    this.loaded = _data !== null
 
     let wrapStyle = null
     let subcard = fromJS(_card).toJS()
@@ -147,6 +149,8 @@
     }
 
     _config.setting.sub_field = subconfig.columns.map(col => col.field).join(',')
+    _config.setting.all_field = _config.setting.arr_field + ',' + _config.setting.sub_field
+
     let pageOptions = ['10', '25', '50', '100', '500', '1000']
 
     if (!_config.setting.laypage) {
@@ -180,7 +184,6 @@
       selected,
       precards,
       nextcards,
-      data: _data,
       BID: BID || '',
       BData: BData || '',
       config: _config,
@@ -188,14 +191,7 @@
       subconfig: subconfig,
       wrapStyle: wrapStyle,
       card: _card,
-      search: Utils.initMainSearch(_config.search),
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      search: _config.$searches
     })
   }
 
@@ -203,10 +199,15 @@
     const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
     
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
@@ -218,10 +219,35 @@
       })
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-        let _data = res.map((item, index) => {
+    if (config.setting.onload === 'true') {
+      this.initExec()
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      let getData = (res) => {
+        return res.map((item, index) => {
           let children = []
 
           if (item[config.setting.subdata]) {
@@ -257,43 +283,50 @@
 
           return item
         })
+      }
+      
+      if (config.$time && !config.setting.laypage) {
+        Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+          if (!res.valid) {
+            setTimeout(() => {
+              this.loadData('', 'init')
+            }, config.setting.delay || 0)
+          }
 
-        this.setState({data: _data})
-      })
+          if (!res.data) return
+  
+          this.setState({data: getData(res.data)})
+        })
+      } else {
+        Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+          if (!res.data || this.loaded) return
+  
+          this.setState({data: getData(res.data)})
+        })
+
+        setTimeout(() => {
+          this.loadData('', 'init')
+        }, config.setting.delay || 0)
+      }
+    } else {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
     }
   }
 
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  UNSAFE_componentWillReceiveProps (nextProps) {
+  searchRefresh = (searchId) => {
     const { config } = this.state
 
-    if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({pageIndex: 1}, () => {
-        this.loadData()
-      })
-    }
-  }
-
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    MKEmitter.removeListener('reloadData', this.reloadData)
-    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
-    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
-    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
-
-    this.timer && this.timer.stop()
+    if (config.$searchId !== searchId) return
+    
+    this.setState({pageIndex: 1}, () => {
+      this.loadData()
+    })
   }
 
   /**
    * @description 鎸夐挳鎵ц瀹屾垚鍚庨〉闈㈠埛鏂�
-   * @param {*} menuId     // 鑿滃崟Id
-   * @param {*} position   // 鍒锋柊浣嶇疆
-   * @param {*} btn        // 鎵ц鐨勬寜閽�
    */
   refreshByButtonResult = (menuId, position, btn, id = '', lines) => {
     const { config, BID } = this.state
@@ -319,10 +352,28 @@
     } else {
       this.loadData(id)
     }
+  }
 
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
+  refreshLineData = (menuId, btn, uuid, count) => {
+    const { config, data } = this.state
+
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(data).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
+      }
+      item.children.forEach(cell => {
+        if (cell.$$uuid === uuid) {
+          cell[btn.field] = count
+        }
+      })
+      return item
+    })
+
+    this.setState({
+      data: _data
+    })
   }
 
   checkTopLine = (id) => {
@@ -473,32 +524,29 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, search, orderBy } = this.state
+    const { config, search, orderBy } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: orderBy || config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
   async loadData (id, type) {
-    const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, pageSize, search, BID, BData, selected, card, orderBy } = this.state
+    const { config, pageIndex, pageSize, search, BID, BData, selected, card, orderBy } = this.state
 
     if (config.setting.supModule && !BID && config.wrap.supKey !== 'false') { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.loaded = true
@@ -517,7 +565,7 @@
       if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
         setTimeout(() => {
           this.checkTopLine(id)
-        }, 200)
+        }, 10)
         if (selected === 'init') {
           this.setState({selected: 'false'})
         }
@@ -528,17 +576,17 @@
     }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -549,7 +597,7 @@
     }
 
     let _orderBy = orderBy || config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -559,14 +607,14 @@
       }
 
       this.loaded = true
-      if (config.$cache && pageIndex === 1 && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
         setTimeout(() => {
           this.checkTopLine(id)
-        }, 200)
+        }, 10)
         if (selected === 'init') {
           this.setState({selected: 'false'})
         }
@@ -663,13 +711,18 @@
         opens = []
       }
 
+      let total = result.total || 0
+      if (config.setting.custompage && data.length) {
+        total = data[data.length - 1].mk_total || 0
+      }
+
       this.setState({
         activeKey: '',
         selectKeys: [],
         opens: opens,
         selectedData: [],
         data: data,
-        total: result.total,
+        total: total,
         loading: false
       })
 
@@ -679,16 +732,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
+
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -702,16 +770,25 @@
    * @description 鑾峰彇鍗曡鏁版嵁
    */ 
   async loadLinedata (id) {
-    const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
+    const { config, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
+
+    if (config.forbidLine) {
+      this.setState({
+        pageIndex: 1
+      }, () => {
+        this.loadData()
+      })
+      return
+    }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
@@ -720,61 +797,120 @@
     })
 
     let _orderBy = orderBy || config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let data = fromJS(this.state.data).toJS()
+      let selectedData = fromJS(this.state.selectedData).toJS()
+      let selectKeys = fromJS(this.state.selectKeys).toJS()
+      let activeKey = this.state.activeKey
+
       if (result.data && result.data[0]) {
         let _data = result.data[0]
+        _data.$$uuid = _data[config.setting.primaryKey] || ''
+        _data.$$BID = BID || ''
+        _data.$$BData = BData || ''
 
-        try {
-          data = data.map(item => {
-            if (item[config.setting.primaryKey] === _data[config.setting.primaryKey]) {
-              let children = []
+        data = data.map(item => {
+          if (item.$$uuid === _data.$$uuid) {
+            let children = []
 
-              if (_data[config.setting.subdata]) {
-                let _children = _data[config.setting.subdata]
+            if (_data[config.setting.subdata]) {
+              let _children = _data[config.setting.subdata]
 
-                delete _data[config.setting.subdata]
+              delete _data[config.setting.subdata]
 
-                _children.forEach((cell, i) => {
-                  cell.key = i
-                  cell.$$uuid = cell[config.setting.subKey] || ''
-                  cell.$$parentId = _data[config.setting.primaryKey] || ''
-                  cell.$$BID = _data[config.setting.primaryKey] || ''
-                  cell.$$BData = {..._data}
-                  cell.$Index = i + 1 + ''
+              _children.forEach((cell, i) => {
+                cell.key = i
+                cell.$$uuid = cell[config.setting.subKey] || ''
+                cell.$$parentId = _data[config.setting.primaryKey] || ''
+                cell.$$BID = _data[config.setting.primaryKey] || ''
+                cell.$$BData = {..._data}
+                cell.$Index = i + 1 + ''
 
-                  if (cell.$$uuid) {
-                    children.push(cell)
-                  }
-                })
-              }
-
-              _data.children = children
-
-              _data.key = item.key
-              _data.$$uuid = _data[config.setting.primaryKey] || ''
-              _data.$$BID = BID || ''
-              _data.$$BData = BData || ''
-              _data.$Index = item.$Index
-              return _data
-            } else {
-              return item
+                if (cell.$$uuid) {
+                  children.push(cell)
+                }
+              })
             }
+
+            _data.children = children
+            _data.key = item.key
+            _data.$Index = item.$Index
+            return _data
+          } else {
+            return item
+          }
+        })
+
+        if (!_data.$Index) {
+          this.setState({
+            loading: false
           })
-        } catch (e) {
-          console.warn('鏁版嵁鏌ヨ閿欒')
+          return
         }
 
-        MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
-      }
+        selectedData = selectedData.map(item => {
+          if (item.$$uuid === _data.$$uuid) {
+            return _data
+          }
+          return item
+        })
 
-      this.setState({
-        data: data,
-        loading: false
-      })
+        this.setState({
+          data: data,
+          selectedData: selectedData,
+          loading: false
+        })
+
+        if (_data.key === activeKey) {
+          MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
+        }
+      } else {
+        let index = data.findIndex(item => item.$$uuid === id)
+
+        if (index === -1) {
+          this.setState({
+            loading: false
+          })
+          return
+        }
+
+        data = data.filter(item => item.$$uuid !== id)
+        data = data.map((item, i) => {
+          item.key = i
+          return item
+        })
+        
+        let trans = activeKey === index
+        let _item = null
+        
+        if (config.wrap.cardType) {
+          selectKeys = selectKeys.filter(key => key !== index)
+          selectKeys = selectKeys.map(key => key > index ? key - 1 : key)
+
+          selectedData = selectKeys.map(key => data[key]).filter(Boolean)
+
+          activeKey = selectKeys.length ? selectKeys[selectKeys.length - 1] : ''
+
+          if (trans && selectedData.length) {
+            _item = selectedData[selectedData.length - 1]
+          }
+        }
+
+        this.setState({
+          data: data,
+          activeKey: activeKey,
+          selectKeys: selectKeys,
+          selectedData: selectedData,
+          loading: false
+        })
+
+        if (trans) {
+          MKEmitter.emit('resetSelectLine', config.uuid, (_item ? _item.$$uuid : ''), _item)
+        }
+      }
     } else {
       this.setState({
         loading: false
@@ -865,6 +1001,7 @@
       if (activeKey === index) return
 
       _selectedData = [item]
+      _selectKeys = [index]
       _activeKey = index
     }
 
@@ -1003,7 +1140,7 @@
           <div className={`data-zoom ${config.wrap.wrapClass}`} style={config.wrap.minWidth ? {minWidth: config.wrap.minWidth} : null}>
             <Row className={'card-row-list '}>
               {precards.map((item, index) => (
-                <Col key={'pre' + index} className="extend-card" span={item.setting.width || 6}>
+                <Col key={'pre' + index} className="extend-card" style={item.wStyle} span={item.setting.width || 6}>
                   {item.setting.cardRole === 'header' ? <TableHeader card={item} data={extendData} refresh={this.refreshByHeader}>
                     {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
                   </TableHeader> : <CardItem card={item} cards={config} data={extendData}>
@@ -1035,7 +1172,7 @@
                 }
 
                 return (
-                  <Col key={index} span={card.setting.width}>
+                  <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(index, subClass)} onClick={() => {this.changeCard(index, item, subClass)}}>
                         <span className="circle-select"></span>
@@ -1052,7 +1189,7 @@
                 )
               })}
               {nextcards.map((item, index) => (
-                <Col key={'next' + index} className="extend-card" span={item.setting.width || 6}>
+                <Col key={'next' + index} className="extend-card" style={item.wStyle} span={item.setting.width || 6}>
                   {item.setting.cardRole === 'header' ? <TableHeader card={item} data={extendData} refresh={this.refreshByHeader}>
                     {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
                   </TableHeader> : <CardItem card={item} cards={config} data={extendData}>
diff --git a/src/tabviews/custom/components/card/double-data-card/index.scss b/src/tabviews/custom/components/card/double-data-card/index.scss
index 0ee2e47..c6a13e8 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.scss
+++ b/src/tabviews/custom/components/card/double-data-card/index.scss
@@ -34,6 +34,7 @@
   }
   .card-row-list {
     flex: 10;
+    max-width: 100%;
   }
   .card-row-list.flex-layout {
     display: flex;
@@ -130,6 +131,7 @@
     display: none;
     width: 16px;
     height: 16px;
+    min-width: 16px;
     border: 1px solid #cccccc;
     border-radius: 50%;
     box-sizing: content-box;
diff --git a/src/tabviews/custom/components/card/prop-card/index.jsx b/src/tabviews/custom/components/card/prop-card/index.jsx
index 592322d..f114efa 100644
--- a/src/tabviews/custom/components/card/prop-card/index.jsx
+++ b/src/tabviews/custom/components/card/prop-card/index.jsx
@@ -15,9 +15,7 @@
 
 class PropCard extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -25,21 +23,19 @@
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
     activeKey: '',             // 閫変腑鏁版嵁
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: {},                  // 鏁版嵁
     BData: '',
     selected: 'false',
   }
 
   loaded = false
+  autoTimer = null
 
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = { $$empty: true }
-    let _sync = false
-
     let BID = ''
     let BData = ''
 
@@ -51,26 +47,26 @@
     if (BData) {
       BID = BData.$BID || ''
     }
-    
-    if (_config.wrap.datatype === 'dynamic') {
-      _sync = _config.setting.sync === 'true'
 
-      if (_sync && data) {
-        _data = data[_config.dataName] || {$$empty: true}
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
+    if (_config.wrap.datatype === 'dynamic') {
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
+
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
         }
-        _sync = false
+
+        _config.setting.sync = 'false'
+
+        _data = _data[0] || {$$empty: true}
+
         this.loaded = true
-      } else if (_sync && initdata) {
-        _data = initdata
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
-        this.loaded = true
+
+        window.GLOB.SyncData.delete(_config.dataName)
       }
-    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.get(_config.wrap.publicId)) {
+    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.has(_config.wrap.publicId)) {
       _data = window.GLOB.CacheData.get(_config.wrap.publicId)
       _data = fromJS(_data).toJS()
       this.loaded = true
@@ -95,6 +91,14 @@
           card.setting.click = ''
         }
       }
+
+      if (card.style.clear === 'left') {
+        card.wStyle = {clear: 'left'}
+      } else if (card.style.clear === 'right') {
+        card.wStyle = {float: 'right'}
+      }
+
+      delete card.style.clear
     })
 
     let selected = _config.wrap.selected || 'false'
@@ -111,43 +115,10 @@
 
     this.setState({
       selected,
-      sync: _sync,
       data: _data,
       BID: BID || '',
       BData: BData || '',
-      config: _config,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.wrap.datatype === 'dynamic' && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      } else if (_config.wrap.datatype === 'public') {
-        if (_data.$$loaded && selected !== 'false') {
-          setTimeout(() => {
-            this.checkTopLine()
-          }, 200)
-        }
-      } else if (!_sync && selected !== 'false') {
-        setTimeout(() => {
-          this.checkTopLine()
-        }, 200)
-      }
-
-      if (_config.wrap.datatype === 'dynamic' && this.loaded) {
-        if (_config.wrap.goback === 'true' && _data.$$empty) {
-          this.timer && this.timer.stop()
-
-          MKEmitter.emit('closeTabView', _config.$pageId)
-        } else {
-          this.autoExec()
-        }
-      }
-      if (_data.$$uuid) {
-        setTimeout(() => {
-          this.transferLine()
-        }, 200)
-      }
+      config: _config
     })
   }
 
@@ -155,9 +126,18 @@
     const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
 
     if (config.wrap.datatype === 'public') {
       MKEmitter.addListener('mkPublicData', this.mkPublicData)
@@ -165,19 +145,10 @@
 
     if (config.timer && config.wrap.datatype === 'dynamic') {
       this.timer = new TimerTask()
-      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData(true)})
+      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData('timer')})
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        let _data = res[0]
-        _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-        this.setState({data: _data})
-      })
-    }
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -190,53 +161,187 @@
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('mkPublicData', this.mkPublicData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
   }
 
-  /**
-   * @description 鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID, BData, selected } = this.state
+  initExec = () => {
+    const { config, selected, data, BID } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = { $$empty: true }
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
+    if (config.wrap.datatype === 'dynamic') {
+      if (config.$cache) {
+        if (config.$time) {
+          if (!this.loaded) {
+            Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+              if (!res.valid && config.setting.onload === 'true') {
+                setTimeout(() => {
+                  this.loadData('init')
+                }, config.setting.delay || 0)
+              }
+
+              if (!res.data || this.loaded) return
+  
+              let _data = res.data[0] || {$$empty: true}
+              _data.$$uuid = _data[config.setting.primaryKey] || ''
+      
+              this.setState({data: _data}, () => {
+                if (selected !== 'false') {
+                  this.checkTopLine()
+                }
+              })
+            })
+          } else {
+            if (config.wrap.goback === 'true' && data.$$empty) {
+              this.timer && this.timer.stop()
+    
+              MKEmitter.emit('closeTabView', config.$pageId)
+            } else {
+              if (selected !== 'false') {
+                this.checkTopLine()
+              } else {
+                this.transferLine()
+              }
+              this.autoExec()
+            }
+          }
+        } else {
+          if (!this.loaded) {
+            Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+              if (!res.data || this.loaded) return
+      
+              let _data = res.data[0] || {$$empty: true}
+              _data.$$uuid = _data[config.setting.primaryKey] || ''
+      
+              this.setState({data: _data})
+            })
+          }
+  
+          if (config.setting.onload === 'true') {
+            setTimeout(() => {
+              this.loadData('init')
+            }, config.setting.delay || 0)
+          } else if (this.loaded) {
+            if (config.wrap.goback === 'true' && data.$$empty) {
+              this.timer && this.timer.stop()
+    
+              MKEmitter.emit('closeTabView', config.$pageId)
+            } else {
+              if (selected !== 'false') {
+                this.checkTopLine()
+              } else {
+                this.transferLine()
+              }
+              this.autoExec()
+            }
+          }
         }
-      }
-
-      _data.$$BID = BID || ''
-      _data.$$BData = BData || ''
-      _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data}, () => {
-        if (config.wrap.goback === 'true' && _data.$$empty) {
+      } else if (config.setting.onload === 'true') {
+        setTimeout(() => {
+          this.loadData()
+        }, config.setting.delay || 0)
+      } else if (this.loaded) {
+        if (config.wrap.goback === 'true' && data.$$empty) {
           this.timer && this.timer.stop()
 
           MKEmitter.emit('closeTabView', config.$pageId)
         } else {
           if (selected !== 'false') {
             this.checkTopLine()
-          } else if (_data.$$uuid) {
+          } else {
             this.transferLine()
           }
           this.autoExec()
         }
-      })
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
+      }
+    } else if (config.wrap.datatype === 'public') {
+      if (this.loaded) {
+        if (config.wrap.goback === 'true' && data.$$empty) {
+          this.timer && this.timer.stop()
+  
+          MKEmitter.emit('closeTabView', config.$pageId)
+        } else {
+          if (selected !== 'false') {
+            this.checkTopLine()
+          } else if (data.$$uuid) {
+            this.transferLine()
+          }
+          this.autoExec()
+        }
+      }
+    } else {
+      if (selected !== 'false') {
+        this.checkTopLine()
+      }
+
+      if (config.$cache && config.$time && config.wrap.autoExec) {
+        Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+          if (res.valid) return
+          
+          this.autoExec()
+          
+          Api.writeCacheConfig(config.uuid, [], BID)
+        })
+      } else {
+        this.autoExec()
+      }
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { BID, BData, selected } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data[0] || {$$empty: true}
+
+    _data.$$BID = BID || ''
+    _data.$$BData = BData || ''
+    _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+    this.loaded = true
+
+    this.setState({data: _data}, () => {
+      if (config.wrap.goback === 'true' && _data.$$empty) {
+        this.timer && this.timer.stop()
+
+        MKEmitter.emit('closeTabView', config.$pageId)
+      } else {
+        if (selected !== 'false') {
+          this.checkTopLine()
+        } else if (_data.$$uuid) {
+          this.transferLine()
+        }
+        this.autoExec()
+      }
+    })
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   mkPublicData = (publicId, data) => {
@@ -268,14 +373,23 @@
     }
   }
 
-  autoExec = () => {
+  autoExec = (times) => {
     const { config, data } = this.state
 
     if (!config.wrap.autoExec) return
 
-    setTimeout(() => {
+    let btn = document.getElementById('button' + config.wrap.autoExec)
+
+    clearTimeout(this.autoTimer)
+
+    if (btn) {
       MKEmitter.emit('triggerBtnId', config.wrap.autoExec, data.$$empty ? [] : [data])
-    }, 200)
+    } else if (!times || times < 20) {
+      times = times ? times + 1 : 1
+      this.autoTimer = setTimeout(() => {
+        this.autoExec(times)
+      }, 1000)
+    }
   }
 
   checkTopLine = () => {
@@ -318,12 +432,21 @@
     if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
       MKEmitter.emit('reloadData', config.setting.supModule, BID)
     } else {
-      this.loadData()
+      this.loadData('', btn)
     }
+  }
 
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
+  refreshLineData = (menuId, btn, uuid, count) => {
+    const { config, data } = this.state
+
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(data).toJS()
+    _data[btn.field] = count
+
+    this.setState({
+      data: _data
+    })
   }
 
   resetParentParam = (MenuID, id, data) => {
@@ -342,18 +465,18 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
     const { config } = this.state
 
     if (config.uuid !== menuId) return
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
     callback({
-      arr_field: '',
       orderBy: '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
@@ -365,9 +488,8 @@
     this.loadData()
   }
 
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID, BData, selected } = this.state
+  async loadData (type, btn) {
+    const { config, BID, BData, selected } = this.state
 
     if (config.wrap.datatype === 'public') {
       MKEmitter.emit('reloadData', config.wrap.publicId)
@@ -378,6 +500,10 @@
       this.setState({
         data: {$$BID: BID || '', $$BData: BData, $$empty: true},
       })
+
+      if (!btn) {
+        this.autoExec()
+      }
       return
     } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -387,29 +513,31 @@
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let _data = {}
 
       this.loaded = true
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       if (!result.data || !result.data[0]) {
@@ -436,7 +564,9 @@
           } else {
             this.transferLine()
           }
-          this.autoExec()
+          if (!btn) {
+            this.autoExec()
+          }
         }
       })
 
@@ -446,16 +576,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
+
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -506,7 +651,7 @@
             }
 
             return (
-              <Col className={className} key={index} span={item.setting.width || 6} offset={item.offset || 0}>
+              <Col className={className} key={index} style={item.wStyle} span={item.setting.width || 6} offset={item.offset || 0}>
                 <CardItem card={item} cards={config} data={data} onClick={() => {this.changeCard(index, item)}}/>
               </Col>
             )
diff --git a/src/tabviews/custom/components/card/table-card/index.jsx b/src/tabviews/custom/components/card/table-card/index.jsx
index 16fc44e..f131f2c 100644
--- a/src/tabviews/custom/components/card/table-card/index.jsx
+++ b/src/tabviews/custom/components/card/table-card/index.jsx
@@ -5,7 +5,6 @@
 import { DownOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
-import Utils from '@/utils/utils.js'
 import asyncComponent from '@/utils/asyncComponent'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import MKEmitter from '@/utils/events.js'
@@ -17,9 +16,7 @@
 
 class TableCard extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -29,7 +26,6 @@
     search: null,              // 鎼滅储鏉′欢
     pageIndex: 1,              // 椤电爜
     total: 0,                  // 鎬绘暟
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: null,                // 鏁版嵁
     BData: ''
   }
@@ -41,12 +37,9 @@
    * 1銆� initdata 涓烘墦鍗版椂浣跨敤鐨勬暟鎹泦
    */
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
-    let _data = null
-    let _sync = _config.setting.sync === 'true'
-
+    let _config = fromJS(config).toJS()
     let BID = ''
     let BData = ''
 
@@ -57,25 +50,6 @@
     }
     if (BData) {
       BID = BData.$BID || ''
-    }
-
-    if (_config.setting.sync === 'true' && data) {
-      _data = data[_config.dataName] || []
-      _sync = false
-    } else if (_config.setting.sync === 'true' && initdata) {
-      _data = initdata || []
-      _sync = false
-    }
-
-    if (_data) {
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[_config.setting.primaryKey] || ''
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1 + ''
-        return item
-      })
     }
 
     let showHeader = false
@@ -92,22 +66,40 @@
       _config.wrap.contentHeight = showHeader ? 'calc(100% - 45px)' : '100%'
     }
 
-    this.loaded = _data !== null
+    let _data = null
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        _data = _data.map((item, index) => {
+          item.key = index
+          item.$$uuid = item[_config.setting.primaryKey] || ''
+          item.$$BID = BID || ''
+          item.$$BData = BData || ''
+          item.$Index = index + 1 + ''
+          return item
+        })
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
+    }
 
     this.setState({
-      sync: _sync,
       BID: BID || '',
       BData: BData || '',
       data: _data,
       config: _config,
-      search: Utils.initMainSearch(_config.search),
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      search: _config.$searches
     })
   }
 
@@ -115,9 +107,18 @@
     const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
 
     if (config.timer) {
       this.timer = new TimerTask()
@@ -130,20 +131,7 @@
       })
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        let _data = res.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[config.setting.primaryKey] || ''
-          item.$Index = index + 1 + ''
-          return item
-        })
-
-        this.setState({data: _data})
-      })
-    }
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -155,42 +143,110 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID, BData } = this.state
+  initExec = () => {
+    const { config, BID } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
+    if (config.$cache) {
+      if (config.$time && !config.setting.laypage) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            let _data = res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+              return item
+            })
+    
+            this.setState({data: _data})
+          })
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            let _data = res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+              return item
+            })
+    
+            this.setState({data: _data})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        }
       }
-
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[config.setting.primaryKey] || ''
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1 + ''
-        return item
-      })
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
         this.loadData()
-      })
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { BID, BData } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data.map((item, index) => {
+      item.key = index
+      item.$$uuid = item[config.setting.primaryKey] || ''
+      item.$$BID = BID || ''
+      item.$$BData = BData || ''
+      item.$Index = index + 1 + ''
+
+      return item
+    })
+
+    this.loaded = true
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   /**
@@ -209,10 +265,23 @@
     } else {
       this.loadData()
     }
+  }
 
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
+  refreshLineData = (menuId, btn, uuid, count) => {
+    const { config, data } = this.state
+
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(data).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
+      }
+      return item
+    })
+
+    this.setState({
+      data: _data
+    })
   }
 
   resetParentParam = (MenuID, id, data) => {
@@ -238,32 +307,29 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, search } = this.state
+    const { config, search } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
   async loadData (type) {
-    const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, search, BID, BData } = this.state
+    const { config, pageIndex, search, BID, BData } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -276,17 +342,17 @@
     }
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key)
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key)) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -297,7 +363,7 @@
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, pageIndex, config.setting.pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -307,8 +373,8 @@
       }
 
       this.loaded = true
-      if (config.$cache && pageIndex === 1 && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       let data = []
@@ -334,9 +400,14 @@
         })
       }
 
+      let total = result.total || 0
+      if (config.setting.custompage && data.length) {
+        total = data[data.length - 1].mk_total || 0
+      }
+
       this.setState({
         data: data,
-        total: result.total,
+        total: total,
         loading: false
       })
 
@@ -346,17 +417,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/card/tableHeader/index.jsx b/src/tabviews/custom/components/card/tableHeader/index.jsx
index c3e229f..ee5030f 100644
--- a/src/tabviews/custom/components/card/tableHeader/index.jsx
+++ b/src/tabviews/custom/components/card/tableHeader/index.jsx
@@ -70,6 +70,8 @@
 
       if (item.style && item.style.clear === 'left') {
         _style_ = {clear: 'left'}
+      } else if (item.style && item.style.clear === 'right') {
+        _style_ = {float: 'right'}
       }
 
       let val = ''
diff --git a/src/tabviews/custom/components/carousel/data-card/index.jsx b/src/tabviews/custom/components/carousel/data-card/index.jsx
index 590bc98..dcdd491 100644
--- a/src/tabviews/custom/components/carousel/data-card/index.jsx
+++ b/src/tabviews/custom/components/carousel/data-card/index.jsx
@@ -16,16 +16,13 @@
 
 class DataCard extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
     BID: '',                   // 涓婄骇ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     card: null,                // 鍗$墖璁剧疆
     data: null,                // 鏁版嵁
     BData: null,
@@ -35,13 +32,10 @@
   loaded = false
 
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
+
+    let _config = fromJS(config).toJS()
     let _card = _config.subcards[0]
-
-    let _data = null
-    let _sync = _config.setting.sync === 'true'
-
     let BID = ''
     let BData = ''
 
@@ -54,24 +48,32 @@
       BID = BData.$BID || ''
     }
 
-    if (_config.setting.sync === 'true' && data) {
-      _data = data[_config.dataName] || []
-      _sync = false
-    } else if (_config.setting.sync === 'true' && initdata) {
-      _data = initdata || []
-      _sync = false
-    }
+    let _data = null
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
 
-    if (_data) {
-      this.loaded = true
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[_config.setting.primaryKey] || ''
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1
-        return item
-      })
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        _data = _data.map((item, index) => {
+          item.key = index
+          item.$$uuid = item[_config.setting.primaryKey] || ''
+          item.$$BID = BID || ''
+          item.$$BData = BData || ''
+          item.$Index = index + 1 + ''
+          return item
+        })
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
     }
 
     if (_card.setting.click) {
@@ -88,21 +90,11 @@
     _config.wrap.speed = (_config.wrap.speed || 3) * 1000
 
     this.setState({
-      sync: _sync,
       data: _data,
       BID: BID || '',
       BData: BData || '',
       config: _config,
-      card: _card,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      } else {
-        this.openModal()
-      }
+      card: _card
     })
   }
 
@@ -113,6 +105,14 @@
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
 
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
@@ -120,65 +120,130 @@
       })
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        let _data = res.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[config.setting.primaryKey] || ''
-          item.$Index = index + 1 + ''
-          return item
-        })
-
-        this.setState({data: _data})
-      })
-    }
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
   }
 
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID, BData } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-      }
-
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[config.setting.primaryKey] || ''
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1
-        return item
-      })
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data}, () => {
-        this.openModal()
-      })
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
-  }
-
   componentWillUnmount () {
     this.setState = () => {
       return
     }
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            let _data = res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+    
+              return item
+            })
+    
+            this.setState({data: _data})
+          })
+        } else {
+          this.openModal()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            let _data = res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+
+              return item
+            })
+    
+            this.setState({data: _data})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.openModal()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.openModal()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { BID, BData } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data.map((item, index) => {
+      item.key = index
+      item.$$uuid = item[config.setting.primaryKey] || ''
+      item.$$BID = BID || ''
+      item.$$BData = BData || ''
+      item.$Index = index + 1 + ''
+
+      return item
+    })
+
+    this.loaded = true
+
+    this.setState({data: _data}, () => {
+      this.openModal()
+    })
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   openModal = (ErrCode) => {
@@ -222,10 +287,6 @@
     } else {
       this.loadData()
     }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
   }
 
   resetParentParam = (MenuID, id, data) => {
@@ -243,24 +304,23 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config } = this.state
+    const { config } = this.state
 
     if (config.uuid !== menuId) return
 
-    let searches = config.setting.useMSearch && mainSearch ? fromJS(mainSearch).toJS() : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
     callback({
-      arr_field: arr_field,
       orderBy: config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
   async loadData (type) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID, BData } = this.state
+    const { config, BID, BData } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -272,9 +332,12 @@
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? fromJS(mainSearch).toJS() : []
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
+
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -285,13 +348,13 @@
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       this.loaded = true
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       let data = result.data.map((item, index) => {
@@ -316,17 +379,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/carousel/prop-card/index.jsx b/src/tabviews/custom/components/carousel/prop-card/index.jsx
index bfeba28..273c51a 100644
--- a/src/tabviews/custom/components/carousel/prop-card/index.jsx
+++ b/src/tabviews/custom/components/carousel/prop-card/index.jsx
@@ -16,16 +16,13 @@
 
 class PropCard extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
     BID: '',                   // 涓婄骇ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: {$$empty: true},
     BData: null,
     visible: false
@@ -34,11 +31,10 @@
   loaded = false
 
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = {$$empty: true}
-    let _sync = false
 
     let BID = ''
     let BData = ''
@@ -53,25 +49,23 @@
     }
     
     if (_config.wrap.datatype === 'dynamic') {
-      _sync = _config.setting.sync === 'true'
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[_config.dataName] || {$$empty: true}
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
         }
-        _sync = false
+
+        _config.setting.sync = 'false'
+
+        _data = _data[0] || {$$empty: true}
+
         this.loaded = true
-      } else if (_sync && initdata) {
-        _data = initdata
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
-        this.loaded = true
+
+        window.GLOB.SyncData.delete(_config.dataName)
       }
-    } else if (_config.wrap.datatype === 'static') {
-      this.loaded = true
     }
 
     _data.$$uuid = _data[_config.setting.primaryKey] || ''
@@ -93,20 +87,10 @@
     _config.wrap.speed = (_config.wrap.speed || 3) * 1000
 
     this.setState({
-      sync: _sync,
       data: _data,
       BID: BID || '',
       BData: BData || '',
-      config: _config,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.wrap.datatype === 'dynamic' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      } else if (_config.wrap.display === 'modal' && _config.wrap.datatype === 'static') {
-        this.openModal()
-      }
+      config: _config
     })
   }
 
@@ -118,6 +102,14 @@
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
 
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer && config.wrap.datatype === 'dynamic') {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
@@ -125,16 +117,7 @@
       })
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        let _data = res[0]
-        _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-        this.setState({data: _data})
-      })
-    }
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -146,48 +129,115 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID, BData } = this.state
+  initExec = () => {
+    const { config, BID } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = {$$empty: true}
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
+    if (config.wrap.datatype === 'dynamic') {
+      if (config.$cache) {
+        if (config.$time) {
+          if (!this.loaded) {
+            Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+              if (!res.valid && config.setting.onload === 'true') {
+                setTimeout(() => {
+                  this.loadData('init')
+                }, config.setting.delay || 0)
+              }
+    
+              if (!res.data || this.loaded) return
+  
+              let _data = res.data[0] || {$$empty: true}
+              _data.$$uuid = _data[config.setting.primaryKey] || ''
+      
+              this.setState({data: _data})
+            })
+          } else {
+            this.openModal()
+          }
+        } else {
+          if (!this.loaded) {
+            Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+              if (!res.data || this.loaded) return
+      
+              let _data = res.data[0] || {$$empty: true}
+              _data.$$uuid = _data[config.setting.primaryKey] || ''
+      
+              this.setState({data: _data})
+            })
+          }
+  
+          if (config.setting.onload === 'true') {
+            setTimeout(() => {
+              this.loadData('init')
+            }, config.setting.delay || 0)
+          } else if (this.loaded) {
+            this.openModal()
+          }
         }
+      } else if (config.setting.onload === 'true') {
+        setTimeout(() => {
+          this.loadData()
+        }, config.setting.delay || 0)
+      } else if (this.loaded) {
+        this.openModal()
       }
-
-      _data.$$uuid = _data[config.setting.primaryKey] || ''
-      _data.$$BID = BID || ''
-      _data.$$BData = BData || ''
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data}, () => {
-        if (config.wrap.display === 'modal') {
-          this.openModal()
-        }
-      })
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
+    } else if (config.wrap.datatype === 'static') {
+      this.openModal()
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { BID, BData } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data[0] || {$$empty: true}
+
+    _data.$$BID = BID || ''
+    _data.$$BData = BData || ''
+    _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+    this.loaded = true
+
+    this.setState({data: _data}, () => {
+      this.openModal()
+    })
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   openModal = (ErrCode) => {
     const { config, data } = this.state
+
+    if (config.wrap.display !== 'modal') return
     
     let code = config.wrap.code || ('modal' + config.uuid)
     let tip = localStorage.getItem(code)
@@ -225,10 +275,6 @@
     } else {
       this.loadData()
     }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
   }
 
   resetParentParam = (MenuID, id, data) => {
@@ -246,18 +292,18 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
     const { config } = this.state
 
     if (config.uuid !== menuId) return
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
     callback({
-      arr_field: '',
       orderBy: '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
@@ -270,8 +316,7 @@
   }
 
   async loadData (type) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID, BData } = this.state
+    const { config, BID, BData } = this.state
 
     if (config.wrap.datatype === 'static') {
       this.setState({
@@ -287,10 +332,12 @@
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -301,15 +348,15 @@
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let _data = {}
 
       this.loaded = true
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       if (!result.data || !result.data[0]) {
@@ -326,9 +373,7 @@
         data: _data,
         loading: false
       }, () => {
-        if (config.wrap.display === 'modal') {
-          this.openModal(result.ErrCode)
-        }
+        this.openModal(result.ErrCode)
       })
 
       if (config.timer && config.clearField && result.data && result.data[0]) {
@@ -337,17 +382,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/chart/antv-G6/index.jsx b/src/tabviews/custom/components/chart/antv-G6/index.jsx
index 8406f8d..9fdeb1e 100644
--- a/src/tabviews/custom/components/chart/antv-G6/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-G6/index.jsx
@@ -797,9 +797,7 @@
 
 class antvG6Chart extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -807,20 +805,19 @@
     BID: '',
     BData: '',
     plot: null,
-    sync: false,
-    arr_field : '',
     chartId: Utils.getuuid(),
     empty: true
   }
 
   data = []
+  mkgraph = null
+  selectedId = ''
+  loaded = false
 
   UNSAFE_componentWillMount () {
-    const { config, data, initdata } = this.props
+    const { config } = this.props
+
     let _config = fromJS(config).toJS()
-
-    let _sync = _config.setting.sync === 'true'
-
     let BID = ''
     let BData = ''
 
@@ -833,12 +830,22 @@
       BID = BData.$BID || ''
     }
 
-    if (_sync && data) {
-      this.data = data[config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      this.data = initdata || []
-      _sync = false
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        this.data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
     }
 
     _config.plot.height = Utils.getHeight(_config.plot.height)
@@ -852,20 +859,8 @@
       config: _config,
       BID: BID || '',
       BData: BData || '',
-      arr_field: _config.columns.map(col => col.field).join(','),
-      plot: _config.plot,
-      sync: _sync
-    }, () => {
-      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      plot: _config.plot
     })
-
-    if (this.data.length > 0) {
-      this.handleData()
-    }
     
     let that = this
 
@@ -995,51 +990,24 @@
     }
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-      }
-
-      if (!is(fromJS(this.data), fromJS(_data))) {
-        this.data = _data
-        this.handleData()
-      }
-
-      this.setState({sync: false})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
-  }
-
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
   }
 
   componentDidMount () {
-    const { config, sync } = this.state
+    const { config } = this.state
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
 
-    if (config.$cache && (config.setting.sync !== 'true' || sync)) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.data.length > 0) return
-
-        if (!is(fromJS(this.data), fromJS(res))) {
-          this.data = res
-          this.handleData()
-        }
-      })
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
     }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
+    this.initExec()
   }
 
   /**
@@ -1050,7 +1018,90 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.data = res.data
+            this.handleData()
+          })
+        } else {
+          this.handleData()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.data = res.data
+            this.handleData()
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.handleData()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.handleData()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    if (!is(fromJS(this.data), fromJS(_data))) {
+      this.data = _data
+      this.handleData()
+    }
+
+    this.loaded = true
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId) => {
@@ -1072,22 +1123,24 @@
     }
   }
 
-  async loadData () {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+  async loadData (type) {
+    const { config, BID } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       if (!is(fromJS(this.data), fromJS([]))) {
         this.data = []
         this.handleData()
       }
+      this.loaded = true
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -1096,13 +1149,15 @@
     })
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
+
+      this.loaded = true
 
       this.setState({
         loading: false
@@ -1112,16 +1167,30 @@
         this.data = result.data || []
         this.handleData()
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -1183,9 +1252,20 @@
 
       _options.push(_item)
     })
-
-    root = this.getTree(root, _options)
+    
+    root.nodeNumber = 0
+    root = this.getTree(root, _options, root)
     root.children = root.children || []
+
+    if (root.selectedItem) {
+      let option = {...root.selectedItem}
+      setTimeout(() => {
+        MKEmitter.emit('resetSelectLine', config.uuid, option.id, option)
+      }, 20)
+      delete root.selectedItem
+    } else {
+      this.selectedId = ''
+    }
 
     if (plot.subtype === 'mindmap') {
       root.type = 'dice-mind-map-root'
@@ -1248,13 +1328,22 @@
     return root
   }
 
-  getTree = (parent, options) => {
+  getTree = (parent, options, root) => {
     parent.children = []
     // 娣诲姞鑿滃崟鐨勫瓙鍏冪礌
     options = options.filter(option => {
       if (option.$parentId === parent.id) {
         delete option.$parentId
+
+        if (this.selectedId && option.id === this.selectedId) {
+          root.selectedItem = {...option}
+          option.selected = true
+        }
+
         parent.children.push(option)
+
+        root.nodeNumber++
+
         return false
       }
       return true
@@ -1264,7 +1353,7 @@
       parent.children = null
     } else {
       parent.children = parent.children.map(item => {
-        item = this.getTree(item, options)
+        item = this.getTree(item, options, root)
 
         return item
       })
@@ -1274,19 +1363,22 @@
   }
 
   handleData = () => {
-    let _element = document.getElementById(this.state.chartId)
-    if (_element) {
-      _element.innerHTML = ''
-    }
+    const { config } = this.state
 
-    setTimeout(() => {
+    MKEmitter.emit('resetSelectLine', config.uuid, '', '')
+
+    if (this.mkgraph) {
+      this.mkgraph.clear()
+      this.resetrender()
+    } else {
       this.viewrender()
-    }, 100)
+    }
   }
 
   viewrender = () => {
     const { plot } = this.state
 
+    this.selectedId = ''
     if (this.data.length === 0) {
       this.setState({empty: true})
     } else {
@@ -1298,6 +1390,44 @@
         this.indentrender()
       } else if (plot.subtype === 'kapmap') {
         this.kapmaprender()
+      }
+    }
+  }
+
+  resetrender = () => {
+    const { plot } = this.state
+
+    if (this.data.length === 0) {
+      this.setState({empty: true})
+      this.selectedId = ''
+    } else {
+      this.setState({empty: false})
+
+      const data = this.getdata()
+      if (plot.subtype === 'mindmap') {
+        this.mkgraph.data(data)
+
+        this.mkgraph.render()
+
+        const width = this.wrap.scrollWidth - 30
+
+        if (plot.collapsed === 'true' && plot.dirField) {
+          this.mkgraph.zoomTo(1, { x: width / 2, y: plot.height / 2 })
+        } else if (plot.collapsed === 'true' || data.nodeNumber < 5) {
+          this.mkgraph.zoomTo(1, { x: 0, y: plot.height / 2 })
+        }
+      } else if (plot.subtype === 'indentTree') {
+        this.mkgraph.data(dataIndTransform(data))
+
+        this.mkgraph.render()
+      } else if (plot.subtype === 'kapmap') {
+        this.mkgraph.data(data)
+        this.mkgraph.render()
+        this.mkgraph.fitView()
+
+        if (plot.collapsed === 'true' || data.nodeNumber < 5) {
+          this.mkgraph.zoomTo(1, { x: 0, y: plot.height / 2 })
+        }
       }
     }
   }
@@ -1357,9 +1487,11 @@
     graph.render()
     graph.fitView()
 
-    if (plot.collapsed === 'true') {
+    if (plot.collapsed === 'true' || data.nodeNumber < 5) {
       graph.zoomTo(1, { x: 0, y: plot.height / 2 })
     }
+
+    this.mkgraph = graph
   }
 
   indentrender = () => {
@@ -1421,6 +1553,8 @@
     tree.data(dataIndTransform(data))
     
     tree.render()
+
+    this.mkgraph = tree
   }
 
   /**
@@ -1480,17 +1614,19 @@
 
     if (plot.collapsed === 'true' && plot.dirField) {
       tree.zoomTo(1, { x: width / 2, y: plot.height / 2 })
-    } else if (plot.collapsed === 'true') {
+    } else if (plot.collapsed === 'true' || data.nodeNumber < 5) {
       tree.zoomTo(1, { x: 0, y: plot.height / 2 })
     }
+
+    this.mkgraph = tree
   }
 
   handleClick = (data = null) => {
     const { plot, config } = this.state
     
-    if (plot.click && !data) return
-
     if (plot.click === 'menus') {
+      if (!data) return
+
       let menu = null
       
       if (plot.menus && plot.menus.length > 0) {
@@ -1521,6 +1657,8 @@
 
       MKEmitter.emit('modifyTabs', newtab, true)
     } else if (plot.click === 'menu') {
+      if (!data) return
+      
       let menuId = plot.menu.slice(-1)[0]
       let newtab = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
 
@@ -1551,7 +1689,13 @@
 
       MKEmitter.emit('modifyTabs', newtab, true)
     } else {
-      MKEmitter.emit('resetSelectLine', config.uuid, (data ? data.$$uuid : ''), data)
+      if (data) {
+        this.selectedId = data.$$uuid || ''
+        MKEmitter.emit('resetSelectLine', config.uuid, data.$$uuid || '', data)
+      } else {
+        this.selectedId = ''
+        MKEmitter.emit('resetSelectLine', config.uuid, '', '')
+      }
     }
   }
 
diff --git a/src/tabviews/custom/components/chart/antv-X6/index.jsx b/src/tabviews/custom/components/chart/antv-X6/index.jsx
new file mode 100644
index 0000000..781b43c
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-X6/index.jsx
@@ -0,0 +1,2071 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Spin, Tooltip, message, Modal, notification, Switch } from 'antd'
+import { UndoOutlined, RedoOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, QuestionCircleOutlined, ClearOutlined } from '@ant-design/icons'
+import { Graph, Shape } from '@antv/x6'
+import { Stencil } from '@antv/x6-plugin-stencil'
+import { Transform } from '@antv/x6-plugin-transform'
+import { Selection } from '@antv/x6-plugin-selection'
+import { Snapline } from '@antv/x6-plugin-snapline'
+import { Keyboard } from '@antv/x6-plugin-keyboard'
+import { Clipboard } from '@antv/x6-plugin-clipboard'
+import { History } from '@antv/x6-plugin-history'
+import { Export } from '@antv/x6-plugin-export'
+
+import Api from '@/api'
+import MKEmitter from '@/utils/events.js'
+import asyncComponent from '@/utils/asyncComponent'
+import NormalHeader from '@/tabviews/custom/components/share/normalheader'
+// import lanes from '@/menu/components/chart/antv-X6/lane.json'
+// import xflows from '@/menu/components/chart/antv-X6/xflow.json'
+import './index.scss'
+
+const { confirm } = Modal
+const NodeUpdate = asyncComponent(() => import('./nodeupdate'))
+
+const groups = {
+  top: {
+    position: 'top',
+    attrs: {
+      circle: {
+        r: 4,
+        magnet: true,
+        stroke: 'var(--mk-sys-color)',
+        strokeWidth: 1,
+        fill: '#fff',
+        style: {
+          visibility: 'hidden'
+        }
+      }
+    }
+  },
+  right: {
+    position: 'right',
+    attrs: {
+      circle: {
+        r: 4,
+        magnet: true,
+        stroke: 'var(--mk-sys-color)',
+        strokeWidth: 1,
+        fill: '#fff',
+        style: {
+          visibility: 'hidden'
+        }
+      }
+    }
+  },
+  bottom: {
+    position: 'bottom',
+    attrs: {
+      circle: {
+        r: 4,
+        magnet: true,
+        stroke: 'var(--mk-sys-color)',
+        strokeWidth: 1,
+        fill: '#fff',
+        style: {
+          visibility: 'hidden'
+        }
+      }
+    }
+  },
+  left: {
+    position: 'left',
+    attrs: {
+      circle: {
+        r: 4,
+        magnet: true,
+        stroke: 'var(--mk-sys-color)',
+        strokeWidth: 1,
+        fill: '#fff',
+        style: {
+          visibility: 'hidden'
+        }
+      }
+    }
+  }
+}
+
+Graph.registerNode(
+  'lane',
+  {
+    inherit: 'rect',
+    markup: [
+      {
+        tagName: 'rect',
+        selector: 'body',
+      },
+      {
+        tagName: 'rect',
+        selector: 'name-rect',
+      },
+      {
+        tagName: 'text',
+        selector: 'name-text',
+      },
+    ],
+    attrs: {
+      body: {
+        fill: '#FFF',
+        stroke: '#5F95FF',
+        strokeWidth: 1,
+      },
+      'name-rect': {
+        width: 200,
+        height: 36,
+        fill: '#5F95FF',
+        stroke: '#fff',
+        strokeWidth: 1,
+        x: -1,
+      },
+      'name-text': {
+        ref: 'name-rect',
+        refY: 0.5,
+        refX: 0.5,
+        textAnchor: 'middle',
+        fontWeight: 'bold',
+        fill: '#fff',
+        fontSize: 14,
+      },
+    },
+    zIndex: 0
+  },
+  true,
+)
+
+Graph.registerNode(
+  'mk-rect',
+  {
+    inherit: 'rect',
+    width: 66,
+    height: 40,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#000000',
+        fill: '#FFFFFF'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-polygon',
+  {
+    inherit: 'polygon',
+    width: 66,
+    height: 40,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#000000',
+        fill: '#FFFFFF'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-paral',
+  {
+    inherit: 'polygon',
+    width: 66,
+    height: 40,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#000000',
+        fill: '#FFFFFF'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'bottom' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-circle',
+  {
+    inherit: 'circle',
+    width: 40,
+    height: 40,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#000000',
+        fill: '#FFFFFF'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-ellipse',
+  {
+    inherit: 'ellipse',
+    width: 66,
+    height: 40,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#000000',
+        fill: '#FFFFFF'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-star',
+  {
+    inherit: 'polygon',
+    width: 40,
+    height: 40,
+    points: '100,10 40,198 190,78 10,78 160,198',
+    attrs: {
+      body: {
+        fill: '#FFFFFF',
+        stroke: '#000000',
+        strokeWidth: 1,
+        fillRule: 'nonzero'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-text',
+  {
+    inherit: 'text-block',
+    width: 66,
+    height: 40,
+    text: '鏂囨湰鍩�',
+    attrs: {
+      body: {
+        fill: '#ffffff',
+        stroke: '#000000',
+        strokeWidth: 1,
+        rx: 0,
+        ry: 0
+      }
+    }
+  },
+  true
+)
+
+const styles = {
+  blue: '#1890ff',
+  red: '#f5222d',
+  orange_red: '#fa541c',
+  orange: '#fa8c16',
+  orange_yellow: '#faad14',
+  yellow: '#fadb14',
+  yellow_green: '#a0d911',
+  green: '#52c41a',
+  cyan: '#13c2c2',
+  blue_purple: '#2f54eb',
+  purple: '#722ed1',
+  magenta: '#eb2f96',
+  grass_green: '#aeb303',
+  deep_red: '#c32539',
+  deep_blue: '#1d3661',
+  blue1: '#e6f7ff',
+  red1: '#fff1f0',
+  orange_red1: '#fff2e8',
+  orange1: '#fff7e6',
+  orange_yellow1: '#fffbe6',
+  yellow1: '#feffe6',
+  yellow_green1: '#fcffe6',
+  green1: '#f6ffed',
+  cyan1: '#e6fffb',
+  blue_purple1: '#f0f5ff',
+  purple1: '#f9f0ff',
+  magenta1: '#fff0f6',
+  grass_green1: '#f2efda',
+  deep_red1: '#fff0f0',
+  deep_blue1: '#eff1f4'
+}
+
+let sysColor = '#1890ff'
+let lightColor = '#e6f7ff'
+if (window.GLOB.style) {
+  let type = window.GLOB.style.replace(/bg_black_style_|bg_white_style_/, '')
+  sysColor = styles[type] || '#1890ff'
+  lightColor = styles[type + '1'] || '#e6f7ff'
+}
+
+class antvX6Chart extends Component {
+  static propTpyes = {
+    config: PropTypes.object
+  }
+
+  state = {
+    config: null,
+    editing: false,
+    node: null,
+    loading: false,
+    status: 0,
+    flowname: '',
+    orgs: []
+  }
+
+  selectNode = null
+  mkGraph = null
+  cells = []
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+    let _config = fromJS(config).toJS()
+
+    let BID = ''
+    let BData = ''
+
+    _config.setting.supModule = ''
+
+    if (_config.plot.supModule && _config.plot.supModule.length > 0) {
+      _config.setting.supModule = _config.plot.supModule.pop()
+    }
+
+    if (_config.setting.supModule) {
+      BData = window.GLOB.CacheData.get(_config.setting.supModule)
+    } else {
+      BData = window.GLOB.CacheData.get(config.$pageId)
+    }
+    if (BData) {
+      BID = BData.$BID || ''
+    }
+
+    this.setState({
+      config: _config,
+      BID: BID || '',
+      BData: BData || '',
+      plot: _config.plot
+    }, () => {
+      this.loadData()
+
+      if (_config.plot.function === 'edit') {
+        this.getorganizations()
+      }
+    })
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+
+    MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+  }
+
+  reloadData = (menuId) => {
+    const { config } = this.state
+
+    if (config.uuid !== menuId) return
+
+    this.loadData()
+  }
+
+  resetParentParam = (MenuID, id) => {
+    const { config } = this.state
+
+    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
+    if (id !== this.state.BID || id !== '') {
+      this.setState({ BID: id }, () => {
+        this.loadData()
+      })
+    }
+  }
+
+  getorganizations = () => {
+    Api.genericInterface({func: 's_get_organizations_v1'}).then(res => {
+      if (!res.status) {
+        notification.error({
+          top: 92,
+          message: res.message,
+          duration: 10
+        })
+        return
+      }
+
+      let orgs = []
+      res.organizations && res.organizations.forEach(com => {
+        let _com = {
+          key: com.OrgCode,
+          title: com.OrgName,
+          shortName: com.ShortName,
+          checkable: false,
+          selectable: false,
+          children: []
+        }
+        let _works = []
+
+        com.departments.forEach(dep => {
+          let _dep = {
+            key: dep.co_pro_code,
+            title: dep.co_pro_name,
+            checkable: false,
+            selectable: false,
+            children: []
+          }
+
+          dep.jobs.forEach(job => {
+            let _job = {
+              key: job.jobcode,
+              title: job.jobname,
+              checkable: false,
+              selectable: false,
+              children: []
+            }
+  
+            job.work_group.forEach(group => {
+              if (group.work_group === 'normal') {
+                group.workers.forEach(work => {
+                  let _work = {
+                    key: work.worker_id,
+                    title: work.workername,
+                    email: work.email || '',
+                    images: work.images || '',
+                    mob: work.mob || '',
+                    sex: work.sex || '',
+                    work_grade: work.work_grade || '',
+                    worker_id: work.worker_id || '',
+                    workercode: work.workercode || '',
+                    workername: work.workername || '',
+                    parentIds: [com.OrgCode, dep.co_pro_code, job.jobcode],
+                    parentNames: [com.OrgName, dep.co_pro_name, job.jobname]
+                  }
+  
+                  _job.children.push(_work)
+                })
+              } else {
+                let _group = {
+                  key: group.work_group,
+                  title: group.work_group,
+                  checkable: false,
+                  selectable: false,
+                  children: []
+                }
+
+                group.workers.forEach(work => {
+                  let _work = {
+                    key: work.worker_id,
+                    title: work.workername,
+                    email: work.email || '',
+                    images: work.images || '',
+                    mob: work.mob || '',
+                    sex: work.sex || '',
+                    work_grade: work.work_grade || '',
+                    worker_id: work.worker_id || '',
+                    workercode: work.workercode || '',
+                    workername: work.workername || '',
+                    parentIds: [com.OrgCode, dep.co_pro_code, job.jobcode, group.work_group],
+                    parentNames: [com.OrgName, dep.co_pro_name, job.jobname, group.work_group]
+                  }
+  
+                  _group.children.push(_work)
+                })
+
+                if (_group.children.length > 0) {
+                  _job.children.push(_group)
+                }
+              }
+            })
+
+            if (_job.children.length > 0) {
+              _dep.children.push(_job)
+            }
+          })
+
+          if (_dep.children.length > 0) {
+            _com.children.push(_dep)
+          }
+        })
+
+        if (_com.children.length > 0) {
+          _com.works = _works
+          orgs.push(_com)
+        }
+      })
+
+      this.setState({orgs: orgs})
+    })
+  }
+
+  async loadData () {
+    const { BID } = this.state
+
+    if (!BID) {
+      if (!is(fromJS(this.data), fromJS([]))) {
+        this.cells = []
+        this.handleData()
+      }
+      this.setState({empty: true})
+      return
+    }
+
+    this.setState({
+      loading: true
+    })
+
+    let param = {
+      func: 's_get_works_flow_local_param_v6',
+      ID: BID
+    }
+
+    let result = await Api.genericInterface(param)
+    if (result.status) {
+      let item = result.data && result.data[0] ? result.data[0] : null
+      let cells = []
+
+      if (item && item.long_param) {
+        let long_param = JSON.parse(window.decodeURIComponent(window.atob(item.long_param)))
+        cells = long_param.cells || []
+      }
+
+      this.cells = cells
+      this.handleData()
+
+      this.setState({
+        status: item.status || 0,
+        flowname: item.works_flow_name,
+        loading: false
+      })
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
+    } else {
+      this.setState({
+        loading: false
+      })
+      
+      if (!result.message) return
+      if (result.ErrCode === 'N') {
+        Modal.error({
+          title: result.message,
+        })
+      } else if (result.ErrCode !== '-2') {
+        notification.error({
+          top: 92,
+          message: result.message,
+          duration: 10
+        })
+      }
+    }
+  }
+
+  handleData = () => {
+    const { config } = this.state
+
+    MKEmitter.emit('resetSelectLine', config.uuid, '', '')
+
+    let _element = document.getElementById(config.uuid + 'container')
+    if (_element) {
+      _element.innerHTML = ''
+    }
+
+    setTimeout(() => {
+      this.viewrender()
+    }, 50)
+  }
+
+  viewrender = () => {
+    const { plot } = this.state
+
+    if (plot.function === 'show') {
+      if (plot.subtype === 'xflow') {
+        this.xflowSrender()
+      } else if (plot.subtype === 'lane') {
+        this.laneSrender()
+      }
+    } else {
+      if (plot.subtype === 'xflow') {
+        this.xflowrender()
+      } else if (plot.subtype === 'lane') {
+        this.lanerender()
+      }
+    }
+  }
+
+  xflowSrender = () => {
+    const { config } = this.state
+
+    const graph = new Graph({
+      container: document.getElementById(config.uuid + 'container'),
+      grid: config.plot.grid,
+      scaling: {
+        min: 0.5,
+        max: 2
+      },
+      autoResize: true,
+      interacting: false,
+      panning: true,
+      background: {
+        color: config.plot.backgroundColor || 'transparent'
+      },
+      mousewheel: {
+        enabled: true,
+        zoomAtMousePosition: true,
+        modifiers: 'ctrl'
+      },
+      connecting: {
+        router: 'manhattan',
+        connector: {
+          name: 'rounded',
+          args: {
+            radius: 8
+          }
+        },
+        anchor: 'center',
+        connectionPoint: 'anchor',
+        allowBlank: false,
+        snap: {
+          radius: 20
+        }
+      }
+    })
+
+    if (this.cells.length > 0) {
+      let cells = []
+      this.cells.forEach((item) => {
+        if (item.shape === 'edge') {
+          cells.push(graph.createEdge(item))
+        } else {
+          cells.push(graph.createNode(item))
+        }
+      })
+      graph.resetCells(cells)
+      graph.positionContent('center')
+    }
+
+    if (config.plot.click) {
+      graph.on('cell:click', ({ node }) => {
+        this.checkNode(graph, node)
+      })
+  
+      graph.on('blank:click', () => {
+        this.checkNode(graph)
+      })
+    }
+  }
+
+  laneSrender = () => {
+    const { config } = this.state
+
+    const graph = new Graph({
+      container: document.getElementById(config.uuid + 'container'),
+      scaling: {
+        min: 0.5,
+        max: 2
+      },
+      interacting: false,
+      autoResize: true,
+      panning: true,
+      background: { color: '#ffffff' },
+      mousewheel: {
+        enabled: true,
+        zoomAtMousePosition: true,
+        modifiers: 'ctrl'
+      },
+      connecting: {
+        router: 'manhattan',
+        connector: {
+          name: 'rounded',
+          args: {
+            radius: 8
+          }
+        },
+        anchor: 'center',
+        connectionPoint: 'anchor',
+        allowBlank: false,
+        snap: {
+          radius: 20
+        }
+      }
+    })
+
+    if (this.cells.length > 0) {
+      let cells = []
+      this.cells.forEach((item) => {
+        if (item.shape === 'edge') {
+          cells.push(graph.createEdge(item))
+        } else {
+          cells.push(graph.createNode(item))
+        }
+      })
+      graph.resetCells(cells)
+      graph.positionContent('top')
+    }
+
+    if (config.plot.click) {
+      graph.on('cell:click', ({ node }) => {
+        this.checkNode(graph, node)
+      })
+  
+      graph.on('blank:click', () => {
+        this.checkNode(graph)
+      })
+    }
+  }
+
+  xflowrender = () => {
+    const { config } = this.state
+
+    const graph = new Graph({
+      container: document.getElementById(config.uuid + 'container'),
+      grid: config.plot.grid,
+      scaling: {
+        min: 0.5,
+        max: 2
+      },
+      autoResize: true,
+      panning: true,
+      background: {
+        color: config.plot.backgroundColor || 'transparent'
+      },
+      mousewheel: {
+        enabled: true,
+        zoomAtMousePosition: true,
+        modifiers: 'ctrl'
+      },
+      connecting: {
+        router: 'manhattan',
+        connector: {
+          name: 'rounded',
+          args: {
+            radius: 8
+          }
+        },
+        anchor: 'center',
+        connectionPoint: 'anchor',
+        allowBlank: false,
+        snap: {
+          radius: 20
+        },
+        createEdge() {
+          return new Shape.Edge({
+            attrs: {
+              line: {
+                stroke: '#000000',
+                strokeWidth: 1,
+                targetMarker: {
+                  name: 'block',
+                  width: 12,
+                  height: 8
+                }
+              }
+            },
+            zIndex: 0
+          })
+        },
+        validateConnection({ targetMagnet }) {
+          return !!targetMagnet
+        }
+      },
+      highlighting: {
+        magnetAdsorbed: {
+          name: 'stroke',
+          args: {
+            attrs: {
+              fill: '#5F95FF',
+              stroke: '#5F95FF'
+            }
+          }
+        }
+      }
+    })
+
+    graph
+      .use(new Transform({
+        resizing: true,
+        rotating: true
+      }))
+      .use(new Selection())
+      .use(new Snapline())
+      .use(new Keyboard())
+      .use(new Clipboard())
+      .use(new History())
+      .use(new Export())
+
+    const stencil = new Stencil({
+      title: '娴佺▼鍥�',
+      target: graph,
+      stencilGraphWidth: 180,
+      stencilGraphHeight: 180,
+      groups: [
+        {
+          title: '閫氱敤鑺傜偣',
+          name: 'group1',
+          graphHeight: 240
+        },
+        {
+          title: '鑷畾涔�',
+          name: 'group2',
+          graphHeight: 150,
+          layoutOptions: {
+            rowHeight: 70
+          }
+        }
+      ],
+      layoutOptions: {
+        columns: 2,
+        columnWidth: 80,
+        rowHeight: 55
+      }
+    })
+
+    document.getElementById(config.uuid + 'stencil').appendChild(stencil.container)
+
+    graph.bindKey(['meta+c', 'ctrl+c'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.copy(cells)
+      }
+      return false
+    })
+    graph.bindKey(['meta+x', 'ctrl+x'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.cut(cells)
+      }
+      return false
+    })
+    graph.bindKey(['meta+v', 'ctrl+v'], () => {
+      if (!graph.isClipboardEmpty()) {
+        graph.paste({ offset: 32 })
+      }
+      return false
+    })
+
+    graph.bindKey(['meta+z', 'ctrl+z'], () => {
+      if (graph.canUndo()) {
+        graph.undo()
+      }
+      return false
+    })
+    graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
+      if (graph.canRedo()) {
+        graph.redo()
+      }
+      return false
+    })
+
+    graph.bindKey(['backspace', 'delete'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.removeCells(cells)
+        this.selectNode = null
+        this.setState({node: null})
+      }
+    })
+
+    // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌
+    const showPorts = (ports, show) => {
+      for (let i = 0, len = ports.length; i < len; i += 1) {
+        ports[i].style.visibility = show ? 'visible' : 'hidden'
+      }
+    }
+    graph.on('node:mouseenter', () => {
+      const container = document.getElementById(config.uuid + 'container')
+      const ports = container.querySelectorAll('.x6-port-body')
+      showPorts(ports, true)
+    })
+    graph.on('node:mouseleave', () => {
+      const container = document.getElementById(config.uuid + 'container')
+      const ports = container.querySelectorAll('.x6-port-body')
+      showPorts(ports, false)
+    })
+
+    graph.on('node:click', ({ node }) => {
+      this.selectNode = node
+      
+      this.setState({node: node.store.data})
+    })
+    graph.on('edge:click', ({ edge }) => {
+      this.selectNode = edge
+      
+      this.setState({node: edge.store.data})
+
+      graph.clearTransformWidgets()
+    })
+    graph.on('blank:click', () => {
+      this.selectNode = null
+      
+      this.setState({node: null})
+    })
+    graph.on('edge:connected', ({ isNew, edge }) => {
+      if (!isNew) return
+
+      let target = edge.getTargetCell()
+      let mkdata = target ? target.prop('mkdata') : null
+
+      if (mkdata) {
+        edge.prop('mkdata', {status: mkdata.status, statusName: mkdata.statusName})
+      }
+    })
+    
+    const r1 = graph.createNode({
+      shape: 'mk-rect',
+      mknode: 'start',
+      mkdata: {status: 0, statusName: '鏈彁浜�'},
+      attrs: {
+        body: {
+          rx: 20,
+          ry: 26,
+          fill: '#52c41a',
+          stroke: '#52c41a'
+        },
+        text: {
+          fill: '#ffffff',
+          text: '寮�濮�'
+        }
+      }
+    })
+    const r2 = graph.createNode({
+      shape: 'mk-rect',
+      attrs: {
+        body: {
+          rx: 20,
+          ry: 26,
+          fill: '#e6f4ff',
+          stroke: '#1890ff'
+        },
+        text: {
+          text: '杩囩▼'
+        }
+      }
+    })
+    const r3 = graph.createNode({
+      shape: 'mk-rect',
+      attrs: {
+        body: {
+          rx: 6,
+          ry: 6,
+          fill: '#fff7e6',
+          stroke: '#fa8c16'
+        },
+        text: {
+          text: '鍙�夎繃绋�'
+        }
+      }
+    })
+    const r4 = graph.createNode({
+      shape: 'mk-rect',
+      attrs: {
+        body: {
+          rx: 0,
+          ry: 0,
+          fill: '#fff7e6',
+          stroke: '#fa8c16'
+        },
+        text: {
+          text: '鑺傜偣'
+        }
+      }
+    })
+    const r5 = graph.createNode({
+      shape: 'mk-polygon',
+      attrs: {
+        body: {
+          refPoints: '0,10 10,0 20,10 10,20',
+          fill: '#f9f0ff',
+          stroke: '#722ed1'
+        },
+        text: {
+          text: '鍐崇瓥'
+        }
+      }
+    })
+    const r6 = graph.createNode({
+      shape: 'mk-paral',
+      attrs: {
+        body: {
+          refPoints: '10,0 40,0 30,20 0,20',
+          fill: '#e6fffb',
+          stroke: '#13c2c2'
+        },
+        text: {
+          text: '鏁版嵁'
+        }
+      }
+    })
+    const r7 = graph.createNode({
+      shape: 'mk-circle',
+      attrs: {
+        body: {
+          fill: '#e6f4ff',
+          stroke: '#1890ff'
+        },
+        text: {
+          text: '杩炴帴'
+        }
+      }
+    })
+
+    const r8 = graph.createNode({
+      shape: 'mk-rect',
+      mknode: 'end',
+      mkdata: {status: 888, statusName: '宸插畬鎴�'},
+      attrs: {
+        body: {
+          rx: 20,
+          ry: 26,
+          fill: '#fa8c16',
+          stroke: '#fa8c16'
+        },
+        text: {
+          fill: '#ffffff',
+          text: '缁撴潫'
+        }
+      }
+    })
+    
+    stencil.load([r1, r2, r3, r4, r5, r6, r7, r8], 'group1')
+    
+    const p1 = graph.createNode({
+      shape: 'mk-ellipse',
+      label: 'ellipse'
+    })
+    const p2 = graph.createNode({
+      shape: 'mk-star',
+      label: ''
+    })
+
+    const p3 = graph.createNode({
+      shape: 'mk-text'
+    })
+    
+    stencil.load([p1, p2, p3], 'group2')
+
+    if (this.cells.length > 0) {
+      let cells = []
+      this.cells.forEach((item) => {
+        if (item.shape === 'edge') {
+          cells.push(graph.createEdge(item))
+        } else {
+          cells.push(graph.createNode(item))
+        }
+      })
+      graph.resetCells(cells)
+      graph.positionContent('center')
+    }
+    
+    this.mkGraph = graph
+  }
+
+  lanerender = () => {
+    const { config } = this.state
+
+    const graph = new Graph({
+      container: document.getElementById(config.uuid + 'container'),
+      scaling: {
+        min: 0.5,
+        max: 2
+      },
+      autoResize: true,
+      panning: true,
+      background: { color: '#ffffff' },
+      mousewheel: {
+        enabled: true,
+        zoomAtMousePosition: true,
+        modifiers: 'ctrl'
+      },
+      connecting: {
+        router: 'manhattan',
+        connector: {
+          name: 'rounded',
+          args: {
+            radius: 8
+          }
+        },
+        anchor: 'center',
+        connectionPoint: 'anchor',
+        allowBlank: false,
+        snap: {
+          radius: 20
+        },
+        createEdge() {
+          return new Shape.Edge({
+            attrs: {
+              line: {
+                stroke: '#000000',
+                strokeWidth: 1,
+                targetMarker: {
+                  name: 'block',
+                  width: 12,
+                  height: 8
+                }
+              }
+            },
+            zIndex: 2
+          })
+        },
+        validateConnection({ targetMagnet }) {
+          return !!targetMagnet
+        }
+      },
+      highlighting: {
+        magnetAdsorbed: {
+          name: 'stroke',
+          args: {
+            attrs: {
+              fill: '#5F95FF',
+              stroke: '#5F95FF'
+            }
+          }
+        }
+      },
+      translating: {
+        restrict(cellView) {
+          const cell = cellView.cell
+          const parentId = cell.prop('parent')
+
+          if (parentId) {
+            const parentNode = graph.getCellById(parentId)
+            if (parentNode) {
+              return parentNode.getBBox().moveAndExpand({
+                x: 0,
+                y: 36,
+                width: 0,
+                height: -36,
+              })
+            }
+          }
+          return cell.getBBox()
+        }
+      }
+    })
+
+    graph
+      .use(new Transform({
+        resizing: true,
+        rotating: true
+      }))
+      .use(new Selection())
+      .use(new Snapline({
+        enabled: true,
+        filter: (Graph) => Graph.prop('shape') !== 'lane'
+      }))
+      .use(new Keyboard())
+      .use(new Clipboard())
+      .use(new History())
+      .use(new Export())
+
+    const stencil = new Stencil({
+      title: '娴佺▼鍥�',
+      target: graph,
+      stencilGraphWidth: 180,
+      stencilGraphHeight: 180,
+      groups: [
+        {
+          title: '閫氱敤鑺傜偣',
+          name: 'group1'
+        },
+        {
+          title: '鑷畾涔�',
+          name: 'group2',
+          graphHeight: 150,
+          layoutOptions: {
+            rowHeight: 70
+          }
+        },
+        {
+          title: '娉抽亾',
+          name: 'group3',
+          graphHeight: 120,
+          layoutOptions: {
+            rowHeight: 70
+          }
+        }
+      ],
+      layoutOptions: {
+        columns: 2,
+        columnWidth: 80,
+        rowHeight: 55
+      }
+    })
+
+    document.getElementById(config.uuid + 'stencil').appendChild(stencil.container)
+
+    graph.bindKey(['meta+c', 'ctrl+c'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        if (cells[0].prop('shape') !== 'lane' && cells[0].prop('shape') !== 'edge') {
+          graph.copy(cells)
+        }
+      }
+      return false
+    })
+    graph.bindKey(['meta+x', 'ctrl+x'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        if (cells[0].prop('shape') !== 'lane' && cells[0].prop('shape') !== 'edge') {
+          graph.cut(cells)
+        }
+      }
+      return false
+    })
+    graph.bindKey(['meta+v', 'ctrl+v'], () => {
+      if (!graph.isClipboardEmpty()) {
+        graph.paste({ offset: { dx: 0, dy: 20 } })
+      }
+      return false
+    })
+
+    graph.bindKey(['meta+z', 'ctrl+z'], () => {
+      if (graph.canUndo()) {
+        graph.undo()
+      }
+      return false
+    })
+    graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
+      if (graph.canRedo()) {
+        graph.redo()
+      }
+      return false
+    })
+
+    graph.bindKey(['backspace', 'delete'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        this.selectNode = null
+        this.setState({node: null})
+        
+        if (cells[0].prop('shape') === 'lane') {
+          graph.startBatch('delete-lane')
+
+          graph.removeCells(cells)
+          this.deleteLane(cells[0], graph)
+
+          graph.stopBatch('delete-lane')
+        } else {
+          graph.removeCells(cells)
+        }
+      }
+    })
+
+    const showPorts = (ports, show) => {
+      for (let i = 0, len = ports.length; i < len; i += 1) {
+        ports[i].style.visibility = show ? 'visible' : 'hidden'
+      }
+    }
+    graph.on('node:mouseenter', ({ cell }) => {
+      if (cell.prop('shape') === 'lane') return
+
+      const container = document.getElementById(config.uuid + 'container')
+      const ports = container.querySelectorAll('.x6-port-body')
+      showPorts(ports, true)
+    })
+    graph.on('node:mouseleave', () => {
+      const container = document.getElementById(config.uuid + 'container')
+      const ports = container.querySelectorAll('.x6-port-body')
+      showPorts(ports, false)
+    })
+
+    graph.on('node:added', ({ cell }) => {
+      if (cell.prop('shape') === 'lane') {
+        if (cell.prop('zIndex') === 0) return
+
+        graph.startBatch('add-lane')
+
+        this.addLane(cell, graph)
+
+        graph.stopBatch('add-lane')
+      } else {
+        let num = graph.getCellCount()
+
+        if (num <= 1) {
+          message.warning('璇锋坊鍔犳吵閬擄紒')
+          graph.removeCells([cell])
+        } else if (!cell.prop('parent')) {
+          this.addNode(cell, graph)
+        }
+      }
+    })
+    graph.on('node:click', ({ node }) => {
+      this.selectNode = node
+      this.setState({node: node.store.data})
+
+      if (node.prop('shape') === 'lane') {
+        graph.clearTransformWidgets()
+      }
+    })
+    graph.on('edge:click', ({ edge }) => {
+      this.selectNode = edge
+      this.setState({node: edge.store.data})
+
+      graph.clearTransformWidgets()
+    })
+    graph.on('blank:click', () => {
+      this.selectNode = null
+      
+      this.setState({node: null})
+    })
+    
+    const r1 = graph.createNode({
+      shape: 'mk-rect',
+      label: '寮�濮�',
+      attrs: {
+        body: {
+          rx: 20,
+          ry: 26
+        }
+      }
+    })
+    const r2 = graph.createNode({
+      shape: 'mk-rect',
+      label: '杩囩▼'
+    })
+    const r3 = graph.createNode({
+      shape: 'mk-rect',
+      attrs: {
+        body: {
+          rx: 6,
+          ry: 6
+        }
+      },
+      label: '鍙�夎繃绋�'
+    })
+    const r4 = graph.createNode({
+      shape: 'mk-polygon',
+      attrs: {
+        body: {
+          refPoints: '0,10 10,0 20,10 10,20'
+        }
+      },
+      label: '鍐崇瓥'
+    })
+    const r5 = graph.createNode({
+      shape: 'mk-paral',
+      attrs: {
+        body: {
+          refPoints: '10,0 40,0 30,20 0,20'
+        }
+      },
+      label: '鏁版嵁'
+    })
+    const r6 = graph.createNode({
+      shape: 'mk-circle',
+      label: '杩炴帴'
+    })
+    
+    stencil.load([r1, r2, r3, r4, r5, r6], 'group1')
+    
+    const p1 = graph.createNode({
+      shape: 'mk-ellipse',
+      label: 'ellipse'
+    })
+    const p2 = graph.createNode({
+      shape: 'mk-star',
+      label: ''
+    })
+
+    const p3 = graph.createNode({
+      shape: 'mk-text'
+    })
+    
+    stencil.load([p1, p2, p3], 'group2')
+
+    const g1 = graph.createNode({
+      shape: 'lane',
+      label: '闃舵n'
+    })
+    
+    stencil.load([g1], 'group3')
+
+    if (this.cells.length > 0) {
+      let cells = []
+      this.cells.forEach((item) => {
+        if (item.shape === 'edge') {
+          cells.push(graph.createEdge(item))
+        } else {
+          cells.push(graph.createNode(item))
+        }
+      })
+      graph.resetCells(cells)
+      graph.positionContent('top')
+    }
+
+    this.mkGraph = graph
+  }
+  
+  setTop = () => {
+    if (!this.selectNode) {
+      message.warning('璇烽�夋嫨鑺傜偣锛�')
+      return
+    }
+    this.selectNode.toFront()
+  }
+
+  setBottom = () => {
+    if (!this.selectNode) {
+      message.warning('璇烽�夋嫨鑺傜偣锛�')
+      return
+    }
+
+    this.selectNode.toBack()
+  }
+
+  setback = () => {
+    if (this.mkGraph.canUndo()) {
+      this.mkGraph.undo()
+    }
+  }
+
+  setprev = () => {
+    if (this.mkGraph.canRedo()) {
+      this.mkGraph.redo()
+    }
+  }
+
+  setZoomIn = () => {
+    this.mkGraph.zoom(0.1)
+  }
+
+  setZoomOut = () => {
+    this.mkGraph.zoom(-0.1)
+  }
+
+  setZoomInt = () => {
+    this.mkGraph.zoomTo(1)
+  }
+
+  save = () => {
+    const { BID, plot, status } = this.state
+
+    if (!BID) {
+      Modal.error({
+        title: '鏈幏鍙栧埌娴佺▼ID锛屼笉鍙繚瀛橈紒',
+      })
+      return
+    }
+
+    let nodes = this.mkGraph.toJSON()
+    let _status = status
+
+    if (plot.subtype === 'xflow' && status === 10) {
+      let start_num = nodes.cells.filter(cell => cell.mknode === 'start').length
+      let end_num = nodes.cells.filter(cell => cell.mknode === 'end').length
+      
+      if (start_num !== 1 || end_num !== 1) {
+        _status = 0
+      }
+    }
+
+    this.setState({
+      loading: true
+    })
+
+    this.mkGraph.toPNG((dataUri) => {
+      let param = {
+        func: 's_works_flow_param_upt_v6',
+        long_param: window.btoa(window.encodeURIComponent(JSON.stringify(nodes))),
+        flow_image: dataUri,
+        status: status,
+        ID: BID,
+        BID: ''
+      }
+  
+      Api.genericInterface(param).then(res => {
+        if (res.status) {
+          notification.success({
+            top: 92,
+            message: '淇濆瓨鎴愬姛锛�',
+            duration: 2
+          })
+          this.setState({
+            loading: false,
+            status: _status
+          })
+        } else {
+          notification.error({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+          this.setState({
+            loading: false
+          })
+        }
+      })
+    }, {padding: 20})
+  }
+
+  clearNode = () => {
+    let cells = this.mkGraph.getCells()
+    const that = this
+
+    if (cells.length === 0) return
+
+    confirm({
+      title: '纭畾娓呯┖鍏冪礌鍚�?',
+      content: '娓呯┖鍚庝笉鍙仮澶嶃��',
+      okText: '纭畾',
+      cancelText: '鍙栨秷',
+      onOk() {
+        that.mkGraph.removeCells(cells)
+        that.mkGraph.cleanHistory()
+      },
+      onCancel() {}
+    })
+  }
+
+  deleteLane = (cell, graph) => {
+    let id = cell.id
+
+    let nodes = graph.getNodes()
+    let cells = []
+
+    nodes.forEach(item => {
+      if (item.prop('shape') === 'lane') return
+
+      if (item.prop('parent') === id) {
+        cells.push(item)
+      }
+    })
+
+    graph.removeCells(cells)
+
+    this.resetlane(cell.id, cell.prop('position/x'), -cell.prop('size/width'))
+  }
+
+  addLane = (cell, graph) => {
+    const { config } = this.state
+
+    let nodes = graph.getNodes()
+
+    cell.prop('zIndex', 0)
+    let basePoint = cell.prop('position/x')
+
+    if (basePoint <= 0 || nodes.length <= 1) {
+      basePoint = 0
+    } else {
+      let _h = false
+      let _l = 0
+      nodes.forEach(item => {
+        if (item.id === cell.id) return
+        if (item.prop('shape') !== 'lane') return
+  
+        let x1 = item.prop('position/x')
+        let x2 = item.prop('position/x') + item.prop('size/width')
+        if (basePoint > x1 && basePoint <= x2) {
+          basePoint = x2
+          _h = true
+        }
+        if (_l < x2) {
+          _l = x2
+        }
+      })
+
+      if (!_h && _l) {
+        basePoint = _l
+      }
+    }
+
+    let height = 400
+
+    if (typeof(config.plot.height) === 'number' || /px/.test(config.plot.height)) {
+      height = parseInt(config.plot.height)
+    }
+
+    cell.prop('size', {width: 200, height: height})
+    cell.prop('position', {x: basePoint, y: 0})
+
+    this.resetlane(cell.id, basePoint, 200)
+  }
+
+  addNode = (cell, graph) => {
+    let nodes = graph.getNodes()
+
+    let cx1 = cell.prop('position/x')
+    let cx2 = cx1 + cell.prop('size/width')
+    let cx3 = parseInt((cx1 + cx2) / 2)
+
+    nodes.forEach(item => {
+      if (item.prop('shape') !== 'lane') return
+
+      let x1 = item.prop('position/x')
+      let x2 = item.prop('position/x') + item.prop('size/width')
+      
+      if (cx3 > x1 && cx3 <= x2) {
+        cell.prop('parent', item.id)
+
+        if (cx1 < x1) {
+          cell.prop('position/x', x1)
+        } else if (cx2 > x2) {
+          cell.prop('position/x', x2 - cell.prop('size/width'))
+        }
+
+        let y1 = item.prop('size/height') - cell.prop('size/height')
+
+        if (cell.prop('position/y') < 36) {
+          cell.prop('position/y', 36)
+        } else if (cell.prop('position/y') > y1) {
+          cell.prop('position/y', y1)
+        }
+      }
+    })
+
+    if (!cell.prop('parent')) {
+      let flane = null
+      let llane = null
+      let lane = null
+      nodes.forEach(item => {
+        if (item.prop('shape') !== 'lane') return
+        if (!flane) {
+          flane = item
+          llane = item
+        } else {
+          if (item.prop('position/x') < flane.prop('position/x')) {
+            flane = item
+          }
+          if (item.prop('position/x') > llane.prop('position/x')) {
+            llane = item
+          }
+        }
+      })
+
+      if (cx1 <= flane.prop('position/x')) {
+        lane = flane
+      } else {
+        lane = llane
+      }
+
+      let x1 = lane.prop('position/x')
+      let x2 = lane.prop('position/x') + lane.prop('size/width')
+      
+      cell.prop('parent', lane.id)
+
+      if (cx1 < x1) {
+        cell.prop('position/x', x1)
+      } else if (cx2 > x2) {
+        cell.prop('position/x', x2 - cell.prop('size/width'))
+      }
+
+      let y1 = lane.prop('size/height') - cell.prop('size/height')
+
+      if (cell.prop('position/y') < 36) {
+        cell.prop('position/y', 36)
+      } else if (cell.prop('position/y') > y1) {
+        cell.prop('position/y', y1)
+      }
+    }
+  }
+
+  changeProps = (value, key) => {
+    const { node } = this.state
+
+    if (node.shape === 'edge') {
+      let labels = this.selectNode.prop('labels')
+      if (!labels || labels.length === 0) {
+        labels = [{
+          attrs: {label: { text: '' }}
+        }]
+      }
+
+      if (key === 'title') {
+        labels = JSON.parse(JSON.stringify(labels))
+        labels[0].attrs.label.text = value
+        this.selectNode.setLabels(labels)
+      } else if (key === 'stroke') {
+        this.selectNode.attr('line/stroke', value)
+      } else if (key === 'strokeWidth') {
+        this.selectNode.attr('line/strokeWidth', value)
+      } else if (key === 'fontSize') {
+        labels = JSON.parse(JSON.stringify(labels))
+        labels[0].attrs.label.fontSize = value
+        this.selectNode.setLabels(labels)
+      } else if (key === 'fontFill') {
+        labels = JSON.parse(JSON.stringify(labels))
+        labels[0].attrs.label.fill = value
+        this.selectNode.setLabels(labels)
+      } else if (key === 'lineType') {
+        if (value === 'dash') {
+          this.selectNode.attr('line/strokeDasharray', 5)
+        } else {
+          this.selectNode.attr('line/strokeDasharray', 0)
+        }
+      } else if (key === 'mkdata') {
+        this.selectNode.prop('mkdata', value)
+      }
+    } else if (node.shape === 'lane') {
+      if (key === 'title') {
+        this.selectNode.attr('text/text', value)
+      } else if (key === 'fill') {
+        this.selectNode.attr('name-rect/fill', value)
+      } else if (key === 'stroke') {
+        this.selectNode.attr('body/stroke', value)
+      } else if (key === 'fontSize') {
+        this.selectNode.attr('name-text/fontSize', value)
+      } else if (key === 'fontFill') {
+        this.selectNode.attr('name-text/fill', value)
+      } else if (key === 'height') {
+        this.selectNode.prop('size/height', value)
+      } else if (key === 'width') {
+        this.mkGraph.startBatch('width-change')
+        let offset = value - this.selectNode.prop('size/width')
+
+        this.selectNode.prop('size/width', value)
+        this.selectNode.attr('name-rect/width', value)
+
+        this.resetlane(this.selectNode.id, this.selectNode.prop('position/x'), offset)
+
+        this.mkGraph.stopBatch('width-change')
+      }
+    } else if (node.shape === 'mk-text') {
+      if (key === 'title') {
+        this.selectNode.attr('label/text', value)
+      } else if (key === 'fill') {
+        this.selectNode.attr('body/fill', value)
+      } else if (key === 'stroke') {
+        this.selectNode.attr('body/stroke', value)
+      } else if (key === 'fontSize') {
+        this.selectNode.attr('label/style/fontSize', value)
+      } else if (key === 'fontFill') {
+        this.selectNode.attr('label/style/color', value)
+      }
+    } else {
+      if (key === 'title') {
+        this.selectNode.attr('text/text', value)
+      } else if (key === 'fill') {
+        this.selectNode.attr('body/fill', value)
+      } else if (key === 'stroke') {
+        this.selectNode.attr('body/stroke', value)
+      } else if (key === 'fontSize') {
+        this.selectNode.attr('text/fontSize', value)
+      } else if (key === 'fontFill') {
+        this.selectNode.attr('text/fill', value)
+      } else if (key === 'mkdata') {
+        this.selectNode.prop('mkdata', value)
+      }
+    }
+  }
+
+  checkNode = (graph, node) => {
+    const { plot, config } = this.state
+
+    let nodes = graph.getNodes()
+
+    nodes.forEach(item => {
+      if (item.prop('shape') === 'lane') return
+
+      if (item.prop('oristyle')) {
+        let style = item.prop('oristyle')
+
+        item.prop('attrs/body/fill', style.fill)
+        item.prop('attrs/body/stroke', style.stroke)
+        item.prop('attrs/text/fill', style.text)
+      }
+    })
+
+    if (!node || ['lane', 'mk-text', 'edge'].includes(node.prop('shape'))) {
+      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
+      return
+    }
+
+    if (!node.prop('oristyle')) {
+      node.prop('oristyle', {
+        fill: node.prop('attrs/body/fill'),
+        stroke: node.prop('attrs/body/stroke'),
+        text: node.prop('attrs/text/fill')
+      })
+    }
+
+    node.prop('attrs/body/fill', lightColor)
+    node.prop('attrs/body/stroke', sysColor)
+    node.prop('attrs/text/fill', sysColor)
+
+    let sign = node.prop('mksign') || ''
+
+    if (plot.click === 'menus') {
+      let menu = null
+      
+      if (plot.menus && plot.menus.length > 0) {
+        plot.menus.forEach(m => {
+          if (sign !== m.sign) return
+          menu = m
+        })
+      }
+      if (!menu || !menu.MenuID) return
+
+      let newtab = {
+        MenuID: menu.MenuID,
+        MenuName: menu.MenuName,
+        MenuNo: menu.MenuNo || '',
+        type: menu.tabType,
+        param: {$BID: sign}
+      }
+
+      MKEmitter.emit('modifyTabs', newtab, true)
+    } else if (plot.click === 'menu') {
+      let menuId = plot.menu.slice(-1)[0]
+      let newtab = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
+
+      if (!newtab && plot.MenuID) {
+        newtab = {
+          MenuID: plot.MenuID,
+          MenuName: plot.MenuName,
+          MenuNo: plot.MenuNo,
+          type: plot.tabType
+        }
+      } else if (!newtab) {
+        return
+      }
+
+      MKEmitter.emit('modifyTabs', {...newtab, param: {$BID: sign}}, true)
+    } else {
+      MKEmitter.emit('resetSelectLine', config.uuid, sign, {})
+    }
+  }
+
+  changeStatus = () => {
+    const { plot, status } = this.state
+
+    let _status = status === 10 ? 0 : 10
+    
+    if (plot.subtype === 'xflow' && _status === 10) {
+      let nodes = this.mkGraph.toJSON()
+      let start_num = nodes.cells.filter(cell => cell.mknode === 'start').length
+      let end_num = nodes.cells.filter(cell => cell.mknode === 'end').length
+
+      if (start_num === 0) {
+        notification.warning({
+          top: 92,
+          message: '璇锋坊鍔犲紑濮嬭妭鐐癸紒',
+          duration: 2
+        })
+      } else if (start_num > 1) {
+        notification.warning({
+          top: 92,
+          message: '寮�濮嬭妭鐐逛笉鍙坊鍔犲涓紒',
+          duration: 2
+        })
+      } else if (end_num === 0) {
+        notification.warning({
+          top: 92,
+          message: '璇锋坊鍔犵粨鏉熻妭鐐癸紒',
+          duration: 2
+        })
+      } else if (end_num > 1) {
+        notification.warning({
+          top: 92,
+          message: '缁撴潫鑺傜偣涓嶅彲娣诲姞澶氫釜锛�',
+          duration: 2
+        })
+      } else {
+        this.setState({status: _status})
+      }
+    } else {
+      this.setState({status: _status})
+    }
+  }
+
+  resetlane = (id, x, offset) => {
+    let nodes = this.mkGraph.getNodes()
+
+    nodes.forEach(item => {
+      if (item.id === id || item.prop('parent') === id) return
+      if (item.prop('shape') === 'edge') return
+
+      let x1 = item.prop('position/x')
+      if (x1 < x) return
+
+      item.prop('position/x', x1 + offset)
+    })
+  }
+
+  render() {
+    const { loading, config, node, orgs, status, flowname } = this.state
+
+    let style = {...config.style}
+
+    if (config.plot.function === 'show') {
+      if (config.plot.empty === 'hidden' && this.cells.length === 0) {
+        style.position = 'absolute'
+        style.width = '100%'
+        style.zIndex = -1
+      }
+
+      return (
+        <div className="custom-x6-plot-box" id={'anchor' + config.uuid} style={style}>
+          {loading ?
+            <div className="loading-mask">
+              <div className="ant-spin-blur"></div>
+              <Spin />
+            </div> : null
+          }
+          <NormalHeader config={config} />
+          <div className={'canvas only-show' + (config.plot.click ? ' switchable' : '')} style={{width: '100%', minHeight: config.plot.height, height: config.plot.height}} id={config.uuid + 'canvas'}>
+            <div id={config.uuid + 'container'} className="mk-container"></div>
+          </div>
+        </div>
+      )
+    }
+
+    return (
+      <div className="custom-x6-plot-box" id={'anchor' + config.uuid} style={config.style}>
+        {loading ?
+          <div className="loading-mask">
+            <div className="ant-spin-blur"></div>
+            <Spin />
+          </div> : null
+        }
+        <NormalHeader config={config} />
+        <div className="mk-toolbar">
+          <div className="left-tool">
+            {config.plot.subtype === 'xflow' ? <Tooltip title="缃墠">
+              <VerticalAlignTopOutlined onClick={this.setTop}/>
+            </Tooltip> : null}
+            {config.plot.subtype === 'xflow' ? <Tooltip title="缃悗">
+              <VerticalAlignBottomOutlined onClick={this.setBottom}/>
+            </Tooltip> : null}
+            <Tooltip title="鏀惧ぇ">
+              <ZoomInOutlined onClick={this.setZoomIn}/>
+            </Tooltip>
+            <Tooltip title="缂╁皬">
+              <ZoomOutOutlined onClick={this.setZoomOut}/>
+            </Tooltip>
+            <Tooltip title="1:1">
+              <OneToOneOutlined onClick={this.setZoomInt}/>
+            </Tooltip>
+            <Tooltip title="鍚庨��">
+              <UndoOutlined onClick={this.setback}/>
+            </Tooltip>
+            <Tooltip title="鍓嶈繘">
+              <RedoOutlined onClick={this.setprev}/>
+            </Tooltip>
+            <Tooltip title="娓呯┖">
+              <ClearOutlined onClick={this.clearNode}/>
+            </Tooltip>
+            <Tooltip overlayStyle={{maxWidth: 260}} title="蹇嵎閿細澶嶅埗锛坈trl+c锛夈�佸壀鍒囷紙ctrl+x锛夈�佺矘璐达紙ctrl+v锛夈�佸悗閫�锛坈trl+z锛夈�佸墠杩涳紙ctrl+shift+z锛夈�佸垹闄わ紙backspace 鎴� delete锛�">
+              <QuestionCircleOutlined />
+            </Tooltip>
+          </div>
+          <div className="flow-name">{flowname}</div>
+          <div className="right-tool">
+            <Tooltip title="鍚敤/鍋滅敤">
+              <Switch size="small" style={{marginRight: '10px'}} checked={status === 10} onChange={this.changeStatus} />
+            </Tooltip>
+            <Tooltip title="淇濆瓨">
+              <SaveOutlined style={{marginRight: '10px'}} onClick={this.save}/>
+            </Tooltip>
+          </div>
+        </div>
+        <div className="canvas" style={{width: '100%', minHeight: config.plot.height, height: config.plot.height}} id={config.uuid + 'canvas'}>
+          <div id={config.uuid + 'stencil'} className="mk-stencil"></div>
+          <div id={config.uuid + 'container'} className="mk-container"></div>
+          <div className="mk-node-edit">
+            <div className="header">璁剧疆</div>
+            {!node ? <div className="empty">鏈�変腑</div> : <NodeUpdate node={node} orgs={orgs} onChange={this.changeProps}/>}
+          </div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default antvX6Chart
\ No newline at end of file
diff --git a/src/tabviews/custom/components/chart/antv-X6/index.scss b/src/tabviews/custom/components/chart/antv-X6/index.scss
new file mode 100644
index 0000000..ccaccfb
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-X6/index.scss
@@ -0,0 +1,232 @@
+.custom-x6-plot-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  
+  .mk-toolbar {
+    position: relative;
+    width: 100%;
+    height: 40px;
+    border-bottom: 1px solid #dfe3e8;
+
+    .left-tool {
+      float: left;
+      line-height: 40px;
+      .anticon {
+        margin: 0 10px;
+        font-size: 16px;
+        cursor: pointer;
+      }
+    }
+    .flow-name {
+      position: absolute;
+      left: 50%;
+      top: 6px;
+      font-size: 16px;
+      color: rgba(0, 0, 0, 0.85);
+      transform: translateX(-50%);
+    }
+    .right-tool {
+      float: right;
+      line-height: 40px;
+      .anticon {
+        margin: 0 10px;
+        font-size: 16px;
+        cursor: pointer;
+      }
+    }
+  }
+  .x6-graph-scroller::-webkit-scrollbar {
+    display: none;
+  }
+  .x6-cell.x6-edge.x6-edge-selected path:nth-child(2) {
+    stroke: #1890ff;
+  }
+  .x6-cell[data-shape="lane"] {
+    cursor: default;
+  }
+  .x6-node[data-shape="mk-polygon"]:hover {
+    .x6-port {
+      circle {
+        visibility: visible!important;
+      }
+    }
+  }
+
+  .canvas {
+    margin: 0px;
+    letter-spacing: 0px;
+    display: flex;
+
+    .mk-stencil {
+      width: 180px;
+      min-width: 180px;
+      height: 100%;
+      position: relative;
+      z-index: 2;
+      border-right: 1px solid #dfe3e8;
+      transition: all 0.2s;
+
+      .x6-widget-stencil-title {
+        display: none;
+      }
+      .x6-widget-stencil-content {
+        overflow-y: auto;
+      }
+      .x6-widget-stencil-content::-webkit-scrollbar {
+        width: 5px;
+      }
+      .x6-widget-stencil-content::-webkit-scrollbar-thumb {
+        border-radius: 5px;
+        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.07);
+        background: rgba(0, 0, 0, 0.07);
+      }
+      .x6-widget-stencil-content::-webkit-scrollbar-track {
+        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+        border-radius: 3px;
+        border: 1px solid rgba(0, 0, 0, 0.07);
+        background: rgba(0, 0, 0, 0);
+      }
+
+      .x6-widget-stencil-group[data-name="group3"] {
+        .x6-graph-svg {
+          top: 5px;
+          left: 5px;
+          right: 5px;
+        }
+        .x6-cell {
+          transform: none!important;
+          rect:nth-child(2) {
+            width: 165px!important;
+          }
+          text {
+            transform: matrix(1,0,0,1,85,18)!important;
+          }
+        }
+      }
+    }
+
+    .mk-node-edit {
+      width: 180px;
+      min-width: 180px;
+      height: 100%;
+      position: relative;
+      z-index: 2;
+      border-left: 1px solid #dfe3e8;
+      background: #ffffff;
+      transition: all 0.2s;
+
+      .header {
+        width: 100%;
+        height: 32px;
+        text-align: center;
+        line-height: 32px;
+        background-color: #f5f5f5!important;
+        overflow-x: hidden;
+        white-space: nowrap;
+      }
+      .empty {
+        width: 100%;
+        text-align: center;
+        padding-top: 20px;
+        overflow-x: hidden;
+        white-space: nowrap;
+      }
+    }
+
+    .mk-container {
+      width: calc(100% - 180px);
+      height: 100%;
+    }
+    .x6-widget-stencil  {
+      background-color: #fff;
+    }
+    .x6-widget-stencil-title {
+      background-color: #fff;
+    }
+    .x6-widget-stencil-group-title {
+      background-color: #f5f5f5!important;
+    }
+    .x6-widget-transform {
+      margin: -1px 0 0 -1px;
+      padding: 0px;
+      border: 1px solid #239edd;
+    }
+    .x6-widget-transform > div {
+      border: 1px solid #239edd;
+    }
+    .x6-widget-transform > div:hover {
+      background-color: #3dafe4;
+    }
+    .x6-widget-transform-active-handle {
+      background-color: #3dafe4;
+    }
+    .x6-widget-transform-resize {
+      border-radius: 0;
+    }
+    .x6-widget-selection-inner {
+      border: 1px solid #239edd;
+    }
+    .x6-widget-selection-box {
+      opacity: 0;
+    }
+  }
+  .only-show {
+    .x6-port {
+      display: none;
+    }
+    .x6-cell.x6-edge {
+      cursor: default;
+      path {
+        cursor: default;
+      }
+    }
+  }
+  .only-show.switchable {
+    .x6-cell.x6-node:not([data-shape="lane"]):not([data-shape="mk-text"]) {
+      cursor: pointer;
+    }
+  }
+
+  .chart-header {
+    position: relative;
+    height: 45px;
+    border-bottom: 1px solid #e8e8e8;
+    overflow: hidden;
+    padding-right: 35px;
+
+    .chart-title {
+      text-decoration: inherit;
+      font-weight: inherit;
+      font-style: inherit;
+      float: left;
+      line-height: 45px;
+      margin-left: 10px;
+      position: relative;
+      z-index: 1;
+    }
+  }
+  .loading-mask {
+    position: absolute;
+    left: 0px;
+    top: 0;
+    right: 0px;
+    bottom: 0px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    text-align: justify;
+    z-index: 3;
+
+    .ant-spin-blur {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      opacity: 0.5;
+      background: #ffffff;
+    }
+  }
+}
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
new file mode 100644
index 0000000..5893982
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
@@ -0,0 +1,513 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Form, Row, Col, Input, Select, Radio, InputNumber, Modal } from 'antd'
+import { FormOutlined } from '@ant-design/icons'
+
+import ColorSketch from '@/tabviews/zshare/mutilform/mkColor'
+import NodeForm from './nodeform'
+import './index.scss'
+
+const { TextArea } = Input
+
+class NodeUpdate extends Component {
+  static propTpyes = {
+    node: PropTypes.object,
+    orgs: PropTypes.array
+  }
+
+  state = {
+    formlist: null,
+    mknode: null,
+    mkdata: null
+  }
+
+  UNSAFE_componentWillMount () {
+    this.setState({
+      mknode: this.props.node,
+      mkdata: this.props.node.mkdata || '',
+      formlist: this.getFormList(this.props.node)
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    if (!is(fromJS(this.props.node), fromJS(nextProps.node))) {
+      this.setState({
+        formlist: null
+      }, () => {
+        this.setState({
+          mknode: nextProps.node,
+          mkdata: nextProps.node.mkdata || '',
+          formlist: this.getFormList(nextProps.node)
+        })
+      })
+    }
+  }
+
+  getFormList = (node) => {
+    let roleList = sessionStorage.getItem('sysRoles')
+    if (roleList) {
+      try {
+        roleList = JSON.parse(roleList)
+      } catch (e) {
+        roleList = []
+      }
+    } else {
+      roleList = []
+    }
+
+    let title = ''
+    if (node.attrs && node.attrs.text) {
+      title = node.attrs.text.text || ''
+    }
+
+    if (node.shape === 'edge') {
+      let stroke = ''
+
+      if (node.attrs && node.attrs.line) {
+        stroke = node.attrs.line.stroke || '#000000'
+      }
+
+      let strokeWidth = ''
+
+      if (node.attrs && node.attrs.line) {
+        strokeWidth = node.attrs.line.strokeWidth || 1
+      }
+
+      let lineType = 'solid'
+
+      if (node.attrs && node.attrs.line && node.attrs.line.strokeDasharray) {
+        lineType = 'dash'
+      }
+
+      let font = node.labels && node.labels[0] ? node.labels[0].attrs.label : {}
+
+      return [
+        {
+          type: 'title',
+          label: '鍐呭'
+        },
+        {
+          type: 'text',
+          field: 'title',
+          label: '鏍囩',
+          initval: font.text || ''
+        },
+        {
+          type: 'title',
+          label: '鏍峰紡'
+        },
+        {
+          type: 'color',
+          field: 'stroke',
+          label: '棰滆壊',
+          initval: stroke
+        },
+        {
+          type: 'number',
+          field: 'strokeWidth',
+          label: '绾垮',
+          initval: strokeWidth
+        },
+        {
+          type: 'radio',
+          field: 'lineType',
+          label: '绾垮瀷',
+          initval: lineType,
+          options: [
+            {value: 'solid', text: '瀹炵嚎'},
+            {value: 'dash', text: '铏氱嚎'}
+          ]
+        },
+        {
+          type: 'title',
+          label: '鏍囩鏍峰紡'
+        },
+        {
+          type: 'number',
+          field: 'fontSize',
+          label: '瀛楀彿',
+          initval: font.fontSize || 14
+        },
+        {
+          type: 'color',
+          field: 'fontFill',
+          label: '棰滆壊',
+          initval: font.fill || '#000000'
+        },
+        {
+          type: 'other',
+          label: '鑷畾涔変俊鎭�'
+        }
+      ]
+    } else if (node.shape === 'lane') {
+      let fontFill = '#262626'
+      if (node.attrs && node.attrs.text) {
+        fontFill = node.attrs.text.fill || '#262626'
+      }
+      
+      let fill = ''
+      if (node.attrs && node.attrs['name-rect']) {
+        fill = node.attrs['name-rect'].fill || ''
+      }
+
+      let width = 100
+      if (node.size) {
+        width = node.size.width || 100
+      }
+      let height = 100
+      if (node.size) {
+        height = node.size.height || 100
+      }
+
+      let fontSize = 12
+      if (node.attrs && node.attrs.text) {
+        fontSize = node.attrs.text.fontSize || 12
+      }
+
+      let stroke = ''
+      if (node.attrs && node.attrs.body) {
+        stroke = node.attrs.body.stroke || ''
+      }
+      return [
+        {
+          type: 'title',
+          label: '鏍囬'
+        },
+        {
+          type: 'text',
+          field: 'title',
+          label: '鏍囩',
+          initval: title
+        },
+        {
+          type: 'title',
+          label: '鏍峰紡'
+        },
+        {
+          type: 'color',
+          field: 'stroke',
+          label: '杈规',
+          initval: stroke
+        },
+        {
+          type: 'number',
+          field: 'width',
+          label: '瀹藉害',
+          help: '瀹藉害涓嶅彲灏忎簬100',
+          initval: width
+        },
+        {
+          type: 'number',
+          field: 'height',
+          label: '楂樺害',
+          help: '楂樺害涓嶅彲灏忎簬100',
+          initval: height
+        },
+        {
+          type: 'title',
+          label: '鏍囬鏍峰紡'
+        },
+        {
+          type: 'color',
+          field: 'fill',
+          label: '鑳屾櫙',
+          initval: fill
+        },
+        {
+          type: 'number',
+          field: 'fontSize',
+          label: '瀛楀彿',
+          initval: fontSize
+        },
+        {
+          type: 'color',
+          field: 'fontFill',
+          label: '棰滆壊',
+          initval: fontFill
+        }
+      ]
+    } else if (node.shape === 'mk-text') {
+      if (node.attrs && node.attrs.label) {
+        title = node.attrs.label.text || ''
+      }
+
+      let fill = ''
+
+      if (node.attrs && node.attrs.body) {
+        fill = node.attrs.body.fill || ''
+      }
+
+      let stroke = ''
+
+      if (node.attrs && node.attrs.body) {
+        stroke = node.attrs.body.stroke || ''
+      }
+
+      let fontFill = '#262626'
+      if (node.attrs && node.attrs.label) {
+        fontFill = node.attrs.label.style.color || '#262626'
+      }
+
+      let fontSize = 14
+      if (node.attrs && node.attrs.label) {
+        fontSize = node.attrs.label.style.fontSize || 14
+      }
+      return [
+        {
+          type: 'title',
+          label: '鍐呭'
+        },
+        {
+          type: 'textarea',
+          field: 'title',
+          label: '鏍囩',
+          initval: title
+        },
+        {
+          type: 'title',
+          label: '鏍峰紡'
+        },
+        {
+          type: 'color',
+          field: 'fill',
+          label: '鑳屾櫙',
+          initval: fill
+        },
+        {
+          type: 'color',
+          field: 'stroke',
+          label: '杈规',
+          initval: stroke
+        },
+        {
+          type: 'title',
+          label: '鏂囨湰鏍峰紡'
+        },
+        {
+          type: 'number',
+          field: 'fontSize',
+          label: '瀛楀彿',
+          initval: fontSize
+        },
+        {
+          type: 'color',
+          field: 'fontFill',
+          label: '棰滆壊',
+          initval: fontFill
+        }
+      ]
+    } else {
+      let fontFill = '#262626'
+      if (node.attrs && node.attrs.text) {
+        fontFill = node.attrs.text.fill || '#262626'
+      }
+      
+      let fill = ''
+
+      if (node.attrs && node.attrs.body) {
+        fill = node.attrs.body.fill || ''
+      }
+      let fontSize = 12
+      if (node.attrs && node.attrs.text) {
+        fontSize = node.attrs.text.fontSize || 12
+      }
+      let stroke = ''
+
+      if (node.attrs && node.attrs.body) {
+        stroke = node.attrs.body.stroke || ''
+      }
+      return [
+        {
+          type: 'title',
+          label: '鍐呭'
+        },
+        {
+          type: 'text',
+          field: 'title',
+          label: '鏍囩',
+          initval: title
+        },
+        {
+          type: 'title',
+          label: '鏍峰紡'
+        },
+        {
+          type: 'color',
+          field: 'fill',
+          label: '鑳屾櫙',
+          initval: fill
+        },
+        {
+          type: 'color',
+          field: 'stroke',
+          label: '杈规',
+          initval: stroke
+        },
+        {
+          type: 'title',
+          label: '鏍囩鏍峰紡'
+        },
+        {
+          type: 'number',
+          field: 'fontSize',
+          label: '瀛楀彿',
+          initval: fontSize
+        },
+        {
+          type: 'color',
+          field: 'fontFill',
+          label: '棰滆壊',
+          initval: fontFill
+        },
+        {
+          type: 'other',
+          label: '鑷畾涔変俊鎭�'
+        }
+      ]
+    }
+  }
+
+  change = (value, key) => {
+    if (key === 'fontSize') {
+      if (typeof(value) !== 'number' || value < 0) {
+        return
+      }
+    } else if (key === 'width' || key === 'height') {
+      if (typeof(value) !== 'number') {
+        return
+      } else if (value < 100) {
+        return
+      }
+    }
+
+    this.props.onChange(value, key)
+  }
+
+  confirm = () => {
+    this.nodeRef.handleConfirm().then(res => {
+      this.setState({visible: false, mkdata: res})
+      this.props.onChange(res, 'mkdata')
+    })
+  }
+
+  getFields() {
+    const { formlist, mkdata, mknode } = this.state
+    const fields = []
+
+    if (!formlist) return
+
+    formlist.forEach((item, index) => {
+      if (item.type === 'title') {
+        fields.push(
+          <Col span={24} key={index}>
+            <span className="split-line">{item.label}</span>
+          </Col>
+        )
+      } else if (item.type === 'text') {
+        fields.push(
+          <Col span={24} key={index}>
+            <Form.Item label={item.label}>
+              <Input defaultValue={item.initval} placeholder="" autoComplete="off" onChange={(e) => this.change(e.target.value, item.field)} />
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'textarea') {
+        fields.push(
+          <Col span={24} key={index} style={{padding: '0 12px'}}>
+            <TextArea defaultValue={item.initval} rows={3} onChange={(e) => this.change(e.target.value, item.field)} />
+          </Col>
+        )
+      } else if (item.type === 'number') {
+        fields.push(
+          <Col span={24} key={index}>
+            <Form.Item label={item.label} help={item.help || null}>
+              <InputNumber defaultValue={item.initval} precision={0} min={0} onChange={(value) => this.change(value, item.field)} />
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'select') {
+        fields.push(
+          <Col span={24} key={index}>
+            <Form.Item label={item.label}>
+              <Select
+                showSearch
+                defaultValue={item.initval}
+                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                onChange={(value) => {this.change(value, item.field)}}
+              >
+                {item.options.map(option =>
+                  <Select.Option key={option.value} value={option.value}>
+                    {option.text}
+                  </Select.Option>
+                )}
+              </Select>
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'radio') {
+        fields.push(
+          <Col span={24} key={index}>
+            <Form.Item label={item.label}>
+              <Radio.Group defaultValue={item.initval} style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.change(e.target.value, item.field)}}>
+                {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={24} key={index}>
+            <Form.Item label={item.label}>
+              <ColorSketch defaultValue={item.initval} onChange={(value) => this.change(value, item.field)}/>
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'other') {
+        fields.push(
+          <Col span={24} key={index}>
+            <span className="split-line">{item.label}锛�<FormOutlined onClick={() => {this.setState({visible: true})}}/></span>
+            {mkdata ? <div className="mk-data">
+              <div>鐘舵�侊細{mkdata.status}<span style={{float: 'right'}}>{mkdata.statusName}</span></div>
+              {mknode.shape !== 'edge' && !mknode.mknode ? <div>鏍囪锛歿mkdata.sign || ''}</div> : null}
+              {mkdata.members && mkdata.members.length ? <div>瀹℃壒浜猴細{mkdata.members.map(item => item.workername).join('銆�')}</div> : null}
+              {mkdata.copys && mkdata.copys.length ? <div>鎶勯�佷汉锛歿mkdata.copys.map(item => item.workername).join('銆�')}</div> : null}
+              <div>澶囨敞锛歿mkdata.remark || ''}</div>
+            </div> : null}
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  render() {
+    const { visible, mkdata, mknode } = this.state
+
+    return (
+      <div className="node-edit-form-wrap">
+        <Form className="node-edit-form">
+          <Row>{this.getFields()}</Row>
+        </Form>
+        <Modal
+          title={mknode && mknode.shape === 'edge' ? '杩炵嚎缂栬緫' : '鑺傜偣缂栬緫'}
+          visible={visible}
+          closable={false}
+          maskClosable={false}
+          width={1000}
+          onOk={this.confirm}
+          onCancel={() => this.setState({visible: false})}
+          destroyOnClose
+        >
+          <NodeForm node={mknode} data={mkdata} orgs={this.props.orgs} handleSubmit={() => this.confirm()} wrappedComponentRef={(inst) => this.nodeRef = inst}/>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default NodeUpdate
\ No newline at end of file
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
new file mode 100644
index 0000000..893aaf2
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
@@ -0,0 +1,231 @@
+.node-edit-form {
+  padding-top: 10px;
+  overflow: hidden;
+  .split-line {
+    display: block;
+    border-bottom: 1px solid #d9d9d9;
+    margin: 5px 12px 10px;
+    padding-bottom: 2px;
+    font-size: 13px;
+  }
+  .mk-data {
+    font-size: 13px;
+    padding: 0 12px;
+    >div {
+      padding-bottom: 2px;
+    }
+  }
+  textarea.ant-input {
+    padding: 0px 4px;
+    border-radius: 0px;
+  }
+  .ant-form-item {
+    display: flex;
+    margin-bottom: 10px;
+
+    .ant-form-item-label {
+      width: 40px;
+      line-height: 24px;
+      label {
+        color: rgba(0,0,0,0.45);
+        font-size: 13px;
+      }
+      label::after {
+        display: none;
+      }
+    }
+    .ant-form-item-control-wrapper {
+      padding: 0 8px;
+      flex: 1;
+      .ant-form-item-control {
+        line-height: 24px;
+      }
+      .ant-form-explain {
+        font-size: 12px;
+        min-height: 18px;
+        color: #c8c8c8;
+        margin-top: 1px;
+      }
+      .ant-input {
+        height: 24px;
+        padding: 0px 4px;
+        font-size: 13px;
+        line-height: 24px;
+        border-radius: 0px;
+      }
+      .ant-input-number {
+        height: 24px;
+        border-radius: 0px;
+        .ant-input-number-input {
+          height: 22px;
+          padding: 2px 4px;
+          font-size: 13px;
+        }
+      }
+      .ant-radio-wrapper {
+        margin-right: 0px;
+      }
+
+      .color-sketch-block {
+        height: 20px;
+        margin-top: 2px;
+        .color-sketch-block-box {
+          width: 20px;
+          height: 20px;
+        }
+        .color-sketch-value {
+          display: none;
+        }
+        .color-sketch-block-inner {
+          border-radius: 0px;
+        }
+      }
+      .ant-select-selection--single {
+        height: 26px;
+        border-radius: 0px;
+      }
+      .ant-select-selection__rendered {
+        line-height: 24px;
+      }
+    }
+  }
+}
+.node-edit-form-wrap {
+  height: calc(100% - 32px);
+  overflow-y: auto;
+}
+.node-edit-form-wrap::-webkit-scrollbar {
+  width: 5px;
+}
+.node-edit-form-wrap::-webkit-scrollbar-thumb {
+  border-radius: 5px;
+  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.07);
+  background: rgba(0, 0, 0, 0.07);
+}
+.node-edit-form-wrap::-webkit-scrollbar-track {
+  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+  border-radius: 3px;
+  border: 1px solid rgba(0, 0, 0, 0.07);
+  background: rgba(0, 0, 0, 0);
+}
+
+.normal-node-form {
+  >.ant-row >.ant-col-24 {
+    .ant-form-item-label {
+      width: 16%;
+    }
+    .ant-form-item-control-wrapper {
+      width: 84%;
+    }
+  }
+  .member-input {
+    display: inline-block;
+    width: 100%;
+    height: 32px;
+    padding: 4px 11px;
+    color: rgba(0, 0, 0, 0.65);
+    font-size: 14px;
+    line-height: 1.5;
+    background-color: #fff;
+    background-image: none;
+    border: 1px solid #d9d9d9;
+    border-radius: 4px;
+
+    .anticon-form {
+      float: right;
+      margin-top: 3px;
+    }
+  }
+}
+.member-transfer {
+  .mk-tree {
+    display: inline-block!important;
+    .circle {
+      position: relative;
+      top: 1px;
+      right: 4px;
+      display: inline-block!important;
+      width: 12px;
+      height: 12px;
+      background: #1890ff;
+      border-radius: 50%;
+    }
+    .green.circle {
+      background: #52c41a;
+    }
+  }
+  .ant-transfer-list:first-child {
+    width: 60%;
+  }
+  .ant-transfer-list:last-child {
+    width: 40%;
+  }
+  .ant-transfer-list-header {
+    .ant-transfer-list-header-selected {
+      span:not(.ant-transfer-list-header-title) {
+        display: none;
+      }
+      .ant-transfer-list-header-title {
+        position: unset;
+      }
+    }
+  }
+}
+
+.member-modal {
+  .ant-modal {
+    top: 50px;
+  }
+  .ant-modal-body {
+    padding-top: 15px;
+
+    .ant-input-search {
+      width: 300px;
+      margin-bottom: 10px;
+    }
+
+    .ant-tree-checkbox-checked .ant-tree-checkbox-inner {
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+    .ant-tree-checkbox-checked::after {
+      border-color: var(--mk-sys-color);
+    }
+    .ant-tree-checkbox:hover .ant-tree-checkbox-inner {
+      border-color: var(--mk-sys-color);
+    }
+    .ant-transfer-list-content-item:not(.ant-transfer-list-content-item-disabled):hover {
+      background-color: var(--mk-sys-color1);
+    }
+    .ant-tree-checkbox-disabled.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after {
+      border-color: var(--mk-sys-color4);
+    }
+    .ant-transfer-operation {
+      .ant-btn, .ant-btn:hover {
+        background-color: var(--mk-sys-color);
+        border-color: var(--mk-sys-color);
+      }
+    }
+
+    .ant-transfer-list-body {
+      max-height: calc(100vh - 320px);
+      min-height: 300px;
+      overflow-y: auto;
+    }
+
+    .ant-transfer-list-body::-webkit-scrollbar {
+      width: 7px;
+    }
+    .ant-transfer-list-body::-webkit-scrollbar-thumb {
+      border-radius: 5px;
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+      background: rgba(0, 0, 0, 0.13);
+    }
+    .ant-transfer-list-body::-webkit-scrollbar-track {
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+      border-radius: 3px;
+      border: 1px solid rgba(0, 0, 0, 0.07);
+      background: rgba(0, 0, 0, 0);
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
new file mode 100644
index 0000000..65f565d
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
@@ -0,0 +1,198 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Modal, Transfer, Tree, Input, notification } from 'antd'
+import { FormOutlined } from '@ant-design/icons'
+
+const { TreeNode } = Tree
+const { Search } = Input
+
+const isChecked = (selectedKeys, eventKey) => {
+  return selectedKeys.indexOf(eventKey) !== -1
+}
+
+const generateTree = (treeNodes = [], checkedKeys = []) => {
+  return treeNodes.map(({ children, ...props }) => (
+    <TreeNode {...props} disabled={checkedKeys.includes(props.key)} key={props.key}>
+      {generateTree(children, checkedKeys)}
+    </TreeNode>
+  ))
+}
+
+const TreeTransfer = ({ dataSource, targetKeys, ...restProps }) => {
+  const transferDataSource = []
+  function flatten(list = []) {
+    list.forEach(item => {
+      transferDataSource.push(item)
+      flatten(item.children)
+    })
+  }
+  flatten(dataSource)
+
+  return (
+    <Transfer
+      {...restProps}
+      targetKeys={targetKeys}
+      dataSource={transferDataSource}
+      className="member-transfer"
+      titles={[<span className="mk-tree"><span className="circle"></span>缁勭粐鏈烘瀯</span>, <span className="mk-tree"><span className="circle green"></span>宸查��</span>]}
+      render={item => item.title}
+      showSelectAll={false}
+    >
+      {({ direction, onItemSelect, selectedKeys }) => {
+        if (direction === 'left') {
+          const checkedKeys = [...selectedKeys, ...targetKeys]
+          return (
+            <Tree
+              blockNode
+              checkable
+              checkStrictly
+              defaultExpandAll
+              checkedKeys={checkedKeys}
+              onCheck={(_, { node: { props: { eventKey } } }) => {
+                onItemSelect(eventKey, !isChecked(checkedKeys, eventKey))
+              }}
+              onSelect={(_, { node: { props: { eventKey } } }) => {
+                onItemSelect(eventKey, !isChecked(checkedKeys, eventKey))
+              }}
+            >
+              {generateTree(dataSource, targetKeys)}
+            </Tree>
+          )
+        }
+      }}
+    </Transfer>
+  )
+}
+
+class MemberForm extends Component {
+  static propTpyes = {
+    node: PropTypes.any,
+    data: PropTypes.any,
+    orgs: PropTypes.array
+  }
+
+  state = {
+    visible: false,
+    targetKeys: [],
+    users: []
+  }
+
+  onChange = targetKeys => {
+    this.setState({ targetKeys })
+  }
+
+  search = (val) => {
+    const { orgs } = this.props
+    
+    let _orgs = fromJS(orgs).toJS()
+    let _orgs_ = []
+    if (val) {
+      let getOrg = (ors) => {
+        return ors.filter(or => {
+          if (or.key.indexOf(val) > -1 || or.title.indexOf(val) > -1) {
+            return true
+          } else if (!or.children) {
+            return false
+          }
+
+          or.children = getOrg(or.children)
+
+          return or.children.length > 0
+        })
+      }
+
+      _orgs_ = getOrg(_orgs)
+    } else {
+      _orgs_ = _orgs
+    }
+
+    this.setState({orgs: _orgs_})
+  }
+
+  trigger = () => {
+    const { orgs, value, title } = this.props
+
+    let userIds = []
+    let users = {}
+
+    let getUsers = (ors) => {
+      ors.forEach(or => {
+        if (or.children) {
+          getUsers(or.children)
+        } else {
+          users[or.worker_id] = or
+          userIds.push(or.worker_id)
+        }
+      })
+    }
+
+    getUsers(orgs)
+
+    let targetKeys = []
+    let lost_works = []
+    value.forEach(user => {
+      if (userIds.includes(user.worker_id)) {
+        targetKeys.push(user.worker_id)
+      } else {
+        lost_works.push(user)
+      }
+    })
+
+    if (lost_works.length) {
+      notification.warning({
+        top: 92,
+        message: `鍘�${title} ${lost_works.map(item => item.workername).join('銆�')} 涓嶅瓨鍦紝璇烽噸鏂版坊鍔犮�俙,
+        duration: 10
+      })
+    }
+
+    this.setState({visible: true, orgs: fromJS(orgs).toJS(), targetKeys, users})
+  }
+
+  confirm = () => {
+    const { targetKeys, users } = this.state
+
+    let value = []
+    targetKeys.forEach(key => {
+      if (!users[key]) return
+
+      let user = fromJS(users[key]).toJS()
+
+      delete user.key
+      delete user.title
+
+      value.push(user)
+    })
+
+    this.setState({visible: false})
+    this.props.onChange(value)
+  }
+
+  render() {
+    const { value } = this.props
+    const { orgs, visible, targetKeys } = this.state
+
+    return (
+      <>
+        <div className="member-input">{value.length}浜�<FormOutlined onClick={this.trigger} /></div>
+        <Modal
+          wrapClassName="member-modal"
+          title="閫夋嫨浜哄憳"
+          visible={visible}
+          closable={false}
+          maskClosable={false}
+          width={1000}
+          onOk={this.confirm}
+          onCancel={() => this.setState({visible: false})}
+          destroyOnClose
+        >
+          <Search onSearch={this.search} enterButton/>
+          <TreeTransfer dataSource={orgs} targetKeys={targetKeys} onChange={this.onChange} />
+        </Modal>
+      </>
+    )
+  }
+}
+
+export default MemberForm
\ No newline at end of file
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
new file mode 100644
index 0000000..e155c71
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
@@ -0,0 +1,154 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Radio, Tooltip, InputNumber } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
+
+import MemberForm from './memberform'
+const { TextArea } = Input
+
+class NodeForm extends Component {
+  static propTpyes = {
+    node: PropTypes.any,
+    data: PropTypes.any,
+    orgs: PropTypes.array
+  }
+
+  state = {}
+
+  handleConfirm = () => {
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  render() {
+    const { node, orgs } = this.props
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+    let data = this.props.data || {}
+    let nodetype = node.shape !== 'edge' ? 'node' : 'edge'
+    if (node.mknode === 'start') {
+      nodetype = 'start'
+    } else if (node.mknode === 'end') {
+      nodetype = 'end'
+    }
+
+    return (
+      <Form {...formItemLayout} className="normal-node-form">
+        <Row gutter={24}>
+          <Col span={12}>
+            <Form.Item label="鐘舵�佸��">
+              {getFieldDecorator('status', {
+                initialValue: data.status,
+                rules: [
+                  {
+                    required: true,
+                    message: '璇疯緭鍏ョ姸鎬佸��!'
+                  }
+                ]
+              })(
+                <InputNumber precision={0}/>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label="鐘舵�佸悕">
+              {getFieldDecorator('statusName', {
+                initialValue: data.statusName || ''
+              })(
+                <Input placeholder="" autoComplete="off"/>
+              )}
+            </Form.Item>
+          </Col>
+          {nodetype === 'node' ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鏍囪灏嗕綔涓鸿妭鐐笽D">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏍囪
+              </Tooltip>
+            }>
+              {getFieldDecorator('sign', {
+                initialValue: data.sign || ''
+              })(
+                <Input placeholder="" autoComplete="off"/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {nodetype === 'edge' ? <Col span={12}>
+            <Form.Item label="璁剧疆瀹℃壒浜�">
+              {getFieldDecorator('approver', {
+                initialValue: data.approver || 'member'
+              })(
+                <Radio.Group>
+                  <Radio value="member">鎸囧畾鎴愬憳</Radio>
+                  <Radio value="departmentManager">閮ㄩ棬涓荤</Radio>
+                  <Radio value="directManager">鐩村睘涓荤</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {nodetype === 'edge' ? <Col span={12}>
+            <Form.Item label="瀹℃壒鏂瑰紡">
+              {getFieldDecorator('approvalMethod', {
+                initialValue: data.approvalMethod || 'orsign'
+              })(
+                <Radio.Group>
+                  <Radio value="countersign">浼氱</Radio>
+                  <Radio value="orsign">鎴栫</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {nodetype === 'edge' ? <Col span={12}>
+            <Form.Item label="瀹℃壒浜�">
+              {getFieldDecorator('members', {
+                initialValue: data.members || [],
+                rules: [{
+                  required: true,
+                  message: '璇锋坊鍔犲鎵逛汉!'
+                }]
+              })(
+                <MemberForm orgs={orgs} title="瀹℃壒浜�"/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {nodetype === 'edge' ? <Col span={12}>
+            <Form.Item label="鎶勯�佷汉">
+              {getFieldDecorator('copys', {
+                initialValue: data.copys || []
+              })(
+                <MemberForm orgs={orgs} title="鎶勯�佷汉"/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={24}>
+            <Form.Item label="澶囨敞">
+              {getFieldDecorator('remark', {
+                initialValue: data.remark || ''
+              })(
+                <TextArea rows={2}/>
+              )}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(NodeForm)
\ No newline at end of file
diff --git a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
index c76b83c..7f2b2cf 100644
--- a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -17,15 +17,12 @@
 import NormalHeader from '@/tabviews/custom/components/share/normalheader'
 import './index.scss'
 
-// const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
 const ExcelOutButton = asyncComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton'))
 const ExcelInButton = asyncComponent(() => import('@/tabviews/zshare/actionList/excelInbutton'))
 
 class LineChart extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
     config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
   }
 
   state = {
@@ -35,7 +32,6 @@
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
     chartId: Utils.getuuid(),  // 鍥捐〃Id
     transfield: {},            // 瀛楁鍚嶇О缈昏瘧
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     plot: null,                // 鍥捐〃璁剧疆
     search: null,              // 鎼滅储鏉′欢
     vFields: [],               // 鏁板�煎瓧娈�
@@ -44,12 +40,12 @@
   }
 
   data = []
+  loaded = false
 
   UNSAFE_componentWillMount () {
-    const { config, data, initdata } = this.props
-    let _config = fromJS(config).toJS()
-    let _sync = config.setting.sync === 'true'
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let BID = ''
     let BData = ''
 
@@ -60,14 +56,6 @@
     }
     if (BData) {
       BID = BData.$BID || ''
-    }
-
-    if (_sync && data) {
-      this.data = data[config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      this.data = initdata || []
-      _sync = false
     }
 
     let vFields = []
@@ -219,7 +207,7 @@
 
     let xc = {label: {
       formatter: (val) => {
-        if (!val || /^\s*$/.test(val)) return val
+        if (!val || /^\s+$/.test(val)) return val
         let _val = `${val}`
         if (_val.length <= limit) return val
         return _val.substring(0, limit) + '...'
@@ -333,52 +321,33 @@
       })
     }
 
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        this.data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
+    }
+
     this.setState({
       config: _config,
       BID: BID || '',
       vFields: vFields,
       vstFields: vstFields,
-      arr_field: _config.columns.map(col => col.field).join(','),
       plot: _config.plot,
-      sync: _sync,
-      search: Utils.initMainSearch(config.search),
+      search: _config.$searches,
       transfield
-    }, () => {
-      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
     })
-
-    if (this.data.length > 0) {
-      this.handleData()
-    }
-  }
-
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-      }
-
-      if (!is(fromJS(this.data), fromJS(_data))) {
-        this.data = _data
-        this.handleData()
-      }
-
-      this.setState({sync: false})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -386,30 +355,29 @@
   }
 
   componentDidMount () {
-    const { config, sync } = this.state
+    const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
     
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.loadData(true)
+        this.loadData('timer')
       })
     }
 
-    if (config.$cache && (config.setting.sync !== 'true' || sync)) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.data.length > 0) return
-
-        if (!is(fromJS(this.data), fromJS(res))) {
-          this.data = res
-          this.handleData()
-        }
-      })
-    }
+    this.initExec()
   }
 
   /**
@@ -420,11 +388,92 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.data = res.data
+            this.handleData()
+          })
+        } else {
+          this.handleData()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.data = res.data
+            this.handleData()
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.handleData()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.handleData()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    this.data = _data
+    this.handleData()
+
+    this.loaded = true
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   /**
@@ -442,10 +491,6 @@
       MKEmitter.emit('reloadData', config.setting.supModule, BID)
     } else {
       this.loadData()
-    }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
     }
   }
 
@@ -472,23 +517,22 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, search } = this.state
+    const { config, search } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: config.setting.order || '',
       search: searches,
       menuName: config.name
@@ -498,47 +542,49 @@
   /**
    * @description 鏁版嵁鍔犺浇
    */
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID, search } = this.state
+  async loadData (type) {
+    const { config, BID, search } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       if (!is(fromJS(this.data), fromJS([]))) {
         this.data = []
         this.handleData()
       }
+      this.loaded = true
       return
     }
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key)
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key)) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
+
+      this.loaded = true
 
       this.setState({
         loading: false
@@ -555,17 +601,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
index 5a584b0..68babea 100644
--- a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
@@ -53,9 +53,7 @@
 
 class DashboardChart extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -63,19 +61,17 @@
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
     chartId: Utils.getuuid(),  // 鍥捐〃Id
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     plot: null,                // 鍥捐〃璁剧疆
     chart: null
   }
 
   data = {}
+  loaded = false
 
   UNSAFE_componentWillMount () {
-    const { config, data, initdata } = this.props
+    const { config } = this.props
+
     let _config = fromJS(config).toJS()
-
-    let _sync = _config.setting.sync === 'true'
-
     let BID = ''
     let BData = ''
 
@@ -88,12 +84,22 @@
       BID = BData.$BID || ''
     }
 
-    if (_sync && data) {
-      this.data = data[config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      this.data = initdata || []
-      _sync = false
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        this.data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
     }
 
     if (_config.subtype !== 'ratioboard') {
@@ -114,52 +120,8 @@
     this.setState({
       config: _config,
       BID: BID || '',
-      arr_field: _config.columns.map(col => col.field).join(','),
-      plot: _config.plot,
-      sync: _sync
-    }, () => {
-      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      plot: _config.plot
     })
-
-    if (config.setting.sync === 'true' && !_sync) {
-      this.handleData()
-    }
-  }
-
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = null
-
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (config.subtype !== 'ratioboard') {
-          if (Array.isArray(_data)) {
-            _data = _data[0] || {}
-          }
-          _data.value = _data[config.plot.valueField] || 0
-        }
-      }
-
-      if (_data && !is(fromJS(this.data), fromJS(_data))) {
-        this.data = _data
-        this.handleData()
-      }
-
-      this.setState({sync: false})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -167,36 +129,27 @@
   }
 
   componentDidMount () {
-    const { config, sync } = this.state
+    const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.loadData(true)
+        this.loadData('timer')
       })
     }
 
-    if (config.$cache && (config.setting.sync !== 'true' || sync)) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res) return
-
-        let _data = null
-        if (config.subtype === 'ratioboard') {
-          _data = res
-        } else {
-          _data = res[0]
-          _data.value = _data[config.plot.valueField] || 0
-        }
-
-        if (!is(fromJS(this.data), fromJS(_data))) {
-          this.data = _data
-          this.handleData()
-        }
-      })
-    }
+    this.initExec()
   }
 
   /**
@@ -207,9 +160,113 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.data = res.data
+
+            if (config.subtype !== 'ratioboard') {
+              if (Array.isArray(this.data)) {
+                this.data = this.data[0] || {}
+              }
+              this.data.value = this.data[config.plot.valueField] || 0
+            }
+
+            this.handleData()
+          })
+        } else {
+          this.handleData()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.data = res.data
+
+            if (config.subtype !== 'ratioboard') {
+              if (Array.isArray(this.data)) {
+                this.data = this.data[0] || {}
+              }
+              this.data.value = this.data[config.plot.valueField] || 0
+            }
+
+            this.handleData()
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.handleData()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.handleData()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    if (config.subtype !== 'ratioboard') {
+      if (Array.isArray(_data)) {
+        _data = _data[0] || {}
+      }
+      _data.value = _data[config.plot.valueField] || 0
+    }
+
+    this.data = _data
+    this.handleData()
+
+    this.loaded = true
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId) => {
@@ -242,9 +299,8 @@
     }, 100)
   }
 
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+  async loadData (type) {
+    const { config, BID } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       let _data = null
@@ -258,30 +314,36 @@
         this.data = _data
         this.handleData()
       }
+
+      this.loaded = true
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
+
+      this.loaded = true
 
       let _data = null
       if (config.subtype === 'ratioboard') {
@@ -306,17 +368,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/chart/antv-pie/index.jsx b/src/tabviews/custom/components/chart/antv-pie/index.jsx
index 46e5ccf..3605b32 100644
--- a/src/tabviews/custom/components/chart/antv-pie/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -18,9 +18,7 @@
 
 class PieChart extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -30,20 +28,18 @@
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
     chartId: Utils.getuuid(),  // 鍥捐〃Id
     title: '',                 // 缁勪欢鏍囬
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     plot: null,                // 鍥捐〃璁剧疆
     search: null,              // 鎼滅储鏉′欢
     chart: null
   }
 
   data = []
+  loaded = false
 
   UNSAFE_componentWillMount () {
-    const { config, data, initdata } = this.props
+    const { config } = this.props
+
     let _config = fromJS(config).toJS()
-
-    let _sync = config.setting.sync === 'true'
-
     let BID = ''
     let BData = ''
 
@@ -54,14 +50,6 @@
     }
     if (BData) {
       BID = BData.$BID || ''
-    }
-
-    if (_sync && data) {
-      this.data = data[config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      this.data = initdata || []
-      _sync = false
     }
 
     _config.plot.height = Utils.getHeight(_config.plot.height)
@@ -81,50 +69,31 @@
 
     _config.plot.$decimal = decimal
 
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        this.data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
+    }
+
     this.setState({
       config: _config,
       BID: BID || '',
-      arr_field: _config.columns.map(col => col.field).join(','),
       plot: _config.plot,
-      sync: _sync,
       title: config.plot.title,
-      search: Utils.initMainSearch(config.search)
-    }, () => {
-      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      search: _config.$searches
     })
-
-    if (this.data.length > 0) {
-      this.handleData()
-    }
-  }
-
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-      }
-
-      if (!is(fromJS(this.data), fromJS(_data))) {
-        this.data = _data
-        this.handleData()
-      }
-
-      this.setState({sync: false})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -132,28 +101,27 @@
   }
 
   componentDidMount () {
-    const { config, sync } = this.state
+    const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.loadData(true)
+        this.loadData('timer')
       })
     }
 
-    if (config.$cache && (config.setting.sync !== 'true' || sync)) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.data.length > 0) return
-
-        if (!is(fromJS(this.data), fromJS(res))) {
-          this.data = res
-          this.handleData()
-        }
-      })
-    }
+    this.initExec()
   }
 
   /**
@@ -164,9 +132,90 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.data = res.data
+            this.handleData()
+          })
+        } else {
+          this.handleData()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.data = res.data
+            this.handleData()
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.handleData()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.handleData()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    this.data = _data
+    this.handleData()
+
+    this.loaded = true
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId) => {
@@ -209,47 +258,48 @@
     }
   }
 
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, search, BID } = this.state
+  async loadData (type) {
+    const { config, search, BID } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       if (!is(fromJS(this.data), fromJS([]))) {
         this.data = []
         this.handleData()
       }
+      this.loaded = true
       return
     }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key)
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key)) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
+      this.loaded = true
 
       this.setState({
         loading: false
@@ -266,17 +316,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/chart/antv-scatter/index.jsx b/src/tabviews/custom/components/chart/antv-scatter/index.jsx
index abc0f0c..f4751c8 100644
--- a/src/tabviews/custom/components/chart/antv-scatter/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-scatter/index.jsx
@@ -20,9 +20,7 @@
 
 class ScatterChart extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -31,19 +29,18 @@
     empty: true,               // 鍥捐〃鏁版嵁涓虹┖
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
     chartId: Utils.getuuid(),  // 鍥捐〃Id
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     plot: null,                // 鍥捐〃璁剧疆
     search: null,              // 鎼滅储鏉′欢
     chart: null
   }
 
   data = []
+  loaded = false
 
   UNSAFE_componentWillMount () {
-    const { config, data, initdata } = this.props
-    let _config = fromJS(config).toJS()
-    let _sync = config.setting.sync === 'true'
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let BID = ''
     let BData = ''
 
@@ -56,14 +53,6 @@
       BID = BData.$BID || ''
     }
 
-    if (_sync && data) {
-      this.data = data[config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      this.data = initdata || []
-      _sync = false
-    }
-
     _config.plot.height = Utils.getHeight(_config.plot.height)
     _config.style.height = 'auto'
     _config.style.minHeight = _config.plot.height + 30
@@ -72,50 +61,31 @@
       _config.style.minHeight = _config.style.minHeight + 45
     }
 
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        this.data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
+    }
+
     this.setState({
       config: _config,
       BID: BID || '',
       empty: this.data.length === 0,
-      arr_field: _config.columns.map(col => col.field).join(','),
       plot: _config.plot,
-      sync: _sync,
-      search: Utils.initMainSearch(config.search),
-    }, () => {
-      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      search: _config.$searches
     })
-
-    if (this.data.length > 0) {
-      this.handleData()
-    }
-  }
-
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-      }
-
-      if (!is(fromJS(this.data), fromJS(_data))) {
-        this.data = _data
-        this.handleData()
-      }
-
-      this.setState({sync: false, empty: _data.length === 0})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -123,32 +93,29 @@
   }
 
   componentDidMount () {
-    const { config, sync } = this.state
+    const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
     
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.loadData(true)
+        this.loadData('timer')
       })
     }
 
-    if (config.$cache && (config.setting.sync !== 'true' || sync)) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.data.length > 0) return
-
-        if (!is(fromJS(this.data), fromJS(res))) {
-          this.data = res
-          this.handleData()
-        }
-
-        this.setState({empty: false})
-      })
-    }
+    this.initExec()
   }
 
   /**
@@ -159,11 +126,98 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.data = res.data
+            this.handleData()
+
+            this.setState({empty: res.data.length === 0})
+          })
+        } else {
+          this.handleData()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.data = res.data
+            this.handleData()
+
+            this.setState({empty: res.data.length === 0})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.handleData()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.handleData()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    this.data = _data
+    this.handleData()
+
+    this.setState({empty: _data.length === 0})
+
+    this.loaded = true
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   /**
@@ -181,10 +235,6 @@
       MKEmitter.emit('reloadData', config.setting.supModule, BID)
     } else {
       this.loadData()
-    }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
     }
   }
 
@@ -211,35 +261,32 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, search } = this.state
+    const { config, search } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
   /**
    * @description 鏁版嵁鍔犺浇
    */
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID, search } = this.state
+  async loadData (type) {
+    const { config, BID, search } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({ empty: true })
@@ -248,38 +295,41 @@
         this.data = []
         this.handleData()
       }
+
+      this.loaded = true
       return
     }
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key)
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key)) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
+      this.loaded = true
       
       this.setState({
         empty: !result.data || result.data.length === 0,
@@ -297,17 +347,31 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/chart/custom-chart/index.jsx b/src/tabviews/custom/components/chart/custom-chart/index.jsx
index f2b717e..1fcd7c8 100644
--- a/src/tabviews/custom/components/chart/custom-chart/index.jsx
+++ b/src/tabviews/custom/components/chart/custom-chart/index.jsx
@@ -4,7 +4,7 @@
 import { Chart } from '@antv/g2'
 import DataSet from '@antv/data-set'
 import * as echarts from 'echarts'
-import { Spin, Empty, notification } from 'antd'
+import { Spin, Empty, notification, Modal } from 'antd'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -16,9 +16,7 @@
 
 class CustomChart extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -26,18 +24,17 @@
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     empty: true,               // 鍥捐〃鏁版嵁涓虹┖
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     plot: null,                // 鍥捐〃璁剧疆
     search: null,              // 鎼滅储鏉′欢
   }
 
   data = []
+  loaded = false
 
   UNSAFE_componentWillMount () {
-    const { config, data, initdata } = this.props
-    let _config = fromJS(config).toJS()
-    let _sync = config.setting.sync === 'true'
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let BID = ''
     let BData = ''
 
@@ -50,61 +47,34 @@
       BID = BData.$BID || ''
     }
 
-    if (_sync && data) {
-      this.data = data[config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      this.data = initdata || []
-      _sync = false
-    }
-
     _config.plot.height = Utils.getHeight(_config.plot.height)
     _config.style.height = 'auto'
+
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        this.data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
+    }
 
     this.setState({
       config: _config,
       empty: this.data.length === 0,
       BID: BID || '',
-      arr_field: _config.columns.map(col => col.field).join(','),
       plot: _config.plot,
-      sync: _sync,
-      search: Utils.initMainSearch(config.search)
-    }, () => {
-      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      search: _config.$searches
     })
-
-    if (this.data.length > 0) {
-      this.handleData()
-    }
-  }
-
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-      }
-
-      if (!is(fromJS(this.data), fromJS(_data))) {
-        this.data = _data
-        this.handleData()
-      }
-
-      this.setState({sync: false, empty: _data.length === 0})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -112,31 +82,29 @@
   }
 
   componentDidMount () {
-    const { config, sync } = this.state
+    const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
     
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.loadData(true)
+        this.loadData('timer')
       })
     }
 
-    if (config.$cache && (config.setting.sync !== 'true' || sync)) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.data.length > 0) return
-
-        if (!is(fromJS(this.data), fromJS(res))) {
-          this.data = res
-          this.handleData()
-        }
-        this.setState({empty: false})
-      })
-    }
+    this.initExec()
   }
 
   /**
@@ -147,11 +115,100 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.data = res.data
+            this.handleData()
+
+            this.setState({empty: res.data.length === 0})
+          })
+        } else {
+          this.handleData()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.data = res.data
+            this.handleData()
+
+            this.setState({empty: res.data.length === 0})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.handleData()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.handleData()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    if (!is(fromJS(this.data), fromJS(_data))) {
+      this.data = _data
+      this.handleData()
+    }
+
+    this.setState({empty: _data.length === 0})
+
+    this.loaded = true
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   /**
@@ -169,10 +226,6 @@
       MKEmitter.emit('reloadData', config.setting.supModule, BID)
     } else {
       this.loadData()
-    }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
     }
   }
 
@@ -199,35 +252,32 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, search } = this.state
+    const { config, search } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
   /**
    * @description 鏁版嵁鍔犺浇
    */
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID, search } = this.state
+  async loadData (type) {
+    const { config, BID, search } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -238,38 +288,41 @@
         this.data = []
         this.handleData()
       }
+
+      this.loaded = true
       return
     }
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key)
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key)) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
+      this.loaded = true
 
       this.setState({
         loading: false,
@@ -287,16 +340,37 @@
           this.timer && this.timer.stop()
         }
       }
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+      
+      if (!result.message) return
+      if (result.ErrCode === 'N') {
+        Modal.error({
+          title: result.message,
+        })
+      } else if (result.ErrCode !== '-2') {
+        notification.error({
+          top: 92,
+          message: result.message,
+          duration: 10
+        })
+      }
     }
   }
 
diff --git a/src/tabviews/custom/components/code/sand-box/index.jsx b/src/tabviews/custom/components/code/sand-box/index.jsx
index dc1a995..d5b40b7 100644
--- a/src/tabviews/custom/components/code/sand-box/index.jsx
+++ b/src/tabviews/custom/components/code/sand-box/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification } from 'antd'
+import { Spin, notification, Modal } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -10,16 +10,13 @@
 
 class SandBoxComponent extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
     BID: '',                   // 涓婄骇ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: [],                  // 鏁版嵁
     html: '',
     result: {}
@@ -28,12 +25,10 @@
   loaded = false
 
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = []
-    let _sync = false
-
     let BID = ''
     let BData = ''
 
@@ -47,20 +42,21 @@
     }
     
     if (_config.wrap.datatype !== 'static') {
-      _sync = _config.setting.sync === 'true'
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[_config.dataName] || []
-        _sync = false
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
         this.loaded = true
-      } else if (_sync && initdata) {
-        _data = initdata || {}
-        _sync = false
-        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
       }
-    } else {
-      _data = {}
-      this.loaded = true
     }
     
     if (_config.css) {
@@ -74,18 +70,9 @@
     }
 
     this.setState({
-      sync: _sync,
       data: _data,
       BID: BID || '',
-      config: _config,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
-      this.renderView()
+      config: _config
     })
   }
 
@@ -94,15 +81,15 @@
 
     MKEmitter.addListener('reloadData', this.reloadData)
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        this.setState({data: res}, () => {
-          this.renderView()
-        })
-      })
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
     }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -114,34 +101,98 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
+  initExec = () => {
+    const { config, BID } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-      }
-
-      this.loaded = true
-
-      if (!is(fromJS(this.state.data), fromJS(_data))) {
+    if (config.wrap.datatype !== 'static') {
+      if (config.$cache) {
+        if (config.$time) {
+          if (!this.loaded) {
+            Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+              if (!res.valid && config.setting.onload === 'true') {
+                setTimeout(() => {
+                  this.loadData('init')
+                }, config.setting.delay || 0)
+              }
+    
+              if (!res.data || this.loaded) return
+  
+              this.setState({data: res.data}, () => {
+                this.renderView()
+              })
+            })
+          } else {
+            this.renderView()
+          }
+        } else {
+          if (!this.loaded) {
+            Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+              if (!res.data || this.loaded) return
+      
+              this.setState({data: res.data}, () => {
+                this.renderView()
+              })
+            })
+          }
+  
+          if (config.setting.onload === 'true') {
+            setTimeout(() => {
+              this.loadData('init')
+            }, config.setting.delay || 0)
+          } else if (this.loaded) {
+            this.renderView()
+          }
+        }
+      } else if (config.setting.onload === 'true') {
         setTimeout(() => {
-          this.renderView()
-        }, 10)
+          this.loadData()
+        }, config.setting.delay || 0)
+      } else if (this.loaded) {
+        this.renderView()
       }
-
-      this.setState({sync: false, data: _data})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
+    } else {
+      this.renderView()
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    if (!is(fromJS(this.state.data), fromJS(_data))) {
+      setTimeout(() => {
+        this.renderView()
+      }, 10)
+    }
+
+    this.setState({data: _data})
+
+    this.loaded = true
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId) => {
@@ -152,9 +203,8 @@
     this.loadData()
   }
 
-  async loadData () {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+  async loadData (type) {
+    const { config, BID } = this.state
 
     if (config.wrap.datatype === 'static') {
       this.setState({
@@ -171,10 +221,12 @@
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -183,15 +235,15 @@
     })
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let _data = result.data || []
 
       this.loaded = true
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       if (!is(fromJS(this.state.data), fromJS(_data))) {
@@ -208,15 +260,37 @@
         result: _result,
         loading: false
       })
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+
+      if (!result.message) return
+      if (result.ErrCode === 'N') {
+        Modal.error({
+          title: result.message
+        })
+      } else if (result.ErrCode !== '-2') {
+        notification.error({
+          top: 92,
+          message: result.message,
+          duration: 10
+        })
+      }
     }
   }
 
@@ -244,8 +318,8 @@
       if (js) {
         try {
           // eslint-disable-next-line
-          let evalfunc = eval('(true && function (data, result) {' + js + '})')
-          evalfunc(data, result)
+          let evalfunc = eval('(true && function (data, result, Api, notification) {' + js + '})')
+          evalfunc(data, result, Api, notification)
         } catch (e) {
           console.warn(e)
         }
diff --git a/src/tabviews/custom/components/editor/braft-editor/index.jsx b/src/tabviews/custom/components/editor/braft-editor/index.jsx
index a4084ac..163424a 100644
--- a/src/tabviews/custom/components/editor/braft-editor/index.jsx
+++ b/src/tabviews/custom/components/editor/braft-editor/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification } from 'antd'
+import { Spin, notification, Modal } from 'antd'
 
 import asyncComponent from '@/utils/asyncComponent'
 import Api from '@/api'
@@ -14,25 +14,21 @@
 
 class BraftEditorContent extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
     BID: '',                   // 涓婄骇ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: {}                   // 鏁版嵁
   }
 
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = { $$empty: true }
-    let _sync = false
 
     let BID = ''
     let BData = ''
@@ -46,21 +42,16 @@
       BID = BData.$BID || ''
     }
     
-    if (_config.setting && _config.wrap.datatype === 'dynamic') {
-      _sync = _config.setting.sync === 'true'
+    if (_config.wrap.datatype === 'dynamic') {
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[_config.dataName] || {$$empty: true}
-        if (_data && Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
-      } else if (_sync && initdata) {
-        _data = initdata
-        if (_data && Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+        _data = _data[0] || {$$empty: true}
+
+        _config.setting.sync = 'false'
+  
+        window.GLOB.SyncData.delete(_config.dataName)
       }
     }
 
@@ -69,17 +60,9 @@
     }
 
     this.setState({
-      sync: _sync,
       data: _data,
       BID: BID || '',
       config: _config,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.wrap.datatype === 'dynamic' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
     })
   }
 
@@ -89,9 +72,19 @@
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
 
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.wrap.datatype === 'public') {
       MKEmitter.addListener('mkPublicData', this.mkPublicData)
     }
+
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -104,30 +97,44 @@
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('mkPublicData', this.mkPublicData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
+  initExec = () => {
+    const { config } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = {$$empty: true}
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (_data && Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-      }
-
-      this.setState({sync: false, data: _data})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
+    if (config.wrap.datatype === 'dynamic' && config.setting.onload === 'true') {
+      setTimeout(() => {
         this.loadData()
-      })
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+    _data = _data[0] || {$$empty: true}
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   mkPublicData = (publicId, data) => {
@@ -160,8 +167,7 @@
   }
 
   async loadData () {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+    const { config, BID } = this.state
 
     if (config.wrap.datatype === 'public') {
       MKEmitter.emit('reloadData', config.wrap.publicId)
@@ -182,10 +188,12 @@
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -194,25 +202,48 @@
     })
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      let _data = result.data && result.data[0] ? result.data[0] : {$$empty: true}
+      let _data = result.data || []
+      _data = _data[0] || {$$empty: true}
 
       this.setState({
         data: _data,
         loading: false
       })
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+      
+      if (!result.message) return
+      if (result.ErrCode === 'N') {
+        Modal.error({
+          title: result.message
+        })
+      } else if (result.ErrCode !== '-2') {
+        notification.error({
+          top: 92,
+          message: result.message,
+          duration: 10
+        })
+      }
     }
   }
 
diff --git a/src/tabviews/custom/components/form/simple-form/index.jsx b/src/tabviews/custom/components/form/simple-form/index.jsx
index 96156c2..60be28f 100644
--- a/src/tabviews/custom/components/form/simple-form/index.jsx
+++ b/src/tabviews/custom/components/form/simple-form/index.jsx
@@ -8,8 +8,6 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import MKEmitter from '@/utils/events.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import './index.scss'
 
 const MutilForm = asyncSpinComponent(() => import('@/tabviews/zshare/mutilform'))
@@ -18,17 +16,13 @@
 
 class SimpleForm extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     BID: '',
     config: null,
     loading: false,
-    sync: false,
     data: null,
     group: null,
     BData: '',
@@ -36,40 +30,39 @@
   }
 
   UNSAFE_componentWillMount () {
-    const { data } = this.props
-    let config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = null
-    let _sync = false
-
     let BID = ''
     let BData = ''
 
-    if (config.setting.supModule) {
-      BData = window.GLOB.CacheData.get(config.setting.supModule)
+    if (_config.setting.supModule) {
+      BData = window.GLOB.CacheData.get(_config.setting.supModule)
     } else {
-      BData = window.GLOB.CacheData.get(config.$pageId)
+      BData = window.GLOB.CacheData.get(_config.$pageId)
     }
     if (BData) {
       BID = BData.$BID || ''
     }
 
-    if (config.wrap.datatype !== 'static') {
-      _sync = config.setting.sync === 'true'
+    if (_config.wrap.datatype === 'dynamic') {
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[config.dataName] || {$$empty: true}
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
-        _data.$$uuid = _data[config.setting.primaryKey] || ''
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+        _data = _data[0] || {$$empty: true}
+        _data.$$uuid = _data[_config.setting.primaryKey] || ''
+
+        _config.setting.sync = 'false'
+  
+        window.GLOB.SyncData.delete(_config.dataName)
       }
     } else {
       _data = {$$empty: true}
     }
 
-    let _group = config.subcards[0]
+    let _group = _config.subcards[0]
 
     if (_group.subButton.enable === 'false' && (!_group.closeButton || _group.closeButton.enable !== 'true')) {
       _group.subButton.style.display = 'none'
@@ -77,27 +70,31 @@
     }
 
     this.setState({
-      sync: _sync,
       data: _data,
       group: _group,
       BID: BID || '',
       BData: BData || '',
-      config: config,
-      arr_field: config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (config.wrap.datatype !== 'static' && config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, config.setting.delay || 0)
-      }
+      config: _config
     })
   }
 
   componentDidMount () {
+    const { config } = this.state
+
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('mkFormSubmit', this.mkFormSubmit)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -110,33 +107,46 @@
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('mkFormSubmit', this.mkFormSubmit)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = {$$empty: true}
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-      }
-
-      _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-      this.setState({sync: false, data: _data})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
+  initExec = () => {
+    const { config } = this.state
+    
+    if (config.wrap.datatype === 'dynamic' && config.setting.onload === 'true') {
+      setTimeout(() => {
         this.loadData()
-      })
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+    _data = _data[0] || {$$empty: true}
+    _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId, id) => {
@@ -158,7 +168,7 @@
 
     if (group.uuid !== menuId) return
 
-    if (position === 'mainline' && config.setting.supModule && BID) {
+    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
       MKEmitter.emit('reloadData', config.setting.supModule, BID)
     } else {
       this.loadData()
@@ -212,8 +222,7 @@
   }
 
   async loadData () {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+    const { config, BID } = this.state
 
     if (config.wrap.datatype === 'static') {
       this.setState({
@@ -226,13 +235,16 @@
       }, () => {
         this.setState({data: {$$empty: true}})
       })
+      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -241,7 +253,7 @@
     })
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -255,16 +267,33 @@
       }, () => {
         this.setState({data: _data})
       })
+
+      MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false,
       })
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -291,7 +320,7 @@
   }
 
   render() {
-    const { config, loading, BID, BData, data, group, dict } = this.state
+    const { config, loading, BID, BData, data, group } = this.state
 
     if (config.wrap.empty === 'hidden' && (!data || data.$$empty)) return null
     if (config.idCtrl && (!data || data.$$empty)) return null
@@ -308,7 +337,6 @@
         {data ? <MutilForm
           BID={BID}
           BData={BData}
-          dict={dict}
           data={data}
           action={group}
           unload={config.setting.supModule && !BID}
diff --git a/src/tabviews/custom/components/form/simple-form/index.scss b/src/tabviews/custom/components/form/simple-form/index.scss
index 123523e..78ba331 100644
--- a/src/tabviews/custom/components/form/simple-form/index.scss
+++ b/src/tabviews/custom/components/form/simple-form/index.scss
@@ -17,6 +17,7 @@
     .submit {
       min-width: 70px;
       border: none;
+      border-style: solid;
     }
   }
   .mk-form-action.no-button {
diff --git a/src/tabviews/custom/components/form/step-form/index.jsx b/src/tabviews/custom/components/form/step-form/index.jsx
index 561a5b7..cd83384 100644
--- a/src/tabviews/custom/components/form/step-form/index.jsx
+++ b/src/tabviews/custom/components/form/step-form/index.jsx
@@ -8,8 +8,6 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import MKEmitter from '@/utils/events.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import './index.scss'
 
 const MutilForm = asyncSpinComponent(() => import('@/tabviews/zshare/mutilform'))
@@ -17,17 +15,13 @@
 
 class StepForm extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     BID: '',
     config: null,
     loading: false,
-    sync: false,
     data: null,
     group: null,
     BData: '',
@@ -35,53 +29,52 @@
   }
 
   UNSAFE_componentWillMount () {
-    const { data } = this.props
-    let config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = null
-    let _sync = false
-
     let BID = ''
     let BData = ''
 
-    if (config.setting.supModule) {
-      BData = window.GLOB.CacheData.get(config.setting.supModule)
+    if (_config.setting.supModule) {
+      BData = window.GLOB.CacheData.get(_config.setting.supModule)
     } else {
-      BData = window.GLOB.CacheData.get(config.$pageId)
+      BData = window.GLOB.CacheData.get(_config.$pageId)
     }
     if (BData) {
       BID = BData.$BID || ''
     }
 
-    if (config.wrap.datatype !== 'static') {
-      _sync = config.setting.sync === 'true'
+    if (_config.wrap.datatype === 'dynamic') {
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[config.dataName] || {$$empty: true}
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
-        _data.$$uuid = _data[config.setting.primaryKey] || ''
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+        _data = _data[0] || {$$empty: true}
+        _data.$$uuid = _data[_config.setting.primaryKey] || ''
+
+        _config.setting.sync = 'false'
+  
+        window.GLOB.SyncData.delete(_config.dataName)
       }
     } else {
       _data = {$$empty: true}
     }
 
-    if (!config.wrap.groupLabel) {
-      if (config.subcards.length > 1) {
-        config.wrap.groupLabel = 'show'
+    if (!_config.wrap.groupLabel) {
+      if (_config.subcards.length > 1) {
+        _config.wrap.groupLabel = 'show'
       } else {
-        config.wrap.groupLabel = 'hidden'
+        _config.wrap.groupLabel = 'hidden'
       }
     }
 
-    config.subcards = config.subcards.map((group, i) => {
+    _config.subcards = _config.subcards.map((group, i) => {
       group.sort = i + 1
       if (i === 0 && group.prevButton.actionType !== 'close') {
         group.prevButton.enable = 'false'
       }
-      if (i + 1 === config.subcards.length && group.nextButton.actionType !== 'close') {
+      if (i + 1 === _config.subcards.length && group.nextButton.actionType !== 'close') {
         group.nextButton.enable = 'false'
       }
 
@@ -96,48 +89,52 @@
       return group
     })
 
-    let _group = config.subcards[0]
+    let _group = _config.subcards[0]
 
-    if (_data && config.wrap.statusControl && _data[config.wrap.statusControl] !== undefined) {
-      let _status = _data[config.wrap.statusControl] + ''
+    if (_data && _config.wrap.statusControl && _data[_config.wrap.statusControl] !== undefined) {
+      let _status = _data[_config.wrap.statusControl] + ''
 
-      let _groups = config.subcards.filter(item => item.setting.status === _status)[0]
+      let _groups = _config.subcards.filter(item => item.setting.status === _status)[0]
       _group = _groups || _group
     }
 
-    config.titleStyle = {}
-    config.sortStyle = {}
+    _config.titleStyle = {}
+    _config.sortStyle = {}
 
-    if (config.style.fontSize) {
-      let size = parseInt(config.style.fontSize)
-      config.titleStyle = {fontSize: size}
+    if (_config.style.fontSize) {
+      let size = parseInt(_config.style.fontSize)
+      _config.titleStyle = {fontSize: size}
       let s = size * 1.5 + 'px'
-      config.sortStyle = {width: s, height: s, lineHeight: s, borderRadius: s}
+      _config.sortStyle = {width: s, height: s, lineHeight: s, borderRadius: s}
     }
 
     this.setState({
-      sync: _sync,
       data: _data,
       group: _group,
       step: _group.sort - 1,
       BID: BID || '',
       BData: BData || '',
-      config: config,
-      arr_field: config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (config.wrap.datatype !== 'static' && config.setting && config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, config.setting.delay || 0)
-      }
+      config: _config
     })
   }
 
   componentDidMount () {
+    const { config } = this.state
+
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('mkFormSubmit', this.mkFormSubmit)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -150,40 +147,54 @@
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('mkFormSubmit', this.mkFormSubmit)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, group } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = {$$empty: true}
-      let _group = group
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-      }
-
-      _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-      if (config.wrap.statusControl && _data[config.wrap.statusControl] !== undefined) {
-        let _status = _data[config.wrap.statusControl] + ''
-        let _groups = config.subcards.filter(item => item.setting.status === _status)[0]
-        _group = _groups || _group
-      }
-
-      this.setState({sync: false, data: _data, group: _group, step: _group.sort - 1,})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
+  initExec = () => {
+    const { config } = this.state
+    
+    if (config.wrap.datatype === 'dynamic' && config.setting.onload === 'true') {
+      setTimeout(() => {
         this.loadData()
-      })
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, group } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+    _data = _data[0] || {$$empty: true}
+    _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+    let _group = group
+
+    if (config.wrap.statusControl && _data[config.wrap.statusControl] !== undefined) {
+      let _status = _data[config.wrap.statusControl] + ''
+      let _groups = config.subcards.filter(item => item.setting.status === _status)[0]
+      _group = _groups || _group
+    }
+
+    this.setState({data: _data, group: _group, step: _group.sort - 1})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId, id) => {
@@ -205,7 +216,7 @@
 
     if (group.uuid !== menuId) return
 
-    if (position === 'mainline' && config.setting.supModule && BID) {
+    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
       MKEmitter.emit('reloadData', config.setting.supModule, BID)
     } else {
       this.loadData()
@@ -271,8 +282,7 @@
   }
 
   async loadData (type) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+    const { config, BID } = this.state
 
     if (config.wrap.datatype === 'static') {
       this.setState({
@@ -285,13 +295,16 @@
       }, () => {
         this.setState({data: {$$empty: true}})
       })
+      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -300,7 +313,7 @@
     })
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -333,16 +346,33 @@
       }, () => {
         this.setState({group: _group})
       })
+
+      MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false,
       })
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -393,7 +423,7 @@
   }
 
   render() {
-    const { config, loading, BID, BData, data, group, dict, step } = this.state
+    const { config, loading, BID, BData, data, group, step } = this.state
 
     if (config.wrap.empty === 'hidden' && (!data || data.$$empty)) return null
     if (config.idCtrl && (!data || data.$$empty)) return null
@@ -419,7 +449,6 @@
         {group && data ? <MutilForm
           BID={BID}
           BData={BData}
-          dict={dict}
           data={data}
           action={group}
           unload={config.setting.supModule && !BID}
diff --git a/src/tabviews/custom/components/form/step-form/index.scss b/src/tabviews/custom/components/form/step-form/index.scss
index 12ca54d..8a2908a 100644
--- a/src/tabviews/custom/components/form/step-form/index.scss
+++ b/src/tabviews/custom/components/form/step-form/index.scss
@@ -71,6 +71,7 @@
     .submit {
       min-width: 70px;
       border: none;
+      border-style: solid;
     }
     .skip {
       color: rgba(0, 0, 0, 0.85);
diff --git a/src/tabviews/custom/components/form/tab-form/index.jsx b/src/tabviews/custom/components/form/tab-form/index.jsx
index 0538eed..6286532 100644
--- a/src/tabviews/custom/components/form/tab-form/index.jsx
+++ b/src/tabviews/custom/components/form/tab-form/index.jsx
@@ -8,8 +8,6 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import MKEmitter from '@/utils/events.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import './index.scss'
 
 const MutilForm = asyncSpinComponent(() => import('@/tabviews/zshare/mutilform'))
@@ -17,65 +15,60 @@
 
 class TabForm extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     BID: '',                   // 涓婄骇ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: null,
     BData: '',
-    group: null,
+    group: null
   }
 
   UNSAFE_componentWillMount () {
-    const { data } = this.props
-    let config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = null
-    let _sync = false
-
     let BID = ''
     let BData = ''
 
-    if (config.setting.supModule) {
-      BData = window.GLOB.CacheData.get(config.setting.supModule)
+    if (_config.setting.supModule) {
+      BData = window.GLOB.CacheData.get(_config.setting.supModule)
     } else {
-      BData = window.GLOB.CacheData.get(config.$pageId)
+      BData = window.GLOB.CacheData.get(_config.$pageId)
     }
     if (BData) {
       BID = BData.$BID || ''
     }
 
-    if (config.wrap.datatype !== 'static') {
-      _sync = config.setting.sync === 'true'
+    if (_config.wrap.datatype === 'dynamic') {
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[config.dataName] || {$$empty: true}
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
-        _data.$$uuid = _data[config.setting.primaryKey] || ''
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+        _data = _data[0] || {$$empty: true}
+        _data.$$uuid = _data[_config.setting.primaryKey] || ''
+
+        _config.setting.sync = 'false'
+  
+        window.GLOB.SyncData.delete(_config.dataName)
       }
     } else {
       _data = {$$empty: true}
     }
 
-    if (!config.wrap.groupLabel) {
-      if (config.subcards.length > 1) {
-        config.wrap.groupLabel = 'show'
+    if (!_config.wrap.groupLabel) {
+      if (_config.subcards.length > 1) {
+        _config.wrap.groupLabel = 'show'
       } else {
-        config.wrap.groupLabel = 'hidden'
+        _config.wrap.groupLabel = 'hidden'
       }
     }
 
-    config.subcards = config.subcards.map(group => {
+    _config.subcards = _config.subcards.map(group => {
       if (group.subButton.enable === 'false') {
         group.subButton.style.display = 'none'
         group.$button = 'no-button'
@@ -84,34 +77,38 @@
       return group
     })
 
-    config.titleStyle = {}
+    _config.titleStyle = {}
 
-    if (config.style.fontSize) {
-      config.titleStyle = {fontSize: parseInt(config.style.fontSize)}
+    if (_config.style.fontSize) {
+      _config.titleStyle = {fontSize: parseInt(_config.style.fontSize)}
     }
 
     this.setState({
-      sync: _sync,
       data: _data,
-      group: config.subcards[0],
+      group: _config.subcards[0],
       BID: BID || '',
       BData: BData || '',
-      config: config,
-      arr_field: config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (config.wrap.datatype !== 'static' && config.setting && config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, config.setting.delay || 0)
-      }
+      config: _config
     })
   }
 
   componentDidMount () {
+    const { config } = this.state
+
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('mkFormSubmit', this.mkFormSubmit)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -124,36 +121,46 @@
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('mkFormSubmit', this.mkFormSubmit)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, group } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = {$$empty: true}
-      let _group = group
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-      }
-
-      _data.$$uuid = _data[config.setting.primaryKey] || ''
-
-      this.setState({sync: false, data: _data, group: null}, () => {
-        this.setState({group: _group})
-      })
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
+  initExec = () => {
+    const { config } = this.state
+    
+    if (config.wrap.datatype === 'dynamic' && config.setting.onload === 'true') {
+      setTimeout(() => {
         this.loadData()
-      })
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+    _data = _data[0] || {$$empty: true}
+    _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId, id) => {
@@ -175,7 +182,7 @@
 
     if (group.uuid !== menuId) return
 
-    if (position === 'mainline' && config.setting.supModule && BID) {
+    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
       MKEmitter.emit('reloadData', config.setting.supModule, BID)
     } else {
       this.loadData()
@@ -228,8 +235,7 @@
   }
 
   async loadData () {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+    const { config, BID } = this.state
 
     if (config.wrap.datatype === 'static') {
       this.setState({
@@ -242,13 +248,16 @@
       }, () => {
         this.setState({data: {$$empty: true}})
       })
+      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -257,7 +266,7 @@
     })
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -271,16 +280,33 @@
       }, () => {
         this.setState({data: _data})
       })
+
+      MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
+      
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false,
       })
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -309,7 +335,7 @@
   }
 
   render() {
-    const { config, loading, BID, BData, data, group, dict } = this.state
+    const { config, loading, BID, BData, data, group } = this.state
 
     if (config.wrap.empty === 'hidden' && (!data || data.$$empty)) return null
     if (config.idCtrl && (!data || data.$$empty)) return null
@@ -332,7 +358,6 @@
         {group && data ? <MutilForm
           BID={BID}
           BData={BData}
-          dict={dict}
           data={data}
           action={group}
           unload={config.setting.supModule && !BID}
diff --git a/src/tabviews/custom/components/form/tab-form/index.scss b/src/tabviews/custom/components/form/tab-form/index.scss
index a079e22..c26ee74 100644
--- a/src/tabviews/custom/components/form/tab-form/index.scss
+++ b/src/tabviews/custom/components/form/tab-form/index.scss
@@ -24,12 +24,12 @@
   .mk-normal-form-title.mkbtn {
     .form-title {
       background: #ffffff;
-      color: #1890ff;
-      border: 1px solid #1890ff;
+      color: var(--mk-sys-color);
+      border: 1px solid var(--mk-sys-color);
       transition: all 0.3s;
     }
     .form-title.active {
-      background: #1890ff;
+      background: var(--mk-sys-color);
       color: #ffffff;
     }
     .form-title:first-child {
@@ -60,6 +60,7 @@
     .submit {
       min-width: 70px;
       border: none;
+      border-style: solid;
     }
   }
   .mk-form-action.no-button {
diff --git a/src/tabviews/custom/components/group/normal-group/index.jsx b/src/tabviews/custom/components/group/normal-group/index.jsx
index 6cbc3cb..5a87122 100644
--- a/src/tabviews/custom/components/group/normal-group/index.jsx
+++ b/src/tabviews/custom/components/group/normal-group/index.jsx
@@ -1,315 +1,33 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Col, notification, Row } from 'antd'
 
-import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
-import {
-  getStructuredParams,
-  getStructDefaultParam
-} from '@/utils/utils-datamanage.js'
-import Utils from '@/utils/utils.js'
 import './index.scss'
 
-// 閫氱敤缁勪欢
-const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line'))
-const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie'))
-const AntvDashboard = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-dashboard'))
-const AntvScatter = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-scatter'))
-const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card'))
-const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card'))
-const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table'))
-const DoubleDataCard = asyncComponent(() => import('@/tabviews/custom/components/card/double-data-card'))
-const EditTable = asyncComponent(() => import('@/tabviews/custom/components/table/edit-table'))
-const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card'))
-const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor'))
-const SandBox = asyncComponent(() => import('@/tabviews/custom/components/code/sand-box'))
-const SimpleForm = asyncComponent(() => import('@/tabviews/custom/components/form/simple-form'))
-const NormalForm = asyncComponent(() => import('@/tabviews/custom/components/form/step-form'))
-const TabForm = asyncComponent(() => import('@/tabviews/custom/components/form/tab-form'))
-const NormalTree = asyncComponent(() => import('@/tabviews/custom/components/tree/antd-tree'))
-const CarouselDataCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/data-card'))
-const CarouselPropCard = asyncComponent(() => import('@/tabviews/custom/components/carousel/prop-card'))
-const Balcony = asyncComponent(() => import('@/tabviews/custom/components/card/balcony'))
-const TimeLine = asyncComponent(() => import('@/tabviews/custom/components/timeline/normal-timeline'))
-const CustomChart = asyncComponent(() => import('@/tabviews/custom/components/chart/custom-chart'))
-const AntvG6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-G6'))
+const TabTransfer = asyncComponent(() => import('@/tabviews/custom/components/share/tabtransfer'))
 
-class TabTransfer extends Component {
+class NormalGroup extends Component {
   static propTpyes = {
     config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 鍏ㄥ眬鎼滅储鏉′欢
   }
 
-  state = {
-    mainSearch: [],
-    // printing: false,
-    data: null
-  }
-
-  UNSAFE_componentWillMount () {
-    const { config, mainSearch } = this.props
-
-    // 鑾峰彇涓绘悳绱㈡潯浠�
-    let _mainSearch = mainSearch ? fromJS(mainSearch).toJS() : []
-    let params = []
-    config.components.forEach(item => {
-      if (item.type === 'tabs') return
-
-      if (!item.setting || item.setting.interType !== 'system') return
-      if (!item.format) return
-
-      if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') {
-        let searchlist = []
-        if (item.search && item.search.length > 0) {
-          searchlist = Utils.initMainSearch(item.search)
-        }
-        if (item.setting.useMSearch) {
-          let keys = searchlist.map(item => item.key)
-          _mainSearch.forEach(item => {
-            if (!keys.includes(item.key)) {
-              searchlist.push(item)
-            }
-          })
-        }
-
-        if (searchlist.filter(cell => cell.required && cell.value === '').length > 0) {
-          item.setting.sync = 'false'
-          item.setting.onload = 'false'
-        } else {
-          params.push(getStructDefaultParam(item, searchlist, params.length === 0))
-        }
-      } else {
-        item.setting.sync = 'false'
-      }
-    })
-
-    this.setState({mainSearch: _mainSearch})
-
-    if (params.length > 0) {
-      this.loadmaindata(params)
-    }
-  }
-
-  UNSAFE_componentWillReceiveProps(nextProps) {
-    if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({mainSearch: null}, () => {
-        this.setState({mainSearch: fromJS(nextProps.mainSearch).toJS()})
-      })
-    }
-  }
-
-  /**
-   * @description 涓昏〃鏁版嵁鍔犺浇
-   */ 
-  loadmaindata = (params) => {
-    const { config } = this.props
-    let BID = ''
-    let BData = window.GLOB.CacheData.get(config.$pageId)
-
-    if (BData) {
-      BID = BData.$BID || ''
-    }
-
-    let param = getStructuredParams(params, config, BID)
-
-    Api.genericInterface(param).then(result => {
-      if (result.status) {
-        delete result.status
-        delete result.message
-        delete result.ErrMesg
-        delete result.ErrCode
-
-        if (config.$cache) {
-          params.forEach((item) => {
-            let _data = result[item.name] || ''
-            if (_data && !Array.isArray(_data)) {
-              _data = [_data]
-            }
-            Api.writeCacheConfig(item.uuid, _data)
-          })
-        }
-
-        this.setState({
-          data: result
-        })
-      } else {
-        this.setState({
-          data: ''
-        })
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
-    })
-  }
-
-  getComponents = () => {
-    const { config } = this.props
-    const { mainSearch, data } = this.state
-
-    return config.components.map(item => {
-      let style = null
-
-      if (item.style && item.style.clear === 'left') {
-        style = {clear: 'left'}
-      }
-
-      if (item.type === 'card' && item.subtype === 'datacard') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <DataCard config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'card' && item.subtype === 'propcard') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <PropCard config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'table' && item.subtype === 'normaltable') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTable config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'card' && item.subtype === 'dualdatacard') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <DoubleDataCard config={item} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'bar' || item.type === 'line') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <AntvBarAndLine data={data} config={item} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'pie') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <AntvPie data={data} config={item} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'dashboard') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <AntvDashboard config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'form' && item.subtype === 'simpleform') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <SimpleForm config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'form' && item.subtype === 'stepform') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <NormalForm config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'form' && item.subtype === 'tabform') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <TabForm config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'scatter') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <AntvScatter config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'carousel' && item.subtype === 'datacard') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselDataCard config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'carousel' && item.subtype === 'propcard') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselPropCard config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'card' && item.subtype === 'tablecard') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <TableCard config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'table' && item.subtype === 'editable') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <EditTable config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'tree') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'editor') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <BraftEditor config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'code') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <SandBox config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'balcony') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <Balcony config={item} data={data}/>
-          </Col>
-        )
-      } else if (item.type === 'timeline') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <TimeLine config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'chart') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <CustomChart config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else if (item.type === 'antvG6') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <AntvG6 config={item} data={data} mainSearch={mainSearch}/>
-          </Col>
-        )
-      } else {
-        return null
-      }
-    })
-  }
+  state = {}
 
   render() {
     const { config } = this.props
 
-    if (!config.components || config.components.length === 0) return (<div style={config.style}></div>)
+    if (config.components.length === 0) return (<div style={config.style}></div>)
     
     return (
       <div className={'normal-group-wrap ' + (config.setting.layout || '')} id={'anchor' + config.uuid} style={config.style}>
         {config.setting && config.setting.title ? <div className="group-header" style={config.headerStyle}>
           <span className="title">{config.setting.title}</span>
         </div> : null}
-        <Row className="component-wrap">{this.getComponents()}</Row>
+        <TabTransfer config={config}/>
+        {/* <Row className="component-wrap">{this.getComponents()}</Row> */}
       </div>
     )
   }
 }
 
-export default TabTransfer
\ No newline at end of file
+export default NormalGroup
\ No newline at end of file
diff --git a/src/tabviews/custom/components/group/normal-group/index.scss b/src/tabviews/custom/components/group/normal-group/index.scss
index a179389..cafae68 100644
--- a/src/tabviews/custom/components/group/normal-group/index.scss
+++ b/src/tabviews/custom/components/group/normal-group/index.scss
@@ -7,6 +7,9 @@
     border: 0;
     background: transparent;
   }
+  .print-button:hover, .print-button:focus, .print-button:active {
+    color: var(--mk-sys-color5);
+  }
 
   .group-header {
     position: relative;
diff --git a/src/tabviews/custom/components/iframe/index.jsx b/src/tabviews/custom/components/iframe/index.jsx
index 62981a9..3737715 100644
--- a/src/tabviews/custom/components/iframe/index.jsx
+++ b/src/tabviews/custom/components/iframe/index.jsx
@@ -12,9 +12,7 @@
 
 class NormalIframe extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -22,18 +20,15 @@
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
     activeKey: '',             // 閫変腑鏁版嵁
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: {},                  // 鏁版嵁
     linkUrl: ''
   }
 
   UNSAFE_componentWillMount () {
-    const { data } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = { $$empty: true }
-    let _sync = false
-
     let BID = ''
     let BData = ''
     let linkUrl = ''
@@ -48,36 +43,33 @@
     }
     
     if (_config.wrap.datatype === 'dynamic') {
-      _sync = _config.setting.sync === 'true'
+      _config.setting.onload = _config.setting.sync === 'true' ? 'false' : 'true'
 
-      if (_sync && data) {
-        _data = data[_config.dataName] || {$$empty: true}
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-        _sync = false
+      if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+        _data = _data[0] || {$$empty: true}
+        
+        linkUrl = _data[_config.wrap.linkField] || ''
+
+        _config.setting.sync = 'false'
+  
+        window.GLOB.SyncData.delete(_config.dataName)
       }
-
-      linkUrl = _data[_config.wrap.linkField] || ''
     } else {
       if (_config.wrap.linkType !== 'input') {
         linkUrl = _config.wrap.linkUrl || ''
       }
     }
 
+    if (_config.wrap.height === '100vh') {
+      _config.wrap.height = 'calc(100vh - 92px)'
+    }
+
     this.setState({
       linkUrl: linkUrl,
-      sync: _sync,
       data: _data,
       BID: BID || '',
-      config: _config,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.wrap.datatype === 'dynamic' && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
+      config: _config
     })
   }
 
@@ -87,12 +79,22 @@
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
 
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.wrap.linkType === 'input' && config.wrap.focus !== 'false') {
       setTimeout(() => {
         let node = document.getElementById(config.uuid)
         node && node.select && node.select()
       }, 200)
     }
+
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -108,32 +110,46 @@
     }
 
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
   }
 
-  /**
-   * @description 鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = { $$empty: true }
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName]
-        if (Array.isArray(_data)) {
-          _data = _data[0] || {$$empty: true}
-        }
-      }
-
-      let linkUrl = _data[config.wrap.linkField] || ''
-
-      this.setState({sync: false, data: _data, linkUrl})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
+  initExec = () => {
+    const { config } = this.state
+    
+    if (config.wrap.datatype === 'dynamic' && config.setting.onload === 'true') {
+      setTimeout(() => {
         this.loadData()
-      })
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+    _data = _data[0] || {$$empty: true}
+    
+    let linkUrl = _data[config.wrap.linkField] || ''
+
+    this.setState({data: _data, linkUrl})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   resetParentParam = (MenuID, id, data) => {
@@ -157,8 +173,7 @@
   }
 
   async loadData () {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+    const { config, BID } = this.state
     
     if (config.wrap.datatype === 'static') {
       this.setState({
@@ -172,15 +187,17 @@
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -194,12 +211,27 @@
         linkUrl: _data[config.wrap.linkField] || '',
         data: _data
       })
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -257,7 +289,7 @@
         </div> : null}
         <div className="iframe-wrap" style={{height: config.wrap.height}}>
           {loading ? <div className="mask"><Spin size="large" /></div> : null}
-          {linkUrl ? <iframe title="mk" className="iframe" src={linkUrl} frameBorder="0"></iframe> : <Empty description={false}/>}
+          {linkUrl ? <iframe title="mk" className="iframe" src={linkUrl.replace(/@loginuid@/ig, sessionStorage.getItem('LoginUID'))} frameBorder="0"></iframe> : <Empty description={false}/>}
         </div>
       </div>
     )
diff --git a/src/tabviews/custom/components/interfaces/interItem/index.jsx b/src/tabviews/custom/components/interfaces/interItem/index.jsx
index 3ba9519..fe1514e 100644
--- a/src/tabviews/custom/components/interfaces/interItem/index.jsx
+++ b/src/tabviews/custom/components/interfaces/interItem/index.jsx
@@ -110,7 +110,7 @@
 
     this.loading = true
 
-    let param = UtilsDM.getQueryDataParams(config.setting, config.columns.map(col => col.field).join(','), [], config.setting.order, 1, 1, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, [], config.setting.order, 1, 1, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -122,8 +122,6 @@
         _data.$$uuid = _data[config.setting.primaryKey] || ''
       }
       
-      _data.$$loaded = true
-
       window.GLOB.CacheData.set(config.uuid, _data)
 
       MKEmitter.emit('mkPublicData', config.uuid, _data)
@@ -132,15 +130,30 @@
       if (config.setting.loadlevel === 'init') {
         MKEmitter.emit('interFinish', config.MenuID, config.uuid)
       }
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.loading = false
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/module/voucher/index.jsx b/src/tabviews/custom/components/module/voucher/index.jsx
index f11d8c0..361e710 100644
--- a/src/tabviews/custom/components/module/voucher/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/index.jsx
@@ -362,7 +362,7 @@
           attachments: res.attachments_int,
           title: res.voucher_text || '',
           remark: res.remark || '',
-          status: 'saved'
+          status: res.copy_type === 'true' ? 'copy' : 'saved'
         })
       } else {
         this.setState({
@@ -609,7 +609,7 @@
           sup_data.push(`'${n.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${n.voucher_sup_lp || ''}','${item.subject_code}','${item.subject_name}','${n.sup_voucher_text || ''}','${direct}',${item.debit || item.credit},'${n.customercode || ''}','${n.customername || ''}','${n.suppliercode || ''}','${n.suppliername || ''}','${n.co_pro_code || ''}','${n.co_pro_name || ''}','${n.workercode || ''}','${n.workername || ''}','${n.project_code || ''}','${n.project_name || ''}','${n.productcode || ''}','${n.productname || ''}','${n.cash_flow_code || ''}','${n.cash_flow_name || ''}','${n.sup_acc_code || ''}','${n.sup_acc_name || ''}','${n.sup_acc_type || ''}','${item.uuid}',0,'${n.lessor_code || ''}','${n.lessor_name || ''}','${n.logistics_code || ''}','${n.logistics_name || ''}'`)
         })
       }
-      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`
+      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : ''}','${curr ? item.exratename : ''}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`
     })
 
     if (type === 'createVoucher') {
@@ -625,7 +625,7 @@
       let curr = item.foreign_currency_type === 'Y'
       let direct = item.debit ? 'debit' : 'credit'
 
-      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`)
+      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit},'${direct}','${curr ? item.exratecode : ''}','${curr ? item.exratename : ''}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.debit ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`)
     })
 
     supMap.forEach(n => {
@@ -688,6 +688,15 @@
           oriAttachs: fromJS(attachlist).toJS(),
           saved: true
         })
+      }
+
+      let tabId = ''
+      if (config.wrap.linkmenu && config.wrap.linkmenu.length > 0) {
+        tabId = config.wrap.linkmenu[config.wrap.linkmenu.length - 1]
+      }
+
+      if (tabId) {
+        MKEmitter.emit('reloadMenuView', tabId, 'table')
       }
     })
   }
@@ -781,7 +790,7 @@
   }
 
   voucherTempSave = (list, name, typeChar, typeName) => {
-    const { type, BID, data, book, title, orgcode, orgname, tempTypeClass, tempTypeName } = this.state
+    const { type, config, BID, data, book, title, orgcode, orgname, tempTypeClass, tempTypeName } = this.state
 
     if (!book) {
       notification.warning({
@@ -893,7 +902,7 @@
           sup_data.push(`'${n.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${n.voucher_sup_lp || ''}','${item.subject_code}','${item.subject_name}','${n.sup_voucher_text || ''}','${direct}',${item.debit || item.credit || 0},'${n.customercode || ''}','${n.customername || ''}','${n.suppliercode || ''}','${n.suppliername || ''}','${n.co_pro_code || ''}','${n.co_pro_name || ''}','${n.workercode || ''}','${n.workername || ''}','${n.project_code || ''}','${n.project_name || ''}','${n.productcode || ''}','${n.productname || ''}','${n.cash_flow_code || ''}','${n.cash_flow_name || ''}','${n.sup_acc_code || ''}','${n.sup_acc_name || ''}','${n.sup_acc_type || ''}','${item.uuid}',0,'${n.lessor_code || ''}','${n.lessor_name || ''}','${n.logistics_code || ''}','${n.logistics_name || ''}'`)
         })
       }
-      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`
+      return `'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : ''}','${curr ? item.exratename : ''}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},0,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`
     })
 
     voucherMap.forEach(item => {
@@ -901,7 +910,7 @@
       let curr = item.foreign_currency_type === 'Y'
       let direct = !item.credit ? 'debit' : 'credit'
 
-      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : '01010001'}','${curr ? item.exratename : 'CNY'}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`)
+      subject_data.push(`'${item.uuid}','${item.subject_voucher_code || ''}','${item.voucher_lp || ''}','${item.subject_code}','${item.subject_name}','${item.subject_voucher_text || ''}',${count ? item.fcc_count || 0 : 0},${count ? item.net_unitprice || 0 : 0},'${item.unit}',${item.debit || item.credit || 0},'${direct}','${curr ? item.exratecode : ''}','${curr ? item.exratename : ''}',${curr ? item.unitratio || 0 : 0},'${item.sup_accounting}',${item.direct ? 1 : -1},${curr ? item.foreign_amount || 0 : 0},1,'${item.local_currency || ''}','${count ? 'Y' : ''}','${curr ? 'Y' : ''}','${item.closing_foreign_exchange || ''}'`)
     })
 
     supMap.forEach(n => {
@@ -932,6 +941,15 @@
           status: 'saved',
           data: fromJS(list).toJS(),
         })
+      }
+
+      let tabId = ''
+      if (config.wrap.linkmenu && config.wrap.linkmenu.length > 0) {
+        tabId = config.wrap.linkmenu[config.wrap.linkmenu.length - 1]
+      }
+
+      if (tabId) {
+        MKEmitter.emit('reloadMenuView', tabId, 'table')
       }
     })
   }
@@ -1048,27 +1066,16 @@
   triggerclose = () => {
     const { config, status } = this.state
 
-    let tabId = ''
-    if (config.wrap.linkmenu && config.wrap.linkmenu.length > 0) {
-      tabId = config.wrap.linkmenu[config.wrap.linkmenu.length - 1]
-    }
-
     if (status === 'change') {
       confirm({
         content: '鍐呭宸插彉鏇达紝纭畾瑕佸叧闂悧锛�',
         onOk() {
           MKEmitter.emit('closeTabView', config.$pageId)
-          if (tabId) {
-            MKEmitter.emit('reloadMenuView', tabId, 'table')
-          }
         },
         onCancel() {}
       })
     } else {
       MKEmitter.emit('closeTabView', config.$pageId)
-      if (tabId) {
-        MKEmitter.emit('reloadMenuView', tabId, 'table')
-      }
     }
   }
 
diff --git a/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/index.jsx b/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/index.jsx
index a47a6e2..2f1954d 100644
--- a/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/index.jsx
@@ -60,7 +60,7 @@
         <Col span={12}>
           <Form.Item label="鏂囦欢澶�">
             {getFieldDecorator('data_code', {
-              initialValue: '',
+              initialValue: files[0] ? files[0].data_code : '',
               rules: [
                 {
                   required: true,
diff --git a/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx b/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx
index fcbcb81..cbf864d 100644
--- a/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx
@@ -255,8 +255,8 @@
               return <div className="attach-item" key={item.id}>
                 <img src={item.icon} alt=""/>
                 <div className="attach-msg">
-                  <div>{item.attachments_title}</div>
-                  <div>{item.data_name ? item.data_name + ' / ' : ''}{item.attachments_url}</div>
+                  {/* <div>{item.attachments_title}</div> */}
+                  <div>{item.data_name ? item.data_name + ' / ' : ''}{item.attachments_title}</div>
                 </div>
                 <div>
                   <DeleteOutlined onClick={() => this.deleteFile(item.id)}/>
diff --git a/src/tabviews/custom/components/module/voucher/resetAttach/index.scss b/src/tabviews/custom/components/module/voucher/resetAttach/index.scss
index 94b8bcf..de3273a 100644
--- a/src/tabviews/custom/components/module/voucher/resetAttach/index.scss
+++ b/src/tabviews/custom/components/module/voucher/resetAttach/index.scss
@@ -34,6 +34,7 @@
           flex: 1;
           width: calc(100% - 95px);
           padding: 5px 0px;
+          line-height: 45px;
           div {
             color: #000000;
             overflow: hidden;
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index 83b7612..90c6088 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -330,32 +330,47 @@
       )
     } else if (col.type === 'formula') {
       let content = col.formula
-      Object.keys(record).forEach(key => {
-        let reg = new RegExp('@' + key + '@', 'ig')
-        content = content.replace(reg, record[key])
-      })
 
-      if (col.eval !== 'false') {
+      if (col.eval === 'func') {
         try {
           // eslint-disable-next-line
-          content = eval(content)
+          let func = new Function('data', col.formula)
+          content = func([record])
         } catch (e) {
-          if (window.debugger) {
-            console.info(content)
+          if (window.GLOB.debugger === true) {
             console.warn(e)
           }
           content = ''
         }
-
-        if (col.round && typeof(content) === 'number') {
-          content = Math.round(content * col.round) / col.round
-          content = content.toFixed(col.decimal)
+      } else {
+        Object.keys(record).forEach(key => {
+          let reg = new RegExp('@' + key + '@', 'ig')
+          content = content.replace(reg, record[key])
+        })
+        if (col.eval !== 'false') {
+          try {
+            // eslint-disable-next-line
+            content = eval(content)
+          } catch (e) {
+            if (window.GLOB.debugger === true) {
+              console.info(content)
+              console.warn(e)
+            }
+            content = ''
+          }
+  
+          if (col.round && typeof(content) === 'number') {
+            content = Math.round(content * col.round) / col.round
+            content = content.toFixed(col.decimal)
+          }
         }
       }
 
       content = content === undefined ? '' : content
 
-      if (content !== '') {
+      if (col.eval === 'func') {
+        content = <span dangerouslySetInnerHTML={{__html: content}}></span>
+      } else if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
         content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
@@ -430,7 +445,7 @@
     let rowspans = []
     let orderfields = {}
 
-    if (window.GLOB.dataFormat && !window.GLOB.mkHS) {
+    if (window.GLOB.dataFormat) {
       _format = true
 
       if (window.GLOB.memberLevel >= 30) {
@@ -735,9 +750,6 @@
     }
   }
 
-  /**
-   * 
-   */
   onSelectChange = (selectedRowKeys, e) => {
     const { setting, MenuID, data } = this.props
 
@@ -797,7 +809,7 @@
     }
 
     let selects = this.props.data.filter((item, _index) => newkeys.includes(_index) && !item.$disabled)
-    
+
     this.props.chgSelectData(selects)
 
     if (setting.$hasSyncModule) {
@@ -839,20 +851,52 @@
     MKEmitter.emit('resetSelectLine', MenuID, _id, _data)
   }
 
-  resetTable = (id, repage, pageIndex) => {
-    const { MenuID } = this.props
+  resetTable = (id, type, Index) => {
+    const { MenuID, setting, data } = this.props
 
     if (id !== MenuID) return
 
-    if (repage === 'false') {
+    if (type === 'delete') {
+      let selectKeys = fromJS(this.state.selectedRowKeys).toJS()
+      let activeKey = this.state.activeIndex
+
+      let trans = activeKey === Index
+      let _item = null
+      let selects = []
+      
+      if (setting.tableType) {
+        selectKeys = selectKeys.filter(key => key !== Index)
+        selectKeys = selectKeys.map(key => key > Index ? key - 1 : key)
+
+        selects = selectKeys.map(key => data[key]).filter(Boolean)
+
+        activeKey = selectKeys.length ? selectKeys[selectKeys.length - 1] : null
+
+        if (trans && selects.length) {
+          _item = selects[selects.length - 1]
+        }
+      }
+
+      this.setState({ selectedRowKeys: selectKeys, activeIndex: activeKey })
+
+      this.props.chgSelectData(selects)
+
+      if (trans) {
+        MKEmitter.emit('resetSelectLine', MenuID, (_item ? _item.$$uuid : ''), _item)
+      }
+
+      if (setting.$hasSyncModule) {
+        MKEmitter.emit('syncBalconyData', MenuID, selects, data.length === selects.length)
+      }
+    } else if (type === 'false') {
       this.setState({
         selectedRowKeys: [],
         activeIndex: null,
         pickup: false
       })
-    } else if (repage === 'repage') {
+    } else if (type === 'repage') {
       this.setState({
-        pageIndex: pageIndex,
+        pageIndex: Index,
         selectedRowKeys: [],
         activeIndex: null,
         pickup: false
diff --git a/src/tabviews/custom/components/share/tabtransfer/index.jsx b/src/tabviews/custom/components/share/tabtransfer/index.jsx
index 79c6827..a4f5005 100644
--- a/src/tabviews/custom/components/share/tabtransfer/index.jsx
+++ b/src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Row, Col, Empty, notification } from 'antd'
+import { fromJS } from 'immutable'
+import { Row, Col, Empty, notification, Modal } from 'antd'
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
@@ -9,7 +9,7 @@
   getStructuredParams,
   getStructDefaultParam
 } from '@/utils/utils-datamanage.js'
-import Utils from '@/utils/utils.js'
+import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
 // 閫氱敤缁勪欢
@@ -39,93 +39,85 @@
 const CustomChart = asyncComponent(() => import('@/tabviews/custom/components/chart/custom-chart'))
 const MkBaseTable = asyncComponent(() => import('@/tabviews/custom/components/table/base-table'))
 const AntvG6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-G6'))
+const AntvX6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-X6'))
+const Calendar = asyncComponent(() => import('@/tabviews/custom/components/calendar'))
 
 class TabTransfer extends Component {
   static propTpyes = {
     config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 鍏ㄥ眬鎼滅储鏉′欢
-  }
-
-  state = {
-    mainSearch: [],
-    self: false,
-    data: null
   }
 
   UNSAFE_componentWillMount () {
-    const { config, mainSearch } = this.props
-
-    // 鑾峰彇涓绘悳绱㈡潯浠�
-    let _mainSearch = []
-    let self = false
-    config.components.forEach(component => {
-      if (component.type === 'search') {
-        self = true
-        _mainSearch = Utils.initMainSearch(component.search)
-      }
-    })
-
-    if (!self) {
-      _mainSearch = fromJS(mainSearch).toJS()
-    }
+    let _config = fromJS(this.props.config).toJS()
 
     let params = []
-    let delay = 20
-    config.components.forEach(item => {
-      if (item.type === 'tabs' || item.type === 'group') return
+    if (_config.type !== 'group') {
+      _config.components = this.formatSetting(_config.components, params)
+    } else {
+      let delay = 110
+      _config.components.forEach(item => {
+        if (!item.setting || item.setting.interType !== 'system') return
+        if (!item.format) return
+        
+        item.setting.delay = delay
+        delay += 20
+      })
+    }
 
-      if (!item.setting || item.setting.interType !== 'system') return
-      if (!item.format) return
+    this.setState({
+      config: _config
+    }, () => {
+      if (params.length > 0) {
+        this.loadmaindata(params)
+      }
+    })
+  }
 
-      if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') {
-        let searchlist = []
-        if (item.search && item.search.length > 0) {
-          searchlist = Utils.initMainSearch(item.search)
-        }
+  formatSetting = (components, params) => {
+    let delay = 110
+    return components.map(item => {
+      if (item.type === 'tabs') return item
+      if (item.type === 'group') {
+        item.components = this.formatSetting(item.components, params)
+        return item
+      }
+
+      if (!item.setting || item.setting.interType !== 'system') return item
+      if (!item.format) return item
+
+      if (item.setting.sync === 'true') {
+        let searchlist = item.$searches || []
+  
         if (item.setting.useMSearch) {
-          let keys = searchlist.map(item => item.key)
-          _mainSearch.forEach(item => {
-            if (!keys.includes(item.key)) {
-              searchlist.push(item)
-            }
+          let mainSearch = window.GLOB.SearchBox.get(item.$searchId)
+          let keys = item.$s_keys || []
+          mainSearch.forEach(item => {
+            if (keys.includes(item.key.toLowerCase())) return
+
+            searchlist.push(item)
           })
         }
 
-        if (searchlist.filter(cell => cell.required && cell.value === '').length > 0) {
+        if (item.$s_req && searchlist.filter(item => item.required && item.value === '').length > 0) {
           item.setting.sync = 'false'
           item.setting.onload = 'false'
         } else {
           params.push(getStructDefaultParam(item, searchlist, params.length === 0))
         }
-      } else {
-        item.setting.sync = 'false'
-        item.setting.delay = delay
-        delay += 20
       }
+      
+      item.setting.delay = delay
+      delay += 20
+
+      return item
     })
-
-    this.setState({mainSearch: _mainSearch, self})
-
-    if (params.length > 0) {
-      this.loadmaindata(params)
-    }
-  }
-
-  UNSAFE_componentWillReceiveProps(nextProps) {
-    const { self } = this.state
-    
-    if (!self && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({mainSearch: null}, () => {
-        this.setState({mainSearch: fromJS(nextProps.mainSearch).toJS()})
-      })
-    }
   }
 
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
    */ 
   loadmaindata = (params) => {
-    const { config } = this.props
+    const { config } = this.state
     let BID = ''
     let BData = window.GLOB.CacheData.get(config.$pageId)
 
@@ -135,101 +127,118 @@
 
     let param = getStructuredParams(params, config, BID)
 
+    if (config.$cache && config.$time) {
+      Api.getLCacheConfig(params[0].uuid, config.$time, BID).then(res => {
+        if (!res.valid) {
+          this.getMainData(param, params, config.uuid)
+        }
+      })
+    } else {
+      this.getMainData(param, params, config.uuid)
+    }
+  }
+
+  getMainData = (param, params, tabId) => {
     Api.genericInterface(param).then(result => {
       if (result.status) {
-        delete result.status
-        delete result.message
-        delete result.ErrMesg
-        delete result.ErrCode
-
-        if (config.$cache) {
-          params.forEach((item) => {
-            let _data = result[item.name] || ''
-            if (_data && !Array.isArray(_data)) {
-              _data = [_data]
-            }
-            Api.writeCacheConfig(item.uuid, _data)
-          })
+        if (result.message) {
+          if (result.ErrCode === 'Y') {
+            Modal.success({
+              title: result.message
+            })
+          } else if (result.ErrCode === 'S') {
+            notification.success({
+              top: 92,
+              message: result.message,
+              duration: 2
+            })
+          }
         }
 
-        this.setState({
-          data: result
+        params.forEach((item) => {
+          let _data = result[item.name] || ''
+          if (_data && !Array.isArray(_data)) {
+            _data = [_data]
+          }
+          window.GLOB.SyncData.set(item.name, _data)
         })
+
+        MKEmitter.emit('transferSyncData', tabId)
       } else {
-        this.setState({
-          data: ''
-        })
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
+        MKEmitter.emit('transferSyncData', tabId)
+
+        if (!result.message) return
+        if (result.ErrCode === 'N') {
+          Modal.error({
+            title: result.message,
+          })
+        } else if (result.ErrCode !== '-2') {
+          notification.error({
+            top: 92,
+            message: result.message,
+            duration: 10
+          })
+        }
       }
     })
   }
 
-  resetSearch = (search) => {
-    this.setState({mainSearch: null}, () => {
-      this.setState({mainSearch: search})
-    })
-  }
-
   getComponents = (components) => {
-    const { mainSearch, data } = this.state
-
     return components.map(item => {
       let style = null
 
       if (item.style && item.style.clear === 'left') {
         style = {clear: 'left'}
+      } else if (item.style && item.style.clear === 'right') {
+        style = {float: 'right'}
       }
 
       if (item.type === 'card' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DataCard config={item} data={data} mainSearch={mainSearch}/>
+            <DataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'propcard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <PropCard config={item} data={data} mainSearch={mainSearch}/>
+            <PropCard config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'normaltable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTable config={item} data={data} mainSearch={mainSearch}/>
+            <NormalTable config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'dualdatacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DoubleDataCard config={item} mainSearch={mainSearch}/>
+            <DoubleDataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'bar' || item.type === 'line') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvBarAndLine data={data} config={item} mainSearch={mainSearch}/>
+            <AntvBarAndLine config={item}/>
           </Col>
         )
       } else if (item.type === 'pie') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvPie data={data} config={item} mainSearch={mainSearch}/>
+            <AntvPie config={item}/>
           </Col>
         )
       } else if (item.type === 'dashboard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvDashboard config={item} data={data} mainSearch={mainSearch}/>
+            <AntvDashboard config={item}/>
           </Col>
         )
       } else if (item.type === 'scatter') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvScatter config={item} data={data} mainSearch={mainSearch}/>
+            <AntvScatter config={item}/>
           </Col>
         )
       } else if (item.type === 'search') {
@@ -240,109 +249,121 @@
         }
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <MainSearch config={item} BID={BID} refreshdata={this.resetSearch} />
+            <MainSearch config={item} BID={BID}/>
           </Col>
         )
       } else if (item.type === 'tabs') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvTabs config={item} mainSearch={mainSearch}/>
+            <AntvTabs config={item}/>
           </Col>
         )
       } else if (item.type === 'carousel' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselDataCard config={item} data={data} mainSearch={mainSearch}/>
+            <CarouselDataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'carousel' && item.subtype === 'propcard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselPropCard config={item} data={data} mainSearch={mainSearch}/>
+            <CarouselPropCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'tablecard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TableCard config={item} data={data} mainSearch={mainSearch}/>
+            <TableCard config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'basetable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <MkBaseTable config={item} data={data} mainSearch={mainSearch}/>
+            <MkBaseTable config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'editable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <EditTable config={item} mainSearch={mainSearch}/>
+            <EditTable config={item}/>
           </Col>
         )
       } else if (item.type === 'group' && item.subtype === 'normalgroup') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalGroup config={item} mainSearch={mainSearch}/>
+            <NormalGroup config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'simpleform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <SimpleForm config={item} data={data} mainSearch={mainSearch}/>
+            <SimpleForm config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'stepform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <StepForm config={item} data={data} mainSearch={mainSearch}/>
+            <StepForm config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'tabform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TabForm config={item} data={data} mainSearch={mainSearch}/>
+            <TabForm config={item}/>
           </Col>
         )
       } else if (item.type === 'tree') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
+            <NormalTree config={item}/>
+          </Col>
+        )
+      } else if (item.type === 'calendar') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <Calendar config={item}/>
           </Col>
         )
       } else if (item.type === 'editor') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <BraftEditor config={item} data={data} mainSearch={mainSearch}/>
+            <BraftEditor config={item}/>
           </Col>
         )
       } else if (item.type === 'code') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <SandBox config={item} data={data} mainSearch={mainSearch}/>
+            <SandBox config={item}/>
           </Col>
         )
       } else if (item.type === 'balcony') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <Balcony config={item} data={data}/>
+            <Balcony config={item}/>
           </Col>
         )
       } else if (item.type === 'timeline') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TimeLine config={item} data={data} mainSearch={mainSearch}/>
+            <TimeLine config={item}/>
           </Col>
         )
       } else if (item.type === 'chart') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CustomChart config={item} data={data} mainSearch={mainSearch}/>
+            <CustomChart config={item}/>
           </Col>
         )
       } else if (item.type === 'antvG6') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvG6 config={item} data={data} mainSearch={mainSearch}/>
+            <AntvG6 config={item}/>
+          </Col>
+        )
+      } else if (item.type === 'antvX6') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <AntvX6 config={item}/>
           </Col>
         )
       } else {
@@ -352,10 +373,16 @@
   }
 
   render() {
-    const { config } = this.props
+    const { config } = this.state
 
     if (!config || !config.components || config.components.length === 0) return (<Empty description={false} />)
 
+    if (config.type === 'group') {
+      return (
+        <Row className="component-wrap">{this.getComponents(config.components)}</Row>
+      )
+    }
+
     return (
       <Row className="component-wrap" id={'anchor' + config.uuid} gutter={8}>{this.getComponents(config.components)}</Row>
     )
diff --git a/src/tabviews/custom/components/table/base-table/index.jsx b/src/tabviews/custom/components/table/base-table/index.jsx
index 9658a04..4f1d0fd 100644
--- a/src/tabviews/custom/components/table/base-table/index.jsx
+++ b/src/tabviews/custom/components/table/base-table/index.jsx
@@ -4,7 +4,6 @@
 import { notification, Modal } from 'antd'
 
 import Api from '@/api'
-import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import asyncComponent from '@/utils/asyncComponent'
 import MKEmitter from '@/utils/events.js'
@@ -17,9 +16,7 @@
 
 class MkBaseTable extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
     config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
   }
 
   state = {
@@ -28,7 +25,6 @@
     config: {},           // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佹悳绱€�佹樉绀哄垪銆佹爣绛剧瓑
     actions: null,        // 鎸夐挳闆�
     columns: null,        // 鏄剧ず鍒�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
     setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
     data: [],             // 鍒楄〃鏁版嵁闆�
     selectedData: [],     // 宸查�夎〃鏍兼暟鎹�
@@ -85,8 +81,7 @@
       setting: setting,
       actions: _config.action,
       columns: _config.cols,
-      arr_field: _config.columns.map(col => col.field).join(','),
-      search: Utils.initMainSearch(_config.search) // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級
+      search: _config.$searches
     }, () => {
       if (_config.setting.onload === 'true') {
         setTimeout(() => {
@@ -103,8 +98,7 @@
    * @param { String }  repage 琛ㄦ牸鏄惁閲嶇疆椤电爜
    */
   async loadmaindata (reset, repage, id) {
-    const { mainSearch } = this.props
-    const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+    const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
     if (setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -122,17 +116,17 @@
     }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -141,7 +135,7 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -183,32 +177,39 @@
         start = pageSize * (pageIndex - 1) + 1
       }
 
-      this.setState({
-        data: result.data.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[setting.primaryKey] || ''
-          item.$$key = '' + item.key + item.$$uuid
-          item.$$BID = BID || ''
-          item.$$BData = BData || ''
-          item.$Index = start + index + ''
+      let data = result.data.map((item, index) => {
+        item.key = index
+        item.$$uuid = item[setting.primaryKey] || ''
+        item.$$key = '' + item.key + item.$$uuid
+        item.$$BID = BID || ''
+        item.$$BData = BData || ''
+        item.$Index = start + index + ''
 
-          if (config.absFields) {
-            config.absFields.forEach(f => {
-              if (!isNaN(item[f])) {
-                item[f] = Math.abs(item[f])
-              }
-            })
-          }
-          if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField] + '')) {
-              item.$disabled = true
+        if (config.absFields) {
+          config.absFields.forEach(f => {
+            if (!isNaN(item[f])) {
+              item[f] = Math.abs(item[f])
             }
+          })
+        }
+        if (setting.controlField) {
+          if (setting.controlVal.includes(item[setting.controlField] + '')) {
+            item.$disabled = true
           }
-          
-          return item
-        }),
+        }
+        
+        return item
+      })
+
+      let total = result.total || 0
+      if (config.setting.custompage && data.length) {
+        total = data[data.length - 1].mk_total || 0
+      }
+
+      this.setState({
+        data: data,
         selectedData: [],
-        total: result.total,
+        total: total,
         loading: false
       })
 
@@ -217,6 +218,20 @@
           MKEmitter.emit('autoGetData', config.MenuID)
         } else {
           MKEmitter.emit('autoMaticOver', config.MenuID)
+        }
+      }
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
         }
       }
     } else {
@@ -228,11 +243,12 @@
         MKEmitter.emit('autoMaticError', config.MenuID)
       }
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -246,16 +262,21 @@
    * @description 鑾峰彇鍗曡鏁版嵁
    */ 
   async loadmainLinedata (id) {
-    const { mainSearch } = this.props
-    const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+    const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+
+    if (config.forbidLine) {
+      this.reloadtable()
+      return
+    }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
@@ -264,12 +285,13 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let data = fromJS(this.state.data).toJS()
       let selectedData = fromJS(this.state.selectedData).toJS()
+
       if (result.data && result.data[0]) {
         let _data = result.data[0] || {}
         _data.$$uuid = _data[setting.primaryKey] || ''
@@ -284,35 +306,67 @@
           })
         }
 
-        try {
-          data = data.map(item => {
-            if (item.$$uuid === _data.$$uuid) {
-              _data.key = item.key
-              _data.$$key = '' + item.key + item.$$uuid
-              _data.$Index = item.$Index
-              return _data
-            } else {
-              return item
-            }
-          })
-          selectedData = selectedData.map(item => {
-            if (_data.$$uuid === item.$$uuid) {
-              return _data
-            }
+        data = data.map(item => {
+          if (item.$$uuid === _data.$$uuid) {
+            _data.key = item.key
+            _data.$$key = '' + item.key + item.$$uuid
+            _data.$Index = item.$Index
+            return _data
+          } else {
             return item
+          }
+        })
+
+        if (!_data.$Index) {
+          this.setState({
+            loading: false
           })
-        } catch (e) {
-          console.warn('鏁版嵁鏌ヨ閿欒')
+          return
         }
 
-        MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
-      }
+        selectedData = selectedData.map(item => {
+          if (_data.$$uuid === item.$$uuid) {
+            return _data
+          }
+          return item
+        })
 
-      this.setState({
-        data,
-        selectedData,
-        loading: false
-      })
+        if (selectedData.length && _data.$$uuid === selectedData[selectedData.length - 1].$$uuid) {
+          MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
+        }
+        
+        this.setState({
+          data,
+          selectedData,
+          loading: false
+        })
+      } else {
+        let index = data.findIndex(item => item.$$uuid === id)
+
+        if (index === -1) {
+          this.setState({
+            loading: false
+          })
+          return
+        }
+
+        data = data.filter(item => item.$$uuid !== id)
+        data = data.map((item, i) => {
+          item.key = i
+          item.$$key = '' + item.key + item.$$uuid
+
+          return item
+        })
+
+        this.setState({
+          data: data,
+          loading: false
+        })
+
+        setTimeout(() => {
+          MKEmitter.emit('resetTable', config.uuid, 'delete', index)
+        }, 20)
+      }
     } else {
       this.setState({
         loading: false
@@ -329,7 +383,6 @@
    * @description 鑾峰彇鍚堣瀛楁鍊�
    */
   getStatFieldsValue = () => {
-    const { mainSearch } = this.props
     const { setting, config, search, BID, orderBy } = this.state
 
     if (setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
@@ -342,16 +395,17 @@
     if (config.statFields.length === 0 || setting.interType !== 'system' || !setting.dataresource) return
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -396,6 +450,8 @@
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
   refreshbysearch = (searches) => {
+    const { config} = this.state
+
     this.setState({
       pageIndex: 1,
       search: searches
@@ -403,6 +459,11 @@
       this.loadmaindata(true, 'true')
       this.getStatFieldsValue()
     })
+
+    if (config.$main) {
+      window.GLOB.SearchBox.set(config.$searchId, searches)
+      MKEmitter.emit('searchRefresh', config.$searchId)
+    }
   }
 
   /**
@@ -455,26 +516,24 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, orderBy, search, setting} = this.state
+    const { config, orderBy, search, setting } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: orderBy || setting.order,
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
@@ -528,20 +587,16 @@
     } else {
       this.reloadtable(btn, id)
     }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
   }
 
-  UNSAFE_componentWillReceiveProps(nextProps) {
+  searchRefresh = (searchId) => {
     const { config } = this.state
 
-    if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({pageIndex: 1}, () => {
-        this.reloadtable()
-      })
-    }
+    if (config.$searchId !== searchId) return
+    
+    this.setState({pageIndex: 1}, () => {
+      this.reloadtable()
+    })
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -549,10 +604,16 @@
   }
 
   componentDidMount () {
+    const { config } = this.state
+
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
   }
 
   /**
@@ -563,6 +624,7 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
diff --git a/src/tabviews/custom/components/table/edit-table/index.jsx b/src/tabviews/custom/components/table/edit-table/index.jsx
index d1281be..fd88ed1 100644
--- a/src/tabviews/custom/components/table/edit-table/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/index.jsx
@@ -19,7 +19,6 @@
 class EditableTable extends Component {
   static propTpyes = {
     config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
   }
 
   state = {
@@ -28,7 +27,6 @@
     config: {},           // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佹悳绱€�佹樉绀哄垪銆佹爣绛剧瓑
     actions: null,        // 鎸夐挳闆�
     columns: null,        // 鏄剧ず鍒�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
     setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
     data: [],             // 鍒楄〃鏁版嵁闆�
     selectedData: [],     // 宸查�夎〃鏍兼暟鎹�
@@ -174,8 +172,7 @@
       setting: setting,
       actions: _config.action,
       columns: _columns,
-      arr_field: _config.columns.map(col => col.field).join(','),
-      search: Utils.initMainSearch(_config.search) // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級
+      search: _config.$searches
     }, () => {
       if (_config.setting.onload === 'true') {
         setTimeout(() => {
@@ -191,8 +188,7 @@
    * @param { String }  repage 琛ㄦ牸鏄惁閲嶇疆椤电爜
    */
   async loadmaindata (reset, repage) {
-    const { mainSearch } = this.props
-    const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+    const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
     if (setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -205,17 +201,17 @@
     }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -224,7 +220,7 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -254,24 +250,44 @@
         return item
       })
 
+      let total = result.total || 0
+      if (config.setting.custompage && data.length) {
+        total = data[data.length - 1].mk_total || 0
+      }
+
       this.setState({
         data: data,
         selectedData: [],
-        total: result.total,
+        total: total,
         loading: false
       })
 
       MKEmitter.emit('transferData', config.uuid, data)
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -285,16 +301,21 @@
    * @description 鑾峰彇鍗曡鏁版嵁
    */ 
   async loadmainLinedata (id) {
-    const { mainSearch } = this.props
-    const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+    const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
+    if (config.forbidLine) {
+      this.reloadtable()
+      return
+    }
+    
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
@@ -303,7 +324,7 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -422,26 +443,24 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, orderBy, search, setting} = this.state
+    const { config, orderBy, search, setting } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: orderBy || setting.order,
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
@@ -496,20 +515,40 @@
     } else {
       this.reloadtable(btn)
     }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
   }
 
-  UNSAFE_componentWillReceiveProps(nextProps) {
+  refreshLineData = (menuId, btn, uuid, count) => {
     const { config } = this.state
 
-    if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({pageIndex: 1}, () => {
-        this.reloadtable()
-      })
-    }
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(this.state.data).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
+      }
+      return item
+    })
+    let _selectedData = fromJS(this.state.selectedData).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
+      }
+      return item
+    })
+
+    this.setState({
+      data: _data,
+      selectedData: _selectedData
+    })
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({pageIndex: 1}, () => {
+      this.reloadtable()
+    })
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -517,10 +556,17 @@
   }
 
   componentDidMount () {
+    const { config } = this.state
+
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
   }
 
   /**
@@ -531,6 +577,8 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
diff --git a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
index a38bb09..10f41bf 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -433,21 +433,35 @@
       )
     } else if (col.type === 'formula') {
       let content = col.formula
-      Object.keys(record).forEach(key => {
-        let reg = new RegExp('@' + key + '@', 'ig')
-        content = content.replace(reg, record[key])
-      })
 
-      if (col.eval !== 'false') {
+      if (col.eval === 'func') {
         try {
           // eslint-disable-next-line
-          content = eval(content)
+          let func = new Function('data', col.formula)
+          content = func([record])
         } catch (e) {
-          if (window.debugger) {
-            console.info(content)
+          if (window.GLOB.debugger === true) {
             console.warn(e)
           }
           content = ''
+        }
+      } else {
+        Object.keys(record).forEach(key => {
+          let reg = new RegExp('@' + key + '@', 'ig')
+          content = content.replace(reg, record[key])
+        })
+  
+        if (col.eval !== 'false') {
+          try {
+            // eslint-disable-next-line
+            content = eval(content)
+          } catch (e) {
+            if (window.GLOB.debugger === true) {
+              console.info(content)
+              console.warn(e)
+            }
+            content = ''
+          }
         }
       }
 
@@ -462,7 +476,9 @@
         content = content.toFixed(col.decimal)
       }
 
-      if (content !== '') {
+      if (col.eval === 'func') {
+        content = <span dangerouslySetInnerHTML={{__html: content}}></span>
+      } else if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
         content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
@@ -826,21 +842,35 @@
       )
     } else if (col.type === 'formula') {
       let content = col.formula
-      Object.keys(record).forEach(key => {
-        let reg = new RegExp('@' + key + '@', 'ig')
-        content = content.replace(reg, record[key])
-      })
 
-      if (col.eval !== 'false') {
+      if (col.eval === 'func') {
         try {
           // eslint-disable-next-line
-          content = eval(content)
+          let func = new Function('data', col.formula)
+          content = func([record])
         } catch (e) {
-          if (window.debugger) {
-            console.info(content)
+          if (window.GLOB.debugger === true) {
             console.warn(e)
           }
           content = ''
+        }
+      } else {
+        Object.keys(record).forEach(key => {
+          let reg = new RegExp('@' + key + '@', 'ig')
+          content = content.replace(reg, record[key])
+        })
+  
+        if (col.eval !== 'false') {
+          try {
+            // eslint-disable-next-line
+            content = eval(content)
+          } catch (e) {
+            if (window.GLOB.debugger === true) {
+              console.info(content)
+              console.warn(e)
+            }
+            content = ''
+          }
         }
       }
 
@@ -855,7 +885,9 @@
         content = content.toFixed(col.decimal)
       }
 
-      if (content !== '') {
+      if (col.eval === 'func') {
+        content = <span dangerouslySetInnerHTML={{__html: content}}></span>
+      } else if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
         content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
@@ -1127,7 +1159,7 @@
     let mainItems = []  // 浜戠鎴栧崟鐐规暟鎹�
     let localItems = [] // 鏈湴鏁版嵁
     let cache = setting.cache !== 'false'
-    let debug = window.GLOB.debugger === true || window.debugger === true
+    let debug = window.GLOB.debugger === true
     let _sql = `Declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)  select @mk_departmentcode='${sessionStorage.getItem('departmentcode') || ''}',@mk_organization='${sessionStorage.getItem('organization') || ''}',@mk_user_type='${sessionStorage.getItem('mk_user_type') || ''}'\n`
     let _sso = _sql
 
@@ -1642,22 +1674,12 @@
     if (submit.intertype === 'system') { // 绯荤粺瀛樺偍杩囩▼
       param.func = 'sPC_TableData_InUpDe'
       
-      if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        result.sql = result.sql.replace(/\$@/ig, '/*')
-        result.sql = result.sql.replace(/@\$/ig, '*/')
-        result.bottom = result.bottom.replace(/\$@/ig, '/*')
-        result.bottom = result.bottom.replace(/@\$/ig, '*/')
-      } else {
-        result.sql = result.sql.replace(/@\$|\$@/ig, '')
-        result.bottom = result.bottom.replace(/@\$|\$@/ig, '')
-      }
-      
-      param.excel_in_type = 'true'
-      param.LText1 = Utils.formatOptions(result.insert)
-      param.LText2 = Utils.formatOptions(result.bottom)
+      delete param.excel_in
+
+      param.exec_type = 'y'
       param.LText = Utils.formatOptions(result.sql)
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+      param.secretkey = Utils.encrypt('', param.timestamp)
 
       param.menuname = submit.logLabel
 
@@ -1671,11 +1693,18 @@
         } else {
           this.execError(res)
         }
-      }, () => {
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') return
+
         this.execError({})
       })
     } else if (submit.intertype === 'inner' && submit.innerFunc) { // 鑷畾涔夊瓨鍌ㄨ繃绋�
       param.func = submit.innerFunc
+
+      if (submit.recordUser === 'true') {
+        param.username = sessionStorage.getItem('User_Name') || ''
+        param.fullname = sessionStorage.getItem('Full_Name') || ''
+      }
 
       Api.genericInterface(param).then((res) => {
         if (res.status) {
@@ -1683,7 +1712,9 @@
         } else {
           this.execError(res)
         }
-      }, () => {
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') return
+
         this.execError({})
       })
     }
diff --git a/src/tabviews/custom/components/table/normal-table/index.jsx b/src/tabviews/custom/components/table/normal-table/index.jsx
index ca20ae8..63b75d4 100644
--- a/src/tabviews/custom/components/table/normal-table/index.jsx
+++ b/src/tabviews/custom/components/table/normal-table/index.jsx
@@ -4,7 +4,6 @@
 import { notification, Collapse, Modal } from 'antd'
 
 import Api from '@/api'
-import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import asyncComponent from '@/utils/asyncComponent'
 import MKEmitter from '@/utils/events.js'
@@ -21,9 +20,7 @@
 
 class NormalTable extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
@@ -32,7 +29,6 @@
     config: {},           // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佹悳绱€�佹樉绀哄垪銆佹爣绛剧瓑
     actions: null,        // 鎸夐挳闆�
     columns: null,        // 鏄剧ず鍒�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
     setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
     data: [],             // 鍒楄〃鏁版嵁闆�
     selectedData: [],     // 宸查�夎〃鏍兼暟鎹�
@@ -52,11 +48,10 @@
    * 1銆� initdata 涓烘墦鍗版椂浣跨敤鐨勬暟鎹泦
    */
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
-    let _data = null
-    let _sync = _config.setting.sync === 'true'
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
+    let _data = null
     let BID = ''
     let BData = ''
 
@@ -85,51 +80,58 @@
       setting.orisel = true
     }
 
-    if (_sync && data) {
-      _data = data[_config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      _data = initdata || []
-      _sync = false
-    }
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
 
-    if (_data) {
-      this.loaded = true
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[_config.setting.primaryKey] || ''
-        item.$$key = '' + item.key + item.$$uuid
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1 + ''
-
-        if (_config.absFields) {
-          _config.absFields.forEach(f => {
-            if (!isNaN(item[f])) {
-              item[f] = Math.abs(item[f])
-            }
-          })
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
         }
-
-        if (setting.controlField) {
-          if (setting.controlVal.includes(item[setting.controlField] + '')) {
-            item.$disabled = true
+  
+        _config.setting.sync = 'false'
+  
+        _data = _data.map((item, index) => {
+          item.key = index
+          item.$$uuid = item[_config.setting.primaryKey] || ''
+          item.$$key = '' + item.key + item.$$uuid
+          item.$$BID = BID || ''
+          item.$$BData = BData || ''
+          item.$Index = index + 1 + ''
+  
+          if (_config.absFields) {
+            _config.absFields.forEach(f => {
+              if (!isNaN(item[f])) {
+                item[f] = Math.abs(item[f])
+              }
+            })
+          }
+  
+          if (setting.controlField) {
+            if (setting.controlVal.includes(item[setting.controlField] + '')) {
+              item.$disabled = true
+            }
+          }
+  
+          return item
+        })
+  
+        if (setting.selected !== 'false' && _data.length > 0) {
+          setTimeout(() => {
+            MKEmitter.emit('mkCheckTopLine', _config.uuid, '', setting.selected)
+          }, 200)
+          if (setting.selected === 'init') {
+            setting.selected = 'false'
           }
         }
-
-        return item
-      })
-
-      if (setting.selected !== 'false' && _data && _data.length > 0) {
-        setTimeout(() => {
-          MKEmitter.emit('mkCheckTopLine', _config.uuid, '', setting.selected)
-        }, 200)
-        if (setting.selected === 'init') {
-          setting.selected = 'false'
-        }
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
       }
     }
-
+    
     if (_config.wrap.collapse === 'true') {
       _config.wrap.title = _config.wrap.title || ' '
     }
@@ -141,24 +143,204 @@
       BID: BID || '',
       BData: BData || '',
       title: _config.wrap.title,
-      sync: _sync,
       data: _data,
       config: _config,
       setting: setting,
       actions: _config.action,
       columns: _config.cols,
-      arr_field: _config.columns.map(col => col.field).join(','),
-      search: Utils.initMainSearch(_config.search) // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級
-    }, () => {
-      if (_config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadmaindata()
-          this.getStatFieldsValue()
-        }, _config.setting.delay || 0)
-      } else if (_config.setting.onload === 'true') {
-        this.getStatFieldsValue()
-      }
+      search: _config.$searches
     })
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    const { config } = this.state
+
+    MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
+    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
+    if (config.timer) {
+      this.timer = new TimerTask()
+      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
+        this.setState({
+          pageIndex: 1
+        }, () => {
+          this.loadmaindata(true, 'true', '', 'timer')
+        })
+      })
+    }
+
+    this.initExec()
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, setting, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time && !setting.laypage) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadmaindata(false, 'true', '', 'init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.setState({data: res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$$key = '' + item.key + item.$$uuid
+              item.$Index = index + 1 + ''
+    
+              if (config.absFields) {
+                config.absFields.forEach(f => {
+                  if (!isNaN(item[f])) {
+                    item[f] = Math.abs(item[f])
+                  }
+                })
+              }
+    
+              if (setting.controlField) {
+                if (setting.controlVal.includes(item[setting.controlField] + '')) {
+                  item.$disabled = true
+                }
+              }
+              
+              return item
+            })})
+          })
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.setState({data: res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$$key = '' + item.key + item.$$uuid
+              item.$Index = index + 1 + ''
+    
+              if (config.absFields) {
+                config.absFields.forEach(f => {
+                  if (!isNaN(item[f])) {
+                    item[f] = Math.abs(item[f])
+                  }
+                })
+              }
+    
+              if (setting.controlField) {
+                if (setting.controlVal.includes(item[setting.controlField] + '')) {
+                  item.$disabled = true
+                }
+              }
+              
+              return item
+            })})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadmaindata(false, 'true', '', 'init')
+          }, config.setting.delay || 0)
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadmaindata()
+      }, config.setting.delay || 0)
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { setting, BID, BData } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data.map((item, index) => {
+      item.key = index
+      item.$$uuid = item[config.setting.primaryKey] || ''
+      item.$$key = '' + item.key + item.$$uuid
+      item.$$BID = BID || ''
+      item.$$BData = BData || ''
+      item.$Index = index + 1 + ''
+
+      if (config.absFields) {
+        config.absFields.forEach(f => {
+          if (!isNaN(item[f])) {
+            item[f] = Math.abs(item[f])
+          }
+        })
+      }
+
+      if (setting.controlField) {
+        if (setting.controlVal.includes(item[setting.controlField] + '')) {
+          item.$disabled = true
+        }
+      }
+      
+      return item
+    })
+
+    if (setting.selected !== 'false' && _data.length > 0) {
+      setTimeout(() => {
+        MKEmitter.emit('mkCheckTopLine', config.uuid, '', setting.selected)
+      }, 200)
+      if (setting.selected === 'init') {
+        this.setState({setting: {...setting, selected: 'false'}})
+      }
+    }
+
+    this.loaded = true
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
   }
 
   /**
@@ -167,8 +349,7 @@
    * @param { String }  repage 琛ㄦ牸鏄惁閲嶇疆椤电爜
    */
   async loadmaindata (reset, repage, id, type) {
-    const { mainSearch } = this.props
-    const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+    const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
     if (setting.supModule && !BID && setting.supKey !== 'false') { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -188,17 +369,17 @@
     }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
@@ -209,13 +390,13 @@
     }
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       this.loaded = true
-      if (config.$cache && pageIndex === 1 && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       if (repage === 'false' && result.data && result.data.length === 0 && result.total > 0 && pageIndex > 1) {
@@ -281,10 +462,15 @@
         return item
       })
 
+      let total = result.total || 0
+      if (config.setting.custompage && data.length) {
+        total = data[data.length - 1].mk_total || 0
+      }
+
       this.setState({
         data: data,
         selectedData: [],
-        total: result.total,
+        total: total,
         loading: false
       })
 
@@ -294,17 +480,32 @@
           this.timer && this.timer.stop()
         }
       }
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -318,16 +519,21 @@
    * @description 鑾峰彇鍗曡鏁版嵁
    */ 
   async loadmainLinedata (id) {
-    const { mainSearch } = this.props
-    const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+    const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
+
+    if (config.forbidLine) {
+      this.reloadtable()
+      return
+    }
 
     let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
@@ -336,35 +542,27 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      if (!result.data || !result.data[0]) {
-        this.setState({
-          loading: false
-        })
-
-        return
-      }
-
       let data = fromJS(this.state.data).toJS()
       let selectedData = fromJS(this.state.selectedData).toJS()
 
-      let _data = result.data[0]
-      _data.$$uuid = _data[setting.primaryKey] || ''
-      _data.$$BID = BID || ''
-      _data.$$BData = BData || ''
-
-      if (config.absFields) {
-        config.absFields.forEach(f => {
-          if (!isNaN(_data[f])) {
-            _data[f] = Math.abs(_data[f])
-          }
-        })
-      }
-
-      try {
+      if (result.data && result.data[0]) {
+        let _data = result.data[0]
+        _data.$$uuid = _data[setting.primaryKey] || ''
+        _data.$$BID = BID || ''
+        _data.$$BData = BData || ''
+  
+        if (config.absFields) {
+          config.absFields.forEach(f => {
+            if (!isNaN(_data[f])) {
+              _data[f] = Math.abs(_data[f])
+            }
+          })
+        }
+  
         data = data.map(item => {
           if (item.$$uuid === _data.$$uuid) {
             _data.key = item.key
@@ -375,23 +573,61 @@
             return item
           }
         })
+
+        if (!_data.$Index) {
+          this.setState({
+            loading: false
+          })
+          return
+        }
+
         selectedData = selectedData.map(item => {
           if (_data.$$uuid === item.$$uuid) {
             return _data
           }
           return item
         })
-      } catch (e) {
-        console.warn('鏁版嵁鏌ヨ閿欒')
+
+        if (selectedData.length && _data.$$uuid === selectedData[selectedData.length - 1].$$uuid) {
+          MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
+        }
+  
+        this.setState({
+          data,
+          selectedData,
+          loading: false
+        })
+
+        if (config.setting.$hasSyncModule) {
+          MKEmitter.emit('syncBalconyData', config.uuid, selectedData, data.length === selectedData.length)
+        }
+      } else {
+        let index = data.findIndex(item => item.$$uuid === id)
+
+        if (index === -1) {
+          this.setState({
+            loading: false
+          })
+          return
+        }
+
+        data = data.filter(item => item.$$uuid !== id)
+        data = data.map((item, i) => {
+          item.key = i
+          item.$$key = '' + item.key + item.$$uuid
+
+          return item
+        })
+
+        this.setState({
+          data: data,
+          loading: false
+        })
+
+        setTimeout(() => {
+          MKEmitter.emit('resetTable', config.uuid, 'delete', index)
+        }, 20)
       }
-
-      MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
-
-      this.setState({
-        data,
-        selectedData,
-        loading: false
-      })
     } else {
       this.setState({
         loading: false
@@ -405,72 +641,6 @@
   }
 
   /**
-   * @description 鑾峰彇鍚堣瀛楁鍊�
-   */
-  getStatFieldsValue = () => {
-    const { mainSearch } = this.props
-    const { setting, config, search, BID, orderBy } = this.state
-
-    if (setting.supModule && !BID && setting.supKey !== 'false') { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
-      this.setState({
-        statFValue: []
-      })
-      return
-    }
-
-    if (config.statFields.length === 0 || setting.interType !== 'system' || !setting.dataresource) return
-
-    let searches = fromJS(search).toJS()
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
-      mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
-      })
-    }
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
-      return
-    }
-
-    let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getStatQueryDataParams(setting, config.statFields, searches, _orderBy, BID)
-
-    Api.genericInterface(param).then(res => {
-      if (res.status) {
-        let _data = res.data[0]
-        let values = []
-
-        if (_data) {
-          config.statFields.forEach(item => {
-            if (_data[item.field] || _data[item.field] === 0) {
-              let val = +_data[item.field]
-              if (isNaN(val)) {
-                val = 0
-              }
-              val = val.toFixed(item.decimal)
-              values.push({label: item.label, value: val})
-            }
-          })
-        }
-        this.setState({
-          statFValue: values
-        })
-      } else {
-        this.setState({
-          statFValue: []
-        })
-        notification.error({
-          top: 92,
-          message: res.message,
-          duration: 10
-        })
-      }
-    })
-  }
-
-  /**
    * @description 鎼滅储鏉′欢鏀瑰彉鏃讹紝閲嶇疆琛ㄦ牸鏁版嵁
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
@@ -480,7 +650,6 @@
       search: searches
     }, () => {
       this.loadmaindata(true, 'true')
-      this.getStatFieldsValue()
     })
   }
 
@@ -514,11 +683,9 @@
         pageIndex: 1
       }, () => {
         this.loadmaindata(true, 'true', id)
-        this.getStatFieldsValue()
       })
     } else {
       this.loadmaindata(true, 'false', id)
-      this.getStatFieldsValue()
     }
   }
 
@@ -526,26 +693,24 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config, orderBy, search, setting} = this.state
+    const { config, orderBy, search, setting} = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = search ? fromJS(search).toJS() : []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
+      let keys = config.$s_keys || []
       mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
+        if (keys.includes(item.key.toLowerCase())) return
+
+        searches.push(item)
       })
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: orderBy || setting.order,
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
@@ -573,7 +738,6 @@
         BData: data
       }, () => {
         this.loadmaindata(true, 'true')
-        this.getStatFieldsValue()
       })
     }
   }
@@ -600,131 +764,40 @@
     } else {
       this.reloadtable(btn, id)
     }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
   }
 
-  UNSAFE_componentWillReceiveProps(nextProps) {
-    const { sync, config, setting, BID, BData } = this.state
+  refreshLineData = (menuId, btn, uuid, count) => {
+    const { config } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-        _data = _data.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[config.setting.primaryKey] || ''
-          item.$$key = '' + item.key + item.$$uuid
-          item.$$BID = BID || ''
-          item.$$BData = BData || ''
-          item.$Index = index + 1 + ''
-
-          if (config.absFields) {
-            config.absFields.forEach(f => {
-              if (!isNaN(item[f])) {
-                item[f] = Math.abs(item[f])
-              }
-            })
-          }
-
-          if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField] + '')) {
-              item.$disabled = true
-            }
-          }
-          
-          return item
-        })
-
-        if (setting.selected !== 'false' && _data && _data.length > 0) {
-          setTimeout(() => {
-            MKEmitter.emit('mkCheckTopLine', config.uuid, '', setting.selected)
-          }, 200)
-          if (setting.selected === 'init') {
-            this.setState({setting: {...setting, selected: 'false'}})
-          }
-        }
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(this.state.data).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
       }
+      return item
+    })
+    let _selectedData = fromJS(this.state.selectedData).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
+      }
+      return item
+    })
 
-      this.loaded = true
-
-      this.setState({sync: false, data: _data})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({pageIndex: 1}, () => {
-        this.reloadtable()
-      })
-    }
+    this.setState({
+      data: _data,
+      selectedData: _selectedData
+    })
   }
 
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
+  searchRefresh = (searchId) => {
+    const { config } = this.state
 
-  componentDidMount () {
-    const { config, setting } = this.state
-
-    MKEmitter.addListener('reloadData', this.reloadData)
-    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
-    MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
-    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
-
-    if (config.timer) {
-      this.timer = new TimerTask()
-      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.setState({
-          pageIndex: 1
-        }, () => {
-          this.loadmaindata(true, 'true', '', 'timer')
-          this.getStatFieldsValue()
-        })
-      })
-    }
-
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        this.setState({data: res.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[config.setting.primaryKey] || ''
-          item.$$key = '' + item.key + item.$$uuid
-          item.$Index = index + 1 + ''
-
-          if (config.absFields) {
-            config.absFields.forEach(f => {
-              if (!isNaN(item[f])) {
-                item[f] = Math.abs(item[f])
-              }
-            })
-          }
-
-          if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField] + '')) {
-              item.$disabled = true
-            }
-          }
-          
-          return item
-        })})
-      })
-    }
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    MKEmitter.removeListener('reloadData', this.reloadData)
-    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
-    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
-    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
-
-    this.timer && this.timer.stop()
+    if (config.$searchId !== searchId) return
+    
+    this.setState({pageIndex: 1}, () => {
+      this.reloadtable()
+    })
   }
 
   render() {
@@ -735,65 +808,44 @@
       style.display = 'none'
     }
 
+    let content = <>
+      {config.search && config.search.length ?
+        <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
+      }
+      {actions.length > 0 ? <MainAction
+        BID={BID}
+        setting={setting}
+        actions={actions}
+        BData={BData}
+        columns={config.columns}
+        selectedData={selectedData}
+      /> : <div className="mk-action-space" style={{height: '25px'}}></div>}
+      <div className={'main-table-box ' + (!actions || actions.length === 0 ? 'no-action' : '')}>
+        <MainTable
+          setting={setting}
+          columns={columns}
+          MenuID={config.uuid}
+          data={this.state.data}
+          fields={config.columns}
+          total={this.state.total}
+          lineMarks={config.lineMarks}
+          loading={this.state.loading}
+          refreshdata={this.refreshbytable}
+          statFValue={this.state.statFValue}
+          chgSelectData={(selects) => this.setState({selectedData: selects})}
+        />
+      </div>
+    </>
+
     return (
       <div className="custom-normal-table" id={'anchor' + config.uuid} style={style}>
         {config.wrap.collapse === 'true' ? <Collapse bordered={false} defaultActiveKey="1" expandIconPosition="right">
           <Panel forceRender={true} header={<NormalHeader config={config}/>} key="1">
-            {config.search && config.search.length ?
-              <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
-            }
-            {actions.length > 0 ? <MainAction
-              BID={BID}
-              setting={setting}
-              actions={actions}
-              BData={BData}
-              columns={config.columns}
-              selectedData={selectedData}
-            /> : <div className="mk-action-space" style={{height: '25px'}}></div>}
-            <div className="main-table-box">
-              <MainTable
-                setting={setting}
-                columns={columns}
-                MenuID={config.uuid}
-                data={data}
-                fields={config.columns}
-                total={this.state.total}
-                lineMarks={config.lineMarks}
-                loading={this.state.loading}
-                refreshdata={this.refreshbytable}
-                statFValue={this.state.statFValue}
-                chgSelectData={(selects) => this.setState({selectedData: selects})}
-              />
-            </div>
+            {content}
           </Panel>
         </Collapse> : <>
           <NormalHeader config={config}/>
-          {config.search && config.search.length ?
-            <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
-          }
-          {actions.length > 0 ? <MainAction
-            BID={BID}
-            setting={setting}
-            actions={actions}
-            BData={BData}
-            columns={config.columns}
-            selectedData={selectedData}
-          /> : <div className="mk-action-space" style={{height: '25px'}}></div>}
-          <div className={'main-table-box ' + (!actions || actions.length === 0 ? 'no-action' : '')}>
-            <MainTable
-              setting={setting}
-              columns={columns}
-              MenuID={config.uuid}
-              data={this.state.data}
-              fields={config.columns}
-              total={this.state.total}
-              lineMarks={config.lineMarks}
-              loading={this.state.loading}
-              refreshdata={this.refreshbytable}
-              statFValue={this.state.statFValue}
-              chgSelectData={(selects) => this.setState({selectedData: selects})}
-            />
-          </div>
+          {content}
         </>}
       </div>
     )
diff --git a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
index 69b47b4..5fce84e 100644
--- a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
+++ b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
@@ -14,7 +14,6 @@
 class antvTabs extends Component {
   static propTpyes = {
     config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
   }
 
   state = {
@@ -36,16 +35,19 @@
         let val = ''
         Object.keys(data).forEach(key => {
           if (key.toLowerCase() === _tabs.setting.controlField) {
-            val = data[key]
+            val = data[key] + ''
           }
         })
         _tabs.subtabs = config.subtabs.filter(tab => {
-          if (tab.controlVal === val) {
-            return false
-          } else if (/,/ig.test(tab.controlVal)) {
-            return !tab.controlVal.split(',').includes(val)
-          }
-          return true
+          if (tab.$pass) return true
+    
+          return !tab.controlVals.includes(val)
+        })
+      } else {
+        _tabs.subtabs = config.subtabs.filter(tab => {
+          if (tab.$pass) return true
+    
+          return tab.controlVals.includes('@pass_empty@')
         })
       }
     }
@@ -90,23 +92,24 @@
     if (tabs.setting.supModule === MenuID) {
       if (!data) {
         this.setState({
-          tabs: {...tabs, subtabs: []}
+          tabs: {...tabs, subtabs: this.props.config.subtabs.filter(tab => {
+            if (tab.$pass) return true
+    
+            return tab.controlVals.includes('@pass_empty@')
+          })}
         })
       } else {
         let val = ''
         Object.keys(data).forEach(key => {
           if (key.toLowerCase() === tabs.setting.controlField) {
-            val = data[key]
+            val = data[key] + ''
           }
         })
         this.setState({
           tabs: {...tabs, subtabs: this.props.config.subtabs.filter(tab => {
-            if (tab.controlVal === val) {
-              return false
-            } else if (/,/ig.test(tab.controlVal)) {
-              return !tab.controlVal.split(',').includes(val)
-            }
-            return true
+            if (tab.$pass) return true
+    
+            return !tab.controlVals.includes(val)
           })}
         })
       }
@@ -138,7 +141,6 @@
   }
 
   render() {
-    const { mainSearch } = this.props
     const { tabs } = this.state
 
     if (!tabs.subtabs.length) return null
@@ -148,7 +150,7 @@
         <Tabs defaultActiveKey="1" tabBarStyle={{background: tabs.setting.backgroundColor || 'transparent'}} tabPosition={tabs.setting.position} type={tabs.setting.tabStyle}>
           {tabs.subtabs.map(tab => (
             <TabPane tab={<span id={'tab' + tab.uuid}>{tab.icon ? <MkIcon type={tab.icon} /> : null}{tab.label}</span>} style={{backgroundColor: tab.backgroundColor || 'transparent'}} key={tab.uuid}>
-              <TabTransfer config={tab} mainSearch={mainSearch}/>
+              <TabTransfer config={tab}/>
             </TabPane>
           ))}
         </Tabs>
diff --git a/src/tabviews/custom/components/timeline/normal-timeline/index.jsx b/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
index 1905369..9801617 100644
--- a/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
+++ b/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
@@ -16,16 +16,13 @@
 
 class NormalTimeline extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
     BID: '',                   // 涓婄骇ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: null,                // 鏁版嵁
     BData: '',
     card: null,
@@ -36,16 +33,13 @@
 
   /**
    * @description 鍒濆鍖栧鐞�
-   * 1銆� initdata 涓烘墦鍗版椂浣跨敤鐨勬暟鎹泦
    */
   UNSAFE_componentWillMount () {
-    const { data, initdata } = this.props
-    let _config = fromJS(this.props.config).toJS()
+    const { config } = this.props
 
+    let _config = fromJS(config).toJS()
     let _data = null
     let card = null
-    let _sync = _config.setting.sync === 'true'
-
     let BID = ''
     let BData = ''
 
@@ -58,24 +52,31 @@
       BID = BData.$BID || ''
     }
 
-    if (_config.setting.sync === 'true' && data) {
-      _data = data[_config.dataName] || []
-      _sync = false
-    } else if (_config.setting.sync === 'true' && initdata) {
-      _data = initdata || []
-      _sync = false
-    }
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
 
-    if (_data) {
-      this.loaded = true
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[_config.setting.primaryKey] || ''
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1 + ''
-        return item
-      })
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        _data = _data.map((item, index) => {
+          item.key = index
+          item.$$uuid = item[_config.setting.primaryKey] || ''
+          item.$$BID = BID || ''
+          item.$$BData = BData || ''
+          item.$Index = index + 1 + ''
+          return item
+        })
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
     }
 
     _config.search = []
@@ -94,18 +95,10 @@
 
     this.setState({
       card,
-      sync: _sync,
       BID: BID || '',
       BData: BData || '',
       data: _data,
       config: _config,
-      arr_field: _config.columns.map(col => col.field).join(','),
-    }, () => {
-      if (_config.setting.sync !== 'true' && _config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, _config.setting.delay || 0)
-      }
     })
   }
 
@@ -113,30 +106,27 @@
     const { config } = this.state
 
     MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('refreshLineData', this.refreshLineData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
 
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.loadData(true)
+        this.loadData('timer')
       })
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        this.setState({data: res.map((item, index) => {
-          item.key = index
-          item.$$uuid = item[config.setting.primaryKey] || ''
-          item.$Index = index + 1 + ''
-          
-          return item
-        })})
-      })
-    }
+    this.initExec()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -148,42 +138,107 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
+    MKEmitter.removeListener('refreshLineData', this.refreshLineData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
   }
 
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID, BData } = this.state
+  initExec = () => {
+    const { config, BID } = this.state
 
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.setState({data: res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+              
+              return item
+            })})
+          })
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.setState({data: res.data.map((item, index) => {
+              item.key = index
+              item.$$uuid = item[config.setting.primaryKey] || ''
+              item.$Index = index + 1 + ''
+              
+              return item
+            })})
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        }
       }
-
-      _data = _data.map((item, index) => {
-        item.key = index
-        item.$$uuid = item[config.setting.primaryKey] || ''
-        item.$$BID = BID || ''
-        item.$$BData = BData || ''
-        item.$Index = index + 1 + ''
-        return item
-      })
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data})
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
         this.loadData()
-      })
+      }, config.setting.delay || 0)
     }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    const { BID, BData } = this.state
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    _data = _data.map((item, index) => {
+      item.key = index
+      item.$$uuid = item[config.setting.primaryKey] || ''
+      item.$$BID = BID || ''
+      item.$$BData = BData || ''
+      item.$Index = index + 1 + ''
+      return item
+    })
+
+    this.loaded = true
+
+    this.setState({data: _data})
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   /**
@@ -202,10 +257,23 @@
     } else {
       this.loadData()
     }
+  }
 
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
+  refreshLineData = (menuId, btn, uuid, count) => {
+    const { config, data } = this.state
+
+    if (config.uuid !== menuId) return
+    
+    let _data = fromJS(data).toJS().map(item => {
+      if (item.$$uuid === uuid) {
+        item[btn.field] = count
+      }
+      return item
+    })
+
+    this.setState({
+      data: _data
+    })
   }
 
   resetParentParam = (MenuID, id, data) => {
@@ -231,32 +299,23 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config } = this.state
+    const { config } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
-      mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
-      })
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID, BData } = this.state
+  async loadData (type) {
+    const { config, BID, BData } = this.state
     
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -273,34 +332,28 @@
     }
 
     let searches = []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key)
-      mainSearch.forEach(item => {
-        if (!keys.includes(item.key)) {
-          searches.push(item)
-        }
-      })
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
     }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, config.setting.pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, 1, config.setting.pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       this.loaded = true
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       let data = result.data.map((item, index) => {
@@ -323,17 +376,32 @@
           this.timer && this.timer.stop()
         }
       }
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
diff --git a/src/tabviews/custom/components/tree/antd-tree/index.jsx b/src/tabviews/custom/components/tree/antd-tree/index.jsx
index 922eba9..721d876 100644
--- a/src/tabviews/custom/components/tree/antd-tree/index.jsx
+++ b/src/tabviews/custom/components/tree/antd-tree/index.jsx
@@ -18,16 +18,13 @@
 
 class NormalTree extends Component {
   static propTpyes = {
-    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
-    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    config: PropTypes.object
   }
 
   state = {
     BID: '',                   // 涓昏〃ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: null,                // 鏁版嵁
     searchkey: null,           // 杩囨护鏉′欢
     treedata: null,            // 鍒楄〃鏁版嵁闆�
@@ -40,11 +37,10 @@
   loaded = false
 
   UNSAFE_componentWillMount () {
-    const { config, data, initdata } = this.props
+    const { config } = this.props
+
     let _config = fromJS(config).toJS()
     let _data = null
-    let _sync = config.setting.sync === 'true'
-
     let BID = ''
     let BData = ''
 
@@ -57,58 +53,32 @@
       BID = BData.$BID || ''
     }
 
-    if (_sync && data) {
-      _data = data[config.dataName] || []
-      _sync = false
-    } else if (_sync && initdata) {
-      _data = initdata || []
-      _sync = false
+    if (_config.setting.sync === 'true') {
+      _config.setting.onload = 'false'
+
+      if (window.GLOB.SyncData.has(_config.dataName)) {
+        _data = window.GLOB.SyncData.get(_config.dataName) || []
+  
+        if (_config.$cache) {
+          Api.writeCacheConfig(_config.uuid, fromJS(_data).toJS(), BID)
+        }
+  
+        _config.setting.sync = 'false'
+  
+        this.loaded = true
+  
+        window.GLOB.SyncData.delete(_config.dataName)
+      }
     }
 
     _config.wrap.contentHeight = config.wrap.title || config.wrap.searchable === 'true' ? 'calc(100% - 45px)' : '100%'
-
-    this.loaded = _data !== null
 
     this.setState({
       selected: _config.wrap.selected === 'true',
       config: _config,
       data: _data,
-      BID: BID || '',
-      arr_field: _config.columns.map(col => col.field).join(','),
-      sync: _sync
-    }, () => {
-      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
-        setTimeout(() => {
-          this.loadData()
-        }, config.setting.delay || 0)
-      } else if (config.setting.sync === 'true' && _data) {
-        this.handleData()
-      }
+      BID: BID || ''
     })
-  }
-
-  /**
-   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
-   */
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config } = this.state
-
-    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = []
-      if (nextProps.data && nextProps.data[config.dataName]) {
-        _data = nextProps.data[config.dataName] || []
-      }
-
-      this.loaded = true
-
-      this.setState({sync: false, data: _data}, () => {
-        this.handleData()
-      })
-    } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
-      this.setState({}, () => {
-        this.loadData()
-      })
-    }
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -123,22 +93,22 @@
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
     
+    if (config.setting.useMSearch) {
+      MKEmitter.addListener('searchRefresh', this.searchRefresh)
+    }
+
+    if (config.setting.sync === 'true') {
+      MKEmitter.addListener('transferSyncData', this.transferSyncData)
+    }
+
     if (config.timer) {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
-        this.loadData(true)
+        this.loadData('timer')
       })
     }
 
-    if (config.$cache && !this.loaded) {
-      Api.getLCacheConfig(config.uuid).then(res => {
-        if (!res || this.loaded) return
-
-        this.setState({data: res}, () => {
-          this.handleData()
-        })
-      })
-    }
+    this.initExec()
   }
 
   /**
@@ -149,11 +119,95 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('searchRefresh', this.searchRefresh)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
 
     this.timer && this.timer.stop()
+  }
+
+  initExec = () => {
+    const { config, BID } = this.state
+
+    if (config.$cache) {
+      if (config.$time) {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
+            if (!res.valid && config.setting.onload === 'true') {
+              setTimeout(() => {
+                this.loadData('init')
+              }, config.setting.delay || 0)
+            }
+  
+            if (!res.data || this.loaded) return
+
+            this.setState({data: res.data}, () => {
+              this.handleData()
+            })
+          })
+        } else {
+          this.handleData()
+        }
+      } else {
+        if (!this.loaded) {
+          Api.getLCacheConfig(config.uuid, 0, BID).then(res => {
+            if (!res.data || this.loaded) return
+    
+            this.setState({data: res.data}, () => {
+              this.handleData()
+            })
+          })
+        }
+
+        if (config.setting.onload === 'true') {
+          setTimeout(() => {
+            this.loadData('init')
+          }, config.setting.delay || 0)
+        } else if (this.loaded) {
+          this.handleData()
+        }
+      }
+    } else if (config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    } else if (this.loaded) {
+      this.handleData()
+    }
+  }
+
+  transferSyncData = (syncId) => {
+    const { config, BID } = this.state
+
+    if (config.$syncId !== syncId) return
+
+    let _data = window.GLOB.SyncData.get(config.dataName) || []
+
+    if (config.$cache) {
+      Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID)
+    }
+
+    this.loaded = true
+
+    this.setState({data: _data}, () => {
+      this.handleData()
+    })
+
+    window.GLOB.SyncData.delete(config.dataName)
+
+    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
+  }
+
+  searchRefresh = (searchId) => {
+    const { config } = this.state
+
+    if (config.$searchId !== searchId) return
+    
+    this.setState({}, () => {
+      this.loadData()
+    })
   }
 
   reloadData = (menuId) => {
@@ -179,26 +233,18 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { mainSearch } = this.props
-    const { arr_field, config } = this.state
+    const { config } = this.state
 
     if (config.uuid !== menuId) return
 
     let searches = []
-    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
-      let keys = searches.map(item => item.key.toLowerCase())
-      mainSearch.forEach(item => {
-        if (!keys.includes(item.key.toLowerCase())) {
-          searches.push(item)
-        }
-      })
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: config.setting.order || '',
-      search: searches,
-      menuName: config.name
+      search: searches
     })
   }
 
@@ -218,18 +264,13 @@
     } else {
       this.loadData()
     }
-
-    if (position === 'popclose') { // 鎵ц鍚姩寮圭獥鐨勬寜閽墍閫夋嫨鐨勫埛鏂伴」
-      btn.$tabId && MKEmitter.emit('refreshPopButton', btn.$tabId)
-    }
   }
 
   /**
    * @description 鏁版嵁鍔犺浇
    */
-  async loadData (hastimer) {
-    const { mainSearch } = this.props
-    const { config, arr_field, BID } = this.state
+  async loadData (type) {
+    const { config, BID } = this.state
 
     if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
@@ -241,27 +282,29 @@
       return
     }
 
-    let searches = config.setting.useMSearch && mainSearch ? mainSearch : []
+    let searches = []
+    if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
+      searches = window.GLOB.SearchBox.get(config.$searchId) || []
+    }
 
-    let requireFields = searches.filter(item => item.required && item.value === '')
-    if (requireFields.length > 0) {
+    if (config.$s_req && searches.filter(item => item.required && item.value === '').length > 0) {
       return
     }
 
-    if (!hastimer) {
+    if (type !== 'timer') {
       this.setState({
         loading: true
       })
     }
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       this.loaded = true
-      if (config.$cache && config.setting.onload !== 'false') {
-        Api.writeCacheConfig(config.uuid, result.data || '')
+      if (config.$cache && type === 'init') {
+        Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
       this.setState({
@@ -277,17 +320,32 @@
           this.timer && this.timer.stop()
         }
       }
+
+      if (result.message) {
+        if (result.ErrCode === 'Y') {
+          Modal.success({
+            title: result.message
+          })
+        } else if (result.ErrCode === 'S') {
+          notification.success({
+            top: 92,
+            message: result.message,
+            duration: 2
+          })
+        }
+      }
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
+      if (!result.message) return
       if (result.ErrCode === 'N') {
         Modal.error({
           title: result.message,
         })
-      } else {
+      } else if (result.ErrCode !== '-2') {
         notification.error({
           top: 92,
           message: result.message,
@@ -339,6 +397,7 @@
       if (pval === config.wrap.mark) {
         parentNodes.push({
           ...item,
+          mk_floor: 1,
           $$uuid: uuid,
           $title: item[config.wrap.labelField] || '',
           $key: val,
@@ -355,7 +414,7 @@
       }
     })
     let _treedata = this.getTree(parentNodes, _options)
-    
+
     let _treeNodes = []
 
     if (!searchkey) {
@@ -437,6 +496,7 @@
       // 娣诲姞鑿滃崟鐨勫瓙鍏冪礌
       options = options.filter(option => {
         if (option.$parentId === parent.$key) {
+          option.mk_floor = parent.mk_floor + 1
           parent.children.push(option)
           return false
         }
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index 3c6b9b3..80d4e93 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -1,11 +1,9 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { notification, Spin, Row, Col } from 'antd'
+import { notification, Spin, Row, Col, Modal } from 'antd'
 
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import Utils from '@/utils/utils.js'
 import { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js'
 import asyncComponent from '@/utils/asyncComponent'
@@ -40,9 +38,11 @@
 const CustomChart = asyncComponent(() => import('./components/chart/custom-chart'))
 const TimeLine = asyncComponent(() => import('./components/timeline/normal-timeline'))
 const AntvG6 = asyncComponent(() => import('./components/chart/antv-G6'))
+const AntvX6 = asyncComponent(() => import('./components/chart/antv-X6'))
 const Voucher = asyncComponent(() => import('./components/module/voucher'))
 const Account = asyncComponent(() => import('./components/module/account'))
 const Iframe = asyncComponent(() => import('./components/iframe'))
+const Calendar = asyncComponent(() => import('./components/calendar'))
 const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
 const TableNodes = asyncComponent(() => import('@/tabviews/zshare/tablenodes'))
 const MkInterfaces = asyncComponent(() => import('@/tabviews/custom/components/interfaces'))
@@ -50,24 +50,19 @@
 class CustomPage extends Component {
   static propTpyes = {
     param: PropTypes.any,        // 鍏朵粬椤甸潰浼犻�掔殑鍙傛暟
-    Tab: PropTypes.string,       // 寮圭獥鏍囩
     MenuID: PropTypes.string,    // 鑿滃崟Id
-    MenuNo: PropTypes.string,    // 鑿滃崟鍙傛暟
     MenuName: PropTypes.string,  // 鑿滃崟鍚嶇О
     changeTemp: PropTypes.func
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id
     BID: '',              // 椤甸潰璺宠浆鏃舵惡甯D
     loadingview: true,    // 椤甸潰鍔犺浇涓�
     viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
     lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
     config: null,         // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷粍浠剁瓑
-    mainSearch: null,     // 涓绘悳绱�
     userConfig: null,     // 鐢ㄦ埛鑷畾涔夎缃�
-    data: null,           // 鍒楄〃鏁版嵁闆�
     loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
     visible: false,       // 鏍囩椤垫帶鍒�
     shortcuts: null,      // 蹇嵎閿�
@@ -80,12 +75,13 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { MenuID } = this.props
+    const { MenuID, MenuName } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
       MenuID: MenuID
     }
+
     let result = await Api.getCacheConfig(_param)
 
     if (result.status) {
@@ -97,6 +93,7 @@
         config = config.replace(/@mywebsite@\//ig, window.GLOB.baseurl)
         config = JSON.parse(config)
         config.MenuID = MenuID
+        config.MenuName = MenuName || config.MenuName
       } catch (e) {
         console.warn('Parse Failure')
         config = ''
@@ -116,7 +113,7 @@
         this.setState({
           viewlost: true,
           loadingview: false,
-          lostmsg: this.state.dict['main.view.unenabled']
+          lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
         })
         return
       }
@@ -170,11 +167,6 @@
       let userName = sessionStorage.getItem('User_Name') || ''
       let fullName = sessionStorage.getItem('Full_Name') || ''
 
-      if (sessionStorage.getItem('isEditState') === 'true') {
-        userName = sessionStorage.getItem('CloudUserName') || ''
-        fullName = sessionStorage.getItem('CloudFullName') || ''
-      }
-
       let regs = [
         { reg: /@userName@/ig, value: `'${userName}'` },
         { reg: /@fullName@/ig, value: `'${fullName}'` }
@@ -196,35 +188,13 @@
         })
       }
 
-      let popview = 'CustomPage'
-
-      if (config.version === 2.0) {
-        popview = 'popview'
-      }
-
       config.$cache = config.cacheLocal === 'true'
+      config.$time = config.localCacheTime || 0
 
       let initInters = []
 
       config.interfaces = this.formatInterSetting(config.interfaces, regs, MenuID, initInters)
-      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, param, MenuID, config.interfaces, popview, config.$cache)
-      
-      // 鑾峰彇涓绘悳绱㈡潯浠�
-      let mainSearch = []
-      config.components.forEach(component => {
-        if (component.type !== 'search') return
-
-        component.search = component.search.map(item => {
-          item.oriInitval = item.initval
-          if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
-            item.initval = param.$searchval
-          }
-
-          return item
-        })
-
-        mainSearch = Utils.initMainSearch(component.search)
-      })
+      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, param, MenuID, config.interfaces, config.$cache, config.$time, config.MenuName, MenuID, MenuID)
 
       let params = []
       let BID = param.$BID || ''
@@ -236,7 +206,30 @@
         inherit.cacheTime = config.cacheTime
       }
 
-      config.components = this.formatSetting(config.components, params, mainSearch, inherit, regs, balMap)
+      // 瀛楁閫忚
+      config.components.forEach(component => {
+        if (component.type !== 'search') return
+
+        if (param.$searchkey) {
+          component.search = component.search.map(item => {
+            if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
+              item.initval = param.$searchval
+            }
+  
+            return item
+          })
+
+          component.$searches = Utils.initMainSearch(component.search)
+        }
+
+        window.GLOB.SearchBox.set(MenuID, component.$searches)
+
+        if (component.$s_req) {
+          window.GLOB.SearchBox.set(MenuID + 'required', true)
+        }
+      })
+
+      config.components = this.formatSetting(config.components, params, inherit, regs, balMap)
 
       if ([...balMap.keys()].length > 0) {
         config.components = this.filterBalcony(config.components, balMap)
@@ -254,8 +247,7 @@
         BID: BID,
         loadinginter: this.stepInter !== null,
         shortcuts: shortcuts.length > 0 ? shortcuts : null,
-        config,
-        mainSearch
+        config
       }, () => {
         if (config.normalcss) {
           let node = document.getElementById(config.uuid)
@@ -279,9 +271,7 @@
           this.loadmaindata(params)
         }
 
-        if (!this.props.Tab) {
-          this.setShortcut()
-        }
+        this.setShortcut()
       })
     } else {
       this.setState({
@@ -317,7 +307,6 @@
       let _shortcut = `${preKey}+${keyCode}`
 
       if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
-        window.debugger = false
         window.GLOB.breakpoint = false
         sessionStorage.removeItem('breakpoint')
         
@@ -336,11 +325,27 @@
     }
   }
 
-  filterComponent = (components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, popview, cache) => {
+  filterComponent = (components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, cache, time, MenuName, searchId, syncId) => {
     return components.filter(item => {
       item.$pageId = pageId
-      item.$cache = cache
+      item.$searchId = searchId
+      item.$syncId = syncId
       
+      if (cache) {
+        item.$cache = cache
+        item.$time = time
+
+        if (item.wrap && item.wrap.cacheLocal === 'false') {
+          item.$cache = false
+        } else if (item.plot && item.plot.cacheLocal === 'false') {
+          item.$cache = false
+        }
+
+        if (!item.$cache && item.setting && item.setting.sync === 'true') {
+          item.setting.sync = 'false'
+        }
+      }
+
       if (item.style && item.style.boxShadow) {
         delete item.style.hShadow
         delete item.style.vShadow
@@ -348,7 +353,7 @@
         delete item.style.shadowColor
       }
 
-      item.$menuname = (this.props.MenuName || '') + '-' + (item.name || '')
+      item.$menuname = (MenuName || '') + '-' + (item.name || '')
 
       if (item.type === 'tabs') {
         if (
@@ -356,6 +361,13 @@
           item.setting.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
         ) {
           return false
+        }
+
+        if (item.setting.supModule) {
+          let pid = item.setting.supModule.pop()
+          item.setting.supModule = pid || ''
+        } else {
+          item.setting.supModule = ''
         }
 
         item.subtabs = item.subtabs.filter(tab => {
@@ -367,35 +379,37 @@
           } else if (tab.hide === 'true') {
             return false
           }
+
+          if (item.setting.supModule) {
+            if (tab.controlVal === '@pass@') {
+              tab.$pass = true
+            } else if (/,/ig.test(tab.controlVal)) {
+              tab.controlVals = tab.controlVal.split(',')
+            } else {
+              tab.controlVals = [(tab.controlVal || '')]
+            }
+          }
+
           return true
         })
 
         if (item.setting.supModule) {
-          let pid = item.setting.supModule.pop()
-          item.setting.supModule = pid || ''
+          item.setting.controlField = item.setting.controlField.toLowerCase()
 
-          if (item.setting.supModule) {
-            item.setting.controlField = item.setting.controlField.toLowerCase()
-  
-            if (item.setting.supModule === 'preview') {
-              item.setting.supModule = ''
-              let val = ''
-              Object.keys(urlparam).forEach(key => {
-                if (key.toLowerCase() === item.setting.controlField) {
-                  val = urlparam[key]
-                }
-              })
-  
-              item.subtabs = item.subtabs.filter(tab => {
-                if (tab.controlVal === val) {
-                  return false
-                } else if (/,/ig.test(tab.controlVal)) {
-                  return !tab.controlVal.split(',').includes(val)
-                }
-      
-                return true
-              })
-            }
+          if (item.setting.supModule === 'preview') {
+            item.setting.supModule = ''
+            let val = ''
+            Object.keys(urlparam).forEach(key => {
+              if (key.toLowerCase() === item.setting.controlField) {
+                val = urlparam[key]
+              }
+            })
+
+            item.subtabs = item.subtabs.filter(tab => {
+              if (tab.$pass) return true
+    
+              return !tab.controlVals.includes(val)
+            })
           }
         }
 
@@ -422,8 +436,27 @@
 
         item.subtabs = item.subtabs.map(tab => {
           tab.$pageId = pageId
+          tab.$cache = cache
+          tab.$time = time
 
-          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, popview, cache)
+          let _searchId = searchId
+
+          if (tab.components.findIndex(cell => cell.type === 'search') > -1) {
+            _searchId = tab.uuid
+          }
+
+          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, cache, time, MenuName, _searchId, tab.uuid)
+          
+          if (_searchId === tab.uuid) {
+            tab.components.forEach(cell => {
+              if (cell.type !== 'search') return
+              window.GLOB.SearchBox.set(_searchId, cell.$searches)
+              if (cell.$s_req) {
+                window.GLOB.SearchBox.set(_searchId + 'required', true)
+              }
+            })
+          }
+
           return tab
         })
 
@@ -436,10 +469,10 @@
           return false
         }
 
-        item.components = this.filterComponent(item.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, popview, cache)
+        item.components = this.filterComponent(item.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, cache, time, MenuName, searchId, syncId)
 
         return true
-      } else if (['pie', 'bar', 'line', 'dashboard', 'scatter', 'chart'].includes(item.type)) {
+      } else if (['pie', 'bar', 'line', 'dashboard', 'scatter', 'chart', 'antvG6', 'antvX6'].includes(item.type)) {
         if (
           item.plot.blacklist && item.plot.blacklist.length > 0 &&
           item.plot.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
@@ -469,8 +502,10 @@
       }
 
       // 鎼滅储鏉′欢鍒濆鍖�
-      if (item.search && item.search.length > 0) {
-        item.search = Utils.initSearchVal(item.search)
+      if (item.search) {
+        Utils.initSearchVal(item)
+
+        item.$searches = Utils.initMainSearch(item.search)
       }
 
       if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
@@ -495,7 +530,7 @@
         item.action = item.action.filter(cell => {
           if (cell.hidden === 'true') return false
 
-          cell = this.resetButton(item, cell, popview)
+          cell = this.resetButton(item, cell)
 
           cell.$toolbtn = true
 
@@ -508,7 +543,6 @@
       }
 
       if (item.type === 'table') {
-        let statFields = []
         let getCols = (cols) => {
           return cols.filter(col => {
             if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) {
@@ -520,9 +554,6 @@
             }
             
             if (col.type === 'number') {
-              if (col.sum === 'true' && !statFields.includes(col.field)) {
-                statFields.push(col)
-              }
               if (typeof(col.decimal) === 'number') {
                 col.round = Math.pow(10, col.decimal)
                 if (col.format === 'percent') {
@@ -543,7 +574,7 @@
                 if (cell.eleType === 'button') {
                   if (cell.hidden === 'true') return false
 
-                  cell = this.resetButton(item, cell, popview)
+                  cell = this.resetButton(item, cell)
 
                   if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
                     cell = this.getPrinter(cell, item.uuid)
@@ -573,7 +604,6 @@
         }
         
         item.cols = getCols(item.cols)
-        item.statFields = statFields
 
         if (item.subtype === 'editable') {
           item.submit.logLabel = item.$menuname + '-鎻愪氦'
@@ -600,7 +630,7 @@
             if (cell.eleType === 'button') {
               if (cell.hidden === 'true') return false
 
-              cell = this.resetButton(item, cell, popview)
+              cell = this.resetButton(item, cell)
 
               if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
                 cell = this.getPrinter(cell, item.uuid)
@@ -642,7 +672,7 @@
             if (cell.eleType === 'button') {
               if (cell.hidden === 'true') return false
 
-              cell = this.resetButton(item, cell, popview)
+              cell = this.resetButton(item, cell)
 
               if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
                 cell = this.getPrinter(cell, item.uuid)
@@ -666,7 +696,7 @@
           if (cell.eleType === 'button') {
             if (cell.hidden === 'true') return false
 
-            cell = this.resetButton(item, cell, popview)
+            cell = this.resetButton(item, cell)
 
             if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
               cell = this.getPrinter(cell, item.uuid)
@@ -689,6 +719,11 @@
 
           if (!group.subButton.Ot) {
             group.subButton.Ot = item.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
+          }
+
+          if (item.$cache && item.$time) {
+            group.$cache = item.$cache
+            group.$time = item.$time
           }
 
           group.subButton.syncComponentId = group.subButton.syncComponent ? (group.subButton.syncComponent.pop() || '') : ''
@@ -770,14 +805,14 @@
     })
   }
 
-  resetButton = (item, cell, popview) => {
+  resetButton = (item, cell) => {
     cell.logLabel = item.$menuname + '-' + cell.label
     cell.Ot = cell.Ot || 'requiredSgl'
     cell.ContainerId = this.state.ContainerId
     cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
     cell.$menuId = item.uuid
     cell.$MenuID = this.props.MenuID
-    cell.$view = popview
+    cell.$view = 'popview'
 
     if (cell.btnstyle) { // 鍏煎
       cell.style = cell.style || {}
@@ -790,6 +825,24 @@
       } else {
         cell.controlVals = [(cell.controlVal || '')]
       }
+    }
+
+    if (cell.OpenType === 'excelOut') { // 瀵煎嚭
+      cell.$menuName = item.name
+
+      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
+        cell.errorType = 'error1'
+      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom') {
+        if (item.setting.interType !== 'system') {
+          cell.errorType = 'error2'
+        } else if (item.type === 'balcony' || item.subtype === 'propcard') {
+          cell.errorType = 'error2'
+        }
+      }
+    } else if (cell.OpenType === 'pop' && item.$cache && item.$time && cell.modal) {
+      cell.modal.$cache = item.$cache
+      cell.modal.$time = item.$time
+      cell.modal.uuid = cell.uuid + 'pop'
     }
 
     if (cell.syncComponentId) {
@@ -823,6 +876,11 @@
 
   resetElement = (cell) => {
     cell.style = cell.style || {}
+
+    if (cell.style.display === 'inline-block') {
+      cell.style.verticalAlign = 'top'
+    }
+
     if (['text', 'number', 'formula'].includes(cell.eleType)) {
       if (!cell.height) {
         cell.innerHeight = 'auto'
@@ -877,35 +935,44 @@
   }
 
   // 鏍煎紡鍖栭粯璁よ缃�
-  formatSetting = (components, params, mainSearch, inherit, regs, balMap) => {
+  formatSetting = (components, params, inherit, regs, balMap) => {
     let delay = 20
     return components.map(component => {
       if (component.type === 'tabs') {
         component.subtabs = component.subtabs.map(tab => {
-          tab.components = this.formatSetting(tab.components, null, null, inherit, regs, balMap)
+          tab.components = this.formatSetting(tab.components, null, inherit, regs, balMap)
           tab = {...tab, ...inherit}
           return tab
         })
         return component
       } else if (component.type === 'group') {
-        component.components = this.formatSetting(component.components, null, null, inherit, regs, balMap)
-        component = {...component, ...inherit}
+        component.components = this.formatSetting(component.components, params, null, regs, balMap)
         return component
       } else if (component.wrap && component.wrap.datatype === 'public') {
         component.setting.useMSearch = false
+        component.setting.sync = 'false'
 
         return component
       } else if (component.wrap && component.wrap.datatype === 'static') {
         component.format = ''
         component.setting = component.setting || {}
         component.setting.useMSearch = false
+        component.setting.sync = 'false'
 
         return component
       } else if (!component.setting || !component.format) {
         return component
       }
 
+      component.setting.arr_field = component.columns ? component.columns.map(col => col.field).join(',') : ''
       component.setting.useMSearch = component.setting.useMSearch === 'true'
+      if (component.setting.useMSearch) {
+        if (!window.GLOB.SearchBox.has(component.$searchId)) {
+          component.setting.useMSearch = false
+        } else if (window.GLOB.SearchBox.has(component.$searchId + 'required')) {
+          component.$s_req = true
+        }
+      }
 
       if (component.wrap && component.wrap.goback === 'true') {
         component.setting.sync = 'false'
@@ -918,9 +985,15 @@
       }
 
       let _customScript = ''
+      let _tailScript = ''
       component.scripts && component.scripts.forEach(script => {
-        if (script.status !== 'false') {
+        if (script.status === 'false') return
+        if (script.position !== 'back') {
           _customScript += `
+          ${script.sql}
+          `
+        } else {
+          _tailScript += `
           ${script.sql}
           `
         }
@@ -938,51 +1011,63 @@
       }
   
       if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        component.setting.dataresource = component.setting.dataresource.replace(/@\$/ig, '*/')
-        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        _customScript = _customScript.replace(/@\$/ig, '*/')
+        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
       } else {
         component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
         _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
       }
 
       regs.forEach(cell => {
         component.setting.dataresource = component.setting.dataresource.replace(cell.reg, cell.value)
         _customScript = _customScript.replace(cell.reg, cell.value)
+        _tailScript = _tailScript.replace(cell.reg, cell.value)
       })
 
       component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+      component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
+
+      component.setting.custompage = /@pageSize@|@orderBy@/i.test(component.setting.dataresource + component.setting.customScript)
+
+      if (!component.setting.execute || component.setting.custompage) {
+        component.forbidLine = true
+      }
+
+      if (component.setting.sync === 'true') {
+        // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
+        if ((!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true') {
+
+        } else {
+          component.setting.sync = 'false'
+        }
+      }
 
       // dataName 绯荤粺鐢熸垚鐨勬暟鎹簮鍚嶇О
       if (component.setting.sync === 'true') {
         component.dataName = 'mk' + component.uuid.slice(-18)
-      }
-
-      // floor    缁勪欢鐨勫眰绾�
-      // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
-      if (params && (!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true' && component.setting.sync === 'true') {
-        let searchlist = []
-        if (component.search && component.search.length > 0) {
-          searchlist = Utils.initMainSearch(component.search)
-        }
-        if (component.setting.useMSearch) {
-          let keys = searchlist.map(item => item.key)
-          mainSearch.forEach(item => {
-            if (!keys.includes(item.key)) {
+        
+        if (params) {
+          let searchlist = component.$searches || []
+  
+          if (component.setting.useMSearch) {
+            let mainSearch = window.GLOB.SearchBox.get(component.$searchId)
+            let keys = component.$s_keys || []
+            mainSearch.forEach(item => {
+              if (keys.includes(item.key.toLowerCase())) return
+  
               searchlist.push(item)
-            }
-          })
+            })
+          }
+  
+          if (component.$s_req && searchlist.filter(item => item.required && item.value === '').length > 0) {
+            component.setting.sync = 'false'
+            component.setting.onload = 'false'
+          } else {
+            params.push(getStructDefaultParam(component, searchlist, params.length === 0))
+          }
         }
-
-        if (searchlist.filter(item => item.required && item.value === '').length > 0) {
-          component.setting.sync = 'false'
-          component.setting.onload = 'false'
-        } else {
-          params.push(getStructDefaultParam(component, searchlist, params.length === 0))
-        }
-      } else if (params) {
-        component.setting.sync = 'false'
       }
       
       component.setting.delay = delay
@@ -1032,12 +1117,20 @@
         inter.setting.onload = 'false'
       }
 
+      inter.setting.arr_field = inter.columns.map(col => col.field).join(',')
+
       if (inter.setting.interType !== 'system') return inter
 
       let _customScript = ''
+      let _tailScript = ''
       inter.scripts.forEach(script => {
-        if (script.status !== 'false') {
+        if (script.status === 'false') return
+        if (script.position !== 'back') {
           _customScript += `
+          ${script.sql}
+          `
+        } else {
+          _tailScript += `
           ${script.sql}
           `
         }
@@ -1056,21 +1149,25 @@
       }
   
       if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        inter.setting.dataresource = inter.setting.dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        inter.setting.dataresource = inter.setting.dataresource.replace(/@\$/ig, '*/')
-        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        _customScript = _customScript.replace(/@\$/ig, '*/')
+        inter.setting.dataresource = inter.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
       } else {
         inter.setting.dataresource = inter.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
         _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
       }
 
       regs.forEach(cell => {
         inter.setting.dataresource = inter.setting.dataresource.replace(cell.reg, cell.value)
         _customScript = _customScript.replace(cell.reg, cell.value)
+        _tailScript = _tailScript.replace(cell.reg, cell.value)
       })
 
       inter.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+      inter.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
+
+      inter.setting.custompage = /@pageSize@|@orderBy@/i.test(inter.setting.dataresource + inter.setting.customScript)
 
       return inter
     })
@@ -1080,42 +1177,71 @@
    * @description 涓昏〃鏁版嵁鍔犺浇
    */ 
   loadmaindata = (params) => {
-    const { config } = this.state
-    let param = getStructuredParams(params, config, this.state.BID || '')
+    const { config, BID } = this.state
+    let param = getStructuredParams(params, config, BID || '')
 
     this.setState({loading: true, loadingview: false})
 
-    Api.genericInterface(param).then(result => {
-      if (result.status) {
-        delete result.status
-        delete result.message
-        delete result.ErrMesg
-        delete result.ErrCode
-
-        if (config.$cache) {
-          params.forEach((item) => {
-            let _data = result[item.name] || ''
-            if (_data && !Array.isArray(_data)) {
-              _data = [_data]
-            }
-            Api.writeCacheConfig(item.uuid, _data)
+    if (config.$cache && config.$time) {
+      Api.getLCacheConfig(params[0].uuid, config.$time, BID).then(res => {
+        if (!res.valid) {
+          this.getMainData(param, params, config.MenuID)
+        } else {
+          this.setState({
+            loading: false
           })
         }
+      })
+    } else {
+      this.getMainData(param, params, config.MenuID)
+    }
+  }
 
-        this.setState({
-          data: result,
-          loading: false
+  getMainData = (param, params, MenuID) => {
+    Api.genericInterface(param).then(result => {
+      this.setState({
+        loading: false
+      })
+
+      if (result.status) {
+        if (result.message) {
+          if (result.ErrCode === 'Y') {
+            Modal.success({
+              title: result.message
+            })
+          } else if (result.ErrCode === 'S') {
+            notification.success({
+              top: 92,
+              message: result.message,
+              duration: 2
+            })
+          }
+        }
+
+        params.forEach((item) => {
+          let _data = result[item.name] || ''
+          if (_data && !Array.isArray(_data)) {
+            _data = [_data]
+          }
+          window.GLOB.SyncData.set(item.name, _data)
         })
+
+        MKEmitter.emit('transferSyncData', MenuID)
       } else {
-        this.setState({
-          data: '',
-          loading: false
-        })
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
+        MKEmitter.emit('transferSyncData', MenuID)
+
+        if (!result.message) return
+        if (result.ErrCode === 'N') {
+          Modal.error({
+            title: result.message,
+          })
+        } else if (result.ErrCode !== '-2') {
+          notification.error({
+            top: 92,
+            message: result.message,
+            duration: 10
+          })
+        }
       }
     })
   }
@@ -1129,9 +1255,9 @@
   }
 
   resetActiveMenu = (menuId) => {
-    const { MenuID, Tab } = this.props
+    const { MenuID } = this.props
 
-    if (MenuID !== menuId || Tab) return
+    if (MenuID !== menuId) return
 
     this.setShortcut()
   }
@@ -1209,8 +1335,13 @@
         })
       } else if (item.type === 'group') {
         this.deleteCache(item.components)
+      } else if (item.type === 'search') {
+        window.GLOB.SearchBox.delete(item.$searchId)
       } else {
         window.GLOB.CacheData.delete(item.uuid)
+      }
+      if (item.dataName) {
+        window.GLOB.SyncData.delete(item.dataName)
       }
     })
   }
@@ -1233,21 +1364,14 @@
       viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
       config: null,         // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷粍浠剁瓑
       loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
-      shortcuts: null,
-      data: ''
+      shortcuts: null
     }, () => {
       this.loadconfig()
     })
   }
 
-  resetSearch = (search) => {
-    this.setState({mainSearch: null}, () => {
-      this.setState({mainSearch: search})
-    })
-  }
-
   getComponents = () => {
-    const { config, BID, data, mainSearch, loadinginter } = this.state
+    const { config, BID, loadinginter } = this.state
 
     if (!config || !config.components || loadinginter) return
 
@@ -1256,156 +1380,170 @@
 
       if (item.style && item.style.clear === 'left') {
         style = {clear: 'left'}
+      } else if (item.style && item.style.clear === 'right') {
+        style = {float: 'right'}
       }
 
       if (item.type === 'card' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DataCard config={item} data={data} mainSearch={mainSearch}/>
+            <DataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'propcard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <PropCard config={item} data={data} mainSearch={mainSearch}/>
+            <PropCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'dualdatacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DoubleDataCard config={item} mainSearch={mainSearch}/>
+            <DoubleDataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'normaltable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTable config={item} data={data} mainSearch={mainSearch}/>
+            <NormalTable config={item}/>
           </Col>
         )
       } else if (item.type === 'bar' || item.type === 'line') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvBarAndLine config={item} data={data} mainSearch={mainSearch}/>
+            <AntvBarAndLine config={item}/>
           </Col>
         )
       } else if (item.type === 'pie') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvPie config={item} data={data} mainSearch={mainSearch}/>
+            <AntvPie config={item}/>
           </Col>
         )
       } else if (item.type === 'scatter') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvScatter config={item} data={data} mainSearch={mainSearch}/>
+            <AntvScatter config={item}/>
           </Col>
         )
       } else if (item.type === 'dashboard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvDashboard config={item} data={data} mainSearch={mainSearch}/>
+            <AntvDashboard config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'simpleform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <SimpleForm config={item} data={data} mainSearch={mainSearch}/>
+            <SimpleForm config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'stepform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <StepForm config={item} data={data} mainSearch={mainSearch}/>
+            <StepForm config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'tabform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TabForm config={item} data={data} mainSearch={mainSearch}/>
+            <TabForm config={item}/>
           </Col>
         )
       } else if (item.type === 'search') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <MainSearch config={item} BID={BID} refreshdata={this.resetSearch} />
+            <MainSearch config={item} BID={BID}/>
           </Col>
         )
       } else if (item.type === 'tabs') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvTabs config={item} mainSearch={mainSearch} />
+            <AntvTabs config={item}/>
           </Col>
         )
       } else if (item.type === 'balcony') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <Balcony config={item} data={data}/>
+            <Balcony config={item}/>
           </Col>
         )
       } else if (item.type === 'timeline') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TimeLine config={item} data={data} mainSearch={mainSearch}/>
+            <TimeLine config={item}/>
           </Col>
         )
       } else if (item.type === 'carousel' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselDataCard config={item} data={data} mainSearch={mainSearch}/>
+            <CarouselDataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'carousel' && item.subtype === 'propcard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselPropCard config={item} data={data} mainSearch={mainSearch}/>
+            <CarouselPropCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'tablecard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TableCard config={item} data={data} mainSearch={mainSearch}/>
+            <TableCard config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'editable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <EditTable config={item} mainSearch={mainSearch}/>
+            <EditTable config={item}/>
           </Col>
         )
       } else if (item.type === 'group' && item.subtype === 'normalgroup') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalGroup config={item} mainSearch={mainSearch}/>
+            <NormalGroup config={item}/>
           </Col>
         )
       } else if (item.type === 'editor') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <BraftEditor config={item} data={data} mainSearch={mainSearch}/>
+            <BraftEditor config={item}/>
           </Col>
         )
       } else if (item.type === 'tree') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
+            <NormalTree config={item}/>
+          </Col>
+        )
+      } else if (item.type === 'calendar') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <Calendar config={item}/>
           </Col>
         )
       } else if (item.type === 'code') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <SandBox config={item} data={data} mainSearch={mainSearch}/>
+            <SandBox config={item}/>
           </Col>
         )
       } else if (item.type === 'chart') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CustomChart config={item} data={data} mainSearch={mainSearch}/>
+            <CustomChart config={item}/>
           </Col>
         )
       } else if (item.type === 'antvG6') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvG6 config={item} data={data} mainSearch={mainSearch}/>
+            <AntvG6 config={item}/>
+          </Col>
+        )
+      } else if (item.type === 'antvX6') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <AntvX6 config={item}/>
           </Col>
         )
       } else if (item.type === 'module' && item.subtype === 'voucher') {
@@ -1423,7 +1561,7 @@
       } else if (item.type === 'iframe') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <Iframe config={item} data={data} mainSearch={mainSearch}/>
+            <Iframe config={item}/>
           </Col>
         )
       } else {
@@ -1436,13 +1574,13 @@
     const { loadingview, viewlost, config, loading, shortcuts, BID } = this.state
 
     return (
-      <div className={`custom-page-wrap ${config && config.minWidth ? 'mk-scroll' : ''} ${loadingview || loading ? 'loading' : ''}`} id={this.state.ContainerId} style={config ? config.style : null}>
+      <div className={`custom-page-wrap ${config && config.minWidth ? 'mk-scroll' : ''} ${loadingview || loading ? 'loading' : ''} ${config && config.mask === 'false' ? 'mk-no-mask' : ''}`} id={this.state.ContainerId} style={config ? config.style : null}>
         {(loadingview || (loading && !config.$cache)) ? <Spin className="view-spin" size="large" /> : null}
         <Row id={config ? 'menu' + config.uuid : ''} style={config && config.minWidth ? {minWidth: config.minWidth} : null} className="component-wrap">{this.getComponents()}</Row>
         {config && config.interfaces.length > 0 ? <MkInterfaces BID={BID} interfaces={config.interfaces}/> : null}
         {config && window.GLOB.breakpoint ? <DebugTable /> : null}
         {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <TableNodes config={config} /> : null}
-        {!window.GLOB.mkHS && config ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts || []}/> : null}
+        {!window.GLOB.mkHS && config ? <SettingComponent config={config} shortcuts={shortcuts || []}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
     )
diff --git a/src/tabviews/custom/index.scss b/src/tabviews/custom/index.scss
index 2c2a5fe..ede42fb 100644
--- a/src/tabviews/custom/index.scss
+++ b/src/tabviews/custom/index.scss
@@ -49,6 +49,18 @@
     display: none;
   }
 }
+.custom-page-wrap.mk-no-mask {
+  .loading-mask {
+    max-height: 80vh;
+  }
+  .ant-spin-blur {
+    background: transparent!important;
+    opacity: 1;
+  }
+  .ant-spin-blur::after {
+    opacity: 0;
+  }
+}
 .custom-page-wrap.mk-scroll {
   height: calc(100vh - 93px);
   overflow: auto;
diff --git a/src/tabviews/custom/popview/index.jsx b/src/tabviews/custom/popview/index.jsx
index 0093459..7463f80 100644
--- a/src/tabviews/custom/popview/index.jsx
+++ b/src/tabviews/custom/popview/index.jsx
@@ -1,13 +1,12 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { notification, Spin, Row, Col } from 'antd'
+import { notification, Spin, Row, Col, Modal } from 'antd'
 
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import Utils from '@/utils/utils.js'
 import { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js'
+import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import NotFount from '@/components/404'
 import './index.scss'
@@ -40,7 +39,9 @@
 const TimeLine = asyncComponent(() => import('../components/timeline/normal-timeline'))
 const Voucher = asyncComponent(() => import('../components/module/voucher'))
 const Iframe = asyncComponent(() => import('../components/iframe'))
+const Calendar = asyncComponent(() => import('../components/calendar'))
 const AntvG6 = asyncComponent(() => import('../components/chart/antv-G6'))
+const AntvX6 = asyncComponent(() => import('../components/chart/antv-X6'))
 
 class CustomPage extends Component {
   static propTpyes = {
@@ -49,13 +50,10 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     BID: '',              // 椤甸潰璺宠浆鏃舵惡甯D
     viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
     lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
     config: null,         // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷粍浠剁瓑
-    mainSearch: null,     // 涓绘悳绱�
-    data: null,           // 鍒楄〃鏁版嵁闆�
     loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
   }
 
@@ -90,7 +88,7 @@
     if (!config.enabled) {
       this.setState({
         viewlost: true,
-        lostmsg: this.state.dict['main.view.unenabled']
+        lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
       })
       return
     }
@@ -113,11 +111,6 @@
     let userName = sessionStorage.getItem('User_Name') || ''
     let fullName = sessionStorage.getItem('Full_Name') || ''
 
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
-
     let regs = [
       { reg: /@userName@/ig, value: `'${userName}'` },
       { reg: /@fullName@/ig, value: `'${fullName}'` }
@@ -130,38 +123,35 @@
       })
     }
 
-    config.$cache = config.cacheLocal === 'true'
-
-    config.components = this.filterComponent(config.components, roleId, balMap, param, Tab, config.$cache)
+    config.components = this.filterComponent(config.components, roleId, balMap, param, Tab, Tab.uuid, Tab.uuid)
     
     // 鑾峰彇涓绘悳绱㈡潯浠�
-    let mainSearch = []
     config.components.forEach(component => {
       if (component.type !== 'search') return
 
-      component.search = component.search.map(item => {
-        item.oriInitval = item.initval
-        if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
-          item.initval = param.$searchval
-        }
+      if (param.$searchkey) {
+        component.search = component.search.map(item => {
+          if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
+            item.initval = param.$searchval
+          }
 
-        return item
-      })
+          return item
+        })
 
-      mainSearch = Utils.initMainSearch(component.search)
+        component.$searches = Utils.initMainSearch(component.search)
+      }
+
+      window.GLOB.SearchBox.set(Tab.uuid, component.$searches)
+
+      if (component.$s_req) {
+        window.GLOB.SearchBox.set(Tab.uuid + 'required', true)
+      }
     })
 
     let params = []
     let BID = param.$BID || ''
-    let inherit = {}
 
-    if (config.cacheUseful === 'true') { // 缂撳瓨缁ф壙
-      inherit.cacheUseful = config.cacheUseful
-      inherit.timeUnit = config.timeUnit
-      inherit.cacheTime = config.cacheTime
-    }
-
-    config.components = this.formatSetting(config.components, params, mainSearch, inherit, regs, balMap)
+    config.components = this.formatSetting(config.components, params, regs, balMap)
 
     if ([...balMap.keys()].length > 0) {
       config.components = this.filterBalcony(config.components, balMap)
@@ -169,8 +159,7 @@
 
     this.setState({
       BID: BID,
-      config,
-      mainSearch
+      config
     }, () => {
       if (params.length > 0) {
         this.loadmaindata(params)
@@ -178,10 +167,11 @@
     })
   }
 
-  filterComponent = (components, roleId, balMap, urlparam, Tab, cache) => {
+  filterComponent = (components, roleId, balMap, urlparam, Tab, searchId, syncId) => {
     return components.filter(item => {
       item.$pageId = Tab.uuid
-      item.$cache = cache
+      item.$searchId = searchId
+      item.$syncId = syncId
       
       if (item.style && item.style.boxShadow) {
         delete item.style.hShadow
@@ -200,6 +190,13 @@
           return false
         }
 
+        if (item.setting.supModule) {
+          let pid = item.setting.supModule.pop()
+          item.setting.supModule = pid || ''
+        } else {
+          item.setting.supModule = ''
+        }
+
         item.subtabs = item.subtabs.filter(tab => {
           if (
             tab.blacklist && tab.blacklist.length > 0 &&
@@ -209,35 +206,37 @@
           } else if (tab.hide === 'true') {
             return false
           }
+
+          if (item.setting.supModule) {
+            if (tab.controlVal === '@pass@') {
+              tab.$pass = true
+            } else if (/,/ig.test(tab.controlVal)) {
+              tab.controlVals = tab.controlVal.split(',')
+            } else {
+              tab.controlVals = [(tab.controlVal || '')]
+            }
+          }
+
           return true
         })
 
         if (item.setting.supModule) {
-          let pid = item.setting.supModule.pop()
-          item.setting.supModule = pid || ''
+          item.setting.controlField = item.setting.controlField.toLowerCase()
 
-          if (item.setting.supModule) {
-            item.setting.controlField = item.setting.controlField.toLowerCase()
-  
-            if (item.setting.supModule === 'preview') {
-              item.setting.supModule = ''
-              let val = ''
-              Object.keys(urlparam).forEach(key => {
-                if (key.toLowerCase() === item.setting.controlField) {
-                  val = urlparam[key]
-                }
-              })
-  
-              item.subtabs = item.subtabs.filter(tab => {
-                if (tab.controlVal === val) {
-                  return false
-                } else if (/,/ig.test(tab.controlVal)) {
-                  return !tab.controlVal.split(',').includes(val)
-                }
-      
-                return true
-              })
-            }
+          if (item.setting.supModule === 'preview') {
+            item.setting.supModule = ''
+            let val = ''
+            Object.keys(urlparam).forEach(key => {
+              if (key.toLowerCase() === item.setting.controlField) {
+                val = urlparam[key]
+              }
+            })
+
+            item.subtabs = item.subtabs.filter(tab => {
+              if (tab.$pass) return true
+    
+              return !tab.controlVals.includes(val)
+            })
           }
         }
 
@@ -265,7 +264,24 @@
         item.subtabs = item.subtabs.map(tab => {
           tab.$pageId = Tab.uuid
 
-          tab.components = this.filterComponent(tab.components, roleId, balMap, urlparam, Tab, cache)
+          let _searchId = searchId
+
+          if (tab.components.findIndex(cell => cell.type === 'search') > -1) {
+            _searchId = tab.uuid
+          }
+
+          tab.components = this.filterComponent(tab.components, roleId, balMap, urlparam, Tab, _searchId, tab.uuid)
+
+          if (_searchId === tab.uuid) {
+            tab.components.forEach(cell => {
+              if (cell.type !== 'search') return
+              window.GLOB.SearchBox.set(_searchId, cell.$searches)
+              if (cell.$s_req) {
+                window.GLOB.SearchBox.set(_searchId + 'required', true)
+              }
+            })
+          }
+
           return tab
         })
 
@@ -278,7 +294,7 @@
           return false
         }
 
-        item.components = this.filterComponent(item.components, roleId, balMap, urlparam, Tab, cache)
+        item.components = this.filterComponent(item.components, roleId, balMap, urlparam, Tab, searchId, syncId)
 
         return true
       } else if (['pie', 'bar', 'line', 'dashboard', 'scatter', 'chart'].includes(item.type)) {
@@ -298,8 +314,10 @@
       }
 
       // 鎼滅储鏉′欢鍒濆鍖�
-      if (item.search && item.search.length > 0) {
-        item.search = Utils.initSearchVal(item.search)
+      if (item.search) {
+        Utils.initSearchVal(item)
+
+        item.$searches = Utils.initMainSearch(item.search)
       }
 
       if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
@@ -326,7 +344,6 @@
       }
 
       if (item.type === 'table') {
-        let statFields = []
         let getCols = (cols) => {
           return cols.filter(col => {
             if (col.blacklist && col.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0) {
@@ -338,9 +355,6 @@
             }
             
             if (col.type === 'number') {
-              if (col.sum === 'true' && !statFields.includes(col.field)) {
-                statFields.push(col)
-              }
               if (typeof(col.decimal) === 'number') {
                 col.round = Math.pow(10, col.decimal)
                 if (col.format === 'percent') {
@@ -386,7 +400,6 @@
         }
         
         item.cols = getCols(item.cols)
-        item.statFields = statFields
 
         if (item.subtype === 'editable') {
           item.submit.logLabel = item.$menuname + '-鎻愪氦'
@@ -486,6 +499,7 @@
           group.subButton.OpenType = 'formSubmit'
           group.subButton.execError = 'never'
           group.subButton.logLabel = item.$menuname + '-' + group.subButton.label
+          group.subButton.$tabId = Tab.uuid
 
           if (!group.subButton.Ot) {
             group.subButton.Ot = item.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
@@ -585,6 +599,20 @@
       }
     }
 
+    if (cell.OpenType === 'excelOut') { // 瀵煎嚭
+      cell.$menuName = item.name
+
+      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
+        cell.errorType = 'error1'
+      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom') {
+        if (item.setting.interType !== 'system') {
+          cell.errorType = 'error2'
+        } else if (item.type === 'balcony' || item.subtype === 'propcard') {
+          cell.errorType = 'error2'
+        }
+      }
+    }
+
     if (cell.syncComponentId) {
       if (cell.syncComponentId === item.setting.supModule) {
         cell.syncComponentId = ''
@@ -616,6 +644,11 @@
 
   resetElement = (cell) => {
     cell.style = cell.style || {}
+
+    if (cell.style.display === 'inline-block') {
+      cell.style.verticalAlign = 'top'
+    }
+
     if (['text', 'number', 'formula'].includes(cell.eleType)) {
       if (!cell.height) {
         cell.innerHeight = 'auto'
@@ -670,35 +703,43 @@
   }
 
   // 鏍煎紡鍖栭粯璁よ缃�
-  formatSetting = (components, params, mainSearch, inherit, regs, balMap) => {
+  formatSetting = (components, params, regs, balMap) => {
     let delay = 20
     return components.map(component => {
       if (component.type === 'tabs') {
         component.subtabs = component.subtabs.map(tab => {
-          tab.components = this.formatSetting(tab.components, null, null, inherit, regs, balMap)
-          tab = {...tab, ...inherit}
+          tab.components = this.formatSetting(tab.components, null, regs, balMap)
           return tab
         })
         return component
       } else if (component.type === 'group') {
-        component.components = this.formatSetting(component.components, null, null, inherit, regs, balMap)
-        component = {...component, ...inherit}
+        component.components = this.formatSetting(component.components, params, regs, balMap)
         return component
       } else if (component.wrap && component.wrap.datatype === 'public') {
         component.setting.useMSearch = false
+        component.setting.sync = 'false'
 
         return component
       } else if (component.wrap && component.wrap.datatype === 'static') {
         component.format = ''
         component.setting = component.setting || {}
         component.setting.useMSearch = false
+        component.setting.sync = 'false'
 
         return component
       } else if (!component.setting || !component.format) {
         return component
       }
 
+      component.setting.arr_field = component.columns ? component.columns.map(col => col.field).join(',') : ''
       component.setting.useMSearch = component.setting.useMSearch === 'true'
+      if (component.setting.useMSearch) {
+        if (!window.GLOB.SearchBox.has(component.$searchId)) {
+          component.setting.useMSearch = false
+        } else if (window.GLOB.SearchBox.has(component.$searchId + 'required')) {
+          component.$s_req = true
+        }
+      }
 
       if (component.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
         component.setting.sync = 'false'
@@ -707,9 +748,15 @@
       }
 
       let _customScript = ''
+      let _tailScript = ''
       component.scripts && component.scripts.forEach(script => {
-        if (script.status !== 'false') {
+        if (script.status === 'false') return
+        if (script.position !== 'back') {
           _customScript += `
+          ${script.sql}
+          `
+        } else {
+          _tailScript += `
           ${script.sql}
           `
         }
@@ -727,51 +774,63 @@
       }
   
       if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        component.setting.dataresource = component.setting.dataresource.replace(/@\$/ig, '*/')
-        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-        _customScript = _customScript.replace(/@\$/ig, '*/')
+        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
       } else {
         component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
         _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
       }
 
       regs.forEach(cell => {
         component.setting.dataresource = component.setting.dataresource.replace(cell.reg, cell.value)
         _customScript = _customScript.replace(cell.reg, cell.value)
+        _tailScript = _tailScript.replace(cell.reg, cell.value)
       })
 
       component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+      component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
+
+      component.setting.custompage = /@pageSize@|@orderBy@/i.test(component.setting.dataresource + component.setting.customScript)
+
+      if (!component.setting.execute || component.setting.custompage) {
+        component.forbidLine = true
+      }
+
+      if (component.setting.sync === 'true') {
+        // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
+        if ((!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true') {
+
+        } else {
+          component.setting.sync = 'false'
+        }
+      }
 
       // dataName 绯荤粺鐢熸垚鐨勬暟鎹簮鍚嶇О
       if (component.setting.sync === 'true') {
         component.dataName = 'mk' + component.uuid.slice(-18)
-      }
 
-      // floor    缁勪欢鐨勫眰绾�
-      // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
-      if (params && (!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true' && component.setting.sync === 'true') {
-        let searchlist = []
-        if (component.search && component.search.length > 0) {
-          searchlist = Utils.initMainSearch(component.search)
-        }
-        if (component.setting.useMSearch) {
-          let keys = searchlist.map(item => item.key)
-          mainSearch.forEach(item => {
-            if (!keys.includes(item.key)) {
+        if (params) {
+          let searchlist = component.$searches || []
+  
+          if (component.setting.useMSearch) {
+            let mainSearch = window.GLOB.SearchBox.get(component.$searchId)
+            let keys = component.$s_keys || []
+            mainSearch.forEach(item => {
+              if (keys.includes(item.key.toLowerCase())) return
+  
               searchlist.push(item)
-            }
-          })
+            })
+          }
+  
+          if (component.$s_req && searchlist.filter(item => item.required && item.value === '').length > 0) {
+            component.setting.sync = 'false'
+            component.setting.onload = 'false'
+          } else {
+            params.push(getStructDefaultParam(component, searchlist, params.length === 0))
+          }
         }
-
-        if (searchlist.filter(item => item.required && item.value === '').length > 0) {
-          component.setting.sync = 'false'
-          component.setting.onload = 'false'
-        } else {
-          params.push(getStructDefaultParam(component, searchlist, params.length === 0))
-        }
-      } else if (params) {
-        component.setting.sync = 'false'
       }
 
       component.setting.delay = delay
@@ -790,42 +849,56 @@
    * @description 涓昏〃鏁版嵁鍔犺浇
    */ 
   loadmaindata = (params) => {
+    const { Tab } = this.props
     const { config } = this.state
     let param = getStructuredParams(params, config, this.state.BID || '')
 
     this.setState({loading: true})
 
     Api.genericInterface(param).then(result => {
-      if (result.status) {
-        delete result.status
-        delete result.message
-        delete result.ErrMesg
-        delete result.ErrCode
+      this.setState({
+        loading: false
+      })
 
-        if (config.$cache) {
-          params.forEach((item) => {
-            let _data = result[item.name] || ''
-            if (_data && !Array.isArray(_data)) {
-              _data = [_data]
-            }
-            Api.writeCacheConfig(item.uuid, _data)
-          })
+      if (result.status) {
+        if (result.message) {
+          if (result.ErrCode === 'Y') {
+            Modal.success({
+              title: result.message
+            })
+          } else if (result.ErrCode === 'S') {
+            notification.success({
+              top: 92,
+              message: result.message,
+              duration: 2
+            })
+          }
         }
 
-        this.setState({
-          data: result,
-          loading: false
+        params.forEach((item) => {
+          let _data = result[item.name] || ''
+          if (_data && !Array.isArray(_data)) {
+            _data = [_data]
+          }
+          window.GLOB.SyncData.set(item.name, _data)
         })
+
+        MKEmitter.emit('transferSyncData', Tab.uuid)
       } else {
-        this.setState({
-          data: '',
-          loading: false
-        })
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
+        MKEmitter.emit('transferSyncData', Tab.uuid)
+
+        if (!result.message) return
+        if (result.ErrCode === 'N') {
+          Modal.error({
+            title: result.message,
+          })
+        } else if (result.ErrCode !== '-2') {
+          notification.error({
+            top: 92,
+            message: result.message,
+            duration: 10
+          })
+        }
       }
     })
   }
@@ -861,20 +934,20 @@
         })
       } else if (item.type === 'group') {
         this.deleteCache(item.components)
+      } else if (item.type === 'search') {
+        window.GLOB.SearchBox.delete(item.$searchId)
       } else {
         window.GLOB.CacheData.delete(item.uuid)
+      }
+
+      if (item.dataName) {
+        window.GLOB.SyncData.delete(item.dataName)
       }
     })
   }
 
-  resetSearch = (search) => {
-    this.setState({mainSearch: null}, () => {
-      this.setState({mainSearch: search})
-    })
-  }
-
   getComponents = () => {
-    const { config, BID, data, mainSearch } = this.state
+    const { config, BID } = this.state
 
     if (!config) return
 
@@ -883,24 +956,26 @@
 
       if (item.style && item.style.clear === 'left') {
         style = {clear: 'left'}
+      } else if (item.style && item.style.clear === 'right') {
+        style = {float: 'right'}
       }
 
       if (item.type === 'card' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DataCard config={item} data={data} mainSearch={mainSearch}/>
+            <DataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'propcard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <PropCard config={item} data={data} mainSearch={mainSearch}/>
+            <PropCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'dualdatacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DoubleDataCard config={item} mainSearch={mainSearch}/>
+            <DoubleDataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'basetable') {
@@ -912,127 +987,133 @@
       } else if (item.type === 'bar' || item.type === 'line') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvBarAndLine config={item} data={data} mainSearch={mainSearch}/>
+            <AntvBarAndLine config={item}/>
           </Col>
         )
       } else if (item.type === 'pie') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvPie config={item} data={data} mainSearch={mainSearch}/>
+            <AntvPie config={item}/>
           </Col>
         )
       } else if (item.type === 'scatter') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvScatter config={item} data={data} mainSearch={mainSearch}/>
+            <AntvScatter config={item}/>
           </Col>
         )
       } else if (item.type === 'dashboard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvDashboard config={item} data={data} mainSearch={mainSearch}/>
+            <AntvDashboard config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'simpleform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <SimpleForm config={item} data={data} mainSearch={mainSearch}/>
+            <SimpleForm config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'stepform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <StepForm config={item} data={data} mainSearch={mainSearch}/>
+            <StepForm config={item}/>
           </Col>
         )
       } else if (item.type === 'form' && item.subtype === 'tabform') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TabForm config={item} data={data} mainSearch={mainSearch}/>
+            <TabForm config={item}/>
           </Col>
         )
       } else if (item.type === 'search') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <MainSearch config={item} BID={BID} refreshdata={this.resetSearch} />
+            <MainSearch config={item} BID={BID} />
           </Col>
         )
       } else if (item.type === 'tabs') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvTabs config={item} mainSearch={mainSearch} />
+            <AntvTabs config={item}/>
           </Col>
         )
       } else if (item.type === 'balcony') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <Balcony config={item} data={data}/>
+            <Balcony config={item}/>
           </Col>
         )
       } else if (item.type === 'timeline') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TimeLine config={item} data={data} mainSearch={mainSearch}/>
+            <TimeLine config={item}/>
           </Col>
         )
       } else if (item.type === 'carousel' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselDataCard config={item} data={data} mainSearch={mainSearch}/>
+            <CarouselDataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'carousel' && item.subtype === 'propcard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CarouselPropCard config={item} data={data} mainSearch={mainSearch}/>
+            <CarouselPropCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'tablecard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TableCard config={item} data={data} mainSearch={mainSearch}/>
+            <TableCard config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'normaltable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTable config={item} data={data} mainSearch={mainSearch}/>
+            <NormalTable config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'editable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <EditTable config={item} mainSearch={mainSearch}/>
+            <EditTable config={item}/>
           </Col>
         )
       } else if (item.type === 'group' && item.subtype === 'normalgroup') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalGroup config={item} mainSearch={mainSearch}/>
+            <NormalGroup config={item}/>
           </Col>
         )
       } else if (item.type === 'editor') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <BraftEditor config={item} data={data} mainSearch={mainSearch}/>
+            <BraftEditor config={item}/>
           </Col>
         )
       } else if (item.type === 'tree') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
+            <NormalTree config={item}/>
+          </Col>
+        )
+      } else if (item.type === 'calendar') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <Calendar config={item}/>
           </Col>
         )
       } else if (item.type === 'code') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <SandBox config={item} data={data} mainSearch={mainSearch}/>
+            <SandBox config={item}/>
           </Col>
         )
       } else if (item.type === 'chart') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <CustomChart config={item} data={data} mainSearch={mainSearch}/>
+            <CustomChart config={item}/>
           </Col>
         )
       } else if (item.type === 'module' && item.subtype === 'voucher') {
@@ -1044,13 +1125,19 @@
       } else if (item.type === 'iframe') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <Iframe config={item} data={data} mainSearch={mainSearch}/>
+            <Iframe config={item}/>
           </Col>
         )
       } else if (item.type === 'antvG6') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvG6 config={item} data={data} mainSearch={mainSearch}/>
+            <AntvG6 config={item}/>
+          </Col>
+        )
+      } else if (item.type === 'antvX6') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <AntvX6 config={item}/>
           </Col>
         )
       } else {
@@ -1064,7 +1151,7 @@
 
     return (
       <div className={'pop-page-wrap ' + (loading ? 'loading' : '')} style={config ? config.style : null}>
-        {loading && !config.$cache ? <Spin className="view-spin" size="large" /> : null}
+        {loading ? <Spin className="view-spin" size="large" /> : null}
         <Row className="component-wrap">{this.getComponents()}</Row>
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
diff --git a/src/tabviews/debugtable/index.jsx b/src/tabviews/debugtable/index.jsx
index afcae04..9f52daa 100644
--- a/src/tabviews/debugtable/index.jsx
+++ b/src/tabviews/debugtable/index.jsx
@@ -27,22 +27,22 @@
       interType: 'system',
       execute: true,
       laypage: true,
-      dataresource: '(select * from s_debug_value_log where createuserid=@userid@) tb'
-    },
-    arr_field: 'ID,Sort,CDefine1,CDefine2,CDefine3,CDefine4,CDefine5,CDefine6,CDefine7,createdate'
+      dataresource: '(select * from s_debug_value_log where createuserid=@userid@) tb',
+      arr_field: 'ID,Sort,CDefine1,CDefine2,CDefine3,CDefine4,CDefine5,CDefine6,CDefine7,createdate'
+    }
   }
 
   /**
    * @description 瀛愯〃鏁版嵁鍔犺浇
    */
   async loadmaindata () {
-    const { setting, arr_field } = this.state
+    const { setting } = this.state
 
     this.setState({
       loading: true
     })
 
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, [], 'sort', 1, 50, '')
+    let param = UtilsDM.getQueryDataParams(setting, [], 'sort', 1, 50, '')
 
     let result = await Api.genericInterface(param)
 
diff --git a/src/tabviews/formtab/actionList/index.jsx b/src/tabviews/formtab/actionList/index.jsx
deleted file mode 100644
index 9b97235..0000000
--- a/src/tabviews/formtab/actionList/index.jsx
+++ /dev/null
@@ -1,368 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import moment from 'moment'
-import { Button, Modal, notification, message } from 'antd'
-import Utils, { getSysDefaultSql } from '@/utils/utils.js'
-import options from '@/store/options.js'
-import Api from '@/api'
-import './index.scss'
-
-const { confirm } = Modal
-
-class MainAction extends Component {
-  static propTpyes = {
-    MenuID: PropTypes.string,      // 鑿滃崟ID
-    primaryId: PropTypes.string,   // 涓婚敭
-    actions: PropTypes.array,      // 鎸夐挳缁�
-    dict: PropTypes.object,        // 瀛楀吀椤�
-    data: PropTypes.any,           // 鏁版嵁
-    setting: PropTypes.any,        // 椤甸潰閫氱敤璁剧疆
-    getFormData: PropTypes.func,   // 鑾峰彇琛ㄥ崟鍊�
-    refreshdata: PropTypes.func,   // 鎵ц瀹屾垚鍚庢暟鎹埛鏂�
-  }
-
-  state = {
-    formdata: null,
-    loadingUuid: ''
-  }
-  
-  /**
-   * @description 瑙﹀彂鎸夐挳鎿嶄綔
-   */
-  actionTrigger = (item) => {
-    const { data } = this.props
-    let _this = this
-
-    if (item.btnType !== 'cancel') {
-      this.props.getFormData().then(res => {
-        if (item.OpenType === 'prompt') {
-          confirm({
-            title: this.props.dict['main.action.confirm.tip'],
-            onOk() {
-              return new Promise(resolve => {
-                _this.execSubmit(item, data, resolve, res)
-              })
-            },
-            onCancel() {}
-          })
-        } else if (item.OpenType === 'exec') {
-          this.setState({loadingUuid: item.uuid})
-
-          this.execSubmit(item, data, () => {
-            this.setState({loadingUuid: ''})
-          }, res)
-        }
-      })
-    } else {
-      item.afterExecSuccess = 'close'
-      this.props.refreshdata(item, 'success', '')
-    }
-  }
-
-  /**
-   * @description 鎸夐挳鎻愪氦鎵ц
-   */
-  execSubmit = (btn, data, _resolve, formdata) => {
-    const { setting, primaryId } = this.props
-
-    let _primaryId = primaryId
-
-    if (btn.intertype === 'inner') {
-      let param = { // 绯荤粺瀛樺偍杩囩▼
-        func: btn.innerFunc,
-        BID: ''
-      }
-
-      param[setting.primaryKey] = primaryId
-
-      formdata.forEach(_data => {
-        param[_data.key] = _data.value
-      })
-
-      if (!param[setting.primaryKey]) {
-        param[setting.primaryKey] = Utils.getguid()
-      }
-
-      _primaryId = param[setting.primaryKey]
-
-      Api.genericInterface(param).then((res) => {
-        if (res.status) {
-          this.execSuccess(btn, res, _primaryId, formdata)
-        } else {
-          this.execError(res, btn)
-        }
-        _resolve()
-      })
-    } else if (btn.intertype === 'system') {
-      // 浣跨敤绯荤粺鎺ュ彛鏃讹紝鏁版嵁婧愪笉鍙负绌�, 浣跨敤绯荤粺鍑芥暟鏃讹紝绫诲瀷涓嶅彲涓虹┖
-      if (!btn.sql || !btn.sqlType) {
-        this.actionSettingError()
-        _resolve()
-        return
-      }
-
-      // 鍒涘缓鍑瘉鏃讹紝闇�瑕侀�夋嫨琛屾椂
-      if (!data && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤鍒涘缓鍑瘉鍑芥暟锛岄渶瑕侀�夋嫨琛岋紒',
-          duration: 5
-        })
-        return
-      }
-
-      let param = { // 绯荤粺瀛樺偍杩囩▼
-        func: 'sPC_TableData_InUpDe',
-        exec_type: 'y', // 鍚庡彴瑙g爜
-        BID: ''
-      }
-
-      if (btn.sql && btn.sqlType === 'insert') { // 绯荤粺鍑芥暟娣诲姞鏃讹紝鐢熸垚uuid
-        param.ID = Utils.getguid()
-        param.LText = getSysDefaultSql(btn, setting, formdata, param, data, []) // 鏁版嵁婧�
-        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.secretkey = Utils.encrypt('', param.timestamp)
-        param.LText = Utils.formatOptions(param.LText)
-
-        _primaryId = param.ID
-      } else if (btn.sql && btn.sqlType === 'insertOrUpdate') { // 绯荤粺鍑芥暟娣诲姞鎴栦慨鏀规椂
-        param.ID = primaryId || Utils.getguid()
-        param.LText = getSysDefaultSql(btn, setting, formdata, param, data, []) // 鏁版嵁婧�
-        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.secretkey = Utils.encrypt('', param.timestamp)
-        param.LText = Utils.formatOptions(param.LText)
-
-        _primaryId = param.ID
-      } else if (btn.sql) {
-        param.ID = primaryId
-        param.LText = getSysDefaultSql(btn, setting, formdata, param, data, []) // 鏁版嵁婧�
-        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.secretkey = Utils.encrypt('', param.timestamp)
-        param.LText = Utils.formatOptions(param.LText)
-      }
-
-      if (window.GLOB.mkHS && param.timestamp) { // 浜戠楠岃瘉
-        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
-      }
-
-      Api.genericInterface(param).then((res) => {
-        if (res.status) {
-          this.execSuccess(btn, res, _primaryId, formdata)
-        } else {
-          this.execError(res, btn)
-        }
-        _resolve()
-      })
-    } else if (btn.intertype === 'outer') {
-      /** *********************璋冪敤澶栭儴鎺ュ彛************************* */
-
-      if (!btn.interface) { // 鎺ュ彛鍦板潃涓嶅瓨鍦ㄦ椂鎶ラ敊
-        this.actionSettingError()
-        _resolve()
-        return
-      }
-
-      let param = {
-        BID: ''
-      }
-
-      param[setting.primaryKey] = primaryId
-
-      formdata.forEach(_data => {
-        param[_data.key] = _data.value
-      })
-
-      if (!param[setting.primaryKey]) {
-        param[setting.primaryKey] = Utils.getguid()
-      }
-      _primaryId = param[setting.primaryKey]
-
-      let _outParam = null
-  
-      new Promise(resolve => {
-        // 鍐呴儴璇锋眰
-        if (btn.innerFunc) {
-          param.func = btn.innerFunc
-          // 瀛樺湪鍐呴儴鍑芥暟鏃讹紝鏁版嵁棰勫鐞�
-          Api.genericInterface(param).then(res => {
-            if (res.status) {
-              delete res.ErrCode
-              delete res.ErrMesg
-              delete res.message
-              delete res.status
-  
-              // 浣跨敤澶勭悊鍚庣殑鏁版嵁璋冪敤澶栭儴鎺ュ彛
-              resolve(res)
-            } else {
-              this.execError(res, btn)
-              resolve(false)
-              _resolve()
-            }
-          })
-        } else {
-          resolve(param)
-        }
-      }).then(res => {
-        if (!res) return
-        // 澶栭儴璇锋眰
-        _outParam = JSON.parse(JSON.stringify(res))
-  
-        if (window.GLOB.mkHS) {
-          if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-            res.rduri = options.cloudServiceApi
-            res.userid = sessionStorage.getItem('CloudUserID') || ''
-            res.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
-          } else if (btn.sysInterface !== 'true') {
-            res.rduri = btn.interface
-          }
-        } else {
-          if (btn.sysInterface === 'true' && window.GLOB.mainSystemApi) {
-            res.rduri = window.GLOB.mainSystemApi
-          } else if (btn.sysInterface !== 'true') {
-            res.rduri = btn.interface
-          }
-        }
-
-        if (btn.outerFunc) {
-          res.func = btn.outerFunc
-        }
-  
-        return Api.genericInterface(res)
-      }).then(response => {
-        if (!response) return
-        // 鍥炶皟璇锋眰
-        if (btn.callbackFunc) {
-          // 瀛樺湪鍥炶皟鍑芥暟鏃讹紝璋冪敤
-          delete response.message
-          delete response.status
-  
-          response.func = btn.callbackFunc
-  
-          let _callbackparam = {..._outParam, ...response}
-          return Api.genericInterface(_callbackparam)
-        } else {
-          if (response.status) {
-            this.execSuccess(btn, response, _primaryId, formdata)
-            _resolve()
-          } else {
-            this.execError(response, btn)
-            _resolve()
-          }
-        }
-      }).then(res => {
-        if (!res) return
-  
-        if (res.status) {
-          this.execSuccess(btn, res, _primaryId, formdata)
-          _resolve()
-        } else {
-          this.execError(res, btn)
-          _resolve()
-        }
-      })
-      
-    } else {
-      this.actionSettingError()
-      _resolve()
-      return
-    }
-  }
-
-  /**
-   * @description 鎿嶄綔鎴愬姛鍚庡鐞�
-   * 1銆乪xcel瀵煎嚭锛屾垚鍔熷悗鍙栨秷瀵煎嚭鎸夐挳鍔犺浇涓姸鎬�
-   * 2銆佺姸鎬佺爜涓� S 鏃讹紝鏄剧ず鎴愬姛淇℃伅鍚庣郴缁熼粯璁や俊鎭�
-   * 3銆佺姸鎬佺爜涓� -1 鏃讹紝涓嶆樉绀轰换浣曚俊鎭�
-   * 4銆佹ā鎬佹鎵ц鎴愬姛鍚庢槸鍚﹀叧闂�
-   * 5銆侀�氱煡涓诲垪琛ㄥ埛鏂�
-   */
-  execSuccess = (btn, res, primaryId, formdata) => {
-    if (res && res.ErrCode === 'S') { // 鎵ц鎴愬姛
-      notification.success({
-        top: 92,
-        message: res.ErrMesg || this.props.dict['main.action.confirm.success'],
-        duration: 2
-      })
-    } else if (res && res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
-
-    }
-
-    this.props.refreshdata(btn, 'success', primaryId, formdata)
-  }
-
-  /**
-   * @description 鎿嶄綔澶辫触鍚庡鐞�
-   * 1銆佺姸鎬佺爜涓� E銆丯銆丗銆丯M 鏃讹紝鏄剧ず鐩稿簲鎻愮ず淇℃伅
-   * 2銆乪xcel瀵煎嚭锛屽け璐ュ悗鍙栨秷瀵煎嚭鎸夐挳鍔犺浇涓姸鎬�
-   * 3銆侀�氱煡涓诲垪琛ㄥ埛鏂�
-   */
-  execError = (res, btn) => {
-    if (res.ErrCode === 'E') {
-      Modal.error({
-        title: res.message || res.ErrMesg,
-      })
-    } else if (res.ErrCode === 'N') {
-      notification.error({
-        top: 92,
-        message: res.message || res.ErrMesg,
-        duration: 10
-      })
-    } else if (res.ErrCode === 'F') {
-      notification.error({
-        className: 'notification-custom-error',
-        top: 92,
-        message: res.message || res.ErrMesg,
-        duration: 10
-      })
-    } else if (res.ErrCode === 'NM') {
-      message.error(res.message || res.ErrMesg)
-    }
-    
-    this.props.refreshdata(btn, 'error')
-  }
-
-  /**
-   * @description 鎸夐挳閰嶇疆淇℃伅閿欒鎻愮ず
-   */
-  actionSettingError = () => {
-    notification.warning({
-      top: 92,
-      message: '鎸夐挳璁剧疆閿欒锛�',
-      duration: 5
-    })
-  }
-
-  
-  render() {
-    const { loadingUuid } = this.state
-
-    return (
-      <div className="button-list formtab-button">
-        {this.props.actions.map((item, index) => {
-          if (loadingUuid === item.uuid) {
-            return (
-              <Button
-                className={'mk-btn mk-' + item.class}
-                icon={item.icon}
-                key={'action' + index}
-                onClick={() => {this.actionTrigger(item)}}
-                loading
-              >{item.label}</Button>
-            )
-          } else {
-            return (
-              <Button
-                className={'mk-btn mk-' + item.class}
-                icon={item.icon}
-                key={'action' + index}
-                onClick={() => {this.actionTrigger(item)}}
-              >{item.label}</Button>
-            )
-          }
-        })}
-      </div>
-    )
-  }
-}
-
-export default MainAction
\ No newline at end of file
diff --git a/src/tabviews/formtab/actionList/index.scss b/src/tabviews/formtab/actionList/index.scss
deleted file mode 100644
index 3a6a441..0000000
--- a/src/tabviews/formtab/actionList/index.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-.button-list.formtab-button {
-  padding: 20px 20px 10px;
-  background: #ffffff;
-  text-align: center;
-  button {
-    min-width: 70px;
-    margin-right: 20px;
-    margin-bottom: 10px;
-    height: 35px;
-    font-size: 15px;
-    padding: 5px 20px;
-  }
-  .ant-spin {
-    position: fixed;
-    z-index: 1010;
-    left: calc(50vw - 22px);
-    top: calc(50vh - 70px);
-  }
-}
diff --git a/src/tabviews/formtab/formgroup/index.jsx b/src/tabviews/formtab/formgroup/index.jsx
deleted file mode 100644
index 53e2d67..0000000
--- a/src/tabviews/formtab/formgroup/index.jsx
+++ /dev/null
@@ -1,725 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Input, InputNumber, Select, DatePicker, notification, Collapse } from 'antd'
-import moment from 'moment'
-import { formRule } from '@/utils/option.js'
-import FileUpload from '@/tabviews/zshare/fileupload'
-import './index.scss'
-
-const {MonthPicker} = DatePicker
-const { TextArea } = Input
-const { Panel } = Collapse
-
-class MainSearch extends Component {
-  static propTpyes = {
-    setting: PropTypes.object,   // 鍩烘湰淇℃伅
-    groups: PropTypes.array,     // 琛ㄥ崟缁�
-    dict: PropTypes.object,      // 瀛楀吀椤�
-    data: PropTypes.any,         // 琛ㄦ牸鏁版嵁
-    configMap: PropTypes.object, // 鎸夐挳鍙婁笅鎷夎〃鍗曢厤缃俊鎭泦
-    inputSubmit: PropTypes.func  // input鍥炶溅鎻愪氦
-  }
-
-  state = {
-    datatype: null,
-    readtype: null,
-    readin: null,
-    fieldlen: null,
-    groups: null,
-    formlist: [],
-    encrypts: [],    // 鍔犲瘑瀛楁
-    intercepts: [],  // 鎴彇瀛楁
-    record: {}
-  }
-
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    const { datatype, encrypts } = this.state
-    if (nextProps.data && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-
-      let _fieldsvalue = {}
-      let _record = {}
-      Object.keys(nextProps.data).forEach(key => {
-        if (this.props.form.getFieldValue(key) !== undefined) {
-          if (datatype[key] === 'multiselect') {
-            let _val = nextProps.data[key] ? nextProps.data[key].split(',').filter(Boolean) : []
-            _fieldsvalue[key] = _val
-          } else if (datatype[key] === 'date') {
-            let _val = nextProps.data[key] ? nextProps.data[key] : null
-
-            if (_val) {
-              _val = moment(_val, 'YYYY-MM-DD')
-            }
-
-            _fieldsvalue[key] = _val
-          } else if (datatype[key] === 'datemonth') {
-            let _val = nextProps.data[key] ? nextProps.data[key] : null
-
-            if (_val) {
-              _val = moment(_val, 'YYYY-MM')
-            }
-
-            _fieldsvalue[key] = _val
-          } else if (datatype[key] === 'datetime') {
-            let _val = nextProps.data[key] ? nextProps.data[key] : null
-
-            if (_val) {
-              _val = moment(_val, 'YYYY-MM-DD HH:mm:ss')
-            }
-
-            _fieldsvalue[key] = _val
-          } else if (datatype[key] === 'fileupload') {
-            let _val = nextProps.data[key] ? nextProps.data[key] : ''
-
-            _fieldsvalue[key] = _val
-          } else if (datatype[key] === 'text' || datatype[key] === 'textarea') {
-            let _value = nextProps.data[key]
-            if (encrypts.includes(key)) { // 鍔犲瘑瀛楁
-              try {
-                _value = window.btoa(window.encodeURIComponent(_value))
-              } catch (e) {
-                console.warn(e)
-              }
-            }
-
-            _fieldsvalue[key] = _value
-          } else {
-            _fieldsvalue[key] = nextProps.data[key]
-          }
-        } else {
-          let _value = nextProps.data[key]
-          if (encrypts.includes(key)) { // 鍔犲瘑瀛楁
-            try {
-              _value = window.btoa(window.encodeURIComponent(_value))
-            } catch (e) {
-              console.warn(e)
-            }
-          }
-
-          _record[key] = _value
-        }
-      })
-
-      if (Object.keys(_fieldsvalue).length > 0) {
-        this.props.form.setFieldsValue(_fieldsvalue)
-      }
-      
-      this.setState({
-        record: _record
-      })
-    }
-  }
-
-  UNSAFE_componentWillMount () {
-    const { data, groups } = this.props
-
-    let datatype = {}
-    let readtype = {}
-    let readin = {}
-    let fieldlen = {}
-    let _formlist = []
-    let encrypts = []
-    let intercepts = []
-
-    let _groups = groups.map(group => {
-      group.sublist = group.sublist.map(item => {
-        let _readin = item.readin !== 'false'
-        if (item.type === 'funcvar') {
-          _readin = false
-          item.initval = '' // 鍒濆鍖栦负绌�
-        }
-
-        if (item.type === 'textarea' && item.encryption === 'true') {
-          encrypts.push(item.field)
-        }
-        if (item.interception !== 'false') {
-          intercepts.push(item.field)
-        }
-
-        item.initVal = item.initval ? JSON.parse(JSON.stringify(item.initval)) : ''
-
-        let _fieldlen = item.fieldlength || 50
-        if (item.type === 'textarea' || item.type === 'fileupload' || item.type === 'multiselect') {
-          _fieldlen = item.fieldlength || 512
-        } else if (item.type === 'number') {
-          _fieldlen = item.decimal ? item.decimal : 0
-        }
-
-        datatype[item.field] = item.type
-        readtype[item.field] = item.readonly === 'true'
-        readin[item.field] = _readin
-        fieldlen[item.field] = _fieldlen
-
-        if (_readin && !/^date/.test(item.type) && data && data.hasOwnProperty(item.field)) {
-          let newval = data[item.field]
-
-          if (encrypts.includes(item.field) && newval) {
-            try {
-              newval = window.decodeURIComponent(window.atob(newval))
-            } catch (e) {
-              console.warn(e)
-            }
-          }
-
-          item.initval = newval
-        }
-
-        if (item.supvalue) {
-          item.supvalue = item.supvalue.split(',')
-        }
-
-        _formlist.push(item)
-
-        return item
-      })
-
-      return group
-    })
-
-    _groups = _groups.map(group => {
-      group.sublist = group.sublist.map(item => {
-        if (item.type === 'link') {
-          let supItem = _formlist.filter(form => form.field === item.linkField)[0]
-  
-          // 鍏宠仈鏄剧ず鍒椾腑鐨勫瓧娈靛�硷紝閫氳繃璇ュ�艰繃婊や笅鎷夐�夐」
-          if (!supItem && data && data.hasOwnProperty(item.linkField)) {
-            supItem = {initval: data[item.linkField]}
-          }
-          
-          if (!supItem) {
-            notification.warning({
-              top: 92,
-              message: '鏈煡璇㈠埌琛ㄥ崟銆�' + item.label + '銆嬪叧鑱斿瓧娈碉紒',
-              duration: 5
-            })
-          } else {
-            item.options = item.oriOptions.filter(option => option.ParentID === supItem.initval)
-          }
-        }
-        return item
-      })
-
-      return group
-    })
-    
-    this.setState({
-      readtype: readtype,
-      datatype: datatype,
-      readin: readin,
-      fieldlen: fieldlen,
-      formlist: _formlist,
-      groups: _groups
-    })
-  }
-
-  resetform = (groups, supfields, index, fieldsvalue) => {
-    index++
-    let subfields = []
-
-    supfields.forEach(supfield => {
-      groups = groups.map(group => {
-        group.sublist = group.sublist.map(item => {
-          if (item.type === 'link' && item.linkField === supfield.field) {
-            item.options = item.oriOptions.filter(option => option.ParentID === supfield.initval)
-            item.initval = item.options[0] ? item.options[0].Value : ''
-
-            fieldsvalue[item.field] = item.initval
-    
-            subfields.push(item)
-          }
-
-          return item
-        })
-        return group
-      })
-    })
-
-    if (subfields.length === 0 || index > 6) {
-      return {groups: groups, fieldsvalue: fieldsvalue}
-    } else {
-      return this.resetform(groups, subfields, index, fieldsvalue)
-    }
-  }
-
-  selectChange = (_field, value, option) => {
-    const { record } = this.state
-    let groups = JSON.parse(JSON.stringify(this.state.groups))
-
-    let subfields = []
-    let fieldsvalue = {}
-    let _record = {}
-    groups = groups.map(group => {
-      group.sublist = group.sublist.map(item => {
-        if (item.type === 'link' && item.linkField === _field.field) {
-          item.options = item.oriOptions.filter(option => option.ParentID === value)
-          item.initval = item.options[0] ? item.options[0].Value : ''
-  
-          fieldsvalue[item.field] = item.initval
-  
-          subfields.push(item)
-        }
-        return item
-      })
-      return group
-    })
-    
-    // 琛ㄥ崟鍒囨崲鏃讹紝鏇存柊鍏宠仈瀛楁
-    if (_field.type === 'select' && _field.linkSubField && _field.linkSubField.length > 0 && option.props.data) {
-      let _data = option.props.data
-      _field.linkSubField.forEach(subfield => {
-        if (this.props.form.getFieldValue(subfield) !== undefined) {
-          fieldsvalue[subfield] = _data[subfield]
-        } else {
-          _record[subfield] = _data[subfield]
-        }
-      })
-    }
-
-    if (subfields.length === 0) {
-      if (Object.keys(fieldsvalue).length > 0) {
-        this.props.form.setFieldsValue(fieldsvalue)
-      }
-      if (Object.keys(_record).length > 0) {
-        this.setState({
-          record: {...record, ..._record}
-        })
-      }
-    } else {
-      let result = this.resetform(groups, subfields, 0, fieldsvalue)
-
-      if (Object.keys(result.fieldsvalue).length > 0) {
-        this.props.form.setFieldsValue(fieldsvalue)
-      }
-
-      let _param = {
-        groups: result.groups
-      }
-
-      if (Object.keys(_record).length > 0) {
-        _param.record = {...record, ..._record}
-      }
-
-      this.setState(_param)
-    }
-  }
-
-  getFields(formlist) {
-    const { getFieldDecorator } = this.props.form
-
-    const fields = []
-    let cols = 2
-    if (this.props.setting && this.props.setting.cols) {
-      cols = parseInt(this.props.setting.cols)
-      if (cols > 4 || cols < 1) {
-        cols = 2
-      }
-    }
-
-    formlist.forEach((item, index) => {
-      if (item.hidden === 'true') return
-
-      if (item.supField && !item.supvalue.includes(this.props.form.getFieldValue(item.supField))) return
-      
-      if (item.type === 'text') {
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: item.initval || '',
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.readonly === 'true'} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'number') { // 鏁板瓧
-        let min = (item.min || item.min === 0) ? item.min : -Infinity
-        let max = (item.max || item.max === 0) ? item.max : Infinity
-        let _initval = item.initval
-        let precision = (item.decimal || item.decimal === 0) ? item.decimal : null
-
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: _initval,
-                rules: [
-                  {
-                    required: true,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  }
-                ]
-              })(
-                precision === null ?
-                <InputNumber min={min} max={max} disabled={item.readonly === 'true'} onPressEnter={this.handleSubmit} /> :
-                <InputNumber min={min} max={max} precision={precision} disabled={item.readonly === 'true'} onPressEnter={this.handleSubmit} />
-                )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'select' || item.type === 'link') { // 涓嬫媺鎼滅储
-        let hasSubField = false
-        if (item.linkSubField && item.linkSubField.length > 0) { // 瀛樺湪鍏宠仈瀛楁锛屾暟鎹瓨鍌�
-          hasSubField = true
-        }
-        
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: item.initval,
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Select
-                  showSearch
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  onChange={(value, option) => {this.selectChange(item, value, option)}}
-                  disabled={item.readonly === 'true'}
-                >
-                  {item.options.map(option =>
-                    <Select.Option id={option.key} data={hasSubField ? option : ''} title={option.Text} key={option.key} value={option.Value}>{option.Text}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'multiselect') { // 澶氶��
-        let _initval = item.initval ? item.initval.split(',').filter(Boolean) : []
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: _initval,
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Select
-                  showSearch
-                  mode="multiple"
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  disabled={item.readonly === 'true'}
-                >
-                  {item.options.map(option =>
-                    <Select.Option id={option.key} title={option.Text} key={option.key} value={option.Value}>{option.Text}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'date') { // 鏃堕棿鎼滅储
-        let _initval = this.props.data ? this.props.data[item.field] : ''
-        if (_initval && this.state.readin[item.field]) {
-          _initval = moment(_initval, 'YYYY-MM-DD')
-        } else {
-          _initval = item.initval ? moment().subtract(item.initval, 'days') : null
-        }
-
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: _initval,
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <DatePicker disabled={item.readonly === 'true'} />
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'datemonth') {
-        let _initval = this.props.data ? this.props.data[item.field] : ''
-        if (_initval && this.state.readin[item.field]) {
-          _initval = moment(_initval, 'YYYY-MM')
-        } else {
-          _initval = item.initval ? moment().subtract(item.initval, 'month') : null
-        }
-
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: _initval,
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <MonthPicker disabled={item.readonly === 'true'} />
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'datetime') {
-        let _initval = this.props.data ? this.props.data[item.field] : ''
-        
-        if (_initval && this.state.readin[item.field]) {
-          _initval = moment(_initval, 'YYYY-MM-DD HH:mm:ss')
-        } else {
-          _initval = item.initval ? moment().subtract(item.initval, 'days') : null
-        }
-
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: _initval,
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <DatePicker showTime disabled={item.readonly === 'true'} />
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'fileupload') {
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: item.initval,
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <FileUpload config={item}/>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'funcvar') {
-        fields.push(
-          <Col span={24 / cols} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.field, {
-                initialValue: '绯荤粺鑷姩鐢熸垚',
-              })(<Input placeholder="" autoComplete="off" disabled={true} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'textarea') {
-        let _labelcol = cols !== 3 ? 8 / cols : 3
-        let _wrapcol = cols !== 3 ? 16 + (cols - 1) * 4 : 21
-        let _style = {}
-        if (cols === 2 || cols === 4) {
-          _style.paddingLeft = '7px'
-        }
-        fields.push(
-          <Col span={24} key={index} className="textarea-row" style={{..._style}}>
-            <Form.Item label={item.label} labelCol={{xs: { span: 24 }, sm: { span: _labelcol }}} wrapperCol={ {xs: { span: 24 }, sm: { span: _wrapcol }} }>
-              {getFieldDecorator(item.field, {
-                initialValue: item.initval || '',
-                rules: [
-                  {
-                    required: item.required === 'true',
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  },
-                  {
-                    max: formRule.textarea.max,
-                    message: formRule.textarea.message
-                  }
-                ]
-              })(<TextArea autoSize={{ minRows: 2, maxRows: item.maxRows || 6 }} disabled={item.readonly === 'true'} />)}
-            </Form.Item>
-          </Col>
-        )
-      }
-    })
-    
-    return fields
-  }
-
-  handleConfirm = () => {
-    const { record, encrypts, intercepts } = this.state
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          let search = []
-          // 闅愯棌琛ㄥ崟
-          this.state.formlist.forEach(item => {
-            if (!item.field) return
-
-            if (item.type === 'funcvar') {
-              let _val = item.initval
-              if (values.hasOwnProperty(item.field)) {
-                _val = values[item.field] === '绯荤粺鑷姩鐢熸垚' ? '' : values[item.field]
-              } else if (record.hasOwnProperty(item.field)) {
-                _val = record[item.field]
-              }
-              search.push({
-                type: 'funcvar',
-                readonly: 'true',
-                readin: false,
-                fieldlen: this.state.fieldlen[item.field],
-                key: item.field,
-                value: _val
-              })
-            } else if (item.hidden === 'true' && item.field !== this.props.setting.primaryKey) {
-              let _val = item.initval
-              if (record.hasOwnProperty(item.field)) {
-                _val = record[item.field]
-              }
-
-              search.push({
-                type: this.state.datatype[item.field],
-                readonly: this.state.readtype[item.field],
-                readin: this.state.readin[item.field],
-                fieldlen: this.state.fieldlen[item.field],
-                key: item.field,
-                value: _val
-              })
-            } else if (item.supField && !item.supvalue.includes(this.props.form.getFieldValue(item.supField))) {
-              search.push({
-                type: this.state.datatype[item.field],
-                readonly: this.state.readtype[item.field],
-                readin: this.state.readin[item.field],
-                fieldlen: this.state.fieldlen[item.field],
-                key: item.field,
-                value: item.initVal
-              })
-            }
-          })
-
-          Object.keys(values).forEach(key => {
-            if (this.state.datatype[key] === 'funcvar')  return
-
-            let _value = ''
-            if (this.state.datatype[key] === 'datetime') {
-              if (values[key]) {
-                _value = moment(values[key]).format('YYYY-MM-DD HH:mm:ss')
-              }
-            } else if (this.state.datatype[key] === 'datemonth') {
-              if (values[key]) {
-                _value = moment(values[key]).format('YYYY-MM')
-              }
-            } else if (this.state.datatype[key] === 'date') {
-              if (values[key]) {
-                _value = moment(values[key]).format('YYYY-MM-DD')
-              }
-            } else if (this.state.datatype[key] === 'number') {
-              _value = values[key]
-
-            } else if (this.state.datatype[key] === 'multiselect') {
-              _value = values[key] ? values[key].join(',') : ''
-
-            } else if (this.state.datatype[key] === 'fileupload') {
-              _value = values[key]
-
-            } else if (this.state.datatype[key] === 'text' || this.state.datatype[key] === 'textarea') {
-              _value = values[key].replace(/\t*|\v*/g, '') // 鍘婚櫎鍒惰〃绗�
-
-              if (intercepts.includes(key)) {              // 鍘婚櫎棣栧熬绌烘牸
-                _value = _value.replace(/(^\s*|\s*$)/g, '')
-              }
-            } else {
-              _value = values[key]
-
-            }
-
-            search.push({
-              type: this.state.datatype[key],
-              readonly: this.state.readtype[key],
-              readin: this.state.readin[key],
-              fieldlen: this.state.fieldlen[key],
-              key: key,
-              value: _value
-            })
-          })
-
-          if (encrypts && encrypts.length > 0) {
-            search = search.map(item => {
-              let _value = item.value
-              if (encrypts.includes(item.key)) {
-                try {
-                  _value = window.btoa(window.encodeURIComponent(_value))
-                } catch (e) {
-                  console.warn(e)
-                }
-              }
-              item.value = _value
-
-              return item
-            })
-          }
-          resolve(search)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-    this.props.inputSubmit()
-  }
-
-  render() {
-    const { setting } = this.props
-    const { groups } = this.state
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    let _width = (setting && setting.width) || 100
-
-    let keys = groups.map(group => group.uuid)
-
-    return (
-      <Form {...formItemLayout} className="form-tab-form-field">
-        <Collapse
-          defaultActiveKey={keys}
-          expandIconPosition='right'
-        >
-          {groups.map(group =>
-            <Panel header={group.label} key={group.uuid}>
-              <Row style={{margin: '0 auto', width: _width + '%'}} gutter={24}>{this.getFields(group.sublist)}</Row>
-            </Panel>
-          )}
-        </Collapse>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/tabviews/formtab/formgroup/index.scss b/src/tabviews/formtab/formgroup/index.scss
deleted file mode 100644
index 1d63657..0000000
--- a/src/tabviews/formtab/formgroup/index.scss
+++ /dev/null
@@ -1,47 +0,0 @@
-.form-tab-form-field {
-  position: relative;
-  padding: 0px;
-  .ant-form-item {
-    display: flex;
-  }
-  .ant-form-item-control-wrapper {
-    flex: 1;
-  }
-  .ant-form-item-label {
-    overflow: hidden;
-    display: inline-block;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-  }
-  .textarea-row {
-    .ant-col-sm-3 {
-      width: 10.5%;
-    }
-    .ant-col-sm-21 {
-      width: 89.5%;
-    }
-  }
-  .ant-form-explain {
-    overflow:hidden;
-    text-overflow:ellipsis;
-    white-space:nowrap;
-  }
-  p {
-    color: #1890ff;
-    border-bottom: 1px solid #d9d9d9;
-  }
-  .ant-input-disabled {
-    color: rgba(0, 0, 0, 0.65)!important;
-    cursor: default!important;
-  }
-  .ant-input-number-input {
-    color: rgba(0, 0, 0, 0.65)!important;
-    cursor: default!important;
-  }
-  .ant-select-disabled {
-    color: rgba(0, 0, 0, 0.65)!important;
-    .ant-select-selection--multiple .ant-select-selection__choice {
-      color: rgba(0, 0, 0, 0.65)!important;
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/tabviews/formtab/index.jsx b/src/tabviews/formtab/index.jsx
deleted file mode 100644
index dcc0d1d..0000000
--- a/src/tabviews/formtab/index.jsx
+++ /dev/null
@@ -1,663 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { notification, Spin, Tabs} from 'antd'
-import moment from 'moment'
-
-import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
-import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
-import asyncComponent from '@/utils/asyncLoadComponent'
-import MKEmitter from '@/utils/events.js'
-import MkIcon from '@/components/mk-icon'
-import FormGroup from './formgroup'
-import FormAction from './actionList'
-import NotFount from '@/components/404'
-import './index.scss'
-
-const { TabPane } = Tabs
-const SubTable = asyncComponent(() => import('@/tabviews/subtable'))
-const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
-
-class NormalTable extends Component {
-  static propTpyes = {
-    MenuID: PropTypes.string,       // 鑿滃崟Id
-    param: PropTypes.any,           // 涓昏〃浼犻�掑弬鏁�
-  }
-
-  state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id
-    loadingview: true,    // 椤甸潰鍔犺浇涓�
-    viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
-    lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
-    config: {},           // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佽〃鍗曘�佹爣绛剧瓑
-    groups: null,         // 琛ㄥ崟缁�
-    actions: null,        // 鎸夐挳闆�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
-    setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
-    data: null,           // 鍒楄〃鏁版嵁闆�
-    BIDs: {},             // 涓婄骇琛╥d
-    primaryId: null,
-  }
-
-  /**
-   * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
-   */
-  async loadconfig () {
-    const { MenuID } = this.props
-
-    let param = {
-      func: 'sPC_Get_LongParam',
-      MenuID: MenuID
-    }
-    let result = await Api.getCacheConfig(param)
-    if (result.status) {
-      let config = ''
-
-      try { // 閰嶇疆淇℃伅瑙f瀽
-        config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-      } catch (e) {
-        console.warn('Parse Failure')
-        config = ''
-      }
-
-      // 椤甸潰閰嶇疆瑙f瀽閿欒鏃舵彁绀�
-      if (!config) {
-        this.setState({
-          loadingview: false,
-          viewlost: true
-        })
-        return
-      }
-
-      // 椤甸潰鏈惎鐢ㄦ椂锛屾樉绀烘湭鍚敤椤甸潰
-      if (!config.enabled) {
-        this.setState({
-          loadingview: false,
-          viewlost: true,
-          lostmsg: this.state.dict['main.view.unenabled']
-        })
-        return
-      }
-
-      // 鍏煎鏍囩
-      if (!config.tabgroups) {
-        config.tabgroups = [{ uuid: 'tabs', sublist: [] }]
-      } else if (typeof(config.tabgroups[0]) === 'string') {
-        let _tabgroups = []
-        config.tabgroups.forEach(groupId => {
-          let _group = {
-            uuid: groupId,
-            sublist: fromJS(config[groupId]).toJS()
-          }
-  
-          delete config[groupId]
-  
-          _tabgroups.push(_group)
-        })
-  
-        config.tabgroups = _tabgroups
-      }
-
-      config.tabgroups.forEach(group => {
-        group.sublist = group.sublist.map(tab => {
-          if (tab.supMenu === 'mainTable') {
-            tab.supMenu = MenuID
-          }
-          tab.ContainerId = this.state.ContainerId
-          return tab
-        })
-      })
-
-      // 鎸夐挳绫诲瀷鍏煎
-      config.action = config.action.map(item => {
-        if (item.intertype === 'inner' && !item.innerFunc) {
-          item.intertype = 'system'
-        }
-        return item
-      })
-
-      let _arrField = [config.setting.primaryKey]     // 瀛楁闆� , 榛樿娣诲姞涓婚敭
-      let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
-
-      config.groups.forEach(group => {
-        group.sublist = group.sublist.filter(item => {
-          item.field && _arrField.push(item.field)
-          if (!item.blacklist || item.blacklist.length === 0) {
-            return true
-          }
-          return item.blacklist.filter(v => roleId.indexOf(v) > -1).length === 0
-        })
-      })
-      _arrField = _arrField.join(',')
-
-      this.setState({
-        config: config,
-        setting: config.setting,
-        actions: config.action,
-        arr_field: _arrField,
-        primaryId: this.props.param.primaryId || '',
-        data: this.props.param.data || null,
-        BIDs: {
-          [MenuID]: config.setting.onload !== 'false' ? (this.props.param.primaryId || '') : '',
-          [MenuID + 'data']: config.setting.onload !== 'false' ? (config.setting.datatype === 'query' ? '' : this.props.param.data) : ''
-        }
-      }, () => {
-        this.improveSelectOption(config.groups)
-
-        if (config.setting.datatype === 'query' && config.setting.onload !== 'false') {
-          this.loadmaindata()
-        } else if (config.setting.datatype !== 'query' && (!this.props.param.primaryId || !this.props.param.data)) {
-          notification.warning({
-            top: 92,
-            message: '鏈幏鍙栧埌涓昏〃鏁版嵁锛�',
-            duration: 5
-          })
-        }
-      })
-    } else {
-      this.setState({
-        loadingview: false,
-        viewlost: true
-      })
-      notification.warning({
-        top: 92,
-        message: result.message,
-        duration: 5
-      })
-    }
-  }
-
-  /**
-   * @description 琛ㄥ崟涓嬫媺閫夐」鍔犺浇
-   */
-  improveSelectOption = (groups) => {
-    let deffers = []
-    groups.forEach(group => {
-      group.sublist = group.sublist.map(item => {
-        if (item.type !== 'multiselect' && item.type !== 'select' && item.type !== 'link') return item
-
-        if (item.setAll === 'true') {
-          item.options.unshift({
-            key: Utils.getuuid(),
-            Value: '',
-            Text: '鍏ㄩ儴'
-          })
-        }
-  
-        if (item.resourceType === '1' && item.dataSource) {
-          let _option = Utils.getSelectQueryOptions(item)
-          let _sql = Utils.formatOptions(_option.sql)
-  
-          let param = {
-            func: 'sPC_Get_SelectedList',
-            LText: _sql,
-            obj_name: 'data',
-            arr_field: _option.field
-          }
-  
-          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-          param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-
-          if (window.GLOB.mkHS) { // 浜戠鏁版嵁楠岃瘉
-            param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
-
-            if (item.database === 'sso' && options.cloudServiceApi) { // 瀛樺湪浜戠鍦板潃鏃讹紝浣跨敤浜戠绯荤粺鍙傛暟
-              param.rduri = options.cloudServiceApi
-              param.userid = sessionStorage.getItem('CloudUserID') || ''
-              param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
-            }
-          } else if (item.database === 'sso' && window.GLOB.mainSystemApi && window.GLOB.systemType === 'production') {
-            param.rduri = window.GLOB.mainSystemApi
-          }
-  
-          let defer = new Promise(resolve => {
-            Api.getSystemCacheConfig(param).then(res => {
-              res.search = item
-              resolve(res)
-            })
-          })
-          deffers.push(defer)
-        } else if (item.resourceType === '1' && !item.dataSource) {
-          notification.warning({
-            top: 92,
-            message: item.label + ': 鏁版嵁婧愰厤缃敊璇紒',
-            duration: 5
-          })
-        }
-
-        return item
-      })
-    })
-    
-    if (deffers.length === 0) {
-      this.setState({
-        loadingview: false,
-        groups: groups
-      })
-      return
-    }
-
-    Promise.all(deffers).then(result => {
-      let _result = {}
-      result.forEach(res => {
-        if (res.status) {
-          let _options = res.data.map(cell => {
-            let _item = {
-              key: Utils.getuuid(),
-              Value: cell[res.search.valueField],
-              Text: cell[res.search.valueText]
-            }
-
-            if (res.search.type === 'link') {
-              _item.ParentID = cell[res.search.linkField]
-            } else if (res.search.type === 'select' && res.search.linkSubField && res.search.linkSubField.length > 0) {
-              res.search.linkSubField.forEach(_field => {
-                _item[_field] = (cell[_field] || cell[_field] === 0) ? cell[_field] : ''
-              })
-            }
-
-            return _item
-          })
-
-          _result[res.search.uuid] = _options
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.search.label + ':' + res.message,
-            duration: 5
-          })
-        }
-      })
-
-      groups.forEach(group => {
-        group.sublist = group.sublist.map(item => {
-          if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') {
-            if (_result[item.uuid]) {
-              item.options = [...item.options, ..._result[item.uuid]]
-            }
-            item.oriOptions = JSON.parse(JSON.stringify(item.options))
-          }
-          
-          return item
-        })
-      })
-
-      this.setState({
-        loadingview: false,
-        groups: groups
-      })
-    })
-  }
-
-  /**
-   * @description 涓昏〃鏁版嵁鍔犺浇
-   */ 
-  async loadmaindata () {
-    const { setting, BIDs, config } = this.state
-
-    if (setting.datatype !== 'query') {
-      notification.warning({
-        top: 92,
-        message: '鏈缃暟鎹煡璇㈤厤缃紒',
-        duration: 5
-      })
-      return
-    }
-
-    let param = null
-
-    if (setting.interType !== 'inner' || (setting.interType === 'inner' && setting.innerFunc)) {
-      param = this.getCustomParam()
-    } else {
-      param = this.getDefaultParam()
-    }
-
-    if (!param) return // 鏈幏鍙栧弬鏁版椂锛屼笉鍙戣姹�
-
-    // 鏁版嵁绠$悊鏉冮檺
-    if (sessionStorage.getItem('dataM') === 'true') {
-      param.dataM = 'Y'
-    }
-
-    let result = await Api.genericInterface(param)
-    if (result.status) {
-      let _data = result.data[0] || ''
-      let _primaryId = ''
-
-      if (_data) {
-        _primaryId = _data[setting.primaryKey] || ''
-      } else {
-        notification.warning({
-          top: 92,
-          message: '鏈煡璇㈠埌鏁版嵁淇℃伅锛�',
-          duration: 5
-        })
-      }
-
-      this.setState({
-        data: _data,
-        primaryId: _primaryId,
-        BIDs: { ...BIDs, [this.props.MenuID]: _primaryId, [this.props.MenuID + 'data']: _data }
-      })
-
-      if (_data && (setting.interType !== 'inner' || (setting.interType === 'inner' && setting.innerFunc))) {
-        let keys = Object.keys(_data)
-        let emptys = []
-
-        if (!keys.includes(config.setting.primaryKey)) {
-          emptys.push(config.setting.primaryKey)
-        }
-
-        config.groups.forEach(group => {
-          group.sublist.forEach(item => {
-            if (!keys.includes(item.field)) {
-              emptys.push(item.field + '(' + item.label + ')')
-            }
-          })
-        })
-
-        if (emptys.length > 0) {
-          notification.warning({
-            top: 92,
-            message: '鏈煡璇㈠埌' + emptys.join(', ') + '瀛楁淇℃伅锛�',
-            duration: 5
-          })
-        }
-      }
-    } else {
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
-    }
-  }
-
-  /**
-   * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼鐨勫弬鏁�
-   */
-  getDefaultParam = () => {
-    const { arr_field, setting, primaryId } = this.state
-
-    if (!arr_field) {
-      notification.warning({
-        top: 92,
-        message: '鏈缃〃鍗曞瓧娈碉紒',
-        duration: 5
-      })
-      return null
-    }
-    
-    let param = {
-      func: 'sPC_Get_TableData',
-      obj_name: 'data',
-      arr_field: arr_field,
-      ID: primaryId
-    }
-    
-    let _dataresource = setting.dataresource
-
-    if (/\s/.test(_dataresource)) {
-      _dataresource = '(' + _dataresource + ') tb'
-    }
-
-    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-      _dataresource = _dataresource.replace(/\$@/ig, '/*')
-      _dataresource = _dataresource.replace(/@\$/ig, '*/')
-      // param.custom_script = param.custom_script.replace(/\$@/ig, '/*')
-      // param.custom_script = param.custom_script.replace(/@\$/ig, '*/')
-    } else {
-      _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
-      // param.custom_script = param.custom_script.replace(/@\$|\$@/ig, '')
-    }
-
-    if (!/@ID@/ig.test(_dataresource)) {
-      _dataresource = `${_dataresource} where ${setting.primaryKey}='${primaryId}'`
-    }
-
-    let LText = `select ${arr_field} from ${_dataresource}`
-
-    param.LText = Utils.formatOptions(LText)
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-    param.DateCount = ''
-
-    if (window.GLOB.probation) {
-      param.s_debug_type = 'Y'
-    }
-
-    if (!window.GLOB.mkHS) { // 浜戠鏁版嵁楠岃瘉
-      param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
-    }
-
-    return param
-  }
-
-  /**
-   * @description 鑾峰彇鐢ㄦ埛鑷畾涔夊瓨鍌ㄨ繃绋嬩紶鍙�
-   */
-  getCustomParam = () => {
-    const { setting, primaryId } = this.state
-
-    let param = {}
-
-    if (setting.interType === 'inner') {
-      param.func = setting.innerFunc
-    } else {
-      if (window.GLOB.mkHS) {
-        if (setting.sysInterface === 'true' && options.cloudServiceApi) {
-          param.rduri = options.cloudServiceApi
-          param.userid = sessionStorage.getItem('CloudUserID') || ''
-          param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
-        } else if (setting.sysInterface !== 'true') {
-          param.rduri = setting.interface
-        }
-      } else {
-        if (setting.sysInterface === 'true' && window.GLOB.mainSystemApi) {
-          param.rduri = window.GLOB.mainSystemApi
-        } else if (setting.sysInterface !== 'true') {
-          param.rduri = setting.interface
-        }
-      }
-
-      if (setting.outerFunc) {
-        param.func = setting.outerFunc
-      }
-    }
-
-    param[setting.primaryKey] = primaryId
-
-    return param
-  }
-
-  /**
-   * @description 鎸夐挳鎿嶄綔瀹屾垚鍚庯紙鎴愬姛鎴栧け璐ワ級锛岄〉闈㈠埛鏂帮紝閲嶇疆椤电爜鍙婇�夋嫨椤�
-   */
-  refreshbyaction = (btn, type, primaryId, formdata) => {
-    const { BIDs } = this.state
-
-    if (type === 'success' && btn.afterExecSuccess === 'notclose') {
-      this.setState({
-        primaryId: primaryId
-      }, () => {
-        if (btn.execSuccess === 'refresh' || btn.execSuccess === 'grid') {
-          this.loadmaindata()
-        } else {
-          let data = {}
-
-          if (formdata && formdata.length > 0) {
-            formdata.forEach(item => {
-              data[item.key] = item.value
-            })
-          }
-
-          this.setState({
-            BIDs: { ...BIDs, [this.props.MenuID]: primaryId, [this.props.MenuID + 'data']: data }
-          })
-        }
-      })
-    } else if (type === 'success' && btn.afterExecSuccess === 'close') {
-      if (btn.execSuccess !== 'never') {
-        MKEmitter.emit('reloadData', this.props.param.parentId, 'formtab', btn)
-      }
-
-      MKEmitter.emit('closeTabView', this.props.MenuID)
-    } else if (type === 'error' && btn.afterExecError === 'notclose') {
-      if (btn.execError === 'refresh') {
-        this.loadmaindata()
-      }
-    } else if (type === 'error' && btn.afterExecError === 'close') {
-      if (btn.execError !== 'never') {
-        MKEmitter.emit('reloadData', this.props.param.parentId, 'formtab', btn)
-      }
-      MKEmitter.emit('closeTabView', this.props.MenuID)
-    }
-  }
-
-  /**
-   * @description 鑾峰彇琛ㄥ崟鍙傛暟
-   */
-  getFormData = () => {
-    return this.formGroupRef.handleConfirm()
-  }
-
-  reloadview = () => {
-    this.setState({
-      loadingview: true,
-      viewlost: false,
-      lostmsg: '',
-      config: {},
-      groups: null,
-      actions: null,
-      setting: null,
-      data: null,
-      BIDs: {},
-      primaryId: null,
-    }, () => {
-      this.loadconfig()
-    })
-  }
-
-  reloadMenuView = (menuId) => {
-    const { MenuID } = this.props
-
-    if (MenuID !== menuId) return
-
-    this.reloadview()
-  }
-
-  reloadData = (menuId) => {
-    const { MenuID } = this.props
-
-    if (MenuID !== menuId) return
-    
-    this.loadmaindata()
-  }
-
-  changeTableLine = (ContainerId, tableId, id, data) => {
-    if (this.state.ContainerId !== ContainerId) return
-
-    this.setState({
-      BIDs: {...this.state.BIDs, [tableId]: id, [tableId + 'data']: data}
-    })
-  }
-
-  UNSAFE_componentWillMount () {
-    // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
-    this.loadconfig()
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  componentDidMount () {
-    MKEmitter.addListener('reloadData', this.reloadData)
-    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
-    MKEmitter.addListener('changeTableLine', this.changeTableLine)
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-
-    MKEmitter.removeListener('reloadData', this.reloadData)
-    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
-    MKEmitter.removeListener('changeTableLine', this.changeTableLine)
-  }
-
-  render() {
-    const { setting, actions, loadingview, viewlost, config, groups, data } = this.state
-    let hasform = false
-
-    if (groups && (groups.length > 1 || groups[0].sublist.length > 0)) {
-      hasform = true
-    }
-
-    return (
-      <div className="formtab" id={this.state.ContainerId}>
-        {loadingview && <Spin size="large" />}
-        {hasform ?
-          <FormGroup
-            dict={this.state.dict}
-            data={data}
-            groups={groups}
-            setting={setting}
-            wrappedComponentRef={(inst) => this.formGroupRef = inst}
-          /> : null
-        }
-        {hasform ?
-          <FormAction
-            setting={setting}
-            actions={actions}
-            dict={this.state.dict}
-            data={this.state.data}
-            MenuID={this.props.MenuID}
-            primaryId={this.state.primaryId}
-            getFormData={this.getFormData}
-            refreshdata={this.refreshbyaction}
-          /> : null
-        }
-        {!loadingview && !viewlost && config.tabgroups.map(group => {
-            if (group.sublist.length === 0) return null
-
-            return (
-              <Tabs defaultActiveKey="0" key={group.uuid}>
-                {group.sublist.map((_tab, index) => {
-                  return (
-                    <TabPane tab={
-                      <span>
-                        {_tab.icon ? <MkIcon type={_tab.icon} /> : null}
-                        {_tab.label}
-                      </span>
-                    } key={`${index}`}>
-                      <SubTable
-                        Tab={_tab}
-                        MenuID={_tab.linkTab}
-                        SupMenuID={this.props.MenuID}
-                        BID={this.state.BIDs[_tab.supMenu] || ''}
-                        BData={this.state.BIDs[_tab.supMenu + 'data'] || ''}
-                      />
-                    </TabPane>
-                  )
-                })}
-              </Tabs>
-            )
-          })
-        }
-        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
-        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
-      </div>
-    )
-  }
-}
-
-export default NormalTable
\ No newline at end of file
diff --git a/src/tabviews/formtab/index.scss b/src/tabviews/formtab/index.scss
deleted file mode 100644
index b5c70bb..0000000
--- a/src/tabviews/formtab/index.scss
+++ /dev/null
@@ -1,112 +0,0 @@
-.formtab {
-  position: relative;
-  min-height: calc(100vh - 94px);
-  padding-top: 16px;
-  padding-bottom: 80px;
-  .box404 {
-    padding-top: 30px;
-  }
-  >.ant-form.ant-form-horizontal {
-    .ant-collapse {
-      border-radius: 0;
-      border: 0;
-      .ant-collapse-header {
-        cursor: default;
-        border-radius: 0!important;
-        background: #1890ff;
-        color: #ffffff;
-        padding-left: 30px;
-        padding-right: 20px;
-        .anticon {
-          font-size: 16px;
-        }
-        .ant-collapse-extra {
-          .anticon-edit {
-            position: absolute;
-            left: 5px;
-            top: 2px;
-          }
-        }
-      }
-      .ant-collapse-item:last-child {
-        border-radius: 0;
-        .ant-collapse-content {
-          border-radius: 0;
-        }
-      }
-      .ant-collapse-content-box {
-        padding: 16px 30px;
-        > .ant-row {
-          .ant-calendar-picker {
-            min-width: 100px!important;
-            width: 100%;
-          }
-        }
-      }
-    }
-  }
-  
-  .ant-modal-mask {
-    position: absolute;
-  }
-  .ant-modal-wrap {
-    position: absolute;
-  }
-  .action-modal .ant-modal {
-    top: 40px;
-    max-width: 95%;
-    .ant-modal-body {
-      max-height: calc(100vh - 265px);
-    }
-  }
-  > .ant-spin {
-    position: fixed;
-    left: calc(50vw - 22px);
-    top: calc(50vh - 70px);
-  }
-  > .ant-tabs {
-    padding: 0px 20px;
-    margin-bottom: 20px;
-    .ant-tabs-tab:not(.ant-tabs-tab-active) {
-      cursor: pointer;
-    }
-  }
-  > .ant-card {
-    margin: 0 20px 20px;
-    > .ant-card-head {
-      border: 0;
-      padding: 0;
-      min-height: 30px;
-      .ant-card-head-title {
-        padding: 10px 0 0;
-        span {
-          color: #1890ff;
-          display: inline-block;
-          padding: 0 10px;
-          font-size: 15px;
-          border-bottom: 1px solid #1890ff;
-          .anticon {
-            margin-right: 10px;
-          }
-        }
-      }
-    }
-    > .ant-card-body {
-      padding: 0;
-    }
-  }
-  .main-table-box {
-    position: relative;
-    .pickchange {
-      position: absolute;
-      right: 0px;
-      top: -25px;
-      .ant-switch {
-        z-index: 1;
-        float: right;
-        margin-right: 20px;
-        margin-bottom: 5px;
-      }
-    }
-  }
-}
diff --git a/src/tabviews/home/index.jsx b/src/tabviews/home/index.jsx
index 23338d0..d91ecef 100644
--- a/src/tabviews/home/index.jsx
+++ b/src/tabviews/home/index.jsx
@@ -4,7 +4,6 @@
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
-import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
 const DefaultHome = asyncComponent(() => import('./defaulthome'))
@@ -18,27 +17,14 @@
   state = {
     loading: true,
     background: sessionStorage.getItem('home_background'),
-    waitMenu: true,
-    waitAction: true,
+    waiting: true,
     view: ''
   }
 
   componentDidMount () {
     this.loadHomeConfig()
-    if (window.GLOB.mkThdMenus.length > 0) {
-      this.setState({
-        waitMenu: false
-      })
-    } else {
-      MKEmitter.addListener('mkMenuLoaded', this.mkMenuLoaded)
-    }
-    if (window.GLOB.mkActions.loaded) {
-      this.setState({
-        waitAction: false
-      })
-    } else {
-      MKEmitter.addListener('mkActionLoaded', this.mkActionLoaded)
-    }
+
+    this.check(0)
   }
 
   /**
@@ -48,20 +34,20 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('mkMenuLoaded', this.mkMenuLoaded)
-    MKEmitter.removeListener('mkActionLoaded', this.mkActionLoaded)
   }
 
-  mkMenuLoaded = () => {
-    this.setState({
-      waitMenu: false
-    })
-  }
+  check = (times) => {
+    times++
 
-  mkActionLoaded = () => {
-    this.setState({
-      waitAction: false
-    })
+    if ((window.GLOB.mkThdMenus.length > 0 && window.GLOB.mkActions.loaded) || times > 50) {
+      this.setState({
+        waiting: false
+      })
+    } else {
+      setTimeout(() => {
+        this.check(times)
+      }, 200)
+    }
   }
 
   loadHomeConfig = () => {
@@ -70,45 +56,36 @@
       MenuID: this.props.MenuID
     }
     Api.getCacheConfig(_param).then(result => {
-      if (result.status) {
-        if (result.LongParam) {
-          let config = ''
+      let view = 'default'
+      if (result.status && result.LongParam) {
+        let config = ''
 
-          try { // 閰嶇疆淇℃伅瑙f瀽
-            config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-          } catch (e) {
-            console.warn('Parse Failure')
-            config = ''
-          }
-
-          if (!config || !config.enabled) {
-            this.setState({
-              loading: false,
-              waitMenu: false,
-              waitAction: false,
-              view: 'default'
-            })
-          } else {
-            this.setState({
-              loading: false,
-              view: 'custom'
-            })
-          }
-        } else {
-          this.setState({
-            loading: false,
-            waitMenu: false,
-            waitAction: false,
-            view: 'default'
-          })
+        try { // 閰嶇疆淇℃伅瑙f瀽
+          config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
+        } catch (e) {
+          console.warn('Parse Failure')
+          config = ''
         }
+
+        if (config && config.enabled) {
+          view = 'custom'
+        }
+      }
+
+      if (view === 'default') {
+        this.setState({
+          loading: false,
+          waiting: false,
+          view: 'default'
+        })
       } else {
         this.setState({
           loading: false,
-          waitMenu: false,
-          waitAction: false,
-          view: 'default'
+          view: 'custom'
         })
+      }
+
+      if (!result.status) {
         notification.warning({
           top: 92,
           message: result.message,
@@ -119,9 +96,9 @@
   }
 
   render() {
-    const { loading, waitAction, waitMenu, view, background } = this.state
+    const { loading, waiting, view, background } = this.state
 
-    if (loading || waitAction || waitMenu) {
+    if (loading || waiting) {
       return (<div className="home-loading-view" style={{background: background}}><Spin className="home-box-spin" size="large" /></div>)
     } else if (view === 'custom') {
       return (<CustomPage MenuID={this.props.MenuID} MenuName="棣栭〉"/>)
diff --git a/src/tabviews/iframe/index.jsx b/src/tabviews/iframe/index.jsx
index c1186d4..eae4d43 100644
--- a/src/tabviews/iframe/index.jsx
+++ b/src/tabviews/iframe/index.jsx
@@ -6,7 +6,6 @@
   static propTypes = {
     title: PropTypes.string,
     MenuID: PropTypes.string,    // 鑿滃崟Id
-    MenuNo: PropTypes.string,    // 鑿滃崟鍙傛暟
     url: PropTypes.string
   }
 
diff --git a/src/tabviews/rolemanage/index.jsx b/src/tabviews/rolemanage/index.jsx
index 2470166..c673f2d 100644
--- a/src/tabviews/rolemanage/index.jsx
+++ b/src/tabviews/rolemanage/index.jsx
@@ -6,7 +6,6 @@
 import md5 from 'md5'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
@@ -20,7 +19,6 @@
 
 export default class RoleManage extends Component {
   static propTpyes = {
-    MenuNo: PropTypes.string, // 鑿滃崟鍙傛暟
     MenuID: PropTypes.string  // 鑿滃崟Id
   }
 
@@ -75,8 +73,6 @@
   }
 
   getAppList = () => {
-    if (options.sysType !== 'local') return
-
     let param = {
       func: 's_get_kei'
     }
@@ -844,11 +840,8 @@
   render() {
     const { activeKey, filterRoleList, applist, selectApp, selectSubApp, loading, loadingTree, loadingAppTree, primarykey, menuTrees, appTrees, checkedKeys, appCheckedKeys, menuOpenKeys, selectMenuTrees, selectAppTrees, selectRoleId, selectMenuOpenKeys, selectAppOpenKeys, submitloading, appOpenKeys } = this.state
 
-    let ismanage = true
-    // let ismanage = options.sysType !== 'local'
-    
     return (
-      <div className={'rolemanage' + (ismanage ? ' manager' : '')}>
+      <div className={'rolemanage' + (applist.length === 0 ? ' manager' : '')}>
         {loading && <Spin size="large" />}
         <Tabs activeKey={activeKey} type="card" onChange={this.changeType}>
           <TabPane tab="绠$悊绯荤粺" key="manage">
@@ -972,7 +965,6 @@
             </Row>
           </TabPane>
         </Tabs>
-        
       </div>
     )
   }
diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx
index cb9aefe..64cc21a 100644
--- a/src/tabviews/subtable/index.jsx
+++ b/src/tabviews/subtable/index.jsx
@@ -4,8 +4,6 @@
 import { notification, Spin, Switch, Row, Col, Tabs, Modal } from 'antd'
 
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import { updateSubTable } from '@/utils/utils-update.js'
@@ -35,14 +33,12 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     loadingview: true,    // 椤甸潰鍔犺浇涓�
     viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
     lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
     config: null,         // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佹悳绱€�佹樉绀哄垪銆佹爣绛剧瓑
     actions: null,        // 鎸夐挳闆�
     columns: null,        // 鏄剧ず鍒�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
     setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
     data: [],             // 鍒楄〃鏁版嵁闆�
     selectedData: [],     // 宸查�夎〃鏍兼暟鎹�
@@ -57,7 +53,6 @@
     statFields: [],       // 鍚堣瀛楁
     statFValue: [],       // 鍚堣鍊�
     absFields: [],        // 缁濆鍊煎瓧娈�
-    hasReqFields: false,
     BID: '',
     BData: ''
   }
@@ -115,7 +110,7 @@
         this.setState({
           loadingview: false,
           viewlost: true,
-          lostmsg: this.state.dict['main.view.unenabled']
+          lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
         })
         return
       }
@@ -133,14 +128,7 @@
       // 鏉冮檺杩囨护
       config.action = config.action.filter(item => item.hidden !== 'true')
 
-      config.search = Utils.initSearchVal(config.search)
-
-      let hasReqFields = false
-      config.search.forEach(field => {
-        if (field.required) {
-          hasReqFields = true
-        }
-      })
+      Utils.initSearchVal(config)
 
       // 瀛楁鏉冮檺榛戝悕鍗�
       let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
@@ -240,6 +228,16 @@
         item.$menuId = this.props.MenuID
         item.$old = true
 
+        if (item.OpenType === 'excelOut') { // 瀵煎嚭
+          item.$menuName = Tab.label
+    
+          if (!item.verify || !item.verify.columns || item.verify.columns.length === 0) {
+            item.errorType = 'error1'
+          } else if (item.intertype === 'system' && item.verify.dataType !== 'custom' && config.setting.interType !== 'system') {
+            item.errorType = 'error2'
+          }
+        }
+
         if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify) { // 鎵撳嵃鏈鸿缃�
           let _item = window.GLOB.UserCacheMap.get(Tab.uuid + item.uuid)
 
@@ -304,10 +302,8 @@
         }
   
         if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
-          config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
+          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
+          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
         } else {
           config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
           config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
@@ -315,11 +311,6 @@
 
         let userName = sessionStorage.getItem('User_Name') || ''
         let fullName = sessionStorage.getItem('Full_Name') || ''
-
-        if (sessionStorage.getItem('isEditState') === 'true') {
-          userName = sessionStorage.getItem('CloudUserName') || ''
-          fullName = sessionStorage.getItem('CloudFullName') || ''
-        }
 
         let regs = [
           { reg: /@userName@/ig, value: `'${userName}'` },
@@ -358,7 +349,10 @@
         searchRatio: config.setting.searchRatio || '',
         searchLwidth: config.setting.searchLwidth,
         borderRadius: config.setting.borderRadius,
+        resetContrl: config.setting.resetContrl,
       }
+
+      config.setting.arr_field = _arrField.join(',')
 
       this.setState({
         pageSize: config.setting.pageSize || 10,
@@ -372,9 +366,7 @@
         setting: config.setting,
         actions: _actions,
         columns: _columns,
-        arr_field: _arrField.join(','),
-        search: Utils.initMainSearch(config.search),
-        hasReqFields
+        search: Utils.initMainSearch(config.search)
       }, () => {
         if (config.setting.onload !== 'false' && (!Tab.supMenu || this.props.BID || Tab.isTreeNode)) { // 鍒濆鍖栧彲鍔犺浇
           this.loadData()
@@ -397,14 +389,14 @@
   
   loadData = (id) => {
     const { mainSearch } = this.props
-    const { setting, BID, search, hasReqFields } = this.state
+    const { setting, BID, search, config } = this.state
 
     let searches = fromJS(search).toJS()
     if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
       searches = [...mainSearch, ...searches]
     }
 
-    if (hasReqFields) {
+    if (config.$s_req) {
       let requireFields = searches.filter(item => item.required && item.value === '')
       if (requireFields.length > 0) {
         this.setState({
@@ -447,7 +439,7 @@
    */
   async loadmaindata (id) {
     const { mainSearch } = this.props
-    const { setting, BID, arr_field, search, orderBy, pageIndex, pageSize, absFields } = this.state
+    const { setting, BID, search, orderBy, pageIndex, pageSize, absFields } = this.state
 
     let searches = fromJS(search).toJS()
     if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
@@ -459,7 +451,7 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
 
@@ -533,7 +525,7 @@
    */ 
   async loadmainLinedata (id) {
     const { mainSearch } = this.props
-    const { setting, BID, arr_field, search, orderBy, pageIndex, pageSize, absFields } = this.state
+    const { setting, BID, search, orderBy, pageIndex, pageSize, absFields } = this.state
 
     let searches = fromJS(search).toJS()
     if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
@@ -545,7 +537,7 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -705,8 +697,8 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { Tab, mainSearch, MenuID } = this.props
-    const { arr_field, orderBy, search, setting} = this.state
+    const { mainSearch, MenuID } = this.props
+    const { orderBy, search, setting} = this.state
 
     if (MenuID !== menuId) return
 
@@ -716,10 +708,8 @@
     }
 
     callback({
-      arr_field: arr_field,
       orderBy: orderBy || setting.order,
-      search: searches,
-      menuName: Tab.label
+      search: searches
     })
   }
 
@@ -852,7 +842,7 @@
     return (
       <div className="subtable" id={'subtable' + this.props.MenuID}>
         {loadingview && <Spin />}
-        {config.search && config.search.length ?
+        {config && config.search && config.search.length ?
           <SubSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
         }
         {config && config.charts ? <Row className="chart-view" gutter={16}>
@@ -890,7 +880,6 @@
                       setting={setting}
                       columns={columns}
                       pageSize={pageSize}
-                      dict={this.state.dict}
                       data={this.state.data}
                       total={this.state.total}
                       MenuID={this.props.MenuID}
@@ -956,7 +945,6 @@
               setting={setting}
               columns={columns}
               pageSize={pageSize}
-              dict={this.state.dict}
               data={this.state.data}
               total={this.state.total}
               MenuID={this.props.MenuID}
diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx
index 3388d62..0218924 100644
--- a/src/tabviews/subtabtable/index.jsx
+++ b/src/tabviews/subtabtable/index.jsx
@@ -4,8 +4,6 @@
 import { notification, Spin, Modal } from 'antd'
 
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import { updateSubTabTable } from '@/utils/utils-update.js'
@@ -30,14 +28,12 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     loadingview: true,    // 椤甸潰鍔犺浇涓�
     viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
     lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
     config: null,         // 椤甸潰閰嶇疆淇℃伅锛屽寘鎷寜閽�佹悳绱€�佹樉绀哄垪銆佹爣绛剧瓑
     actions: null,        // 鎸夐挳闆�
     columns: null,        // 鏄剧ず鍒�
-    arr_field: '',        // 鏌ヨ瀛楁闆�
     setting: null,        // 椤甸潰鍏ㄥ眬璁剧疆锛氭暟鎹簮銆佹寜閽強鏄剧ず鍒楀浐瀹氥�佷富閿瓑
     data: [],             // 鍒楄〃鏁版嵁闆�
     selectedData: [],     // 宸查�夎〃鏍兼暟鎹�
@@ -50,7 +46,6 @@
     statFields: [],       // 鍚堣瀛楁
     statFValue: [],       // 鍚堣鍊�
     absFields: [],        // 缁濆鍊煎瓧娈�
-    hasReqFields: false
   }
 
   /**
@@ -90,7 +85,7 @@
         this.setState({
           loadingview: false,
           viewlost: true,
-          lostmsg: this.state.dict['main.view.unenabled']
+          lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
         })
         return
       }
@@ -126,14 +121,7 @@
       // 鏉冮檺杩囨护
       config.action = config.action.filter(item => item.hidden !== 'true')
 
-      config.search = Utils.initSearchVal(config.search)
-
-      let hasReqFields = false
-      config.search.forEach(field => {
-        if (field.required) {
-          hasReqFields = true
-        }
-      })
+      Utils.initSearchVal(config)
 
       // 瀛楁鏉冮檺榛戝悕鍗�
       let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
@@ -210,6 +198,18 @@
         item.$menuId = this.props.MenuID
         item.$old = true
 
+        if (item.OpenType === 'popview') return
+
+        if (item.OpenType === 'excelOut') { // 瀵煎嚭
+          item.$menuName = Tab.label
+    
+          if (!item.verify || !item.verify.columns || item.verify.columns.length === 0) {
+            item.errorType = 'error1'
+          } else if (item.intertype === 'system' && item.verify.dataType !== 'custom' && config.setting.interType !== 'system') {
+            item.errorType = 'error2'
+          }
+        }
+
         if (item.controlField) {
           if (/,/ig.test(item.controlVal)) {
             item.controlVals = item.controlVal.split(',')
@@ -259,10 +259,8 @@
         }
   
         if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
-          config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
+          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
+          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
         } else {
           config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
           config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
@@ -270,11 +268,6 @@
 
         let userName = sessionStorage.getItem('User_Name') || ''
         let fullName = sessionStorage.getItem('Full_Name') || ''
-
-        if (sessionStorage.getItem('isEditState') === 'true') {
-          userName = sessionStorage.getItem('CloudUserName') || ''
-          fullName = sessionStorage.getItem('CloudFullName') || ''
-        }
 
         let regs = [
           { reg: /@userName@/ig, value: `'${userName}'` },
@@ -313,7 +306,10 @@
         searchRatio: config.setting.searchRatio || '',
         searchLwidth: config.setting.searchLwidth,
         borderRadius: config.setting.borderRadius,
+        resetContrl: config.setting.resetContrl,
       }
+
+      config.setting.arr_field = _arrField.join(',')
 
       this.setState({
         pageSize: config.setting.pageSize || 10,
@@ -324,9 +320,7 @@
         setting: config.setting,
         actions: _actions,
         columns: _columns,
-        arr_field: _arrField.join(','),
         search: Utils.initMainSearch(config.search), // 鎼滅储鏉′欢鍒濆鍖栵紙鍚湁鏃堕棿鏍煎紡锛岄渶瑕佽浆鍖栵級
-        hasReqFields
       }, () => {
         if (config.setting.onload !== 'false') { // 鍒濆鍖栧彲鍔犺浇
           this.loadData()
@@ -346,11 +340,11 @@
   }
 
   loadData = (id) => {
-    const { setting, search, hasReqFields } = this.state
+    const { setting, search, config } = this.state
 
     let searches = fromJS(search).toJS()
 
-    if (hasReqFields) {
+    if (config.$s_req) {
       let requireFields = searches.filter(item => item.required && item.value === '')
       if (requireFields.length > 0) {
         this.setState({
@@ -381,7 +375,7 @@
    */
   async loadmaindata (id) {
     const { BID } = this.props
-    const { setting, arr_field, search, orderBy, pageIndex, pageSize, absFields } = this.state
+    const { setting, search, orderBy, pageIndex, pageSize, absFields } = this.state
 
     let searches = fromJS(search).toJS()
 
@@ -390,7 +384,7 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
 
@@ -506,7 +500,7 @@
    */ 
   async loadmainLinedata (id) {
     const { BID } = this.props
-    const { setting, arr_field, search, orderBy, pageIndex, pageSize, absFields } = this.state
+    const { setting, search, orderBy, pageIndex, pageSize, absFields } = this.state
 
     let searches = fromJS(search).toJS()
 
@@ -515,7 +509,7 @@
     })
 
     let _orderBy = orderBy || setting.order
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
+    let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -639,16 +633,14 @@
    * @description 瀵煎嚭Excel鏃讹紝鑾峰彇椤甸潰鎼滅储鎺掑簭绛夊弬鏁�
    */
   queryModuleParam = (menuId, callback) => {
-    const { Tab, MenuID } = this.props
-    const { arr_field, orderBy, search, setting} = this.state
+    const { MenuID } = this.props
+    const { orderBy, search, setting} = this.state
 
     if (MenuID !== menuId) return
 
     callback({
-      arr_field: arr_field,
       orderBy: orderBy || setting.order,
-      search: search,
-      menuName: Tab.label
+      search: search
     })
   }
 
@@ -702,7 +694,7 @@
     return (
       <div className="subtabtable" id={'subtabtable' + this.props.MenuID}>
         {loadingview && <Spin />}
-        {config.search && config.search.length ?
+        {config && config.search && config.search.length ?
           <SubSearch BID={this.props.BID} config={config} refreshdata={this.refreshbysearch}/> : null
         }
         {config ? <div style={{minHeight: '25px'}}>
@@ -711,7 +703,6 @@
             actions={actions}
             columns={columns}
             BID={this.props.BID}
-            dict={this.state.dict}
             BData={this.props.BData}
             selectedData={selectedData}
             MenuID={this.props.SupMenuID}
@@ -723,7 +714,6 @@
           columns={columns}
           pageSize={pageSize}
           data={this.state.data}
-          dict={this.state.dict}
           BData={this.props.BData}
           total={this.state.total}
           MenuID={this.props.MenuID}
diff --git a/src/tabviews/tabmanage/index.jsx b/src/tabviews/tabmanage/index.jsx
deleted file mode 100644
index 5274ea9..0000000
--- a/src/tabviews/tabmanage/index.jsx
+++ /dev/null
@@ -1,577 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Row, Col, Input, Button, Card, notification, Modal, Empty, Spin } from 'antd'
-import moment from 'moment'
-
-import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
-import Utils from '@/utils/utils.js'
-import MKEmitter from '@/utils/events.js'
-import TransferForm from './transferform'
-import MutilForm from './mutilform'
-import subtableurl from '@/assets/img/subtable.jpg'
-
-import './index.scss'
-
-const { Search } = Input
-const { confirm } = Modal
-
-class TabManage extends Component {
-  static propTpyes = {
-    MenuNo: PropTypes.string,    // 鑿滃崟鍙傛暟
-    MenuName: PropTypes.string,  // 鑿滃崟鍙傛暟
-    MenuID: PropTypes.string     // 鑿滃崟Id
-  }
-
-  state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id
-    searchKey: '',
-    tabviews: null,
-    loading: true,
-    modaltype: '',
-    editTab: null,
-    submitloading: false,
-    cols: 8,
-    thawVisible: false,
-    thawmenulist: null
-
-  }
-
-  getTabs = () => {
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
-      if (res.status) {
-        this.setState({
-          loading: false,
-          tabviews: res.UserTemp.map(temp => {
-            return {
-              uuid: temp.MenuID,
-              value: temp.MenuID,
-              MenuName: temp.MenuName || '',
-              type: temp.Template,
-              MenuNo: temp.MenuNo || '',
-              Remark: temp.Remark
-            }
-          })
-        })
-      } else {
-        this.setState({
-          loading: false
-        })
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-  }
-
-  UNSAFE_componentWillMount () {
-    let docwidth = document.body.offsetWidth
-    let cols = 8
-
-    if (docwidth > 1800) {
-      cols = 6
-    }
-    
-    this.setState({
-      cols: cols
-    })
-  }
-
-  componentDidMount () {
-    this.getTabs()
-    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
-  }
-
-  reloadMenuView = (menuId) => {
-    const { MenuID } = this.props
-
-    if (MenuID !== menuId) return
-
-    this.setState({
-      searchKey: '',
-      tabviews: null,
-      loading: true,
-      modaltype: '',
-      editTab: null,
-      submitloading: false,
-      thawVisible: false,
-      thawmenulist: null
-    })
-    this.getTabs()
-  }
-
-  handleTab = (tab, type) => {
-    let _this = this
-
-    if (type === 'delete') {
-      confirm({
-        title: "纭畾鍒犻櫎璇ユ爣绛惧悧锛�",
-        onOk() {
-          return new Promise(resolve => {
-            let _param = {
-              func: 'sPC_MainMenu_Del',
-              MenuID: tab.uuid
-            }
-
-            Api.getSystemConfig(_param).then(res => {
-              if (!res.status) {
-                notification.warning({
-                  top: 92,
-                  message: res.message,
-                  duration: 5
-                })
-              } else {
-                notification.success({
-                  top: 92,
-                  message: '鎵ц鎴愬姛',
-                  duration: 2
-                })
-                _this.setState({
-                  loading: true,
-                  tabviews: null
-                }, () => {
-                  _this.getTabs()
-                })
-              }
-              resolve()
-            })
-          })
-        },
-        onCancel() {}
-      })
-    } else {
-      this.setState({
-        editTab: tab,
-        modaltype: type
-      })
-    }
-  }
-
-  handleSubmit = () => {
-    const { editTab, modaltype } = this.state
-
-    this.tabFormRef.handleConfirm().then(res => {
-
-      let _tab = {...editTab, ...res}
-
-      this.setState({submitloading: true})
-
-      Api.getSystemConfig({
-        func: 'sPC_Get_LongParam',
-        MenuID: _tab.uuid
-      }).then(res => {
-
-        if (!res.status) {
-          this.setState({
-            submitloading: false
-          })
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-          return
-        }
-
-        let param = {
-          func: 'sPC_Tab_AddUpt',
-          MenuID: _tab.uuid,
-          MenuNo: _tab.MenuNo,
-          Template: _tab.type,
-          MenuName: _tab.MenuName,
-          Remark: _tab.Remark,
-          PageParam: JSON.stringify({Template: _tab.type}),
-          Sort: 0
-        }
-
-        let _oriActions = []
-
-        let btnParam = {
-          func: 'sPC_Button_AddUpt',
-          Type: 40,
-          ParentID: _tab.uuid,
-          MenuNo: _tab.MenuNo,
-          Template: _tab.type,
-          PageParam: '',
-          LongParam: '',
-          LText: ''
-        }
-
-        if (modaltype === 'edit') {
-          param.LongParam = res.LongParam
-        } else {
-          let _LongParam = ''
-          let _menuId = Utils.getuuid()
-
-          // 瑙f瀽閰嶇疆
-          if (res.LongParam) {
-            try {
-              _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
-            } catch (e) {
-              console.warn('Parse Failure')
-              _LongParam = ''
-            }
-          }
-
-          if (_LongParam) {
-            try {
-              _LongParam.uuid = _menuId
-              _LongParam.tabName = _tab.MenuName
-              _LongParam.tabNo = _tab.MenuNo
-              _LongParam.Remark = _tab.Remark
-  
-              let _linkchange = {}
-              btnParam.LText = []
-  
-              _LongParam.action = _LongParam.action.map((item, index) => {
-                let uuid = Utils.getuuid()
-  
-                if (item.OpenType === 'pop') {
-                  _oriActions.push({
-                    prebtn: JSON.parse(JSON.stringify(item)),
-                    curuuid: uuid,
-                    Template: 'Modal'
-                  })
-                } else if (item.OpenType === 'popview') {
-                  _linkchange[item.linkTab] = Utils.getuuid()
-  
-                  item.linkTab = _linkchange[item.linkTab]
-                }
-  
-                item.uuid = uuid
-  
-                btnParam.LText.push(`select '${item.uuid}' as menuid, '${item.label}' as menuname, '${(index + 1) * 10}' as Sort`)
-  
-                return item
-              })
-  
-              if (_LongParam.funcs && _LongParam.funcs.length > 0) {
-                _LongParam.funcs = _LongParam.funcs.map(item => {
-                  if (item.type === 'tab') {
-                    item.linkTab = _linkchange[item.linkTab]
-                    item.menuNo = ''
-                    item.subfuncs = []
-                  }
-  
-                  return item
-                })
-              }
-  
-              btnParam.LText = btnParam.LText.join(' union all ')
-              btnParam.LText = Utils.formatOptions(btnParam.LText)
-              btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-              btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
-  
-              _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam)))
-            } catch (e) {
-              console.warn('Stringify Failure')
-              _LongParam = ''
-            }
-          }
-
-          param.MenuID = _menuId
-          param.LongParam = _LongParam
-
-          btnParam.ParentID = _menuId
-        }
-
-        new Promise(resolve => {
-          Api.getSystemConfig(param).then(response => {
-            if (response.status) {
-              resolve(true)
-            } else {
-              notification.warning({
-                top: 92,
-                message: response.message,
-                duration: 5
-              })
-              resolve(false)
-            }
-          })
-        }).then(result => {
-          if (!result) return result
-          if (modaltype === 'edit') return true
-          if (!btnParam.LText) return true
-
-          return Api.getSystemConfig(btnParam)
-        }).then(result => {
-          if (!result) return result
-          if (modaltype === 'edit') return true
-          if (!btnParam.LText) return true
-
-          if (result.status) {
-            return true
-          } else {
-            notification.warning({
-              top: 92,
-              message: result.message,
-              duration: 5
-            })
-            return false
-          }
-        }).then(result => {
-          if (!result) return result
-          if (modaltype === 'edit') return true
-          if (_oriActions.length === 0) return true
-
-          let deffers = _oriActions.map(item => {
-            return new Promise(resolve => {
-              Api.getSystemConfig({
-                func: 'sPC_Get_LongParam',
-                MenuID: item.prebtn.uuid
-              }).then(response => {
-                if (!response.status) {
-                  notification.warning({
-                    top: 92,
-                    message: response.message,
-                    duration: 5
-                  })
-                  resolve(false)
-                } else if (response.status && response.LongParam) {
-                  let _param = {
-                    func: 'sPC_ButtonParam_AddUpt',
-                    ParentID: _tab.uuid,
-                    MenuID: item.curuuid,
-                    MenuNo: _tab.MenuNo,
-                    Template: item.Template,
-                    MenuName: item.prebtn.label,
-                    PageParam: JSON.stringify({Template: item.Template}),
-                    LongParam: response.LongParam
-                  }
-                  Api.getSystemConfig(_param).then(resp => {
-                    if (!resp.status) {
-                      notification.warning({
-                        top: 92,
-                        message: resp.message,
-                        duration: 5
-                      })
-                      resolve(false)
-                    } else {
-                      resolve(true)
-                    }
-                  })
-                } else {
-                  resolve(true)
-                }
-              })
-            })
-          })
-
-          return Promise.all(deffers)
-        }).then(result => {
-          if (!result) {
-            this.setState({
-              submitloading: false
-            })
-            return
-          }
-
-          let isSuccess = true
-
-          if (typeof(result) === 'object') {
-            result.forEach(resul => {
-              if (!resul) {
-                isSuccess = false
-              }
-            })
-          }
-
-          if (isSuccess) {
-            notification.success({
-              top: 92,
-              message: '鎵ц鎴愬姛',
-              duration: 2
-            })
-          }
-
-          this.setState({
-            loading: true,
-            submitloading: false,
-            modaltype: '',
-            tabviews: null
-          }, () => {
-            this.getTabs()
-          })
-        })
-      })
-    })
-  }
-
-  triggerDraw = () => {
-    this.setState({
-      thawVisible: true
-    })
-
-    Api.getSystemConfig({
-      func: 'sPC_Get_FrozenMenu',
-      TYPE: 50
-    }).then(res => {
-      if (res.status) {
-        this.setState({
-          thawmenulist: res.data.map(menu => {
-            return {
-              key: menu.MenuID,
-              title: menu.MenuName
-            }
-          })
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-  }
-
-  thawMenuSubmit = () => {
-    if (this.refs.trawmenu.state.targetKeys.length === 0) {
-      notification.warning({
-        top: 92,
-        message: '璇烽�夋嫨瑕佽В闄ゅ喕缁撶殑鏍囩锛�',
-        duration: 5
-      })
-    } else {
-      this.setState({
-        submitloading: true
-      })
-      let defers = this.refs.trawmenu.state.targetKeys.map(item => {
-        return new Promise((resolve) => {
-          Api.getSystemConfig({
-            func: 'sPC_MainMenu_ReDel',
-            MenuID: item
-          }).then(res => {
-            if (res.status) {
-              resolve('')
-            } else {
-              resolve(res.message)
-            }
-          })
-        })
-      })
-      Promise.all(defers).then(res => {
-        let msg = res.filter(Boolean)[0]
-        if (msg) {
-          notification.error({
-            top: 92,
-            message: msg,
-            duration: 10
-          })
-          this.setState({
-            submitloading: false
-          })
-        } else {
-          notification.success({
-            top: 92,
-            message: '鎵ц鎴愬姛',
-            duration: 2
-          })
-          this.setState({
-            submitloading: false,
-            thawVisible: false,
-            thawmenulist: null,
-            tabviews: null
-          }, () => {
-            this.getTabs()
-          })
-        }
-      })
-    }
-  }
-
-  render() {
-    const { cols, tabviews, modaltype, editTab, searchKey, loading } = this.state
-
-    let _tabviews = []
-    if (tabviews) {
-      _tabviews = tabviews.filter(tab => tab.MenuName.toLowerCase().indexOf(searchKey.toLowerCase()) >= 0 || tab.MenuNo.toLowerCase().indexOf(searchKey.toLowerCase()) >= 0)
-    }
-
-    return (
-      <div className="tab-manage" id={this.state.ContainerId}>
-        {loading && <Spin size="large" />}
-        <Row>
-          <Col className="tab-search" span={6}>
-            <Search placeholder="璇疯緭鍏ユ爣绛惧悕绉�" onSearch={value => {this.setState({searchKey: value})}} enterButton />
-          </Col>
-          <Col className="tab-thaw" span={6} offset={12}>
-            <Button type="primary" onClick={this.triggerDraw}>鏍囩瑙e喕</Button>
-          </Col>
-        </Row>
-        {_tabviews.length > 0 ? <Row className="tab-list">
-          {_tabviews.map((tab, index) => {
-            return (
-              <Col span={cols} key={index}>
-                <Card
-                  className="tab-card"
-                  title={tab.MenuName}
-                >
-                  <img onClick={() => {this.previewPicture()}} src={subtableurl} alt=""/>
-                  <div className="tab-operation">
-                    <Button type="primary" onClick={() => this.handleTab(tab, 'edit')}>缂栬緫</Button>
-                    <Button className="mk-green" onClick={() => this.handleTab(tab, 'copy')}>澶嶅埗</Button>
-                    <Button type="danger" onClick={() => this.handleTab(tab, 'delete')}>鍒犻櫎</Button>
-                  </div>
-                </Card>
-              </Col>
-            )
-          })}
-        </Row> : null}
-        {tabviews && _tabviews.length === 0 ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null}
-        {/* 鏍囩淇敼鎴栧鍒� */}
-        <Modal
-          title={modaltype === 'edit' ? '鏍囩缂栬緫' : '鏍囩澶嶅埗'}
-          visible={!!modaltype}
-          width={600}
-          maskClosable={false}
-          onOk={this.handleSubmit}
-          confirmLoading={this.state.submitloading}
-          onCancel={() => {this.setState({modaltype: '', editTab: null})}}
-          destroyOnClose
-        >
-          <MutilForm
-            dict={this.state.dict}
-            tab={editTab}
-            inputSubmit={this.handleSubmit}
-            wrappedComponentRef={(inst) => this.tabFormRef = inst}
-          />
-        </Modal>
-        {/* 瑙e喕鏍囩妯℃�佹 */}
-        <Modal
-          title="鏍囩瑙i櫎鍐荤粨"
-          visible={this.state.thawVisible}
-          width={600}
-          onOk={this.thawMenuSubmit}
-          confirmLoading={this.state.submitloading}
-          onCancel={() => {this.setState({thawVisible: false, thawmenulist: null})}}
-          destroyOnClose
-        >
-          {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />}
-          {this.state.thawmenulist && <TransferForm ref="trawmenu" menulist={this.state.thawmenulist}/>}
-        </Modal>
-      </div>
-    )
-  }
-}
-
-export default TabManage
\ No newline at end of file
diff --git a/src/tabviews/tabmanage/index.scss b/src/tabviews/tabmanage/index.scss
deleted file mode 100644
index d9a7441..0000000
--- a/src/tabviews/tabmanage/index.scss
+++ /dev/null
@@ -1,58 +0,0 @@
-.tab-manage {
-  position: relative;
-  padding: 16px 20px 80px;
-
-  .tab-search {
-    .ant-input-search {
-      max-width: 300px;
-    }
-  }
-  .tab-thaw {
-    text-align: right;
-  }
-  .tab-list {
-    padding-top: 20px;
-    margin-left: -10px;
-    margin-right: -10px;
-    .ant-col {
-      padding: 0 10px 30px;
-    }
-    .tab-card {
-      .ant-card-body {
-        position: relative;
-        padding: 20px 0;
-        img {
-          max-width: 100%;
-        }
-        .tab-operation {
-          position: absolute;
-          top: -10px;
-          right: 10px;
-          opacity: 0;
-          transition: all 0.1s linear;
-
-          button {
-            margin-left: 10px;
-          }
-        }
-      }
-    }
-    .tab-card:hover {
-      .ant-card-body {
-        .tab-operation {
-          top: 10px;
-          opacity: 1;
-        }
-      }
-    }
-  }
-  .ant-empty {
-    margin: 25vh 0;
-  }
-  > .ant-spin {
-    position: fixed;
-    z-index: 10;
-    left: calc(50vw - 22px);
-    top: calc(50vh - 70px);
-  }
-}
diff --git a/src/tabviews/tabmanage/mutilform/index.jsx b/src/tabviews/tabmanage/mutilform/index.jsx
deleted file mode 100644
index 962ffb7..0000000
--- a/src/tabviews/tabmanage/mutilform/index.jsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input } from 'antd'
-import './index.scss'
-
-const { TextArea } = Input
-
-class TabHandleForm extends Component {
-  static propTpyes = {
-    tab: PropTypes.object,       // 鏍囩淇℃伅
-    dict: PropTypes.object,      // 瀛楀吀椤�
-    inputSubmit: PropTypes.func  // input鍥炶溅鎻愪氦
-  }
-
-  componentDidMount () {
-    try {
-      let _form = document.getElementById('MenuName')
-
-      if (_form && _form.select) {
-        _form.select()
-      }
-    } catch (e) {
-      console.warn('focus error锛�')
-    }
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-    this.props.inputSubmit()
-  }
-
-  render() {
-    const { getFieldDecorator } = this.props.form
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-    return (
-      <Form {...formItemLayout} className="tab-manage-form-field" id="tab-handle-form-box">
-        <Row gutter={24}>
-          <Col span={24}>
-              <Form.Item label="鏍囩鍚嶇О">
-                {getFieldDecorator('MenuName', {
-                  initialValue: this.props.tab.MenuName || '',
-                  rules: [
-                    {
-                      required: true,
-                      message: this.props.dict['form.required.input'] + '鏍囩鍚嶇О!'
-                    }
-                  ]
-                })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-              </Form.Item>
-            </Col>
-            <Col span={24}>
-              <Form.Item label="鏍囩鍙傛暟">
-                {getFieldDecorator('MenuNo', {
-                  initialValue: this.props.tab.MenuNo || '',
-                  rules: [
-                    {
-                      required: true,
-                      message: this.props.dict['form.required.input'] + '鏍囩鍙傛暟!'
-                    }
-                  ]
-                })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-              </Form.Item>
-            </Col>
-            <Col span={24}>
-              <Form.Item label="澶囨敞">
-                {getFieldDecorator('Remark', {
-                  initialValue: this.props.tab.Remark || ''
-                })(<TextArea autoSize={{ minRows: 2, maxRows: 6 }} />)}
-              </Form.Item>
-            </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(TabHandleForm)
\ No newline at end of file
diff --git a/src/tabviews/tabmanage/mutilform/index.scss b/src/tabviews/tabmanage/mutilform/index.scss
deleted file mode 100644
index f0d1e6e..0000000
--- a/src/tabviews/tabmanage/mutilform/index.scss
+++ /dev/null
@@ -1,47 +0,0 @@
-.tab-manage-form-field {
-  position: relative;
-  padding: 0px 24px 20px;
-  .ant-form-item {
-    display: flex;
-  }
-  .ant-form-item-control-wrapper {
-    flex: 1;
-  }
-  .ant-form-item-label {
-    overflow: hidden;
-    display: inline-block;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-  }
-  .textarea-row {
-    .ant-col-sm-3 {
-      width: 10.5%;
-    }
-    .ant-col-sm-21 {
-      width: 89.5%;
-    }
-  }
-  .ant-form-explain {
-    overflow:hidden;
-    text-overflow:ellipsis;
-    white-space:nowrap;
-  }
-  p {
-    color: #1890ff;
-    border-bottom: 1px solid #d9d9d9;
-  }
-  .ant-input-disabled {
-    color: rgba(0, 0, 0, 0.65)!important;
-    cursor: default!important;
-  }
-  .ant-input-number-input {
-    color: rgba(0, 0, 0, 0.65)!important;
-    cursor: default!important;
-  }
-  .ant-select-disabled {
-    color: rgba(0, 0, 0, 0.65)!important;
-    .ant-select-selection--multiple .ant-select-selection__choice {
-      color: rgba(0, 0, 0, 0.65)!important;
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/tabviews/tabmanage/transferform/index.jsx b/src/tabviews/tabmanage/transferform/index.jsx
deleted file mode 100644
index 8dd7462..0000000
--- a/src/tabviews/tabmanage/transferform/index.jsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Transfer } from 'antd'
-
-import './index.scss'
-
-class TransferForm extends Component {
-  static propTypes = {
-    menulist: PropTypes.array
-  }
-
-  state = {
-    targetKeys: [],
-    selectedKeys: []
-  }
-
-  handleChange = (nextTargetKeys, direction, moveKeys) => {
-    this.setState({ targetKeys: nextTargetKeys })
-  }
-
-  handleSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
-    this.setState({ selectedKeys: [...sourceSelectedKeys, ...targetSelectedKeys] })
-  }
-
-  render() {
-    const { targetKeys, selectedKeys } = this.state
-
-    return (
-      <div className="trawmenutransfer">
-        <Transfer
-          dataSource={this.props.menulist}
-          targetKeys={targetKeys}
-          selectedKeys={selectedKeys}
-          onChange={this.handleChange}
-          onSelectChange={this.handleSelectChange}
-          render={item => item.title}
-        />
-      </div>
-    )
-  }
-}
-
-export default TransferForm
diff --git a/src/tabviews/tabmanage/transferform/index.scss b/src/tabviews/tabmanage/transferform/index.scss
deleted file mode 100644
index 2e7be3b..0000000
--- a/src/tabviews/tabmanage/transferform/index.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-.trawmenutransfer {
-  .ant-transfer-list {
-    width: calc(50% - 20px);
-    height: 250px;
-  }
-}
\ No newline at end of file
diff --git a/src/tabviews/treepage/index.jsx b/src/tabviews/treepage/index.jsx
index 29bc25e..00b7d2f 100644
--- a/src/tabviews/treepage/index.jsx
+++ b/src/tabviews/treepage/index.jsx
@@ -5,20 +5,15 @@
 import { FolderOpenOutlined, FolderOutlined, FileOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import MKEmitter from '@/utils/events.js'
-import asyncComponent from '@/utils/asyncComponent'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import MkIcon from '@/components/mk-icon'
 import NotFount from '@/components/404'
 import './index.scss'
 
 const SubTable = asyncSpinComponent(() => import('@/tabviews/subtable'))
-const SettingComponent = asyncComponent(() => import('@/tabviews/zshare/settingcomponent'))
-const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
 
 const { TabPane } = Tabs
 const { TreeNode } = Tree
@@ -33,7 +28,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id
     loadingview: true,    // 椤甸潰鍔犺浇涓�
     BID: null,            // 椤甸潰璺宠浆鏃舵惡甯D
@@ -108,7 +102,7 @@
         this.setState({
           loadingview: false,
           viewlost: true,
-          lostmsg: this.state.dict['main.view.unenabled']
+          lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
         })
         return
       }
@@ -171,10 +165,8 @@
         }
   
         if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
-          config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
+          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
+          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/')
         } else {
           config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
           config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
@@ -182,11 +174,6 @@
 
         let userName = sessionStorage.getItem('User_Name') || ''
         let fullName = sessionStorage.getItem('Full_Name') || ''
-
-        if (sessionStorage.getItem('isEditState') === 'true') {
-          userName = sessionStorage.getItem('CloudUserName') || ''
-          fullName = sessionStorage.getItem('CloudFullName') || ''
-        }
 
         let regs = [
           { reg: /@userName@/ig, value: `'${userName}'` },
@@ -198,6 +185,8 @@
           config.setting.customScript = config.setting.customScript.replace(cell.reg, cell.value)
         })
       }
+
+      config.setting.arr_field = `${config.setting.valueField},${config.setting.labelField},${config.setting.parentField}`
 
       this.setState({
         BID: param && param.$BID ? param.$BID : '',
@@ -274,8 +263,7 @@
       loading: true
     })
 
-    let arr_field = `${setting.valueField},${setting.labelField},${setting.parentField}`
-    let param = UtilsDM.getQueryDataParams(setting, arr_field, [], setting.order, '', '', BID)
+    let param = UtilsDM.getQueryDataParams(setting, [], setting.order, '', '', BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -575,7 +563,7 @@
   }
 
   render() {
-    const { setting, loadingview, viewlost, config, tabgroups, treeNodes, treedata, expandedKeys, selectedKeys, shortcuts } = this.state
+    const { setting, loadingview, viewlost, tabgroups, treeNodes, treedata, expandedKeys, selectedKeys } = this.state
 
     return (
       <div className="tree-page" id={this.state.ContainerId}>
@@ -637,8 +625,6 @@
             )}
           </Col>
         </Row> : null}
-        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
-        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
     )
diff --git a/src/tabviews/zshare/actionList/asyncButtonComponent.jsx b/src/tabviews/zshare/actionList/asyncButtonComponent.jsx
index 008bedb..1265253 100644
--- a/src/tabviews/zshare/actionList/asyncButtonComponent.jsx
+++ b/src/tabviews/zshare/actionList/asyncButtonComponent.jsx
@@ -41,7 +41,7 @@
 
       return C ?
         <C {...this.props} /> :
-        <Button className={'mk-btn mk-' + btn.class} style={style} icon={btn.icon} disabled={true} >{btn.label}</Button>
+        <Button className={'mk-btn mk-' + btn.class} style={style} disabled={true} >{btn.label}</Button>
     }
   }
 }
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
index 9311874..d70ca80 100644
--- a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
@@ -4,8 +4,6 @@
 import { Button, notification, Modal } from 'antd'
 
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 // import './index.scss'
@@ -24,7 +22,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     disabled: false,
     hidden: false,
     loading: false
@@ -129,15 +126,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectSingleLine'],
-        duration: 5
-      })
-      return
-    } else if (!setting.primaryKey) {
-      // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾槸鍚﹁缃富閿�
-      notification.warning({
-        top: 92,
-        message: '鏈缃富閿紒',
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -174,7 +163,7 @@
     param[setting.primaryKey] = primaryId
 
     confirm({
-      title: this.state.dict['main.action.confirm.tip'],
+      title: '纭畾瑕佹墽琛屽悧?',
       onOk() {
         return new Promise(resolve => {
           Api.genericInterface(param).then(res => {
@@ -215,7 +204,7 @@
             } else {
               notification.error({
                 top: 92,
-                message: res.message || res.ErrMesg,
+                message: res.message || '鎵ц澶辫触锛�',
                 duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
               })
               _this.setState({loading: false})
diff --git a/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx
index 7610cae..ee873ec 100644
--- a/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx
+++ b/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx
@@ -27,7 +27,8 @@
   onImportExcel = file => {
     const { btn } = this.props
 
-    let columns = btn.verify.columns.map(option => option.Column)
+    let btnColumns = btn.verify.columns.filter(option => option.import !== 'init')
+    let columns = btnColumns.map(option => option.Column)
     let range = btn.verify.range || 0
 
     // excel鏁版嵁澶勭悊
@@ -58,7 +59,7 @@
             errors = 'empty'
           } else {
             let iserror = false
-            btn.verify.columns.forEach(op => {
+            btnColumns.forEach(op => {
               let _name = typeof(header[op.Column]) === 'string' ? header[op.Column].replace(/(^\s*|\s*$)/g, '') : header[op.Column]
               let _text = op.Text ? op.Text.replace(/(^\s*|\s*$)/g, '') : op.Text
 
diff --git a/src/tabviews/zshare/actionList/excelInbutton/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
index 2abe56f..2a9e4a7 100644
--- a/src/tabviews/zshare/actionList/excelInbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -6,10 +6,7 @@
 
 import ExcelIn from './excelin'
 import Utils, { getExcelInSql } from '@/utils/utils.js'
-import options from '@/store/options.js'
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 // import './index.scss'
@@ -27,7 +24,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     loading: false,
     selines: null,
     disabled: false,
@@ -134,7 +130,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectSingleLine'],
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -172,20 +168,20 @@
    * 4銆佹ā鎬佹鎵ц鎴愬姛鍚庢槸鍚﹀叧闂�
    * 5銆侀�氱煡涓诲垪琛ㄥ埛鏂�
    */
-  execSuccess = (res) => {
+  execSuccess = (res = {}) => {
     const { btn } = this.props
 
-    if (res && (res.ErrCode === 'S' || !res.ErrCode)) { // 鎵ц鎴愬姛
+    if (res.ErrCode === 'S' || !res.ErrCode) { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.ErrMesg || this.state.dict['main.action.confirm.success'],
+        message: res.message || '鎵ц鎴愬姛锛�',
         duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
       })
-    } else if (res && res.ErrCode === 'Y') { // 鎵ц鎴愬姛
+    } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.ErrMesg || this.state.dict['main.action.confirm.success']
+        title: res.message || '鎵ц鎴愬姛锛�'
       })
-    } else if (res && res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
+    } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
     }
 
@@ -216,6 +212,10 @@
       let node = document.getElementById('tab' + id)
       node && node.click()
     }
+
+    if (btn.execSuccess === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
+    }
   }
 
   /**
@@ -224,28 +224,32 @@
    * 2銆乪xcel瀵煎嚭锛屽け璐ュ悗鍙栨秷瀵煎嚭鎸夐挳鍔犺浇涓姸鎬�
    * 3銆侀�氱煡涓诲垪琛ㄥ埛鏂�
    */
-  execError = (res) => {
+  execError = (res = {}) => {
     const { btn } = this.props
+
+    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
+      res.ErrCode = 'E'
+    }
 
     if (res.ErrCode === 'E') {
       Modal.error({
-        title: res.message || res.ErrMesg,
+        title: res.message || '鎵ц澶辫触锛�',
       })
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || res.ErrMesg,
+        message: res.message || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || res.ErrMesg,
+        message: res.message || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || res.ErrMesg)
+      message.error(res.message || '鎵ц澶辫触锛�')
     }
     
     this.setState({
@@ -257,13 +261,17 @@
     } else if (btn.execError !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', this.state.selines)
     }
+
+    if (btn.execError === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
+    }
   }
 
   /**
    * @description Excel 瀵煎叆
    */
   getexceldata = (data, errors, sheetName, errDetail) => {
-    const { btn } = this.props
+    const { btn, BID } = this.props
 
     if (errors) {
       if (errors === 'notexit') {
@@ -306,7 +314,7 @@
       })
     }
 
-    let result = getExcelInSql(btn, data, (this.props.BID || ''), this.state.primaryId)
+    let result = getExcelInSql(btn, data, (BID || ''), this.state.primaryId)
 
     if (result.errors) {
       notification.warning({
@@ -323,40 +331,29 @@
       excel_in: result.lines
     }
 
-    if (this.props.BID) {
-      param.BID = this.props.BID
+    if (BID) {
+      param.BID = BID
     }
 
     if (btn.intertype === 'system') { // 绯荤粺瀛樺偍杩囩▼
       param.func = 'sPC_TableData_InUpDe'
-      
-      if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        result.sql = result.sql.replace(/\$@/ig, '/*')
-        result.sql = result.sql.replace(/@\$/ig, '*/')
-        result.bottom = result.bottom.replace(/\$@/ig, '/*')
-        result.bottom = result.bottom.replace(/@\$/ig, '*/')
-      } else {
-        result.sql = result.sql.replace(/@\$|\$@/ig, '')
-        result.bottom = result.bottom.replace(/@\$|\$@/ig, '')
-      }
-      
-      param.excel_in_type = 'true'
-      param.LText1 = Utils.formatOptions(result.insert)
-      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      param.LText2 = result.bottom
+
+      delete param.excel_in
+
+      // param.excel_in_type = 'true'
+      param.exec_type = 'y'
       param.LText = result.sql
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
 
       let unCheckParam = null
 
-      if (/\$check@|@check\$/ig.test(param.LText2) || /\$check@|@check\$/ig.test(param.LText)) {
+      if (/\$check@|@check\$/ig.test(param.LText)) {
         unCheckParam = fromJS(param).toJS()
         param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
-        param.LText2 = param.LText2.replace(/\$check@|@check\$/ig, '')
       }
 
-      param.LText2 = Utils.formatOptions(param.LText2)
       param.LText = Utils.formatOptions(param.LText)
-      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+      param.secretkey = Utils.encrypt('', param.timestamp)
       if (window.GLOB.mkHS && param.timestamp) { // 浜戠楠岃瘉
         param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
       }
@@ -370,11 +367,7 @@
       if (unCheckParam) {
         unCheckParam.LText = unCheckParam.LText.replace(/\$check@/ig, '/*').replace(/@check\$/ig, '*/')
         unCheckParam.LText = Utils.formatOptions(unCheckParam.LText)
-        unCheckParam.LText2 = unCheckParam.LText2.replace(/\$check@/ig, '/*').replace(/@check\$/ig, '*/')
-        unCheckParam.LText2 = Utils.formatOptions(unCheckParam.LText2)
-
-        unCheckParam.secretkey = Utils.encrypt(unCheckParam.LText, unCheckParam.timestamp)
-
+        unCheckParam.secretkey = Utils.encrypt('', unCheckParam.timestamp)
         unCheckParam.menuname = btn.logLabel
 
         if (window.GLOB.probation) {
@@ -387,7 +380,7 @@
           } else if (res.ErrCode === 'C') {
             const _this = this
             confirm({
-              title: '缁х画鎵ц锛�',
+              title: '璇风‘璁�',
               content: res.message,
               onOk() {
                 return new Promise(resolve => {
@@ -408,7 +401,8 @@
           } else {
             this.execError(res)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.execError({})
         })
       } else {
@@ -418,12 +412,18 @@
           } else {
             this.execError(res)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.execError({})
         })
       }
     } else if (btn.intertype === 'inner' && btn.innerFunc) { // 鑷畾涔夊瓨鍌ㄨ繃绋�
       param.func = btn.innerFunc
+
+      if (btn.recordUser === 'true') {
+        param.username = sessionStorage.getItem('User_Name') || ''
+        param.fullname = sessionStorage.getItem('Full_Name') || ''
+      }
 
       Api.genericInterface(param).then((res) => {
         if (res.status) {
@@ -431,7 +431,8 @@
         } else {
           this.execError(res)
         }
-      }, () => {
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') return
         this.execError({})
       })
     } else if (btn.intertype === 'outer') { // 澶栭儴鎺ュ彛
@@ -460,7 +461,8 @@
               this.execError(res)
               resolve(false)
             }
-          }, () => {
+          }, (error) => {
+            if (error && error.ErrCode === 'LoginError') return
             this.execError({})
           })
         } else {
@@ -472,8 +474,8 @@
         _outParam = fromJS(res).toJS()
 
         if (window.GLOB.mkHS) {
-          if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-            param.rduri = options.cloudServiceApi
+          if (btn.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+            param.rduri = window.GLOB.cloudServiceApi
             param.userid = sessionStorage.getItem('CloudUserID') || ''
             param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
           } else if (btn.sysInterface !== 'true') {
@@ -513,7 +515,8 @@
         }
         
         if (window.GLOB.mkHS && res.func === 's_sDataDictb_excelIn') { // s_sDataDictb_excelIn 浜戠楠岃瘉
-          param.LText = Utils.formatOptions(result.sql)
+          let sql = `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),@tbid Nvarchar(512)`
+          param.LText = Utils.formatOptions(sql)
           param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
           param.secretkey = Utils.encrypt(param.LText, param.timestamp)
           param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
@@ -521,7 +524,7 @@
 
         return Api.genericInterface(res)
       }).then(response => {
-        if (!response) return
+        if (!response || response.ErrCode === 'LoginError') return
         // 鍥炶皟璇锋眰
         if (ver_token && response.ErrMesg === 'token_error') {
           this.execError(response)
@@ -542,7 +545,7 @@
           }
         }
       }).then(res => {
-        if (!res) return
+        if (!res || res.ErrCode === 'LoginError') return
 
         if (res.status) {
           this.execSuccess(res)
diff --git a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
index 78fc739..0cab6e9 100644
--- a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -6,10 +6,8 @@
 import * as XLSX from 'sheetjs-style'
 
 import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
 import Api from '@/api'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
+import UtilsDM from '@/utils/utils-datamanage.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 // import './index.scss'
@@ -21,14 +19,10 @@
     selectedData: PropTypes.any,      // 瀛愯〃涓�夋嫨鏁版嵁
     btn: PropTypes.object,            // 鎸夐挳
     setting: PropTypes.any,           // 椤甸潰閫氱敤璁剧疆
-    updateStatus: PropTypes.func,     // 鎸夐挳鐘舵�佹洿鏂�
     disabled: PropTypes.any,          // 琛屾寜閽鐢�
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    excelName: '',  // 鏂囦欢鍚�
-    search: '',     // 鎼滅储鏉′欢
     loading: false, // 瀵煎嚭涓�
     hidden: false,
     disabled: false
@@ -92,22 +86,6 @@
     }
     MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
   }
-
-  /**
-   * @description 鎸夐挳鐘舵�佹敼鍙�
-   */
-  updateStatus = (type, name) => {
-    if (type === 'start') {
-      this.setState({
-        loading: true,
-        excelName: name
-      })
-    } else if (type === 'over') {
-      this.setState({
-        loading: false
-      })
-    }
-  }
   
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
@@ -130,17 +108,17 @@
       return
     }
 
-    if (!btn.verify || !btn.verify.columns || btn.verify.columns.length === 0) {
+    if (btn.errorType === 'error1') {
       notification.warning({
         top: 92,
         message: '璇疯缃鍑哄垪锛�',
         duration: 5
       })
       return
-    } else if (btn.intertype === 'system' && setting.interType !== 'system' && btn.verify.dataType !== 'custom') {
+    } else if (btn.errorType === 'error2') {
       notification.warning({
         top: 92,
-        message: '瀵煎嚭鎸夐挳閰嶇疆閿欒锛�',
+        message: '鎸夐挳闇�鑷畾涔夊鍑烘暟鎹簮锛�',
         duration: 5
       })
       return
@@ -158,10 +136,11 @@
   triggerExcelout = (viewParam) => {
     const { btn } = this.props
 
-    let name = `${viewParam.menuName}${moment().format('YYYYMMDDHHmmss')}.xlsx`
     let pageSize = 1000
 
-    if (((btn.intertype === 'system' && btn.verify.dataType === 'custom' && btn.verify.useSearch === 'true') || btn.intertype !== 'system' || btn.verify.dataType !== 'custom') && btn.search === 'true' && viewParam.search && viewParam.search.length > 0) {
+    if (btn.intertype === 'system' && btn.verify.dataType === 'custom' && btn.verify.useSearch === 'false') {
+      viewParam.search = []
+    } else if (((btn.intertype === 'system' && btn.verify.dataType === 'custom' && btn.verify.useSearch === 'true') || btn.intertype !== 'system' || btn.verify.dataType !== 'custom') && btn.search === 'true' && viewParam.search && viewParam.search.length > 0) {
       let valid = false
       viewParam.search.forEach(item => {
         if (item.value || item.value === 0) {
@@ -179,69 +158,49 @@
       }
     }
 
-    if (btn.intertype === 'system') { // 浣跨敤绯荤粺鍑芥暟
-      if (btn.verify.dataType !== 'custom' && !viewParam.arr_field) {
-        notification.warning({
-          top: 92,
-          message: '鎸夐挳闇�鑷畾涔夊鍑烘暟鎹紒',
-          duration: 5
-        })
-        return
-      } else if (btn.verify.dataType === 'custom') {
-        viewParam.arr_field = []
-        btn.verify.columns.forEach(col => {
-          if (col.Column && col.Column !== '$Index') {
-            viewParam.arr_field.push(col.Column)
-          }
-        })
-        viewParam.arr_field = viewParam.arr_field.join(',')
-
-        viewParam.orderBy = btn.verify.order || ''
-      }
-    }
-    if (btn.intertype === 'system' && btn.verify.enable === 'true') {
-      this.setState({search: fromJS(viewParam.search).toJS()})
-    }
-    if (btn.intertype === 'system' && btn.verify.dataType === 'custom' && btn.verify.useSearch === 'false') {
-      viewParam.search = []
-    }
-
-    viewParam.orderBy = viewParam.orderBy || viewParam.arr_field.split(',')[0]
-    
-    this.updateStatus('start', name)
+    this.setState({
+      loading: true
+    })
 
     if (btn.pagination !== 'true') {
       if (btn.intertype === 'system') { // 浣跨敤绯荤粺鍑芥暟
-        let param = this.getExcelDefaultParam(viewParam.arr_field, viewParam.orderBy, viewParam.search)
+        let param = this.getExcelDefaultParam(viewParam.orderBy, viewParam.search)
 
         Api.genericInterface(param).then(result => {
           if (result.status) {
-            this.exportExcel(result.data)
+            this.exportExcel(result.data, result.ErrCode, result.message)
           } else {
             this.execError(result)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.execError({})
         })
       } else if (btn.intertype === 'inner') { // 浣跨敤鍐呴儴鍑芥暟
         let param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search)
         param.func = btn.innerFunc
 
+        if (btn.recordUser === 'true') {
+          param.username = sessionStorage.getItem('User_Name') || ''
+          param.fullname = sessionStorage.getItem('Full_Name') || ''
+        }
+
         Api.genericInterface(param).then(result => {
           if (result.status) {
-            this.exportExcel(result.data)
+            this.exportExcel(result.data, result.ErrCode, result.message)
           } else {
             this.execError(result)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.execError({})
         })
       } else if (btn.intertype === 'outer' && !btn.innerFunc) { // 浣跨敤澶栭儴鍑芥暟
         let param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search)
 
         if (window.GLOB.mkHS) {
-          if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-            param.rduri = options.cloudServiceApi
+          if (btn.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+            param.rduri = window.GLOB.cloudServiceApi
             param.userid = sessionStorage.getItem('CloudUserID') || ''
             param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
           } else if (btn.sysInterface !== 'true') {
@@ -281,11 +240,12 @@
 
         Api.genericInterface(param).then(result => {
           if (result.status) {
-            this.exportExcel(result.data)
+            this.exportExcel(result.data, result.ErrCode, result.message)
           } else {
             this.execError(result)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.execError({})
         })
       } else if (btn.intertype === 'outer' && btn.innerFunc) {
@@ -300,8 +260,8 @@
             delete res.status
 
             if (window.GLOB.mkHS) {
-              if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-                res.rduri = options.cloudServiceApi
+              if (btn.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+                res.rduri = window.GLOB.cloudServiceApi
                 res.userid = sessionStorage.getItem('CloudUserID') || ''
                 res.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
               } else if (btn.sysInterface !== 'true') {
@@ -341,7 +301,7 @@
       
             Api.genericInterface(res).then(result => {
               if (result.status) {
-                this.exportExcel(result.data)
+                this.exportExcel(result.data, result.ErrCode, result.message)
               } else {
                 this.execError(result)
               }
@@ -349,7 +309,8 @@
           } else {
             this.execError(res)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.execError({})
         })
       } else {
@@ -358,7 +319,9 @@
           message: '瀵煎嚭鎸夐挳璁剧疆閿欒锛�',
           duration: 5
         })
-        this.updateStatus('over')
+        this.setState({
+          loading: false
+        })
       }
     } else if (btn.intertype === 'outer' && btn.innerFunc) { // 鍒嗛〉锛屼笖涓ゆ璇锋眰
       this.getExcelOutDoubleData(viewParam, 1, pageSize, [])
@@ -383,8 +346,8 @@
         delete res.status
 
         if (window.GLOB.mkHS) {
-          if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-            res.rduri = options.cloudServiceApi
+          if (btn.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+            res.rduri = window.GLOB.cloudServiceApi
             res.userid = sessionStorage.getItem('CloudUserID') || ''
             res.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
           } else if (btn.sysInterface !== 'true') {
@@ -432,18 +395,20 @@
               this.getExcelOutDoubleData(viewParam, pageIndex, pageSize, data)
             } else {
               data = data.concat(result.data)
-              this.exportExcel(data)
+              this.exportExcel(data, result.ErrCode, result.message)
             }
           } else {
             this.execError(result)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.execError({})
         })
       } else {
         this.execError(res)
       }
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.execError({})
     })
   }
@@ -455,22 +420,22 @@
     const { btn } = this.props
     let param = null
     if (btn.intertype === 'system') { // 浣跨敤绯荤粺鍑芥暟
-      if (!viewParam.arr_field) {
-        this.execError({ErrCode: 'N', message: '鏈缃樉绀哄垪锛�'})
-        return
-      }
-
-      param = this.getExcelDefaultParam(viewParam.arr_field, viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
+      param = this.getExcelDefaultParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
     } else if (btn.intertype === 'inner') { // 浣跨敤鍐呴儴鍑芥暟
       param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
       param.func = btn.innerFunc
+
+      if (btn.recordUser === 'true') {
+        param.username = sessionStorage.getItem('User_Name') || ''
+        param.fullname = sessionStorage.getItem('Full_Name') || ''
+      }
 
     } else if (btn.intertype === 'outer' && !btn.innerFunc) { // 浣跨敤澶栭儴鍑芥暟
       param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
 
       if (window.GLOB.mkHS) {
-        if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-          param.rduri = options.cloudServiceApi
+        if (btn.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+          param.rduri = window.GLOB.cloudServiceApi
           param.userid = sessionStorage.getItem('CloudUserID') || ''
           param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         } else if (btn.sysInterface !== 'true') {
@@ -520,12 +485,13 @@
           this.getExcelOutData(viewParam, pageIndex, pageSize, data)
         } else {
           data = data.concat(result.data)
-          this.exportExcel(data)
+          this.exportExcel(data, result.ErrCode, result.message)
         }
       } else {
         this.execError(result)
       }
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.execError({})
     })
   }
@@ -533,7 +499,7 @@
   /**
    * @description Excel 鐢熸垚
    */
-  exportExcel = (data) => {
+  exportExcel = (data, ErrCode, message) => {
     const { btn } = this.props
     
     let imgCol = false
@@ -550,6 +516,29 @@
 
       return col
     })
+
+    if (data && data[0]) {
+      let errors = []
+      columns.forEach(col => {
+        if (col.Column && data[0][col.Column] === undefined) {
+          errors.push(col.Text)
+        }
+      })
+
+      if (errors.length) {
+        notification.error({
+          top: 92,
+          message: '鏁版嵁涓己灏戝瓧娈碉細' + errors.join('銆�'),
+          duration: 5
+        })
+
+        this.setState({
+          loading: false
+        })
+        
+        return
+      }
+    }
     
     try {
       if (imgCol) {
@@ -576,13 +565,13 @@
   
           columns.forEach((col, i) => {
             let val = item[col.Column]
-            if (typeof(val) === 'number') {
+            if (col.type === 'number' && typeof(val) === 'number') {
               if (col.abs === 'true') {
                 val = Math.abs(val)
               }
               if (col.round) {
                 val = Math.round(val * col.round) / col.round
-                val = val.toFixed(col.decimal)
+                // val = val.toFixed(col.decimal)
               }
             }
 
@@ -592,13 +581,9 @@
           table.push(_row)
         })
 
-        this.table2excel(column, table, this.state.excelName.replace(/\.xlsx/ig, '.xls'))
+        this.table2excel(column, table)
 
-        if (btn.verify.enable === 'true' && btn.verify.script) {
-          this.execCustomScript()
-        } else {
-          this.execSuccess({ErrCode: 'S', ErrMesg: '瀵煎嚭鎴愬姛锛�'})
-        }
+        this.execSuccess({ErrCode: ErrCode || 'S', message: message || '瀵煎嚭鎴愬姛锛�'})
       } else {
         let letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
         let cols = []
@@ -665,13 +650,13 @@
           columns.forEach((col, i) => {
             let val = item[col.Column]
 
-            if (typeof(val) === 'number') {
+            if (col.type === 'number' && typeof(val) === 'number') {
               if (col.abs === 'true') {
                 val = Math.abs(val)
               }
               if (col.round) {
                 val = Math.round(val * col.round) / col.round
-                val = val.toFixed(col.decimal)
+                // val = val.toFixed(col.decimal)
               }
             }
 
@@ -733,20 +718,16 @@
         const wb = XLSX.utils.book_new()
         XLSX.utils.book_append_sheet(wb, ws, btn.verify.sheet || 'Sheet1')
   
-        XLSX.writeFile(wb, this.state.excelName)
+        XLSX.writeFile(wb, `${btn.$menuName || ''}${moment().format('YYYYMMDDHHmmss')}.xlsx`)
   
-        if (btn.verify.enable === 'true' && btn.verify.script) {
-          this.execCustomScript()
-        } else {
-          this.execSuccess({ErrCode: 'S', ErrMesg: '瀵煎嚭鎴愬姛锛�'})
-        }
+        this.execSuccess({ErrCode: ErrCode || 'S', message: message || '瀵煎嚭鎴愬姛锛�'})
       }
     } catch (e) {
       this.execError({ErrCode: 'N', message: 'Excel鐢熸垚澶辫触锛�'})
     }
   }
 
-  table2excel = (column, data, excelName) => {
+  table2excel = (column, data) => {
     let thead = column.reduce((result, item) => {
       return result + `<th>${item.title}</th>`
     }, '')
@@ -780,71 +761,10 @@
     // let url = 'data:application/vnd.ms-excel;base64,' + window.btoa(unescape(encodeURIComponent(html)))
     let link = document.createElement('a')
     link.href = url
-    link.download = excelName
+    link.download = `${this.props.btn.$menuName || ''}${moment().format('YYYYMMDDHHmmss')}.xls`
     document.body.appendChild(link)
     link.click()
     document.body.removeChild(link)
-  }
-  
-
-  /**
-   * @description 鎵ц鑷畾涔夎剼鏈�
-   */
-  execCustomScript = () => {
-    const { btn } = this.props
-    const { search } = this.state
-    let script = btn.verify.script
-
-    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-      script = script.replace(/\$@/ig, '/*')
-      script = script.replace(/@\$/ig, '*/')
-    } else {
-      script = script.replace(/@\$|\$@/ig, '')
-    }
-
-    let allSearch = Utils.getAllSearchOptions(search)
-    let regoptions = allSearch.map(item => {
-      return {
-        reg: new RegExp('@' + item.key + '@', 'ig'),
-        value: `'${item.value}'`
-      }
-    })
-
-    regoptions.forEach(item => {
-      script = script.replace(item.reg, item.value)
-    })
-
-    let param = {
-      func: 'sPC_TableData_InUpDe',
-      menuname: btn.logLabel
-    }
-
-    if (this.props.BID) {
-      param.BID = this.props.BID
-    }
-
-    param.exec_type = 'y' // 鍚庡彴瑙g爜
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt('', param.timestamp)
-    param.LText = Utils.formatOptions(script)
-
-    if (window.GLOB.mkHS) { // 绯荤粺鍑芥暟浜戠楠岃瘉
-      param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
-    }
-
-    if (window.GLOB.probation) {
-      param.s_debug_type = 'Y'
-    }
-
-    Api.genericInterface(param).then((res) => {
-      if (res.status) {
-        this.execSuccess({ErrCode: 'S', ErrMesg: '瀵煎嚭鎴愬姛锛�'})
-      } else {
-        this.execError(res)
-      }
-    }, () => {
-      this.updateStatus('over')
-    })
   }
 
   /**
@@ -886,198 +806,89 @@
   /**
    * @description 鑾峰彇榛樿瀛樺偍杩囩▼璇锋眰鍙傛暟
    */
-  getExcelDefaultParam = (arr_field, orderBy, search, pagination = false, pageIndex = 1, pageSize = 100) => {
+  getExcelDefaultParam = (orderBy, search, pagination = false, pageIndex = 1, pageSize = 9999) => {
     const { setting, btn, selectedData, BID } = this.props
 
-    let defaultSql = setting.execute || setting.default || 'true'
-    let customScript = setting.customScript || ''
-    let _dataresource = setting.dataresource || ''
-    let queryType = setting.queryType
-    let primaryKey = setting.primaryKey || 'ID'
-
+    let _setting = {}
+    let _orderBy = orderBy || ''
     if (btn.verify.dataType === 'custom') {
-      defaultSql = btn.verify.defaultSql || 'true'
-      _dataresource = btn.verify.dataresource || ''
-      queryType = btn.verify.queryType
-      // primaryKey = btn.verify.primaryKey || 'ID'
+      _setting.arr_field = []
 
-      if (/\s/.test(_dataresource)) {
-        _dataresource = '(' + _dataresource + ') tb'
+      btn.verify.columns.forEach(col => {
+        if (col.Column && col.Column !== '$Index') {
+          _setting.arr_field.push(col.Column)
+        }
+      })
+      _setting.arr_field = _setting.arr_field.join(',')
+      _setting.execute = btn.verify.defaultSql !== 'false'
+      _setting.dataresource = btn.verify.dataresource || ''
+      _setting.primaryKey = _setting.primaryKey || setting.primaryKey || 'ID'
+
+      if (!_setting.execute) {
+        _setting.dataresource = ''
       }
-      customScript = ''
+
+      if (/\s/.test(_setting.dataresource)) {
+        _setting.dataresource = '(' + _setting.dataresource + ') tb'
+      }
+
+      let _customScript = ''
+      let _tailScript = ''
       btn.verify.scripts && btn.verify.scripts.forEach(script => {
-        if (script.status !== 'false') {
-          customScript += `
+        if (script.status === 'false') return
+        if (script.position !== 'back') {
+          _customScript += `
+          ${script.sql}
+          `
+        } else {
+          _tailScript += `
           ${script.sql}
           `
         }
       })
 
       if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        _dataresource = _dataresource.replace(/\$@/ig, '/*')
-        _dataresource = _dataresource.replace(/@\$/ig, '*/')
-        customScript = customScript.replace(/\$@/ig, '/*')
-        customScript = customScript.replace(/@\$/ig, '*/')
+        _setting.dataresource = _setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
       } else {
-        _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
-        customScript = customScript.replace(/@\$|\$@/ig, '')
+        _setting.dataresource = _setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
       }
-    }
 
-    let _search = Utils.joinMainSearchkey(search)
+      _setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+      _setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-    _search = _search ? 'where ' + _search : ''
-    
-    let param = {
-      func: 'sPC_Get_TableData',
-      obj_name: 'data',
-      arr_field: arr_field,
-      custom_script: customScript,
-      default_sql: defaultSql,
-      menuname: btn.logLabel
-    }
+      _setting.laypage = pagination
+      _setting.custompage = /@pageSize@|@orderBy@/i.test(_setting.dataresource + _setting.customScript)
 
-    if (btn.verify.dataType !== 'custom' && setting.sub_field) {
-      arr_field = arr_field + ',' + setting.sub_field
-      param.arr_field = arr_field
-    }
+      _setting.queryType = btn.verify.queryType
+      _setting.$name = btn.logLabel
 
-    // 鏁版嵁绠$悊鏉冮檺
-    if (sessionStorage.getItem('dataM') === 'true') {
-      param.dataM = 'Y'
-    }
-
-    if (BID) {
-      param.BID = BID
-    }
-
-    let userName = sessionStorage.getItem('User_Name') || ''
-    let fullName = sessionStorage.getItem('Full_Name') || ''
-    let RoleID = sessionStorage.getItem('role_id') || ''
-    let departmentcode = sessionStorage.getItem('departmentcode') || ''
-    let organization = sessionStorage.getItem('organization') || ''
-    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
-    let nation = sessionStorage.getItem('nation') || ''
-    let province = sessionStorage.getItem('province') || ''
-    let city = sessionStorage.getItem('city') || ''
-    let district = sessionStorage.getItem('district') || ''
-    let address = sessionStorage.getItem('address') || ''
-
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
-
-    let regoptions = null
-    if (queryType === 'statistics' || param.custom_script) {
-      let allSearch = Utils.getAllSearchOptions(search)
-
-      regoptions = allSearch.map(item => {
-        return {
-          reg: new RegExp('@' + item.key + '@', 'ig'),
-          value: `'${item.value}'`
-        }
-      })
-
-      regoptions.push({
-        reg: new RegExp('@userName@', 'ig'),
-        value: userName
-      }, {
-        reg: new RegExp('@fullName@', 'ig'),
-        value: fullName
-      }, {
-        reg: new RegExp('@orderBy@', 'ig'),
-        value: orderBy || ''
-      }, {
-        reg: new RegExp('@pageSize@', 'ig'),
-        value: pageSize
-      }, {
-        reg: new RegExp('@pageIndex@', 'ig'),
-        value: pageIndex
-      })
-    }
-
-    if (queryType === 'statistics') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲
-      regoptions.forEach(item => {
-        _dataresource = _dataresource.replace(item.reg, item.value)
-      })
-      _search = ''
+      _orderBy = btn.verify.order || ''
+    } else {
+      _setting = {...setting}
+      _setting.laypage = pagination
+      _setting.arr_field = _setting.all_field || _setting.arr_field
     }
 
     let primaryId = ''
     if (btn.Ot === 'requiredOnce' && selectedData && selectedData.length > 0) {
       primaryId = selectedData.map(d => d.$$uuid || '').filter(Boolean).join(',')
-      if (_search && primaryId) {
-        _search += ` and ${primaryKey} in (select ID from dbo.SplitComma('${primaryId}'))`
-      } else if (primaryId) {
-        _search = `where ${primaryKey} in (select ID from dbo.SplitComma('${primaryId}'))`
-      }
+      primaryId = primaryId ? 'excel:' + primaryId : ''
     }
 
-    let LText = ''
-
-    if (defaultSql !== 'false' && !pagination) {
-      LText = ` select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
-    } else if (defaultSql !== 'false') {
-      LText = ` select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
-    }
-
-    if (param.custom_script) {
-      param.custom_script = `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='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
-        ${param.custom_script}
-      `
-      regoptions.forEach(item => {
-        param.custom_script = param.custom_script.replace(item.reg, item.value)
-      })
-
-      if (LText) {
-        LText += `
-          aaa:
-          if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
-        `
-      } else {
-        param.custom_script += `
-          aaa:
-          if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
-        `
-      }
-    } else if (LText) {
-      LText = `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='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
-        ${LText}
-      `
-    }
-
-    LText = LText.replace(/@ID@/ig, `'${primaryId || ''}'`)
-    param.custom_script = param.custom_script.replace(/@ID@/ig, `'${primaryId || ''}'`)
-    LText = LText.replace(/@BID@/ig, `'${BID}'`)
-    param.custom_script = param.custom_script.replace(/@BID@/ig, `'${BID}'`)
-    LText = LText.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    param.custom_script = param.custom_script.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    LText = LText.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    param.custom_script = param.custom_script.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    LText = LText.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    param.custom_script = param.custom_script.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    LText = LText.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    param.custom_script = param.custom_script.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    LText = LText.replace(/@typename@/ig, `'admin'`)
-    param.custom_script = param.custom_script.replace(/@typename@/ig, `'admin'`)
-
-    // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
-      param.custom_script && console.info(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`)
-      LText && console.info(LText)
-    }
+    let param = UtilsDM.getDefaultQueryParam(_setting, search, _orderBy, pageIndex, pageSize, primaryId, BID)
     
-    param.custom_script = Utils.formatOptions(param.custom_script)
-    param.LText = Utils.formatOptions(LText)
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
     param.DateCount = ''
 
-    if (window.GLOB.mkHS) { // 浜戠鏁版嵁楠岃瘉
-      param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+    // 鏁版嵁绠$悊鏉冮檺
+    if (sessionStorage.getItem('dataM') === 'true') {
+      param.dataM = 'Y'
+    }
+    if (BID) {
+      param.BID = BID
     }
 
     return param
@@ -1094,17 +905,17 @@
   execSuccess = (res) => {
     const { btn } = this.props
 
-    if (res && (res.ErrCode === 'S' || !res.ErrCode)) { // 鎵ц鎴愬姛
+    if (res.ErrCode === 'S') { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.ErrMesg || this.state.dict['main.action.confirm.success'],
+        message: res.message,
         duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
       })
-    } else if (res && res.ErrCode === 'Y') { // 鎵ц鎴愬姛
+    } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.ErrMesg || this.state.dict['main.action.confirm.success']
+        title: res.message
       })
-    } else if (res && res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
+    } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
     }
     
@@ -1135,6 +946,10 @@
       let node = document.getElementById('tab' + id)
       node && node.click()
     }
+
+    if (btn.execSuccess === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
+    }
   }
 
   /**
@@ -1143,28 +958,32 @@
    * 2銆乪xcel瀵煎嚭锛屽け璐ュ悗鍙栨秷瀵煎嚭鎸夐挳鍔犺浇涓姸鎬�
    * 3銆侀�氱煡涓诲垪琛ㄥ埛鏂�
    */
-  execError = (res) => {
+  execError = (res = {}) => {
     const { btn } = this.props
+
+    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
+      res.ErrCode = 'E'
+    }
 
     if (res.ErrCode === 'E') {
       Modal.error({
-        title: res.message || res.ErrMesg,
+        title: res.message || '鎵ц澶辫触锛�',
       })
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || res.ErrMesg,
+        message: res.message || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || res.ErrMesg,
+        message: res.message || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || res.ErrMesg)
+      message.error(res.message || '鎵ц澶辫触锛�')
     }
     
     this.setState({
@@ -1175,6 +994,10 @@
       MKEmitter.emit('popclose')
     } else if (btn.execError !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', [])
+    }
+
+    if (btn.execError === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
     }
   }
 
@@ -1211,6 +1034,7 @@
     return (
       <Button
         type={type}
+        id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         loading={loading}
         disabled={disabled}
diff --git a/src/tabviews/zshare/actionList/funczip/index.jsx b/src/tabviews/zshare/actionList/funczip/index.jsx
index 124190f..28d6ed2 100644
--- a/src/tabviews/zshare/actionList/funczip/index.jsx
+++ b/src/tabviews/zshare/actionList/funczip/index.jsx
@@ -348,6 +348,10 @@
     if (btn.execSuccess !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
     }
+
+    if (btn.execSuccess === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
+    }
   }
 
   /**
@@ -399,6 +403,10 @@
     if (btn.execError !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
     }
+
+    if (btn.execError === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
+    }
   }
 
   render() {
diff --git a/src/tabviews/zshare/actionList/index.jsx b/src/tabviews/zshare/actionList/index.jsx
index 8723fa0..4852e23 100644
--- a/src/tabviews/zshare/actionList/index.jsx
+++ b/src/tabviews/zshare/actionList/index.jsx
@@ -129,6 +129,7 @@
             key={item.uuid}
             show={item.show || 'actionList'}
             disabled={false}
+            BID={BID}
             btn={item}
             BData={BData}
             selectedData={selectedData}
diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
index 94b50d8..756c068 100644
--- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx
+++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -3,8 +3,6 @@
 import { is, fromJS } from 'immutable'
 import { Button, notification, Modal } from 'antd'
 
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 import './index.scss'
@@ -13,6 +11,7 @@
 
 class NewPageButton extends Component {
   static propTpyes = {
+    BID: PropTypes.any,               // BID
     BData: PropTypes.any,             // 涓昏〃鏁版嵁
     btn: PropTypes.object,            // 鎸夐挳
     selectedData: PropTypes.any,      // 瀛愯〃涓�夋嫨鏁版嵁
@@ -20,7 +19,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     disabled: false,
     hidden: false,
     visible: false
@@ -102,7 +100,7 @@
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
   actionTrigger = (triggerId, record, type) => {
-    const { btn, selectedData } = this.props
+    const { btn, selectedData, BID } = this.props
     const { disabled } = this.state
 
     if (disabled) return
@@ -114,11 +112,11 @@
 
     let data = record || selectedData || []
 
-    if (btn.Ot && btn.Ot !== 'notRequired' && data.length === 0) {
+    if (btn.Ot !== 'notRequired' && data.length === 0) {
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectline'],
+        message: '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return
@@ -126,7 +124,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectSingleLine'],
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -154,14 +152,18 @@
 
     if (btn.pageTemplate === 'billprint') {
       _name = '鍗曟嵁鎵撳嵃'
-      if (btn.Ot === 'required' && data && data.length > 0) {
-        data.forEach((item, i) => {
+      if (btn.Ot === 'required') {
+        data.forEach(item => {
           let _id = item.$$uuid || ''
-          let url = '#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: _id, tempId: btn.printTemp, dataM: sessionStorage.getItem('dataM') })))
+          let url = '#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: _id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') })))
           window.open(url)
         })
+      } else if (btn.Ot === 'requiredOnce') {
+        Id = data.map(item => item.$$uuid).filter(Boolean).join(',')
+
+        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
       } else {
-        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, dataM: sessionStorage.getItem('dataM') }))))
+        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
       }
     } else if (btn.pageTemplate === 'billprintTemp') {
       let src = '#/menudesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'billPrint', MenuId: Id, MenuNo: MenuNo, MenuName: name || '鎵撳嵃', Remark: Remark })))
@@ -193,18 +195,43 @@
       window.open(url)
     } else if (btn.pageTemplate === 'custom') {
       let url = btn.url
+      if (window.GLOB.systemType === 'production' && btn.proUrl) {
+        url = btn.proUrl
+      }
+
+      if (btn.Ot === 'notRequired' && BID) {
+        Id = BID
+      }
+      
+      if (/#\/iframe\//.test(url)) {
+        url = url.replace(/@loginuid@/ig, sessionStorage.getItem('LoginUID'))
+
+        if (btn.joint === 'true' && Id) {
+          url = url + '/' + Id
+        }
+
+        let menu = {
+          MenuID: btn.uuid,
+          MenuName: btn.label,
+          type: 'iframe',
+          OpenType: 'newtab',
+          src: url
+        }
+        MKEmitter.emit('modifyTabs', menu)
+
+        return
+      }
+      
       let con = '?'
 
       if (/\?/ig.test(url)) {
         con = '&'
       }
-      
-      if (btn.Ot === 'requiredSgl' && btn.joint !== 'false') {
+
+      if (btn.joint === 'true') {
         url = url + `${con}id=${Id}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
-      } else if (btn.Ot === 'requiredSgl' && btn.joint === 'false') {
+      } else if (Id) {
         url = url + `${con}id=${Id}`
-      } else if (btn.joint !== 'false') {
-        url = url + `${con}appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
       }
 
       window.open(url)
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index 8b9b3ea..a5c366c 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -4,12 +4,10 @@
 import qs from 'qs'
 import { is, fromJS } from 'immutable'
 import { Button, Modal, notification, message, Drawer, Switch, Checkbox, Progress } from 'antd'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils, { getSysDefaultSql } from '@/utils/utils.js'
-import options from '@/store/options.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import { updateForm } from '@/utils/utils-update.js'
 import MKEmitter from '@/utils/events.js'
@@ -33,7 +31,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     visible: false,
     formdata: null,
     selines: null,
@@ -62,7 +59,7 @@
     
     if (btn.OpenType === 'form') {
       let data = selectedData && selectedData[0] ? selectedData[0] : null
-      if (btn.formType === 'counter') {
+      if (btn.formType === 'counter' || btn.formType === 'count_line') {
         let count = 0
         if (data && data[btn.field]) {
           count = +data[btn.field]
@@ -109,7 +106,7 @@
 
     if (btn.OpenType === 'form') {
       let data = nextProps.selectedData && nextProps.selectedData[0] ? nextProps.selectedData[0] : null
-      if (btn.formType === 'counter') {
+      if (btn.formType === 'counter' || btn.formType === 'count_line') {
         let count = 0
         if (data && data[btn.field]) {
           count = +data[btn.field]
@@ -259,7 +256,7 @@
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectline'],
+        message: '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return
@@ -267,15 +264,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectSingleLine'],
-        duration: 5
-      })
-      return
-    } else if (!['requiredSgl', 'notRequired', 'requiredOnce', 'required'].includes(btn.Ot)) {
-      // 鏁版嵁閫夋嫨绫诲瀷鏍¢獙
-      notification.warning({
-        top: 92,
-        message: '鎸夐挳琛岃缃敊璇紒',
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -330,6 +319,9 @@
         return
       }
     } else if (!['inner', 'outer', 'system', 'custom'].includes(btn.intertype)) {
+      if (btn.OpenType === 'form' && btn.formType === 'count_line') {
+        return
+      }
       // 鎺ュ彛绫诲瀷閿欒
       notification.warning({
         top: 92,
@@ -351,7 +343,7 @@
     } else if (btn.OpenType === 'prompt') {
       this.setState({loading: true})
       confirm({
-        title: btn.tipTitle || this.state.dict['main.action.confirm.tip'],
+        title: btn.tipTitle || '纭畾瑕佹墽琛屽悧?',
         onOk() {
           return new Promise(resolve => {
             _this.execSubmit(data, resolve)
@@ -460,10 +452,9 @@
         }
 
         if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-          param.LText = param.LText.replace(/\$@/ig, '/*')
-          param.LText = param.LText.replace(/@\$/ig, '*/')
+          param.LText = param.LText.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
         } else {
-          param.LText = param.LText.replace(/@\$|\$@/ig, '')
+          param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
         }
 
         param.exec_type = 'y' // 鍚庡彴瑙g爜
@@ -503,10 +494,9 @@
           }
           
           if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-            param.LText = param.LText.replace(/\$@/ig, '/*')
-            param.LText = param.LText.replace(/@\$/ig, '*/')
+            param.LText = param.LText.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
           } else {
-            param.LText = param.LText.replace(/@\$|\$@/ig, '')
+            param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
           }
 
           param.exec_type = 'y' // 鍚庡彴瑙g爜
@@ -536,10 +526,9 @@
           }
           
           if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-            param.LText = param.LText.replace(/\$@/ig, '/*')
-            param.LText = param.LText.replace(/@\$/ig, '*/')
+            param.LText = param.LText.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
           } else {
-            param.LText = param.LText.replace(/@\$|\$@/ig, '')
+            param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
           }
 
           param.exec_type = 'y' // 鍚庡彴瑙g爜
@@ -609,10 +598,9 @@
           }
           
           if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-            param.LText = param.LText.replace(/\$@/ig, '/*')
-            param.LText = param.LText.replace(/@\$/ig, '*/')
+            param.LText = param.LText.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
           } else {
-            param.LText = param.LText.replace(/@\$|\$@/ig, '')
+            param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
           }
 
           param.exec_type = 'y' // 鍚庡彴瑙g爜
@@ -656,10 +644,9 @@
             }
             
             if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-              param.LText = param.LText.replace(/\$@/ig, '/*')
-              param.LText = param.LText.replace(/@\$/ig, '*/')
+              param.LText = param.LText.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
             } else {
-              param.LText = param.LText.replace(/@\$|\$@/ig, '')
+              param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
             }
 
             param.exec_type = 'y' // 鍚庡彴瑙g爜
@@ -689,10 +676,9 @@
             }
             
             if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-              param.LText = param.LText.replace(/\$@/ig, '/*')
-              param.LText = param.LText.replace(/@\$/ig, '*/')
+              param.LText = param.LText.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
             } else {
-              param.LText = param.LText.replace(/@\$|\$@/ig, '')
+              param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
             }
 
             param.exec_type = 'y' // 鍚庡彴瑙g爜
@@ -745,12 +731,19 @@
     let _params = []
 
     if ( btn.Ot === 'notRequired' || btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce' ) {
-      let param = {
-        func: btn.innerFunc || ''
+      let param = {}
+
+      if (btn.innerFunc) {
+        param.func = btn.innerFunc
       }
 
       if (this.props.BID) {
         param.BID = this.props.BID
+      }
+
+      if (btn.recordUser === 'true') {
+        param.username = sessionStorage.getItem('User_Name') || ''
+        param.fullname = sessionStorage.getItem('Full_Name') || ''
       }
       
       let primaryId = ''
@@ -759,9 +752,7 @@
         let ids = data.map(d => { return d[setting.primaryKey] || ''})
         ids = ids.filter(Boolean)
         primaryId = ids.join(',')
-      }
 
-      if (setting.primaryKey) {
         param[setting.primaryKey] = primaryId // 璁剧疆涓婚敭鍙傛暟
       }
 
@@ -792,6 +783,11 @@
           param.BID = this.props.BID
         }
 
+        if (btn.recordUser === 'true') {
+          param.username = sessionStorage.getItem('User_Name') || ''
+          param.fullname = sessionStorage.getItem('Full_Name') || ''
+        }
+
         let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
 
         if (btn.OpenType === 'pop') { // 琛ㄥ崟
@@ -820,93 +816,6 @@
           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 (retmsg) {
-          param.$callbacksql = this.getSysDeclareSql(btn, formdata, cell, columns, primaryId, this.props.BID)
-        }
-
-        return param
-      })
-    }
-
-    return _params
-  }
-
-  getLineParam = (data, formdata, retmsg) => {
-    const { setting, btn, columns } = this.props
-    let _params = []
-
-    if (btn.Ot === 'notRequired') {
-      if (retmsg) {
-        let param = {
-          $callbacksql: this.getSysDeclareSql(btn, formdata, data[0], columns, '', this.props.BID)
-        }
-        
-        _params.push(param)
-      } else {
-        _params.push({})
-      }
-    } else if ( btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce' ) {
-      let param = {}
-
-      if (this.props.BID) {
-        param.BID = this.props.BID
-      }
-      
-      let primaryId = ''
-
-      if ((btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') && setting.primaryKey) {
-        let ids = data.map(d => { return d[setting.primaryKey] || ''})
-        ids = ids.filter(Boolean)
-        primaryId = ids.join(',')
-      }
-
-      if (setting.primaryKey) {
-        param[setting.primaryKey] = primaryId // 璁剧疆涓婚敭鍙傛暟
-      }
-
-      if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit' || btn.OpenType === 'form') { // 琛ㄥ崟
-        formdata.forEach(_data => {
-          param[_data.key] = _data.value
-        })
-      }
-
-      if (retmsg) {
-        param.$callbacksql = this.getSysDeclareSql(btn, formdata, data[0], columns, primaryId, this.props.BID)
-      }
-
-      _params.push(param)
-    } else if (btn.Ot === 'required') {
-      _params = data.map((cell, index) => {
-        let param = {}
-
-        if (this.props.BID) {
-          param.BID = this.props.BID
-        }
-
-        let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
-
-        if (btn.OpenType === 'pop') { // 琛ㄥ崟
-          if (index !== 0) {
-            let _cell = {}
-            Object.keys(cell).forEach(key => {
-              _cell[key.toLowerCase()] = cell[key]
-            })
-            formdata = formdata.map(_data => {
-              if (_data.readin && _cell.hasOwnProperty(_data.key.toLowerCase())) {
-                _data.value = _cell[_data.key.toLowerCase()]
-              }
-              return _data
-            })
-          }
-
-          formdata.forEach(_data => {
-            param[_data.key] = _data.value
-          })
-        }
-        if (setting.primaryKey) {
-          param[setting.primaryKey] = primaryId
         }
 
         if (retmsg) {
@@ -1071,11 +980,6 @@
     let district = sessionStorage.getItem('district') || ''
     let address = sessionStorage.getItem('address') || ''
   
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
-  
     // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
     _sql += `
         /* 鍑瘉鍙婄敤鎴蜂俊鎭垵濮嬪寲璧嬪�� */
@@ -1104,6 +1008,12 @@
     _sql = _sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
     _sql = _sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
     _sql = _sql.replace(/@typename@/ig, `'admin'`)
+
+    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+      _sql = _sql.replace(/@datam@/ig, '\'Y\'')
+    } else {
+      _sql = _sql.replace(/@datam@/ig, '\'\'')
+    }
 
     return _sql
   }
@@ -1181,13 +1091,14 @@
               }, 600)
             }
 
-            this.triggerNote(res) // 娑堟伅
+            this.triggerNote(res, _param.ID) // 娑堟伅
             this.execSuccess(res)
           } else {
             this.execError(res)
           }
           _resolve()
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
           this.updateStatus()
           _resolve()
         })
@@ -1197,10 +1108,11 @@
             setTimeout(() => {
               Api.genericInterface(param).then(res => {
                 if (res.status) {
-                  this.triggerNote(res) // 娑堟伅
+                  this.triggerNote(res, param.ID) // 娑堟伅
                 }
                 resolve(res)
-              }, () => {
+              }, (error) => {
+                if (error && error.ErrCode === 'LoginError') return
                 this.updateStatus()
                 _resolve()
               })
@@ -1227,7 +1139,7 @@
           _resolve()
         })
       } else { // 瓒呭嚭20涓姹傛椂寰幆鎵ц
-        if (btn.progress === 'progressbar' && btn.$toolbtn && params.length > 1) {
+        if (btn.progress === 'progressbar' && params.length > 1) {
           this.setState({
             loadingTotal: params.length
           })
@@ -1244,13 +1156,11 @@
           item.script_type = 'Y'
           return item
         })
-      } else if (btn.procMode === 'inner') {
-        _params = this.getInnerParam(data, formdata, btn.callbackType === 'script')
       } else {
-        _params = this.getLineParam(data, formdata, btn.callbackType === 'script')
+        _params = this.getInnerParam(data, formdata, btn.callbackType === 'script')
       }
 
-      if (_params.length > 1 && btn.progress === 'progressbar' && btn.$toolbtn) {
+      if (_params.length > 1 && btn.progress === 'progressbar') {
         this.setState({
           loadingTotal: _params.length
         })
@@ -1267,13 +1177,11 @@
           item.script_type = 'Y'
           return item
         })
-      } else if (btn.procMode === 'inner') {
-        params = this.getInnerParam(data, formdata, btn.callbackType === 'script')
       } else {
-        params = this.getLineParam(data, formdata, btn.callbackType === 'script')
+        params = this.getInnerParam(data, formdata, btn.callbackType === 'script')
       }
 
-      if (params.length > 1 && btn.progress === 'progressbar' && btn.$toolbtn) {
+      if (params.length > 1 && btn.progress === 'progressbar') {
         this.setState({
           loadingTotal: params.length
         })
@@ -1296,31 +1204,65 @@
     let record = {
       BID: param.BID || '',
       ID: param.ID || '',
-      callbacksql: param.$callbacksql || ''
+      callbacksql: param.$callbacksql || '',
+      mk_api_key: ''
     }
 
     delete param.$callbacksql
 
-    if (!param.func) {
+    if (param.$pice) {
+      record = param.$record
+
+      delete param.$record
+
+      this.customOuterRequest(params, param, record, _resolve)
+      return
+    } else if (!param.func) {
       this.customOuterRequest(params, param, record, _resolve)
       return
     }
 
     Api.genericInterface(param).then(res => {
+      record.mk_api_key = res.mk_api_key || ''
+
       if (res.status) {
-        if ((res.mk_ex_invoke === 'false' || res.mk_ex_invoke === false) && params.length === 0) {
+        if (res.mk_ex_invoke + '' === 'false' && params.length === 0) {
           this.execSuccess(res)
           _resolve()
-        } else if ((res.mk_ex_invoke === 'false' || res.mk_ex_invoke === false) && params.length > 0) {
+        } else if (res.mk_ex_invoke + '' === 'false' && params.length > 0) {
           this.customLoopRequest(params, _resolve)
         } else {
-          this.customOuterRequest(params, res, record, _resolve)
+          if (res.mk_ex_data) { // 鏁版嵁鍒嗘壒鎵ц
+            if (Array.isArray(res.mk_ex_data) && res.mk_ex_data.length > 0) {
+              let pices = res.mk_ex_data.map(item => {
+                item.$pice = true
+                item.$record = {...record}
+
+                if (item.hasOwnProperty('mk_api_key')) {
+                  item.$record.mk_api_key = item.mk_api_key || record.mk_api_key || ''
+
+                  delete item.mk_api_key
+                }
+                return item
+              })
+              params = [...pices, ...params]
+              this.customLoopRequest(params, _resolve)
+            } else if (params.length === 0) {
+              this.execSuccess(res)
+              _resolve()
+            } else {
+              this.customLoopRequest(params, _resolve)
+            }
+          } else {
+            this.customOuterRequest(params, res, record, _resolve)
+          }
         }
       } else {
         this.execError(res)
         _resolve()
       }
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.updateStatus()
       _resolve()
     })
@@ -1345,21 +1287,26 @@
       url = btn.interface
     }
 
-    let mkey = result.mk_api_key || ''
-
-    delete result.mk_ex_invoke
-    delete result.status
-    delete result.message
-    delete result.ErrCode
-    delete result.ErrMesg
-    delete result.mk_api_key
-
+    
     let param = {}
 
-    Object.keys(result).forEach(key => {
-      key = key.replace(/^mk_/ig, '')
-      param[key] = result[key]
-    })
+    if (result.$pice) {
+      delete result.$pice
+
+      param = {...result}
+    } else {
+      delete result.mk_ex_invoke
+      delete result.status
+      delete result.message
+      delete result.ErrCode
+      delete result.ErrMesg
+      delete result.mk_api_key
+
+      Object.keys(result).forEach(key => {
+        key = key.replace(/^mk_/ig, '')
+        param[key] = result[key]
+      })
+    }
 
     let _params = {
       url: url,
@@ -1400,6 +1347,12 @@
       _params.method = 'post'
     }
 
+    if (btn.ContentType) {
+      _params.headers = {
+        'Content-Type': btn.ContentType
+      }
+    }
+
     Api.directRequest(_params).then(res => {
       if (typeof(res) !== 'object') {
         let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒'
@@ -1409,7 +1362,7 @@
         }
 
         let result = {
-          mk_api_key: mkey,
+          mk_api_key: record.mk_api_key,
           $ErrCode: 'E',
           $ErrMesg: error
         }
@@ -1419,12 +1372,22 @@
         if (Array.isArray(res)) {
           res = { data: res }
         }
-        res.mk_api_key = mkey
+
+        if (btn.outerBlacklist) {
+          let list = btn.outerBlacklist.split(',').map(m => m.toLowerCase())
+          Object.keys(res).forEach(key => {
+            if (list.includes(key.toLowerCase())) {
+             delete res[key]
+            }
+          })
+        }
+        
+        res.mk_api_key = record.mk_api_key
         this.customCallbackRequest(params, res, record, _resolve)
       }
     }, (e) => {
       let result = {
-        mk_api_key: mkey,
+        mk_api_key: record.mk_api_key,
         $ErrCode: 'E',
         $ErrMesg: e && e.statusText ? e.statusText : ''
       }
@@ -1502,6 +1465,8 @@
 
     Api.genericInterface(param).then(res => {
       if (res.status) {
+        this.triggerNote(res, param.ID) // 娑堟伅
+
         if (params.length === 0) {
           this.execSuccess(res)
           _resolve()
@@ -1512,7 +1477,8 @@
         this.execError(res)
         _resolve()
       }
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.updateStatus()
       _resolve()
     })
@@ -1561,14 +1527,14 @@
           if (typeof(val) === 'string') {
             val = val.replace(/'/ig, '"')
           }
-          keys.push(key)
+          keys.push('[' + key + ']')
           vals.push(`'${val}'`)
         }
       })
 
       lines.push({
         table: tb,
-        insert: `Insert into ${pre}${tb} (${keys.join(',')},mk_level,mk_id,mk_bid)`,
+        insert: `Insert into ${pre}${tb} (${keys.join(',')},[mk_level],[mk_id],[mk_bid])`,
         select: `Select ${vals.join(',')},'${level}','${id}','${bid}'`
       })
 
@@ -1652,17 +1618,16 @@
       sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
       sql = sql.replace(/@typename@/ig, `'admin'`)
 
-      if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+      if (window.GLOB.debugger === true) {
         console.info(sql.replace(/\n\s{8}/ig, '\n'))
       }
 
       param.LText = sql
       
       if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        param.LText = param.LText.replace(/\$@/ig, '/*')
-        param.LText = param.LText.replace(/@\$/ig, '*/')
+        param.LText = param.LText.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
       } else {
-        param.LText = param.LText.replace(/@\$|\$@/ig, '')
+        param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
       }
       param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
 
@@ -1689,7 +1654,7 @@
         Sort: index + 1
       }))
 
-      if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+      if (window.GLOB.debugger === true) {
         let sql = [...lineMap.values()].map(item => (`
           ${item.insert}
           ${item.selects.join(` union all
@@ -1715,7 +1680,7 @@
 
     Api.genericInterface(param).then(res => {
       if (res.status) {
-        this.triggerNote(res) // 娑堟伅
+        this.triggerNote(res, param.ID) // 娑堟伅
 
         if (params.length === 0) {
           this.execSuccess(res)
@@ -1727,7 +1692,8 @@
         this.execError(res)
         _resolve()
       }
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.updateStatus()
       _resolve()
     })
@@ -1748,7 +1714,7 @@
 
     Api.genericInterface(param).then(res => {
       if (res.status) {
-        this.triggerNote(res) // 娑堟伅
+        this.triggerNote(res, param.ID) // 娑堟伅
 
         if (params.length === 0) {
           this.execSuccess(res)
@@ -1757,15 +1723,20 @@
           this.checkLoopRequest(params, _resolve)
         }
       } else if (res.ErrCode === 'C') {
+        let msg = res.message || ''
+        if (/\n|\r/.test(msg)) {
+          msg = msg.replace(/\n|\r/ig, '<br/>')
+          msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
+        }
         const _this = this
         confirm({
-          title: '缁х画鎵ц锛�',
-          content: res.message,
+          title: '璇风‘璁�',
+          content: msg,
           onOk() {
             return new Promise(resolve => {
               Api.genericInterface(unCheckParam).then(result => {
                 if (result.status) {
-                  _this.triggerNote(result) // 娑堟伅
+                  _this.triggerNote(result, param.ID) // 娑堟伅
           
                   if (params.length === 0) {
                     _this.execSuccess(result)
@@ -1790,7 +1761,8 @@
         this.execError(res)
         _resolve()
       }
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.updateStatus()
       _resolve()
     })
@@ -1852,7 +1824,8 @@
         this.execError(res)
         _resolve()
       }
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.updateStatus()
       _resolve()
     })
@@ -1871,8 +1844,8 @@
         if (window.GLOB.mainSystemApi) {
           result.rduri = window.GLOB.mainSystemApi
         }
-      } else if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-        result.rduri = options.cloudServiceApi
+      } else if (btn.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+        result.rduri = window.GLOB.cloudServiceApi
         result.userid = sessionStorage.getItem('CloudUserID') || ''
         result.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
       } else if (btn.sysInterface !== 'true') {
@@ -1922,7 +1895,8 @@
         return
       }
       this.outerCallbackRequest(params, res, record, outParam, _resolve)
-    }, () => {
+    }, (error) => {
+      if (error && error.ErrCode === 'LoginError') return
       this.outerCallbackRequest(params, {status: false, message: 500, ErrCode: 'E', ErrMesg: 500}, record, outParam, _resolve)
     })
   }
@@ -2004,6 +1978,8 @@
 
     Api.genericInterface(param).then(res => {
       if (res.status) {
+        this.triggerNote(res, param.ID) // 娑堟伅
+
         // 涓�娆¤姹傛垚鍔燂紝杩涜涓嬩竴椤硅姹�
         if (params.length === 0) {
           this.execSuccess(res)
@@ -2093,7 +2069,16 @@
    */
   execSuccess = (res = {}) => {
     const { btn } = this.props
-    const { btnconfig, autoMatic } = this.state
+    const { autoMatic } = this.state
+
+    if (autoMatic) {
+      this.setState({
+        loading: false,
+        visible: false
+      })
+      MKEmitter.emit('autoExecOver', btn.uuid, 'success')
+      return
+    }
 
     let sign = ''
     if (/^@speak@/i.test(res.message)) {
@@ -2111,44 +2096,9 @@
       if (!res.message) {
         res.ErrCode = '-1'
       }
-    } else if (/@close_tab@|@close_popup@|@goback@/i.test(res.message)) {
-      sign = res.message.match(/@close_tab@|@close_popup@|@goback@/i)[0].toLowerCase()
-      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@/i, '')
-    }
-
-    if ((res.ErrCode === 'S' || !res.ErrCode) || autoMatic) { // 鎵ц鎴愬姛
-      if (btn.formType !== 'counter' || res.message) {
-        notification.success({
-          top: 92,
-          message: res.message || '鎵ц鎴愬姛锛�',
-          duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
-        })
-      }
-    } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
-      Modal.success({
-        title: res.message || '鎵ц鎴愬姛锛�'
-      })
-    } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
-
-    }
-
-    this.setState({
-      loadingNumber: '',
-      loadingTotal: '',
-    })
-    
-    if (autoMatic) {
-      this.setState({
-        loading: false,
-        visible: false
-      })
-      MKEmitter.emit('autoExecOver', btn.uuid, 'success')
-      return
-    } else if (btn.OpenType !== 'pop' || !btnconfig || btnconfig.setting.finish !== 'unclose') {
-      this.setState({
-        loading: false,
-        visible: false
-      })
+    } else if (/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i.test(res.message)) {
+      sign = res.message.match(/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i)[0].toLowerCase()
+      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i, '')
     }
 
     let id = ''
@@ -2159,6 +2109,53 @@
     if (res.mk_icon) {
       sessionStorage.setItem('avatar', res.mk_icon)
     }
+
+    res.ErrCode = res.ErrCode || 'S'
+
+    if (res.ErrCode === 'S') { // 鎵ц鎴愬姛
+      if (btn.formType !== 'counter' || res.message) {
+        notification.success({
+          top: 92,
+          message: res.message || '鎵ц鎴愬姛锛�',
+          duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
+        })
+      }
+    } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
+      let msg = res.message || '鎵ц鎴愬姛锛�'
+      if (/\n|\r/.test(msg)) {
+        msg = msg.replace(/\n|\r/ig, '<br/>')
+        msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
+      }
+      Modal.success({
+        title: msg,
+        onOk: () => {
+          this.successContinue(sign, id)
+        }
+      })
+      return
+    } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
+
+    }
+
+    this.successContinue(sign, id)
+  }
+
+  successContinue = (sign, id) => {
+    const { btn } = this.props
+    const { btnconfig } = this.state
+
+    this.setState({
+      loadingNumber: '',
+      loadingTotal: '',
+    })
+    
+    if (btn.OpenType !== 'pop' || !btnconfig || btnconfig.setting.finish !== 'unclose') {
+      this.setState({
+        loading: false,
+        visible: false
+      })
+    }
+
     let tabId = ''
     if (btn.refreshTab && btn.refreshTab.length > 0) {
       tabId = btn.refreshTab[btn.refreshTab.length - 1]
@@ -2208,7 +2205,7 @@
       node && node.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'})
     }
 
-    if (btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0) {
+    if (btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0 && sign !== '@no_target_menu@') {
       let menuId = btn.openmenu.slice(-1)[0]
       let newtab = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
 
@@ -2227,17 +2224,25 @@
 
       MKEmitter.emit('modifyTabs', newtab, true)
     }
+
+    if (btn.execSuccess === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
+    }
   }
 
-  triggerNote = (res) => {
+  triggerNote = (res, ID) => {
     const { btn } = this.props
 
     if (!btn.verify) return
-    if (btn.verify.noteEnable !== 'true' && btn.verify.wxNote !== 'true') return
+    if (btn.verify.noteEnable !== 'true' && btn.verify.wxNote !== 'true' && btn.verify.printEnable !== 'true') return
 
     let id = ''
     if (btn.output) {
       id = res.mk_b_id || res[btn.output] || ''
+    }
+
+    if (btn.verify.printEnable === 'true') {
+      this.billPrint(id || ID)
     }
 
     if (!id) return
@@ -2261,6 +2266,16 @@
     }
   }
 
+  billPrint = (id) => {
+    const { btn } = this.props
+
+    if (!id) return
+
+    setTimeout(() => {
+      window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: id, tempId: btn.verify.printTempId, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
+    }, 500)
+  }
+
   sendWxMessage = (verify, id) => {
     if (!window.GLOB.nginx) {
       notification.warning({
@@ -2282,7 +2297,7 @@
 
     let domain1 = ''
     let domain2 = ''
-    if (['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok'].includes(verify.wxTemplateId) && options.sysType !== 'cloud') {
+    if (['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok'].includes(verify.wxTemplateId) && window.GLOB.sysType !== 'cloud') {
       domain1 = 'https://cloud.mk9h.cn/'
       domain2 = 'https://cloud.mk9h.cn:8443/'
     }
@@ -2514,6 +2529,29 @@
             duration: 5
           })
         }
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') {
+          let param = {
+            func: 's_visitor_login',
+            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), 
+            SessionUid: 'bh0bapabtd45epsgra79segbch6c1ibk',
+            TypeCharOne: 'pc',
+            appkey: '202004041613277377A6A2456D34A4948AE84'
+          }
+
+          param.LText = md5(window.btoa('bh0bapabtd45epsgra79segbch6c1ibk' + param.timestamp))
+          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
+
+          let params = {
+            url: 'https://sso.mk9h.cn/webapi/dologon',
+            method: 'post',
+            data: JSON.stringify(param)
+          }
+
+          Api.directRequest(params)
+
+          return
+        }
       })
     })
   }
@@ -2526,8 +2564,29 @@
    */
   execError = (res = {}) => {
     const { btn } = this.props
-    const { btnconfig, autoMatic } = this.state
+    const { autoMatic } = this.state
 
+    if (autoMatic) {
+      notification.error({
+        top: 92,
+        message: res.message || '鎵ц澶辫触锛�',
+        duration: 10
+      })
+
+      this.setState({
+        loading: false,
+        loadingNumber: '',
+        loadingTotal: '',
+        visible: false
+      })
+      MKEmitter.emit('autoExecOver', btn.uuid, 'error')
+      return
+    }
+
+    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
+      res.ErrCode = 'E'
+    }
+    
     let sign = ''
     if (/^@speak@/i.test(res.message)) {
       res.message = res.message.replace(/^@speak@/i, '')
@@ -2549,11 +2608,20 @@
       res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@/i, '')
     }
 
-    if (res.ErrCode === 'E' && !autoMatic) {
+    if (res.ErrCode === 'E') {
+      let msg = res.message || '鎵ц澶辫触锛�'
+      if (/\n|\r/.test(msg)) {
+        msg = msg.replace(/\n|\r/ig, '<br/>')
+        msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
+      }
       Modal.error({
-        title: res.message || '鎵ц澶辫触锛�',
+        title: msg,
+        onOk: () => {
+          this.errorContinue(sign)
+        }
       })
-    } else if (res.ErrCode === 'N' || autoMatic) {
+      return
+    } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
         message: res.message || '鎵ц澶辫触锛�',
@@ -2570,16 +2638,14 @@
       message.error(res.message || '鎵ц澶辫触锛�')
     }
 
-    if (autoMatic) {
-      this.setState({
-        loading: false,
-        loadingNumber: '',
-        loadingTotal: '',
-        visible: false
-      })
-      MKEmitter.emit('autoExecOver', btn.uuid, 'error')
-      return
-    } else if (btn.OpenType !== 'pop' || !btnconfig || btnconfig.setting.finish !== 'unclose') {
+    this.errorContinue(sign)
+  }
+
+  errorContinue = (sign) => {
+    const { btn } = this.props
+    const { btnconfig } = this.state
+
+    if (btn.OpenType !== 'pop' || !btnconfig || btnconfig.setting.finish !== 'unclose') {
       this.setState({
         loading: false
       })
@@ -2621,6 +2687,10 @@
 
     if (window.GLOB.breakpoint) {
       MKEmitter.emit('refreshDebugTable')
+    }
+
+    if (btn.execError === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
     }
   }
 
@@ -2821,7 +2891,7 @@
         _item.fieldlen = item.decimal || 0
       } else if (['text', 'textarea', 'linkMain'].includes(_item.type)) {
         _item.value = _item.value + ''
-        _item.value = _item.value.replace(/\t*|\v*/g, '')       // 鍘婚櫎鍒惰〃绗�
+        _item.value = _item.value.replace(/\t+|\v+/g, '')       // 鍘婚櫎鍒惰〃绗�
 
         if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
           _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
@@ -2868,7 +2938,7 @@
       this.execSubmit(selines, () => {}, result)
     } else {
       confirm({
-        title: btn.tipTitle || this.state.dict['main.action.confirm.tip'],
+        title: btn.tipTitle || '纭畾瑕佹墽琛屽悧?',
         onOk() {
           return new Promise(resolve => {
             _this.execSubmit(selines, resolve, result)
@@ -2914,7 +2984,6 @@
         >
           <MutilForm
             BID={BID}
-            dict={this.state.dict}
             action={btnconfig}
             inputSubmit={this.handleOk}
             data={this.state.selines[0]}
@@ -2955,7 +3024,6 @@
         >
           <MutilForm
             BID={BID}
-            dict={this.state.dict}
             action={btnconfig}
             inputSubmit={this.handleOk}
             data={this.state.selines[0]}
@@ -3010,6 +3078,37 @@
     })
   }
 
+  changeLineCount = (count) => {
+    const { btn, selectedData } = this.props
+    const { disabled } = this.state
+
+    if (disabled) return
+
+    let data = selectedData || []
+
+    if (data.length === 0) {
+      // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨琛岋紒',
+        duration: 5
+      })
+      return
+    } else if (data.length !== 1) {
+      // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        duration: 5
+      })
+      return
+    }
+
+    this.setState({count}, () => {
+      MKEmitter.emit('refreshLineData', btn.$menuId, btn, data[0].$$uuid, count)
+    })
+  }
+
   render() {
     const { btn } = this.props
     const { loadingNumber, loadingTotal, loading, disabled, hidden, check, count } = this.state
@@ -3020,6 +3119,8 @@
         return <Switch loading={loading} checked={check} disabled={disabled || loading} title={disabled ? (btn.reason || '') : ''} onChange={(val,e) => {e.stopPropagation();this.actionTrigger()}} style={btn.style} className={btn.size === 'large' ? 'ant-switch-large' : ''} size={btn.size} checkedChildren={btn.openText || ''} unCheckedChildren={btn.closeText || ''}/>
       } else if (btn.formType === 'counter') {
         return <MkCounter count={count} disabled={disabled} btn={btn} onChange={this.changeCount}/>
+      } else if (btn.formType === 'count_line') {
+        return <MkCounter count={count} disabled={disabled} btn={btn} onChange={this.changeLineCount}/>
       } else if (btn.formType === 'radio') {
         return <Checkbox className={btn.checkType || ''} disabled={disabled || loading} title={disabled ? (btn.reason || '') : ''} checked={check} onChange={(e) => {e.stopPropagation();this.actionTrigger()}} style={btn.style}></Checkbox>
       } else {
@@ -3051,14 +3152,15 @@
       className = 'mk-btn mk-' + (btn.class || 'unset')
     }
 
-    if (loadingNumber && !loadingTotal && btn.$toolbtn && (!btn.show || btn.show === 'button')) {
-      label = (loadingNumber && !loadingTotal ? `(${loadingNumber})` : '') + btn.label
+    if (loadingNumber && btn.progress !== 'progressbar' && btn.$toolbtn && (!btn.show || btn.show === 'button')) {
+      label = (loadingNumber ? `(${loadingNumber})` : '') + btn.label
     }
 
     return <>
       <Button
         type={type}
         icon={icon}
+        id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         loading={loading}
         disabled={disabled}
diff --git a/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx b/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx
index 5c0bfe3..05fb8a7 100644
--- a/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx
@@ -48,7 +48,7 @@
 
     this.timer = setTimeout(() => {
       this.props.onChange(val)
-    }, 1000)
+    }, btn.formType === 'count_line' ? 100 : 500)
   }
 
   plus = () => {
@@ -71,7 +71,7 @@
 
     this.timer = setTimeout(() => {
       this.props.onChange(val)
-    }, 1000)
+    }, btn.formType === 'count_line' ? 100 : 500)
   }
 
   submit = () => {
@@ -96,7 +96,21 @@
 
     this.timer = setTimeout(() => {
       this.props.onChange(count)
-    }, 1000)
+    }, btn.formType === 'count_line' ? 100 : 500)
+  }
+
+  onChange = (val) => {
+    const { btn } = this.props
+
+    this.setState({count: val})
+
+    if (btn.formType === 'count_line' && typeof(val) === 'number') {
+      clearTimeout(this.timer)
+
+      this.timer = setTimeout(() => {
+        this.props.onChange(val)
+      }, 100)
+    }
   }
 
   render() {
@@ -106,7 +120,7 @@
     return (
       <div onClick={(e) => e.stopPropagation()} className={'mk-btn-counter ' + (btn.size || '') + (disabled ? ' mk-disabled' : '')} style={btn.style}>
         <span onClick={this.minus}><MinusOutlined /></span>
-        <span><InputNumber value={count} onChange={(val) => this.setState({count: val})} onBlur={this.submit} onPressEnter={this.submit}/></span>
+        <span><InputNumber value={count} onChange={this.onChange} onBlur={this.submit} onPressEnter={this.submit}/></span>
         <span onClick={this.plus}><PlusOutlined /></span>
       </div>
     )
diff --git a/src/tabviews/zshare/actionList/popupbutton/index.jsx b/src/tabviews/zshare/actionList/popupbutton/index.jsx
index f61eadf..efd9c5c 100644
--- a/src/tabviews/zshare/actionList/popupbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/popupbutton/index.jsx
@@ -4,14 +4,11 @@
 import { Button, Modal, notification, Drawer } from 'antd'
 
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 import './index.scss'
 
 const SubTabTable = asyncSpinComponent(() => import('@/tabviews/subtabtable'))
-const CustomPage = asyncSpinComponent(() => import('@/tabviews/custom'))
 const PopView = asyncSpinComponent(() => import('@/tabviews/custom/popview'))
 
 class PopupButton extends Component {
@@ -26,7 +23,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     visible: false,
     popData: null,
     primaryId: '',
@@ -131,7 +127,7 @@
 
     if (btn.uuid !== tabId) return
 
-    if (btn.$view === 'CustomPage') {
+    if (btn.$view === 'popview') {
       if (btn.popClose !== 'never') {
         MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn)
       }
@@ -172,13 +168,6 @@
         duration: 5
       })
       return
-    } else if (setting.tabType === 'subtab') {
-      notification.warning({
-        top: 92,
-        message: '寮圭獥椤甸潰涓嶆敮鎸佹璁剧疆锛�',
-        duration: 5
-      })
-      return
     }
 
     let _data = null
@@ -186,7 +175,7 @@
 
     if (btn.Ot === 'requiredSgl' && setting.primaryKey) {
       _data = data[0]
-      primaryId = _data[setting.primaryKey] || ''
+      primaryId = _data.$$uuid || _data[setting.primaryKey] || ''
     }
 
     this.setState({
@@ -248,19 +237,18 @@
         ratio = ratio + 'vw'
       }
       return <Modal
-        wrapClassName={'popview-modal ' + (!btn.$view ? '' : 'custom-popview')}
+        wrapClassName={'popview-modal ' + (!btn.$view ? '' : 'custom-popview ') + (btn.popshow || '')}
         title={btn.label}
         width={ratio}
         maskClosable={btn.clickouter === 'close'}
         visible={visible}
         onCancel={this.popclose}
         footer={[
-          <Button key="close" onClick={this.popclose}>{this.state.dict['main.close']}</Button>
+          <Button key="close" onClick={this.popclose}>鍏抽棴</Button>
         ]}
         destroyOnClose
       >
         {!btn.$view ? <SubTabTable Tab={btn} MenuID={btn.linkTab} SupMenuID={this.props.MenuID} BID={popData ? primaryId : this.props.BID} BData={popData || this.props.BData}/> : null}
-        {btn.$view === 'CustomPage' ? <CustomPage Tab={btn} MenuID={btn.uuid} MenuName={btn.label} param={{$BID: (popData ? primaryId : this.props.BID), ...(popData || this.props.BData || {})}} /> : null}
         {btn.$view === 'popview' ? <PopView Tab={btn} param={{$BID: (popData ? primaryId : this.props.BID), ...(popData || this.props.BData || {})}} /> : null}
       </Modal>
     } else {
@@ -297,7 +285,6 @@
           destroyOnClose
         >
           {!btn.$view ? <SubTabTable Tab={btn} MenuID={btn.linkTab} SupMenuID={this.props.MenuID} BID={popData ? primaryId : this.props.BID} BData={popData || this.props.BData}/> : null}
-          {btn.$view === 'CustomPage' ? <CustomPage Tab={btn} MenuName={btn.label} MenuID={btn.uuid} param={{$BID: (popData ? primaryId : this.props.BID), ...(popData || this.props.BData || {})}} /> : null}
           {btn.$view === 'popview' ? <PopView Tab={btn} param={{$BID: (popData ? primaryId : this.props.BID), ...(popData || this.props.BData || {})}} /> : null}
           <div className="close-drawer">
             <Button onClick={this.popclose}>
diff --git a/src/tabviews/zshare/actionList/popupbutton/index.scss b/src/tabviews/zshare/actionList/popupbutton/index.scss
index 72a6a3c..5dee830 100644
--- a/src/tabviews/zshare/actionList/popupbutton/index.scss
+++ b/src/tabviews/zshare/actionList/popupbutton/index.scss
@@ -1,5 +1,5 @@
 .custom-popview.popview-modal {
-  >.ant-modal-content >.ant-modal-body {
+  .ant-modal-content .ant-modal-body {
     padding: 0;
     .custom-page-wrap {
       min-height: 200px;
@@ -9,6 +9,19 @@
     }
   }
 }
+.custom-popview.popview-modal.miniview {
+  .ant-modal-header {
+    display: none;
+  }
+  .ant-modal-footer {
+    display: none;
+  }
+  .ant-modal-body {
+    padding: 0px;
+    border-radius: 4px;
+    max-height: calc(100vh - 110px);
+  }
+}
 .table-drawer-popview {
   .close-drawer {
     position: absolute;
diff --git a/src/tabviews/zshare/actionList/printbutton/index.jsx b/src/tabviews/zshare/actionList/printbutton/index.jsx
index 2bbfe85..db4fd6a 100644
--- a/src/tabviews/zshare/actionList/printbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -6,9 +6,6 @@
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import { updateForm } from '@/utils/utils-update.js'
 import MKEmitter from '@/utils/events.js'
@@ -32,7 +29,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     visible: false,
     formdata: null,
     selines: null,
@@ -161,7 +157,7 @@
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectline'],
+        message: '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return
@@ -169,13 +165,9 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectSingleLine'],
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
-      return
-    } else if (!['requiredSgl', 'notRequired', 'requiredOnce', 'required'].includes(btn.Ot)) {
-      // 鏁版嵁閫夋嫨绫诲瀷鏍¢獙
-      this.actionSettingError()
       return
     } else if (!btn.verify || !btn.verify.printMode) {
       notification.warning({
@@ -212,7 +204,7 @@
     } else if (btn.execMode === 'prompt') {
       this.setState({ loading: true })
       confirm({
-        title: this.state.dict['main.action.confirm.tip'],
+        title: '纭畾瑕佹墽琛屽悧?',
         onOk() {
           _this.triggerPrint(data)
         },
@@ -533,7 +525,7 @@
 
       return Api.getSystemCacheConfig(param)
     }).then(result => {
-      if (!result) {
+      if (!result || result.ErrCode === 'LoginError') {
         this.setState({ loading: false })
         return
       }
@@ -576,7 +568,6 @@
     this.execSuccess({
       ErrCode: '-1',
       message: '',
-      ErrMesg: '',
       status: true
     })
 
@@ -912,6 +903,11 @@
         if (btn.intertype === 'inner') {
           params = params.map(_param => {
             _param.func = btn.innerFunc
+
+            if (btn.recordUser === 'true') {
+              _param.username = sessionStorage.getItem('User_Name') || ''
+              _param.fullname = sessionStorage.getItem('Full_Name') || ''
+            }
   
             return _param
           })
@@ -985,10 +981,15 @@
 
     let _dataresource = btn.verify.setting.dataresource
     let _customScript = ''
-
+    let _tailScript = ''
     btn.verify.scripts && btn.verify.scripts.forEach(script => {
-      if (script.status !== 'false') {
+      if (script.status === 'false') return
+      if (script.position !== 'back') {
         _customScript += `
+        ${script.sql}
+        `
+      } else {
+        _tailScript += `
         ${script.sql}
         `
       }
@@ -998,18 +999,28 @@
       _dataresource = ''
     }
 
+    let isDataM = sessionStorage.getItem('dataM') === 'true'
+    let regoptions = [
+      { reg: /@ID@/ig, value: `'${ID}'`},
+      { reg: /@BID@/ig, value: `'${BID || ''}'`},
+      { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
+      { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
+      { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
+      { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      { reg: /@typename@/ig, value: `'admin'`},
+      { reg: /\$@/ig, value: isDataM ? '/*' : ''},
+      { reg: /@\$/ig, value: isDataM ? '*/' : ''},
+      { reg: /@datam@/ig, value: isDataM ? `'Y'` : `''`},
+    ]
+
+    regoptions.forEach(item => {
+      _dataresource = _dataresource.replace(item.reg, item.value)
+      _customScript = _customScript.replace(item.reg, item.value)
+      _tailScript = _tailScript.replace(item.reg, item.value)
+    })
+
     if (/\s/.test(_dataresource)) {
       _dataresource = '(' + _dataresource + ') tb'
-    }
-
-    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-      _dataresource = _dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-      _dataresource = _dataresource.replace(/@\$/ig, '*/')
-      _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
-      _customScript = _customScript.replace(/@\$/ig, '*/')
-    } else {
-      _dataresource = _dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
-      _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
     }
 
     let initsql = `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)
@@ -1097,36 +1108,12 @@
         select ${_initvars.join(',')}
       `
     }
-
     
     if (_customScript) {
       _customScript = `${initsql}
         ${_customScript}
       `
     }
-
-    _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
-    _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
-    _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
-    _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
-    _customScript = _customScript.replace(/\$sum@/ig, '/*')
-    _customScript = _customScript.replace(/@sum\$/ig, '*/')
-
-    _dataresource = _dataresource.replace(/@ID@/ig, `'${ID}'`)
-    _customScript = _customScript.replace(/@ID@/ig, `'${ID}'`)
-    _dataresource = _dataresource.replace(/@BID@/ig, `'${BID || ''}'`)
-    _customScript = _customScript.replace(/@BID@/ig, `'${BID || ''}'`)
-    _dataresource = _dataresource.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    _customScript = _customScript.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    _dataresource = _dataresource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    _customScript = _customScript.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    _dataresource = _dataresource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    _customScript = _customScript.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    _dataresource = _dataresource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _customScript = _customScript.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _dataresource = _dataresource.replace(/@typename@/ig, `'admin'`)
-    _customScript = _customScript.replace(/@typename@/ig, `'admin'`)
-
 
     let LText = ''
 
@@ -1137,17 +1124,27 @@
     if (_customScript) {
       if (LText) {
         LText = `${LText}
+          ${_tailScript}
           aaa:
           if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
         `
       } else {
         _customScript = `${_customScript}
+          ${_tailScript}
           aaa:
           if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
         `
       }
+    } else if (_tailScript) {
+      LText = `${initsql}
+        ${LText}
+        ${_tailScript}
+        aaa:
+        if @ErrorCode!=''
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
+      `
     } else {
       LText = `${initsql}
         ${LText}
@@ -1155,7 +1152,7 @@
     }
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+    if (window.GLOB.debugger === true) {
       _customScript && console.info(`${btn.logLabel ? `/*${btn.logLabel} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
       LText && console.info(`${btn.logLabel ? `/*${btn.logLabel} 鏁版嵁婧�*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
     }
@@ -1169,6 +1166,9 @@
 
     param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     param.secretkey = Utils.encrypt('', param.timestamp)
+
+    param.username = userName
+    param.fullname = fullName
 
     if (window.GLOB.probation) {
       param.s_debug_type = 'Y'
@@ -1219,8 +1219,8 @@
       _outParam = JSON.parse(JSON.stringify(res))
 
       if (window.GLOB.mkHS) {
-        if (btn.sysInterface === 'true' && options.cloudServiceApi) {
-          res.rduri = options.cloudServiceApi
+        if (btn.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+          res.rduri = window.GLOB.cloudServiceApi
           res.userid = sessionStorage.getItem('CloudUserID') || ''
           res.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         } else if (btn.sysInterface !== 'true') {
@@ -1262,7 +1262,7 @@
 
       return Api.genericInterface(res)
     }).then(response => {
-      if (!response) return
+      if (!response || response.ErrCode === 'LoginError') return
 
       if (ver_token && response.ErrMesg === 'token_error') {
         this.execError(response)
@@ -1291,7 +1291,7 @@
         _resolve({next: false, list: []})
       }
     }).then(response => {
-      if (!response) return
+      if (!response || response.ErrCode === 'LoginError') return
 
       if (response.status) {
         _list.push(response)
@@ -1616,7 +1616,7 @@
     Api.postekPrint(param).then(res => {
       if (res.retval === '0') {
         if (params.length === 0) {
-          this.execSuccess({ ErrCode: 'S', message: '', ErrMesg: '鎵撳嵃璇锋眰宸插彂鍑恒��', status: true })
+          this.execSuccess({ ErrCode: 'S', message: '鎵撳嵃璇锋眰宸插彂鍑恒��', status: true })
         } else {
           setTimeout(() => {
             this.loopRFIDPrint(params)
@@ -1735,14 +1735,12 @@
         this.execSuccess({
           ErrCode: '-1',
           message: '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
-          ErrMesg: '',
           status: true
         })
       } else {
         this.execError({
           ErrCode: 'N',
           message: '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
-          ErrMesg: '',
           status: false
         })
       }
@@ -1772,7 +1770,6 @@
       this.execError({
         ErrCode: 'N',
         message: msg.join(' ; ') + ' !',
-        ErrMesg: '',
         status: false
       })
       return
@@ -1785,8 +1782,7 @@
 
       this.execSuccess({
         ErrCode: 'S',
-        message: '',
-        ErrMesg: '鎵撳嵃璇锋眰宸插彂鍑恒��',
+        message: '鎵撳嵃璇锋眰宸插彂鍑恒��',
         status: true
       })
     }
@@ -1797,8 +1793,7 @@
 
       this.execSuccess({
         ErrCode: 'S',
-        message: '',
-        ErrMesg: '鎵撳嵃璇锋眰宸插彂鍑恒��',
+        message: '鎵撳嵃璇锋眰宸插彂鍑恒��',
         status: true
       })
     }
@@ -1813,7 +1808,6 @@
           this.execError({
             ErrCode: 'N',
             message: event.data,
-            ErrMesg: '',
             status: false
           })
 
@@ -1833,8 +1827,7 @@
 
       //   this.execSuccess({
       //     ErrCode: 'S',
-      //     message: '',
-      //     ErrMesg: '鎵撳嵃璇锋眰宸插彂鍑恒��',
+      //     message: '鎵撳嵃璇锋眰宸插彂鍑恒��',
       //     status: true
       //   })
       // } else if (data && data.message && !data.status) {
@@ -1842,7 +1835,6 @@
         this.execError({
           ErrCode: 'N',
           message: data.message,
-          ErrMesg: '',
           status: false
         })
       }
@@ -1852,7 +1844,6 @@
       this.execError({
         ErrCode: 'N',
         message: '鏃犳硶杩炴帴鍒�:' + btn.verify.linkUrl,
-        ErrMesg: '',
         status: false
       })
     }
@@ -1877,19 +1868,19 @@
    * 4銆佹ā鎬佹鎵ц鎴愬姛鍚庢槸鍚﹀叧闂�
    * 5銆侀�氱煡涓诲垪琛ㄥ埛鏂�
    */
-  execSuccess = (res) => {
+  execSuccess = (res = {}) => {
     const { btn } = this.props
     const { autoMatic, btnconfig } = this.state
 
     if ((res.ErrCode === 'S' || !res.ErrCode) || autoMatic) { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.ErrMesg || this.state.dict['main.action.confirm.success'],
+        message: res.message || '鎵ц鎴愬姛锛�',
         duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
       })
     } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.ErrMesg || this.state.dict['main.action.confirm.success']
+        title: res.message || '鎵ц鎴愬姛锛�'
       })
     } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
@@ -1914,6 +1905,10 @@
     if (btn.execSuccess !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn, '', this.state.selines)
     }
+
+    if (btn.execSuccess === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
+      MKEmitter.emit('refreshPopButton', btn.$tabId)
+    }
   }
 
   /**
@@ -1926,25 +1921,29 @@
     const { btn } = this.props
     const { btnconfig, autoMatic } = this.state
 
+    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
+      res.ErrCode = 'E'
+    }
+
     if (res.ErrCode === 'E' && !autoMatic) {
       Modal.error({
-        title: res.message || res.ErrMesg,
+        title: res.message || '鎵ц澶辫触锛�',
       })
     } else if (res.ErrCode === 'N' || autoMatic) {
       notification.error({
         top: 92,
-        message: res.message || res.ErrMesg,
+        message: res.message || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || res.ErrMesg,
+        message: res.message || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || res.ErrMesg)
+      message.error(res.message || '鎵ц澶辫触锛�')
     }
     
     this.setState({
@@ -1964,17 +1963,6 @@
     if (btn.execError !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', this.state.selines)
     }
-  }
-
-  /**
-   * @description 鎸夐挳閰嶇疆淇℃伅閿欒鎻愮ず
-   */
-  actionSettingError = () => {
-    notification.warning({
-      top: 92,
-      message: '鎸夐挳璁剧疆閿欒锛�',
-      duration: 5
-    })
   }
 
   handleModelConfig = (config) => {
@@ -2171,7 +2159,7 @@
         _item.fieldlen = item.decimal || 0
       } else if (['text', 'textarea', 'linkMain'].includes(_item.type)) {
         _item.value = _item.value + ''
-        _item.value = _item.value.replace(/\t*|\v*/g, '')       // 鍘婚櫎鍒惰〃绗�
+        _item.value = _item.value.replace(/\t+|\v+/g, '')       // 鍘婚櫎鍒惰〃绗�
 
         if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
           _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
@@ -2218,7 +2206,7 @@
       this.execSubmit(selines, () => {}, result)
     } else {
       confirm({
-        title: this.state.dict['main.action.confirm.tip'],
+        title: '纭畾瑕佹墽琛屽悧?',
         onOk() {
           _this.triggerPrint(selines, result)
         },
@@ -2268,7 +2256,6 @@
       >
         <MutilForm
           BID={BID}
-          dict={this.state.dict}
           action={btnconfig}
           inputSubmit={this.handleOk}
           data={this.state.selines[0]}
@@ -2349,6 +2336,7 @@
     return <>
       <Button
         type={type}
+        id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         loading={loading}
         disabled={disabled}
diff --git a/src/tabviews/zshare/actionList/tabbutton/index.jsx b/src/tabviews/zshare/actionList/tabbutton/index.jsx
index 9a7662a..184f2c8 100644
--- a/src/tabviews/zshare/actionList/tabbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -3,8 +3,6 @@
 import { is, fromJS } from 'immutable'
 import { Button, notification } from 'antd'
 
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 // import './index.scss'
@@ -20,7 +18,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     disabled: false,
     hidden: false,
     primaryId: ''
@@ -118,7 +115,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: this.state.dict['main.action.confirm.selectSingleLine'],
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -177,9 +174,14 @@
       }
     }
 
-    MKEmitter.emit('modifyTabs', newtab, true)
+    if (btn.openTab === 'view') {
+      window.open('#/view/' + newtab.MenuID + '/' + primaryId)
+    } else {
+      MKEmitter.emit('modifyTabs', newtab, true)
+  
+      MKEmitter.emit('openNewTab')
+    }
 
-    MKEmitter.emit('openNewTab')
     if (window.GLOB.systemType === 'production') {
       MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '鏍囩椤�'})
     }
diff --git a/src/tabviews/zshare/automatic/index.jsx b/src/tabviews/zshare/automatic/index.jsx
index c020117..951001a 100644
--- a/src/tabviews/zshare/automatic/index.jsx
+++ b/src/tabviews/zshare/automatic/index.jsx
@@ -9,6 +9,7 @@
 class AutoMatic extends Component {
   static propTpyes = {
     autoMatic: PropTypes.object,
+    tabId: PropTypes.string,
     config: PropTypes.object
   }
 
@@ -21,10 +22,18 @@
   timer = null
 
   UNSAFE_componentWillMount() {
-    const { autoMatic } = this.props
+    const { autoMatic, tabId } = this.props
 
     if (autoMatic.gap && autoMatic.gap >= 1) {
       this.setState({gap: autoMatic.gap * 1000})
+    }
+
+    if (tabId && tabId === sessionStorage.getItem('autoExecId')) {
+      sessionStorage.removeItem('autoExecId')
+
+      setTimeout(() => {
+        this.trigger()
+      }, 10000)
     }
   }
 
@@ -180,7 +189,7 @@
   }
 
   autoMaticOver = (MenuID) => {
-    const { config, autoMatic } = this.props
+    const { config, autoMatic, tabId } = this.props
 
     if (!this.state.running || MenuID !== config.MenuID) return
 
@@ -189,16 +198,24 @@
     if (autoMatic.onFinish !== 'over') {
       let interval = autoMatic.interval * 1000 || 10
 
-      if (autoMatic.restart === 'first') {
-        this.setState({line: 1})
+      if (autoMatic.restart === 'refresh') {
+        this.timer = setTimeout(() => {
+          sessionStorage.setItem('ThirdMenu', tabId)
+          sessionStorage.setItem('autoExecId', tabId)
+          window.location.reload()
+        }, interval)
       } else {
-        this.setState({line: this.state.line + 1})
+        if (autoMatic.restart === 'first') {
+          this.setState({line: 1})
+        } else {
+          this.setState({line: this.state.line + 1})
+        }
+  
+        this.timer = setTimeout(() => {
+          this.setState({running: true})
+          MKEmitter.emit('autoQueryData', config.MenuID, this.state.line)
+        }, interval)
       }
-
-      this.timer = setTimeout(() => {
-        this.setState({running: true})
-        MKEmitter.emit('autoQueryData', config.MenuID, this.state.line)
-      }, interval)
     }
   }
 
diff --git a/src/tabviews/zshare/calendar/index.jsx b/src/tabviews/zshare/calendar/index.jsx
deleted file mode 100644
index 19c209a..0000000
--- a/src/tabviews/zshare/calendar/index.jsx
+++ /dev/null
@@ -1,398 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Select, Radio, Row, Col, Popover, Badge, Spin } from 'antd'
-import moment from 'moment'
-
-import './index.scss'
-
-const { Option } = Select
-
-class Calendar extends Component {
-  static propTpyes = {
-    data: PropTypes.any,            // 浜嬩欢鏁版嵁
-    calendar: PropTypes.any,
-    changeDate: PropTypes.func,
-    triggerDate: PropTypes.func,
-    loading: false
-  }
-
-  state = {
-    level: 'day',
-    levels: null,
-    yearlist: null,
-    selectYear: moment().format('YYYY'),
-    selectMonth: moment().format('MM'),
-    datelist: null,
-    monthlist: null
-  }
-
-  UNSAFE_componentWillMount() {
-    const { calendar, data } = this.props
-
-    let yearlist = []
-    let _selectYear = +this.state.selectYear
-    yearlist.push(`${_selectYear}`)
-    
-    for (let i = 1; i <= 50; i++) {
-      yearlist.unshift(`${_selectYear - i}`)
-      yearlist.push(`${_selectYear + i}`)
-    }
-
-    let datelist = this.getDateList(this.state.selectYear)
-
-    if (data && data.length > 0) {
-      datelist = this.mountdata(datelist, data)
-    }
-    
-    let _levels = calendar.levels
-    let level = _levels[0]
-    let monthlist = null
-
-    if (_levels.includes('month') || _levels.includes('year')) {
-      monthlist = datelist.filter(item => item.month === moment().format('MM'))[0]
-    }
-
-    this.setState({
-      yearlist,
-      datelist,
-      monthlist,
-      level,
-      levels: _levels
-    })
-  }
-
-  UNSAFE_componentWillReceiveProps(nextProps) {
-    if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let datelist = this.getDateList(this.state.selectYear)
-      let monthlist = null
-      
-      datelist = this.mountdata(datelist, nextProps.data)
-
-      if (this.state.levels.includes('month') || this.state.levels.includes('year')) {
-        monthlist = datelist.filter(item => item.month === this.state.selectMonth)[0]
-      }
-
-      this.setState({
-        datelist: datelist,
-        monthlist
-      })
-    } else if (!is(fromJS(this.props.calendar), fromJS(nextProps.calendar))) {
-      this.setState({
-        levels: nextProps.calendar.levels
-      })
-    }
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props.loading), fromJS(nextProps.loading)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  mountdata = (datelist, data) => {
-    const { calendar } = this.props
-
-    let datalist = []
-    let colors = {
-      transparent: 'rgba(0, 0, 0, 0)',
-      red: 'rgba(208, 2, 27, 1)',
-      orange: 'rgba(245, 166, 35, 1)',
-      yellow: 'rgba(248, 231, 28, 1)',
-      green: 'rgba(126, 211, 33, 1)',
-      cyan: 'rgba(80, 227, 194, 1)',
-      blue: 'rgba(24, 144, 255, 1)',
-      purple: 'rgba(189, 16, 224, 1)',
-      gray: 'rgba(155, 155, 155, 1)'
-    }
-
-    data && data.forEach(item => {
-      let startTime = item[calendar.startfield]
-      let endTime = item[calendar.endfield]
-      let color = item[calendar.colorfield] || '#ffffff'
-
-      if (!startTime || !/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(startTime)) return
-      if (!endTime || !/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(endTime)) return
-      if (!item[calendar.remarkfield]) return
-
-      let equal = endTime.substr(0, 4) === startTime.substr(0, 4)
-
-      datalist.push({
-        color: colors[color] || color,
-        remark: item[calendar.remarkfield],
-        startMonth: startTime.substr(0, 4) + startTime.substr(5, 2),
-        endMonth: endTime.substr(0, 4) + endTime.substr(5, 2),
-        start: startTime.substr(0, 4) + startTime.substr(5, 2) + startTime.substr(8, 2),
-        startTime: equal ? `${startTime.substr(5, 2)}-${startTime.substr(8, 2)}` : `${startTime.substr(0, 4)}-${startTime.substr(5, 2)}-${startTime.substr(8, 2)}`,
-        end: endTime.substr(0, 4) + endTime.substr(5, 2) + endTime.substr(8, 2),
-        endTime: equal ?  `${endTime.substr(5, 2)}-${endTime.substr(8, 2)}` : `${endTime.substr(0, 4)}-${endTime.substr(5, 2)}-${endTime.substr(8, 2)}`
-      })
-    })
-
-    return datelist.map(month => {
-      month.subData = []
-      datalist.forEach(item => {
-        if (item.startMonth <= month.time && item.endMonth >= month.time) {
-          month.subData.push(item)
-        }
-      })
-      month.style = this.getStyle(month.subData[0])
-      month.sublist = month.sublist.map(week => {
-        week.sublist = week.sublist.map(day => {
-          if (!day) return null
-
-          day.subData = []
-          datalist.forEach(item => {
-            if (item.start <= day.time && item.end >= day.time) {
-              day.subData.push(item)
-            }
-          })
-          day.style = this.getStyle(day.subData[0])
-          return day
-        })
-        return week
-      })
-      return month
-    })
-  }
-
-  getStyle = (item ) => {
-    if (!item || !item.color) return null
-    let style = {background: item.color}
-    
-    if (/rgb/ig.test(item.color)) {
-      try {
-        let colors = item.color.match(/\d+/g)
-        if ((colors[0] * 0.299 + colors[1] * 0.578 + colors[2] * 0.114) * colors[3] < 192) {
-          style.color = '#ffffff'
-        }
-      } catch (e) {}
-    }
-
-    return style
-  }
-
-  getDateList = (selectYear) => {
-    let datelist = []
-    let months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
-    let monthName = {
-      '01': '涓�鏈�', '02': '浜屾湀', '03': '涓夋湀', '04': '鍥涙湀', '05': '浜旀湀', '06': '鍏湀',
-      '07': '涓冩湀', '08': '鍏湀', '09': '涔濇湀', '10': '鍗佹湀', '11': '鍗佷竴鏈�', '12': '鍗佷簩鏈�'
-    }
-
-    months.forEach(month => {
-      let _weeklist = [{week: 1, sublist: []}]
-      let _week = moment(`${selectYear}${month}01`, 'YYYYMMDD').weekday()
-      let end = +moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').format('DD')
-
-      for (let i = 0; i < _week; i++) {
-        _weeklist[0].sublist.push(null)
-      }
-
-      for (let i = 1; i <= end; i++) {
-        let _day = i < 10 ? `0${i}` : `${i}`
-
-        if (_weeklist[_weeklist.length - 1].sublist.length < 7) {
-          _weeklist[_weeklist.length - 1].sublist.push({day: _day, time: selectYear + month + _day, label: i, subData: []})
-        } else {
-          let _week = {week: _weeklist.length + 1, sublist: [{day: _day, time: selectYear + month + _day, label: i, subData: []}]}
-          _weeklist.push(_week)
-        }
-      }
-
-      let re = 7 - _weeklist.slice(-1)[0].sublist.length
-      for (let i = 0; i < re; i++) {
-        _weeklist[_weeklist.length - 1].sublist.push(null)
-      }
-
-      datelist.push({
-        month: month,
-        time: selectYear + month,
-        label: monthName[month],
-        sublist: _weeklist,
-        subData: []
-      })
-    })
-
-    return datelist
-  }
-
-  levelChange = (e) => {
-    this.setState({ level: e.target.value })
-  }
-
-  yearChange = (value) => {
-    const { calendar, data } = this.props
-    const { levels, selectMonth } = this.state
-    let datelist = this.getDateList(value)
-    let monthlist = null
-
-    if (levels.includes('month') || levels.includes('year')) {
-      monthlist = datelist.filter(item => item.month === selectMonth)[0]
-    }
-    
-    if (calendar.refresh !== 'true') {
-      datelist = this.mountdata(datelist, data)
-
-      this.setState({ selectYear: value, datelist, monthlist })
-    } else {
-      this.setState({ selectYear: value, datelist, monthlist }, () => {
-        this.props.changeDate(value)
-      })
-    }
-  }
-
-  monthChange = (value) => {
-    const { datelist, levels, selectYear } = this.state
-
-    if (!levels.includes('month')) {
-      if (this.props.triggerDate) {
-        this.props.triggerDate({
-          time: `${selectYear}${value}01`
-        })
-      }
-      return
-    }
-
-    this.setState({
-      level: 'month',
-      selectMonth: value,
-      monthlist: datelist.filter(item => item.month === value)[0]
-    })
-  }
-
-  triggerDay = (item) => {
-    if (this.props.triggerDate) {
-      this.props.triggerDate(item)
-    }
-  }
-
-  render() {
-    const { loading } = this.props
-    const { level, selectMonth, selectYear, yearlist, levels, datelist, monthlist } = this.state
-    const _levelName = {day: '鏃�', month: '鏈�', year: '骞�'}
-
-    return (
-      <div className="mk-calendar">
-        {loading ? <div className="loading-data"><Spin /></div> : null}
-        <div className="mk-calendar-control">
-          <Select value={selectYear} onChange={this.yearChange}>
-            {yearlist.map(item => (<Option key={item} value={item}>{item}骞�</Option>))}
-          </Select>
-          {level === 'month' ? <Select value={selectMonth} onChange={this.monthChange}>
-            <Option value="01">1鏈�</Option>
-            <Option value="02">2鏈�</Option>
-            <Option value="03">3鏈�</Option>
-            <Option value="04">4鏈�</Option>
-            <Option value="05">5鏈�</Option>
-            <Option value="06">6鏈�</Option>
-            <Option value="07">7鏈�</Option>
-            <Option value="08">8鏈�</Option>
-            <Option value="09">9鏈�</Option>
-            <Option value="10">10鏈�</Option>
-            <Option value="11">11鏈�</Option>
-            <Option value="12">12鏈�</Option>
-          </Select> : null}
-          {levels.length > 1 ? <Radio.Group value={level} onChange={this.levelChange}>
-            {levels.map(item => (<Radio.Button key={item} value={item}>{_levelName[item]}</Radio.Button>))}
-          </Radio.Group> : null}
-        </div>
-        <div className="mk-calendar-content">
-          {level === 'day' ? <Row className="day-calendar" gutter={16}>
-            {datelist.map(item => (
-              <Col span={4} key={item.month}>
-                <table>
-                  <thead>
-                    <tr>
-                      <th colSpan="7">{item.label}</th>
-                    </tr>
-                    <tr>
-                      <th>涓�</th><th>浜�</th><th>涓�</th><th>鍥�</th><th>浜�</th><th>鍏�</th><th>鏃�</th>
-                    </tr>
-                  </thead>
-                  <tbody>
-                    {item.sublist.map(cell => (
-                      <tr key={cell.week}>
-                        {cell.sublist.map((d, i) => (
-                          <td key={i}>
-                            {d ? <div className="day-wrap" style={d.style || null} onClick={() => this.triggerDay(d)}>
-                              {d.subData.length > 0 ? <Popover mouseEnterDelay={0.3} overlayClassName="calendar-day-pop" content={
-                                <div>
-                                  {d.subData.map((data, index) => (
-                                    <div key={index} className="message">
-                                      <Badge color={data.color} text={
-                                        <span>
-                                          {data.remark}
-                                          <span style={{color: 'rgba(0,0,0,.45)'}}>({data.startTime + ' ~ ' + data.endTime})</span>
-                                        </span>}
-                                      />
-                                    </div>
-                                  ))}
-                                </div>
-                              } trigger="hover">
-                                {d.label}
-                              </Popover> : d.label}
-                            </div> : null }
-                          </td>
-                        ))}
-                      </tr>
-                    ))}
-                  </tbody>
-                </table>
-              </Col>
-            ))}
-          </Row> : null}
-          {level === 'month' && monthlist ? <div className="month-calendar">
-            <table>
-              <thead>
-                <tr>
-                  <th>涓�</th><th>浜�</th><th>涓�</th><th>鍥�</th><th>浜�</th><th>鍏�</th><th>鏃�</th>
-                </tr>
-              </thead>
-              <tbody>
-                {monthlist.sublist.map(cell => (
-                  <tr key={cell.week}>
-                    {cell.sublist.map((d, i) => (
-                      <td key={i}>
-                        {d ? <div className="month-wrap" style={d.style || null} onClick={() => this.triggerDay(d)}>
-                          <div className="header">
-                            {d.label}
-                          </div>
-                          <ul className="content">
-                            {d.subData.map((data, index) => (
-                              <li key={index} className="message">
-                                <Badge color={d.style ? (data.color === d.style.background ? '#ffffff' : data.color) : data.color} text={data.remark} />
-                              </li>
-                            ))}
-                          </ul>
-                        </div> : null }
-                      </td>
-                    ))}
-                  </tr>
-                ))}
-              </tbody>
-            </table>
-          </div>: null}
-          {level === 'year' && monthlist ? <Row className="year-calendar">
-            {datelist.map(item => (
-              <Col span={8} key={item.month}>
-                <div className="year-wrap" style={item.style || null} onClick={() => this.monthChange(item.month)}>
-                  <div className="header" style={item.style ? null : {color: '#1890ff'}}>
-                    {item.label}
-                  </div>
-                  <ul className="content">
-                    {item.subData.map((data, index) => (
-                      <li key={index} className="message">
-                        <Badge color={item.style ? (data.color === item.style.background ? '#ffffff' : data.color) : data.color} text={`${data.remark} (${data.startTime} ~ ${data.endTime})`}/>
-                      </li>
-                    ))}
-                  </ul>
-                </div>
-              </Col>
-            ))}
-          </Row>: null}
-        </div>
-      </div>
-    )
-  }
-}
-
-export default Calendar
\ No newline at end of file
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index 067bfd2..e9a26ed 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -6,7 +6,6 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import { formRule } from '@/utils/option.js'
 import Utils from '@/utils/utils.js'
 import asyncComponent from '@/utils/asyncComponent'
@@ -31,7 +30,7 @@
 const MkVercode = asyncComponent(() => import('./mkVercode'))
 const MKEditor = asyncComponent(() => import('@/components/editor'))
 
-class MainSearch extends Component {
+class MutilFormComponent extends Component {
   static propTpyes = {
     action: PropTypes.object,    // 鎸夐挳淇℃伅銆佽〃鍗曞垪琛�
     data: PropTypes.any,         // 琛ㄦ牸鏁版嵁
@@ -89,6 +88,7 @@
         } else {
           supvals.push('')
         }
+        supvals = Array.from(new Set(supvals))
         controlFields[item.supField] = controlFields[item.supField] || []
         controlFields[item.supField].push({field: item.field, values: supvals})
       }
@@ -212,6 +212,35 @@
         }
         if (newval === '$empty' && item.initval) {
           newval = moment().subtract(item.initval, 'days').format(_format)
+        }
+
+        if (item.minDate) {
+          if (item.minDate === 'custom') {
+            if (/^\d{4}-\d{2}-\d{2}$/.test(item.minDateField)) {
+              item.minDate = moment(item.minDateField).format('YYYY-MM-DD')
+            } else {
+              let val = data[item.minDateField.toLowerCase()]
+              item.minDate = val ? moment(val).format('YYYY-MM-DD') : ''
+            }
+
+            item.minDate = item.minDate === 'Invalid date' ? '' : item.minDate
+          } else {
+            item.minDate = moment().add(item.minDate, 'days').format('YYYY-MM-DD')
+          }
+        }
+        if (item.maxDate) {
+          if (item.maxDate === 'custom') {
+            if (/^\d{4}-\d{2}-\d{2}$/.test(item.maxDateField)) {
+              item.maxDate = moment(item.maxDateField).format('YYYY-MM-DD')
+            } else {
+              let val = data[item.maxDateField.toLowerCase()]
+              item.maxDate = val ? moment(val).format('YYYY-MM-DD') : ''
+            }
+
+            item.maxDate = item.maxDate === 'Invalid date' ? '' : item.maxDate
+          } else {
+            item.maxDate = moment().add(item.maxDate, 'days').format('YYYY-MM-DD')
+          }
         }
       } else if (item.type === 'datemonth') {
         if (newval !== '$empty') {
@@ -413,9 +442,24 @@
 
         let cell = fieldMap.get(item.field)
 
-        // if (cell.hidden) return
-        
-        if (supItem.hidden || !item.values.includes(supItem.initval)) {
+        let _hidden = false
+
+        if (supItem.hidden) {
+          _hidden = true
+        } else {
+          let box = [...item.values]
+          if (supItem.type === 'multiselect' || (supItem.type === 'checkcard' && supItem.multiple === 'true')) {
+            box.push(...supItem.initval.split(','))
+          } else {
+            box.push(supItem.initval)
+          }
+  
+          if (box.length === Array.from(new Set(box)).length) {
+            _hidden = true
+          }
+        }
+
+        if (_hidden) {
           cell.hidden = true
           if (cell.empty === 'hidden') {
             cell.$hidden = true
@@ -465,6 +509,31 @@
           })
           
           item.options = fromJS(item.oriOptions).toJS()
+        }
+        item.linkSubField = null
+      } else if (item.type === 'switch' && item.linkSubField) {
+        item.options = []
+        item.subFields = []
+        item.linkSubField.forEach(m => {
+          let n = fieldMap.get(m)
+          if (n && ['text', 'number', 'textarea'].includes(n.type)) {
+            item.subFields.push({
+              uuid: n.uuid,
+              field: m
+            })
+          }
+        })
+
+        if (item.subFields.length === 0) {
+          item.subFields = null
+        } else {
+          reFieldsVal = reFieldsVal || {}
+
+          let val = item.initval === item.openVal ? item.openText : item.closeText
+        
+          item.subFields.forEach(n => {
+            reFieldsVal[n.field] = val || ''
+          })
         }
         item.linkSubField = null
       }
@@ -541,8 +610,9 @@
     }
 
     this.record = record
+    let ID = this.props.data ? this.props.data.$$uuid || '' : ''
 
-    this.setState({ formlist, ID: this.props.data ? this.props.data.$$uuid || '' : '' }, () => {
+    this.setState({ formlist, ID }, () => {
       if (unload) return
       
       if (action.setting && action.setting.focus && fieldMap.has(action.setting.focus)) {
@@ -560,13 +630,29 @@
       }
 
       if (deForms.length > 0) {
-        if (!window.GLOB.mkHS && options.sysType === 'local' && window.GLOB.systemType !== 'production') {
-          this.improveSimpleActionForm(deForms)
+        if (action.$cache && action.setting.cache !== 'false') {
+          Api.getLCacheConfig(action.uuid, action.$time, this.props.BID, ID).then(res => {
+            if (!res.valid) {
+              this.getFormData(deForms)
+            } else {
+              this.resetFormList(res.data, true)
+            }
+          })
         } else {
-          this.improveActionForm(deForms)
+          this.getFormData(deForms)
         }
       }
     })
+  }
+
+  getFormData = (deForms) => {
+    if (deForms.length === 1) {
+      this.improveSimpleActionForm(deForms)
+    } else if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
+      this.improveSimpleActionForm(deForms)
+    } else {
+      this.improveActionForm(deForms)
+    }
   }
 
   /**
@@ -578,8 +664,8 @@
     let deffers = []
     let mainItems = []  // 浜戠鎴栧崟鐐规暟鎹�
     let localItems = [] // 鏈湴鏁版嵁
-    let cache = action.setting.cache !== 'false'
-    let debug = window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')
+    let cache = action.setting.cache !== 'false' && !action.$cache
+    let skip = false
 
     let _sql = `Declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)  select @mk_departmentcode='${sessionStorage.getItem('departmentcode') || ''}',@mk_organization='${sessionStorage.getItem('organization') || ''}',@mk_user_type='${sessionStorage.getItem('mk_user_type') || ''}'\n`
     let _sso = _sql
@@ -592,7 +678,7 @@
         sql = sql.replace(/@ID@/ig, `'${this.state.ID || ''}'`)
         sql = sql.replace(/@BID@/ig, `'${BID}'`)
 
-        if (debug) {
+        if (window.GLOB.debugger === true) {
           console.info(sql)
         }
 
@@ -606,7 +692,7 @@
         sql = sql.replace(/@ID@/ig, `'${this.state.ID || ''}'`)
         sql = sql.replace(/@BID@/ig, `'${BID}'`)
 
-        if (debug) {
+        if (window.GLOB.debugger === true) {
           console.info(sql)
         }
 
@@ -643,6 +729,7 @@
                 message: res.message,
                 duration: 5
               })
+              skip = true
             }
             resolve(res)
           })
@@ -666,8 +753,8 @@
 
       if (window.GLOB.mkHS) { // 浜戠鏁版嵁楠岃瘉
         mainparam.open_key = Utils.encryptOpenKey(mainparam.secretkey, mainparam.timestamp)
-        if (options.cloudServiceApi) {
-          mainparam.rduri = options.cloudServiceApi
+        if (window.GLOB.cloudServiceApi) {
+          mainparam.rduri = window.GLOB.cloudServiceApi
           mainparam.userid = sessionStorage.getItem('CloudUserID') || ''
           mainparam.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         }
@@ -684,6 +771,7 @@
                 message: res.message,
                 duration: 5
               })
+              skip = true
             }
             resolve(res)
           })
@@ -699,7 +787,7 @@
       delete result.message
       delete result.status
 
-      this.resetFormList(result)
+      this.resetFormList(result, skip)
     })
   }
 
@@ -707,9 +795,11 @@
    * @description 娴嬭瘯绯荤粺鑾峰彇涓嬫媺琛ㄥ崟閫夐」淇℃伅
    */
   improveSimpleActionForm = (deForms) => {
-    let cache = this.props.action.setting.cache !== 'false'
-    let debug = window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')
+    const { action } = this.props
+
+    let cache = this.props.action.setting.cache !== 'false' && !action.$cache
     let _sql = `Declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)  select @mk_departmentcode='${sessionStorage.getItem('departmentcode') || ''}',@mk_organization='${sessionStorage.getItem('organization') || ''}',@mk_user_type='${sessionStorage.getItem('mk_user_type') || ''}'\n`
+    let skip = false
 
     let deffers = deForms.map((form, index) => {
       let param = {
@@ -722,7 +812,7 @@
       param.LText = param.LText.replace(/@ID@/ig, `'${this.state.ID || ''}'`)
       param.LText = param.LText.replace(/@BID@/ig, `'${this.props.BID || ''}'`)
 
-      if (debug) {
+      if (window.GLOB.debugger) {
         console.info(param.LText)
       }
   
@@ -744,6 +834,7 @@
                   message: res.message,
                   duration: 5
                 })
+                skip = true
               }
               resolve(res)
             })
@@ -754,6 +845,7 @@
 
     Promise.all(deffers).then(response => {
       let result = {}
+      
       response.forEach(res => {
         result = {...result, ...res}
       })
@@ -763,11 +855,17 @@
       delete result.message
       delete result.status
 
-      this.resetFormList(result)
+      this.resetFormList(result, skip)
     })
   }
 
-  resetFormList = (result) => {
+  resetFormList = (result, skip) => {
+    const { BID, action } = this.props
+
+    if (action.$cache && action.setting.cache !== 'false' && !skip) {
+      Api.writeCacheConfig(action.uuid, fromJS(result).toJS(), BID, this.state.ID)
+    }
+
     let reFieldsVal = null
     let _formlist = fromJS(this.state.formlist).toJS().map(item => {
       if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect', 'cascader'].includes(item.type) && result[item.field] && result[item.field].length > 0) {
@@ -929,7 +1027,23 @@
 
       current.controlFields.forEach(cell => {
         let m = map.get(cell.field)
-        m.hidden = current.hidden || !cell.values.includes(val)
+
+        m.hidden = false
+
+        if (current.hidden) {
+          m.hidden = true
+        } else {
+          let box = [...cell.values]
+          if (current.type === 'multiselect' || (current.type === 'checkcard' && current.multiple === 'true')) {
+            box.push(...val.split(','))
+          } else {
+            box.push(val)
+          }
+  
+          if (box.length === Array.from(new Set(box)).length) {
+            m.hidden = true
+          }
+        }
 
         if (m.empty === 'hidden' && m.oriOptions.length === 0) {
           m.hidden = true
@@ -1011,7 +1125,7 @@
           className = 'checkcard'
           content = (<MKCheckCard config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
         } else if (item.type === 'switch') {
-          content = (<MKSwitch config={item} onChange={(val) => this.recordChange({[item.field]: val}, item)}/>)
+          content = (<MKSwitch config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
         } else if (item.type === 'check') {
           content = (<MKCheck config={item} onChange={(val) => this.recordChange({[item.field]: val}, item)}/>)
         } else if (item.type === 'checkbox') {
@@ -1094,7 +1208,7 @@
             _item.fieldlen = item.decimal || 0
           } else if (['text', 'textarea', 'linkMain'].includes(item.type)) {
             _item.value = _item.value + ''
-            _item.value = _item.value.replace(/\t*|\v*/g, '')       // 鍘婚櫎鍒惰〃绗�
+            _item.value = _item.value.replace(/\t+|\v+/g, '')       // 鍘婚櫎鍒惰〃绗�
     
             if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
               _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
@@ -1171,4 +1285,4 @@
   }
 }
 
-export default Form.create()(MainSearch)
\ No newline at end of file
+export default Form.create()(MutilFormComponent)
\ No newline at end of file
diff --git a/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx b/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
index 9d9cb2c..a7dc070 100644
--- a/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Col, Row } from 'antd'
+import { Col, Row, Switch } from 'antd'
 import { CheckOutlined } from '@ant-design/icons'
 
 import MKEmitter from '@/utils/events.js'
@@ -281,6 +281,29 @@
     }
   }
 
+  onChange = (val) => {
+    if (val) {
+      let keys = []
+      this.state.options.forEach(item => {
+        if (item.$disabled) return
+
+        keys.push(item.$value)
+      })
+
+      this.setState({
+        selectKeys: keys
+      }, () => {
+        this.props.onChange(keys.join(','))
+      })
+    } else {
+      this.setState({
+        selectKeys: []
+      }, () => {
+        this.props.onChange('')
+      })
+    }
+  }
+
   render() {
     const { config, options } = this.state
 
@@ -295,6 +318,7 @@
 
     return (
       <div className={'check-card-form-box ' + extend}>
+        {config.checkAll === 'show' && options.length > 3 ? <Switch size="small" onChange={this.onChange}/> : null}
         <Row gutter={12}>{this.getCards()}</Row>
       </div>
     )
diff --git a/src/tabviews/zshare/mutilform/mkCheckCard/index.scss b/src/tabviews/zshare/mutilform/mkCheckCard/index.scss
index b97b1d8..7bb1021 100644
--- a/src/tabviews/zshare/mutilform/mkCheckCard/index.scss
+++ b/src/tabviews/zshare/mutilform/mkCheckCard/index.scss
@@ -1,5 +1,6 @@
 .check-card-form-box {
   margin-top: 5px;
+  position: relative;
   .card-cell {
     position: relative;
     border: 1px solid #bcbcbc;
@@ -135,6 +136,13 @@
     }
   }
 
+  .ant-switch {
+    position: absolute;
+    top: -22px;
+    right: 0px;
+    opacity: 0.7;
+  }
+
   .card-cell.disabled {
     cursor: not-allowed;
   }
diff --git a/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx b/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
index 6643b2b..0fe72ab 100644
--- a/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
@@ -37,8 +37,8 @@
 
     this.state = {
       value,
-      minDate: config.minDate ? moment().add(config.minDate, 'days').startOf('day') : '',
-      maxDate: config.maxDate ? moment().add(config.maxDate, 'days').endOf('day') : '',
+      minDate: config.minDate ? moment(config.minDate).startOf('day') : '',
+      maxDate: config.maxDate ? moment(config.maxDate).endOf('day') : '',
       mode,
       format
     }
diff --git a/src/tabviews/zshare/mutilform/mkRadio/index.jsx b/src/tabviews/zshare/mutilform/mkRadio/index.jsx
index a541852..ac79bbf 100644
--- a/src/tabviews/zshare/mutilform/mkRadio/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkRadio/index.jsx
@@ -20,15 +20,11 @@
   UNSAFE_componentWillMount () {
     const { config } = this.props
     let value = config.initval
+    let option = config.oriOptions[0]
 
-    if (value) {
-      let option = null
-      option= config.oriOptions[0]
-      if (typeof(value) === 'string' && option && typeof(option.value) === 'number') {
+    if (value && option && typeof(option.value) !== typeof(value)) {
+      if (typeof(option.value) === 'number' && !isNaN(value)) {
         value = +value
-        if (isNaN(value)) {
-          value = config.initval
-        }
       }
     }
 
@@ -44,7 +40,7 @@
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
-    const { config } = this.state
+    const { config, value } = this.state
 
     if (!is(fromJS(config.oriOptions), fromJS(nextProps.config.oriOptions))) {
       this.setState({
@@ -52,10 +48,18 @@
         options: fromJS(nextProps.config.options).toJS()
       })
 
+      let option = nextProps.config.oriOptions[0]
+
       if (config.$first) {
         this.setState({
           value: nextProps.config.initval,
         })
+      } else if (option && typeof(option.value) !== typeof(value)) {
+        if (typeof(option.value) === 'number' && !isNaN(value)) {
+          this.setState({
+            value: +value
+          })
+        }
       }
     }
   }
diff --git a/src/tabviews/zshare/mutilform/mkSelect/index.jsx b/src/tabviews/zshare/mutilform/mkSelect/index.jsx
index c46e4ed..c8af8d3 100644
--- a/src/tabviews/zshare/mutilform/mkSelect/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkSelect/index.jsx
@@ -18,12 +18,11 @@
         value = []
       }
     } else if (value) {
-      let option = null
-      option= config.oriOptions[0]
-      if (typeof(value) === 'string' && option && typeof(option.value) === 'number') {
-        value = +value
-        if (isNaN(value)) {
-          value = config.initval
+      let option = config.oriOptions[0]
+
+      if (option && typeof(option.value) !== typeof(value)) {
+        if (typeof(option.value) === 'number' && !isNaN(value)) {
+          value = +value
         }
       }
     }
@@ -57,20 +56,16 @@
         options: fromJS(nextProps.config.options).toJS()
       })
 
+      let option = nextProps.config.oriOptions[0]
       if (config.$first) {
         this.setState({
           value: nextProps.config.initval,
         })
-      } else {
-        let option = null
-        option= nextProps.config.oriOptions[0]
-        if (option && typeof(option.value) === 'number') {
-          let val = +value
-          if (!isNaN(val)) {
-            this.setState({
-              value: val
-            })
-          }
+      } else if (option && typeof(option.value) !== typeof(value)) {
+        if (typeof(option.value) === 'number' && !isNaN(value)) {
+          this.setState({
+            value: +value
+          })
         }
       }
     }
diff --git a/src/tabviews/zshare/mutilform/mkSwitch/index.jsx b/src/tabviews/zshare/mutilform/mkSwitch/index.jsx
index 0601054..62f8822 100644
--- a/src/tabviews/zshare/mutilform/mkSwitch/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkSwitch/index.jsx
@@ -2,6 +2,8 @@
 import PropTypes from 'prop-types'
 import { Switch } from 'antd'
 
+import MKEmitter from '@/utils/events.js'
+
 class MKSwitch extends Component {
   static propTpyes = {
     config: PropTypes.object,
@@ -15,10 +17,21 @@
   onChange = (val) => {
     const { config } = this.props
     
+    let other = {}
+    if (config.subFields) {
+      let _val = val ? config.openText : config.closeText
+      config.subFields.forEach((n, i) => {
+        other[n.field] = _val || ''
+        setTimeout(() => {
+          MKEmitter.emit('mkFC', 'input', n.uuid, _val || '')
+        }, i * 5)
+      })
+    }
+
     if (val) {
-      this.props.onChange(config.openVal)
+      this.props.onChange(config.openVal, other)
     } else {
-      this.props.onChange(config.closeVal)
+      this.props.onChange(config.closeVal, other)
     }
   }
 
diff --git a/src/tabviews/zshare/mutilform/mkVercode/index.jsx b/src/tabviews/zshare/mutilform/mkVercode/index.jsx
index dfa614b..c0569d0 100644
--- a/src/tabviews/zshare/mutilform/mkVercode/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkVercode/index.jsx
@@ -146,7 +146,30 @@
           } else {
             this.props.onSend(send_type, timestamp, n_id)
           }
-        }, () => {
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') {
+            let param = {
+              func: 's_visitor_login',
+              timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), 
+              SessionUid: 'bh0bapabtd45epsgra79segbch6c1ibk',
+              TypeCharOne: 'pc',
+              appkey: '202004041613277377A6A2456D34A4948AE84'
+            }
+            
+            param.LText = md5(window.btoa('bh0bapabtd45epsgra79segbch6c1ibk' + param.timestamp))
+            param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
+    
+            let params = {
+              url: 'https://sso.mk9h.cn/webapi/dologon',
+              method: 'post',
+              data: JSON.stringify(param)
+            }
+  
+            Api.directRequest(params)
+  
+            return
+          }
+
           clearTimeout(this.timer)
           this.setState({
             verdisabled: false,
@@ -182,7 +205,30 @@
         } else {
           this.props.onSend(send_type, timestamp, n_id)
         }
-      }, () => {
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') {
+          let param = {
+            func: 's_visitor_login',
+            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), 
+            SessionUid: 'bh0bapabtd45epsgra79segbch6c1ibk',
+            TypeCharOne: 'pc',
+            appkey: '202004041613277377A6A2456D34A4948AE84'
+          }
+          
+          param.LText = md5(window.btoa('bh0bapabtd45epsgra79segbch6c1ibk' + param.timestamp))
+          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
+  
+          let params = {
+            url: 'https://sso.mk9h.cn/webapi/dologon',
+            method: 'post',
+            data: JSON.stringify(param)
+          }
+
+          Api.directRequest(params)
+
+          return
+        }
+        
         clearTimeout(this.timer)
         this.setState({
           verdisabled: false,
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index 2f6d9ab..300e98e 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -111,7 +111,7 @@
         _columns.push(cell)
       })
     } else {
-      if (window.GLOB.dataFormat && !window.GLOB.mkHS) {
+      if (window.GLOB.dataFormat) {
         _format = true
   
         if (window.GLOB.memberLevel >= 30) {
@@ -710,7 +710,7 @@
       }
 
       if (item.joint === 'true' && _href) {
-        let _quary = `id=${record[this.props.setting.primaryKey]}&userid=${sessionStorage.getItem('UserID')}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
+        let _quary = `id=${record[this.props.setting.primaryKey]}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID')}`
         let _param = ''
         
         try {
@@ -783,6 +783,7 @@
                 <NewPageButton
                   key={btn.uuid}
                   btn={btn}
+                  BID={record.$$BID}
                   disabled={record.$disabled}
                   selectedData={[record]}
                   BData={this.props.BData}
@@ -912,7 +913,7 @@
           }
 
           if (col.joint === 'true' && _href) {
-            let _quary = `id=${record[this.props.setting.primaryKey]}&userid=${sessionStorage.getItem('UserID')}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
+            let _quary = `id=${record[this.props.setting.primaryKey]}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID')}`
             let _param = ''
 
             try {
diff --git a/src/tabviews/zshare/pageMessage/index.jsx b/src/tabviews/zshare/pageMessage/index.jsx
index 4ca2a3b..0d283a3 100644
--- a/src/tabviews/zshare/pageMessage/index.jsx
+++ b/src/tabviews/zshare/pageMessage/index.jsx
@@ -5,7 +5,6 @@
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
 
 import './index.scss'
 
@@ -317,8 +316,8 @@
     const { debug, visible, data } = this.state
 
     return (
-      <div className={'page-message-wrap ' + (debug && options.sysType !== 'cloud' ? 'exist' : '')}>
-        {debug && options.sysType !== 'cloud' ? <Button
+      <div className={'page-message-wrap ' + (debug && window.GLOB.sysType !== 'cloud' ? 'exist' : '')}>
+        {debug && window.GLOB.sysType !== 'cloud' ? <Button
           icon="copy"
           shape="circle"
           className="page-message"
diff --git a/src/tabviews/zshare/settingcomponent/index.jsx b/src/tabviews/zshare/settingcomponent/index.jsx
index c3c366a..76f94ae 100644
--- a/src/tabviews/zshare/settingcomponent/index.jsx
+++ b/src/tabviews/zshare/settingcomponent/index.jsx
@@ -6,7 +6,6 @@
 import Api from '@/api'
 import MKEmitter from '@/utils/events.js'
 import { updateSubTable } from '@/utils/utils-update.js'
-import options from '@/store/options.js'
 import asyncComponent from '@/utils/asyncSpinComponent'
 import './index.scss'
 
@@ -517,7 +516,7 @@
 
     return (
       <div className="page-setting-wrap">
-        {options.sysType === 'local' ? <Button
+        {window.GLOB.sysType === 'local' ? <Button
           icon="setting"
           shape="circle"
           className="page-setting"
diff --git a/src/tabviews/zshare/tablenodes/index.jsx b/src/tabviews/zshare/tablenodes/index.jsx
index f46b98d..21c1919 100644
--- a/src/tabviews/zshare/tablenodes/index.jsx
+++ b/src/tabviews/zshare/tablenodes/index.jsx
@@ -6,7 +6,6 @@
 import Api from '@/api'
 import G6 from "@antv/g6"
 import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
 import './index.scss'
 
 const { Search } = Input
@@ -475,8 +474,8 @@
     const { visible, loading, empty, debug } = this.state
 
     return (
-      <div className={'page-message-wrap ' + (debug && options.sysType !== 'cloud' ? 'exist' : '')}>
-        {debug && options.sysType !== 'cloud' ? <Button
+      <div className={'page-message-wrap ' + (debug && window.GLOB.sysType !== 'cloud' ? 'exist' : '')}>
+        {debug && window.GLOB.sysType !== 'cloud' ? <Button
           icon="fork"
           shape="circle"
           className="page-message"
diff --git a/src/tabviews/zshare/topSearch/advanceform/index.jsx b/src/tabviews/zshare/topSearch/advanceform/index.jsx
index b8b3023..cb8a239 100644
--- a/src/tabviews/zshare/topSearch/advanceform/index.jsx
+++ b/src/tabviews/zshare/topSearch/advanceform/index.jsx
@@ -8,6 +8,9 @@
 
 const MKCheckCard = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkCheckCard'))
 const MKSelect = asyncComponent(() => import('../mkSelect'))
+const MKCheck = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkCheck'))
+const MKSwitch = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkSwitch'))
+const MKRadio = asyncComponent(() => import('../mkRadio'))
 const MKDatePicker = asyncComponent(() => import('../mkDatePicker'))
 
 class AdvanceSearch extends Component {
@@ -48,6 +51,12 @@
         content = (<MKDatePicker config={item}/>)
       } else if (item.type === 'checkcard') {
         content = <MKCheckCard config={item}/>
+      } else if (item.type === 'radio') {
+        content = <MKRadio config={item} onChange={(val) => this.recordChange(val, false, item)} />
+      } else if (item.type === 'check') {
+        content = <MKCheck config={item}/>
+      } else if (item.type === 'switch') {
+        content = <MKSwitch config={item}/>
       }
 
       if (content) {
diff --git a/src/tabviews/zshare/topSearch/dategroup/index.scss b/src/tabviews/zshare/topSearch/dategroup/index.scss
index 57d4a16..e093074 100644
--- a/src/tabviews/zshare/topSearch/dategroup/index.scss
+++ b/src/tabviews/zshare/topSearch/dategroup/index.scss
@@ -4,6 +4,9 @@
   position: relative;
   z-index: 1;
 
+  .ant-tag-checkable:not(.ant-tag-checkable-checked):hover {
+    color: var(--mk-sys-color);
+  }
   .ant-tag {
     position: relative;
     cursor: pointer;
diff --git a/src/tabviews/zshare/topSearch/index.jsx b/src/tabviews/zshare/topSearch/index.jsx
index bb8561d..11d86ec 100644
--- a/src/tabviews/zshare/topSearch/index.jsx
+++ b/src/tabviews/zshare/topSearch/index.jsx
@@ -7,17 +7,18 @@
 import md5 from 'md5'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import Utils from '@/utils/utils.js'
+import MKEmitter from '@/utils/events.js'
 import MKInput from './mkInput'
 import './index.scss'
 
 const MutilForm = asyncSpinComponent(() => import('./advanceform'))
-const MKCheckCard = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkCheckCard'))
+const MKCheckCard = asyncComponent(() => import('./mkCheckCard'))
 const MKCheck = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkCheck'))
 const MKSwitch = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkSwitch'))
+const MKRadio = asyncComponent(() => import('./mkRadio'))
 const MKSelect = asyncComponent(() => import('./mkSelect'))
 const DateGroup = asyncComponent(() => import('./dategroup'))
 const MKDatePicker = asyncComponent(() => import('./mkDatePicker'))
@@ -25,8 +26,7 @@
 class MainSearch extends Component {
   static propTpyes = {
     BID: PropTypes.any,          // 鐖剁骇Id锛岀敤浜庢煡璇笅鎷夐�夋嫨椤�
-    config: PropTypes.object,    // 缁勪欢閰嶇疆淇℃伅(鑷畾涔夐〉闈�)
-    refreshdata: PropTypes.func  // 鍒锋柊鏁版嵁
+    config: PropTypes.object,    // 缁勪欢閰嶇疆淇℃伅
   }
 
   state = {
@@ -51,8 +51,6 @@
     let advanceValues = []
     let linkFields = {}
     let record = {}
-    let hasReqFields = false
-
     let forbid = false // header涓笉璁剧疆楂樼骇鎼滅储
     let _setting = {showAdv: false, show: false, style: null}
     
@@ -66,6 +64,7 @@
       _setting.labelCol = {style: {width: _setting.labelwidth + '%'}}
       _setting.wrapperCol = {style: {width: (100 - _setting.labelwidth) + '%'}}
       _setting.borderRadius = config.wrap.borderRadius
+      _setting.resetContrl = config.wrap.resetContrl || 'init'
     }
     
     if (config.type === 'search') {
@@ -113,10 +112,6 @@
         item.field = item.field + '@tail@'
       }
 
-      if (item.required) {
-        hasReqFields = true
-      }
-
       if (item.advanced && !forbid) {
         _setting.showAdv = true
       } else {
@@ -132,7 +127,9 @@
             val = val + ':00'
           }
         }
-        advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+        if (['text', 'date', 'datemonth', 'dateweek', 'daterange'].includes(item.type)) {
+          advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+        }
       }
 
       if (item.type === 'group') {
@@ -142,7 +139,7 @@
         record[item.field] = item.initval
       }
       
-      if (['select', 'link', 'multiselect', 'checkcard'].includes(item.type)) {
+      if (['select', 'link', 'multiselect', 'checkcard', 'radio'].includes(item.type)) {
         item.options = item.options || []
         item.options = item.options.filter(op => !op.Hide)
         if (item.setAll === 'true' && ['select', 'link'].includes(item.type)) {
@@ -158,12 +155,12 @@
         if (item.resourceType === '1' && item.dataSource) {
           let _option = Utils.getSelectQueryOptions(item)
 
-          if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+          if (window.GLOB.debugger === true) {
             console.info(_option.sql)
           }
 
           // 娴嬭瘯绯荤粺鍗曚釜璇锋眰
-          if (!window.GLOB.mkHS && options.sysType === 'local' && !window.GLOB.systemType) {
+          if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && !window.GLOB.systemType) {
             deForms.push({
               ...item,
               arr_field: _option.field,
@@ -178,6 +175,10 @@
           }
         }
         item.oriOptions = fromJS(item.options).toJS()
+
+        if (item.type === 'checkcard' && item.multiple === 'dropdown' && item.resourceType === '0') {
+          this.resetCheckcard(item)
+        }
       }
 
       fieldMap.set(item.field, item)
@@ -213,16 +214,48 @@
 
     this.setState({
       setting: _setting,
-      hasReqFields,
+      hasReqFields: config.$s_req,
       advanceValues,
       searchlist: _list
     }, () => {
-      if (!window.GLOB.mkHS && options.sysType === 'local' && window.GLOB.systemType !== 'production') {
+      if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
         this.improveSimpleSearch(deForms)
       } else if (mainItems.length > 0 || localItems.length > 0) {
         this.improveSearch(mainItems, localItems)
       }
     })
+  }
+
+  resetCheckcard = (item) => {
+    let pid = item.resourceType === '0' ? 'pid' : item.parentField
+    let _options = []
+    let _others = []
+    item.oriOptions.forEach(op => {
+      if (op[pid] === item.mark) {
+        _options.push(op)
+      } else {
+        _others.push(op)
+      }
+    })
+
+    _options = _options.map(op => {
+      op.children = []
+
+      _others = _others.filter(cell => {
+        if (cell[pid] === op.$value) {
+          op.children.push(cell)
+          return false
+        }
+        return true
+      })
+
+      op.subIds = op.children.map(cell => cell.$value)
+
+      return op
+    })
+
+    item.oriOptions = _options
+    item.options = _options
   }
 
   // 鏌ヨ涓嬫媺鑿滃崟
@@ -288,8 +321,8 @@
 
       if (window.GLOB.mkHS) { // 浜戠鏁版嵁楠岃瘉
         mainparam.open_key = Utils.encryptOpenKey(mainparam.secretkey, mainparam.timestamp)
-        if (options.cloudServiceApi) {
-          mainparam.rduri = options.cloudServiceApi
+        if (window.GLOB.cloudServiceApi) {
+          mainparam.rduri = window.GLOB.cloudServiceApi
           mainparam.userid = sessionStorage.getItem('CloudUserID') || ''
           mainparam.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         }
@@ -384,7 +417,7 @@
 
   resetSearch = (result) => {
     let _searchlist = fromJS(this.state.searchlist).toJS().map(item => {
-      if (['select', 'link', 'multiselect', 'checkcard'].includes(item.type) && result[item.field] && result[item.field].length > 0) {
+      if (['select', 'link', 'multiselect', 'checkcard', 'radio'].includes(item.type) && result[item.field] && result[item.field].length > 0) {
         let options = []
         let map = new Map()
         let all = false
@@ -432,6 +465,10 @@
         })
 
         item.oriOptions = [...item.oriOptions, ...options]
+
+        if (item.type === 'checkcard' && item.multiple === 'dropdown') {
+          this.resetCheckcard(item)
+        }
       }
 
       if (item.linkField) {
@@ -514,6 +551,8 @@
         content = <DateGroup position={index} config={item} onChange={(val, type) => this.dateGroupChange(val, type, item)} />
       } else if (item.type === 'checkcard') {
         content = <MKCheckCard config={item} onChange={(val) => this.cardChange(val, item)} />
+      } else if (item.type === 'radio') {
+        content = <MKRadio config={item} onChange={(val) => this.recordChange(val, false, item)} />
       } else if (item.type === 'check') {
         content = <MKCheck config={item} onChange={(val) => this.recordChange(val, false, item)} />
       } else if (item.type === 'switch') {
@@ -593,7 +632,9 @@
                 val = val + ':00'
               }
             }
-            advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+            if (['text', 'date', 'datemonth', 'dateweek', 'daterange'].includes(item.type)) {
+              advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+            }
           }
         })
         this.setState({advanceValues})
@@ -648,7 +689,12 @@
           this.sign = ''
         }, 2000)
         
-        this.props.refreshdata(searches)
+        if (this.props.refreshdata) {
+          this.props.refreshdata(searches)
+        } else {
+          window.GLOB.SearchBox.set(this.props.config.$searchId, searches)
+          MKEmitter.emit('searchRefresh', this.props.config.$searchId)
+        }
       })
     })
   }
@@ -657,10 +703,16 @@
    * @description 鎼滅储鏉′欢閲嶇疆
    */
   handleReset = () => {
+    const { setting } = this.state
+
     let record = {}
     let advanceValues = []
     let searchlist = this.state.searchlist.map(item => {
       item.initval = item.oriInitval
+
+      if (setting.resetContrl === 'clear' && ['text', 'date', 'datemonth', 'dateweek', 'daterange'].includes(item.type)) {
+        item.initval = ''
+      }
 
       if (item.type === 'group') {
         record[item.datefield] = item.initval
@@ -677,7 +729,9 @@
             val = val + ':00'
           }
         }
-        advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+        if (['text', 'date', 'datemonth', 'dateweek', 'daterange'].includes(item.type)) {
+          advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+        }
       }
 
       return item
@@ -792,7 +846,9 @@
             val = val + ':00'
           }
         }
-        advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+        if (['text', 'date', 'datemonth', 'dateweek', 'daterange'].includes(item.type)) {
+          advanceValues.push({field: item.field, type: item.type, label: item.label, value: val})
+        }
       }
     })
 
diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss
index 0f226d7..49746f8 100644
--- a/src/tabviews/zshare/topSearch/index.scss
+++ b/src/tabviews/zshare/topSearch/index.scss
@@ -64,6 +64,17 @@
         transform: rotate(180deg);
       }
     }
+    .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link).active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):hover, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):focus {
+      color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+    .ant-btn-primary {
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+    .ant-btn-link {
+      color: var(--mk-sys-color);
+    }
   }
   .advanced-list {
     font-size: 13px;
@@ -83,6 +94,9 @@
         padding: 2px;
       }
     }
+    .advance-value {
+      color: var(--mk-sys-color);
+    }
   }
   .ant-calendar-picker-clear, .ant-calendar-picker-icon {
     right: 8px;
diff --git a/src/tabviews/zshare/topSearch/mkCheckCard/index.jsx b/src/tabviews/zshare/topSearch/mkCheckCard/index.jsx
new file mode 100644
index 0000000..2d0caf5
--- /dev/null
+++ b/src/tabviews/zshare/topSearch/mkCheckCard/index.jsx
@@ -0,0 +1,336 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Col, Row, Dropdown, Menu } from 'antd'
+import { CheckOutlined } from '@ant-design/icons'
+
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+class MKCheckCard extends Component {
+  static propTpyes = {
+    config: PropTypes.object,
+    onChange: PropTypes.func
+  }
+
+  state = {
+    selectKeys: null,
+    config: null,
+    options: []
+  }
+
+  UNSAFE_componentWillMount() {
+    let config = fromJS(this.props.config).toJS()
+
+    let selectKeys = config.initval
+    let initlength = 0
+    if (config.multiple === 'true') {
+      selectKeys = config.initval ? config.initval.split(',') : []
+      initlength = selectKeys.length
+      selectKeys = this.filterVals(config.options, selectKeys)
+    }
+
+    if (!config.selectStyle && config.backgroundColor) {
+      config.selectStyle = 'custom'
+    } else if (!config.selectStyle) {
+      config.selectStyle = 'background'
+    }
+
+    if (config.display === 'picture' && !config.picratio) { // 鍏煎鏃ф暟鎹�
+      config.picratio = config.ratio || '1:1'
+    }
+
+    config.selectClass = ` mk-${config.selectStyle} `
+    config.fields = config.fields || []
+
+    this.setState({
+      config: config,
+      options: fromJS(config.options).toJS(),
+      selectKeys: selectKeys
+    }, () => {
+      if (config.multiple === 'true' && selectKeys.length < initlength) {
+        this.props.onChange(selectKeys.join(','))
+      }
+    })
+  }
+
+  componentDidMount () {
+    const { config } = this.state
+
+    if (config.linkField) {
+      MKEmitter.addListener('mkFP', this.mkFormHandle)
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    const { config, selectKeys } = this.state
+
+    if (!is(fromJS(config.oriOptions), fromJS(nextProps.config.oriOptions))) {
+      if (config.multiple === 'true') {
+        let keys = this.filterVals(nextProps.config.options, fromJS(selectKeys).toJS())
+        if (keys.length < selectKeys.length) {
+          this.setState({
+            selectKeys: keys
+          }, () => {
+            this.props.onChange(keys.join(','))
+          })
+        }
+      }
+
+      this.setState({
+        config: {...config, oriOptions: nextProps.config.oriOptions},
+        options: fromJS(nextProps.config.options).toJS()
+      })
+    }
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('mkFP', this.mkFormHandle)
+  }
+
+  filterVals = (options, vals) => {
+    if (options.length === 0 || vals.length === 0) return vals
+
+    let ops = options.map(item => item.$value)
+
+    vals = vals.filter(val => ops.includes(val))
+
+    return vals
+  }
+
+  mkFormHandle = (uuid, parentId, level) => {
+    if (uuid !== this.state.config.uuid) return
+
+    const { config } = this.state
+
+    let options = config.oriOptions.filter(option => option.ParentID === parentId)
+
+    if (config.multiple === 'true') {
+      this.setState({
+        options,
+        selectKeys: []
+      })
+      this.props.onChange('')
+    } else {
+      let _option = options[0] ? options[0] : null
+      let val = _option ? _option.$value : ''
+
+      this.setState({
+        options,
+        selectKeys: val
+      })
+  
+      let other = {}
+  
+      if (config.subFields && _option) {
+        config.subFields.forEach((n, i) => {
+          other[n.field] = _option[n.field]
+          setTimeout(() => {
+            MKEmitter.emit('mkFC', 'input', n.uuid, _option[n.field])
+          }, i * 5)
+        })
+      }
+  
+      this.props.onChange(val, other)
+  
+      if (level < 7 && config.linkFields) {
+        config.linkFields.forEach((m, i) => {
+          setTimeout(() => {
+            MKEmitter.emit('mkFP', m.uuid, val, level + 1)
+          }, (i + 1) * 70)
+        })
+      }
+    }
+  }
+
+  changeCard = (item) => {
+    const { selectKeys, config } = this.state
+
+    if (config.multiple === 'true') {
+      let keys = []
+      if (selectKeys.includes(item.$value)) {
+        keys = selectKeys.filter(key => key !== item.$value)
+      } else {
+        keys = [...selectKeys, item.$value]
+      }
+
+      this.setState({
+        selectKeys: keys
+      }, () => {
+        this.props.onChange(keys.join(','))
+      })
+    } else if (selectKeys !== item.$value) {
+      let other = {}
+      config.subFields && config.subFields.forEach((n, i) => {
+        other[n.field] = item[n.field]
+        setTimeout(() => {
+          MKEmitter.emit('mkFC', 'input', n.uuid, item[n.field])
+        }, i * 5)
+      })
+      config.linkFields && config.linkFields.forEach((m, i) => {
+        setTimeout(() => {
+          MKEmitter.emit('mkFP', m.uuid, item.$value, 0)
+        }, (i + 1) * 100)
+      })
+
+      this.setState({
+        selectKeys: item.$value
+      }, () => {
+        this.props.onChange(item.$value, other)
+      })
+    } else {
+      let other = {}
+      config.linkFields && config.linkFields.forEach((m, i) => {
+        setTimeout(() => {
+          MKEmitter.emit('mkFP', m.uuid, '', 0)
+        }, (i + 1) * 100)
+      })
+
+      this.setState({
+        selectKeys: ''
+      }, () => {
+        this.props.onChange('', other)
+      })
+    }
+  }
+
+  getCards = () => {
+    const { selectKeys, options, config } = this.state
+    const { display, width, fields, picratio, multiple, backgroundColor, selectStyle, selectClass } = config
+
+    if (options.length === 0) {
+      return null
+    } else if (display === 'color') {
+      return options.map(item => {
+        let _active = false
+        if (multiple === 'true') {
+          _active = selectKeys.includes(item.$value)
+        } else {
+          _active = selectKeys === item.$value
+        }
+
+        return <Col span={width} key={item.key}>
+          <div className={'card-color-cell' + (_active ? ' active' : '')} style={{background: item.$color}} onClick={() => this.changeCard(item)}>
+            {fields.map(col => {
+              return <span className="content-line" key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
+            })}
+            <CheckOutlined />
+          </div>
+        </Col>
+      })
+    } else if (display === 'picture') {
+      let paddingTop = '100%'
+      if (picratio === '4:3') {
+        paddingTop = '75%'
+      } else if (picratio === '3:2') {
+        paddingTop = '66.7%'
+      } else if (picratio === '16:9') {
+        paddingTop = '56.25%'
+      }
+
+      return options.map(item => {
+        let _active = false
+        if (multiple === 'true') {
+          _active = selectKeys.includes(item.$value)
+        } else {
+          _active = selectKeys === item.$value
+        }
+
+        return <Col span={width} key={item.key}>
+          <div className={'card-pic-cell ' + (_active ? 'active' : '')} onClick={() => this.changeCard(item)} style={{paddingTop, backgroundImage: `url(${item.$url})`}}>
+            <div className="content-wrap">
+              <div className="content-center">
+                {fields.map(col => {
+                  return <span className="content-line" key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
+                })}
+              </div>
+              <CheckOutlined />
+            </div>
+          </div>
+        </Col>
+      })
+    } else {
+      let _style = selectStyle === 'custom' ? {backgroundColor} : null
+
+      if (multiple === 'dropdown') {
+        return options.map(item => {
+          if (item.children.length) {
+            return <Col span={width} key={item.key}>
+              <Dropdown
+                overlayClassName="mk-search-card"
+                overlay={
+                <Menu>
+                  {item.children.map((cell, index) => (<Menu.Item className={selectKeys === cell.$value ? ' active' : ''} key={index} onClick={() => this.changeCard(cell)}>{cell[fields[0].field]}</Menu.Item>))}
+                </Menu>}
+                placement="bottomCenter"
+              >
+                <div className={'card-cell' + (selectKeys && (selectKeys === item.$value || item.subIds.includes(selectKeys)) ? ' active' : '') + selectClass} onClick={() => this.changeCard(item)}>
+                  <div className="bg-mask" style={_style}></div>
+                  {fields.map(col => {
+                    return <span className="content-line" key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
+                  })}
+                </div>
+              </Dropdown>
+            </Col>
+
+          } else {
+            return <Col span={width} key={item.key}>
+              <div className={'card-cell' + (selectKeys === item.$value ? ' active' : '') + selectClass} onClick={() => this.changeCard(item)}>
+                <div className="bg-mask" style={_style}></div>
+                {fields.map(col => {
+                  return <span className="content-line" key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
+                })}
+              </div>
+            </Col>
+          }
+        })
+      } else {
+        return options.map(item => {
+          let _active = false
+          if (multiple === 'true') {
+            _active = selectKeys.includes(item.$value)
+          } else {
+            _active = selectKeys === item.$value
+          }
+  
+          return <Col span={width} key={item.key}>
+            <div className={'card-cell' + (_active ? ' active' : '') + selectClass} onClick={() => this.changeCard(item)}>
+              <div className="bg-mask" style={_style}></div>
+              {fields.map(col => {
+                return <span className="content-line" key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
+              })}
+            </div>
+          </Col>
+        })
+      }
+    }
+  }
+
+  render() {
+    const { config, options } = this.state
+
+    let extend = ''
+
+    if (options.length * config.width > 24) {
+      extend += ' mutile-line'
+    }
+    if (config.border === 'hide') {
+      extend += ' border-hide'
+    }
+
+    return (
+      <div className={'check-card-form-wrap ' + extend}>
+        <Row gutter={12}>{this.getCards()}</Row>
+      </div>
+    )
+  }
+}
+
+export default MKCheckCard
\ No newline at end of file
diff --git a/src/tabviews/zshare/topSearch/mkCheckCard/index.scss b/src/tabviews/zshare/topSearch/mkCheckCard/index.scss
new file mode 100644
index 0000000..e65f4c6
--- /dev/null
+++ b/src/tabviews/zshare/topSearch/mkCheckCard/index.scss
@@ -0,0 +1,188 @@
+.check-card-form-wrap {
+  margin-top: 5px;
+  .card-cell {
+    position: relative;
+    border: 1px solid #bcbcbc;
+    background: #ffffff;
+    border-radius: 4px;
+    padding: 4px 6px;
+    margin-bottom: 2px;
+    line-height: 1.5;
+    transition: all 0.3s;
+    cursor: pointer;
+    
+    .bg-mask {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      opacity: 0.6;
+      border-radius: 4px;
+      background-color: transparent;
+      transition: opacity 0.3s;
+    }
+  }
+
+  .content-line {
+    display: block;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    position: relative;
+    z-index: 1;
+    line-height: 1.5;
+  }
+  .card-cell.mk-background.active {
+    border-color: var(--mk-sys-color);
+    background: var(--mk-sys-color);
+    span {
+      color: #ffffff!important;
+    }
+  }
+  .card-cell.mk-background.active::after {
+    content: ' ';
+    position: absolute;
+    display: table;
+    border: 2px solid #ffffff;
+    border-top: 0;
+    border-left: 0;
+    bottom: 0;
+    right: 10px;
+    width: 6px;
+    height: 12px;
+    transform: rotate(45deg) scale(1) translate(-50%, -50%);
+  }
+  .card-cell.mk-font.active {
+    border-color: var(--mk-sys-color);
+    span {
+      color: var(--mk-sys-color)!important;
+    }
+  }
+  .card-cell.mk-custom {
+    border-color: transparent;
+  }
+  .card-cell.mk-custom.active {
+    .bg-mask {
+      opacity: 1;
+    }
+  }
+  .card-pic-cell {
+    position: relative;
+    border: 1px solid #e8e8e8;
+    border-radius: 4px;
+    background-size: cover;
+    background-position: center;
+    margin-bottom: 2px;
+    line-height: 1.5;
+    cursor: pointer;
+    transition: all 0.3s;
+
+    .content-wrap {
+      position: absolute;
+      top: 6px;
+      left: 6px;
+      right: 6px;
+      bottom: 6px;
+      .content-center {
+        position: relative;
+        top: 50%;
+        transform: translate(0px, -50%);
+      }
+    }
+    .anticon-check {
+      display: none;
+      position: absolute;
+      color: #ffffff;
+      border-radius: 20px;
+      padding: 3px;
+      width: 18px;
+      height: 18px;
+      font-size: 12px;
+      right: -2px;
+      bottom: -2px;
+      background: var(--mk-sys-color);
+    }
+  }
+
+  .card-color-cell {
+    position: relative;
+    border: 1px solid transparent;
+    border-radius: 4px;
+    padding: 4px 6px;
+    margin-bottom: 2px;
+    min-height: 32px;
+    cursor: pointer;
+
+    .anticon-check {
+      display: none;
+      position: absolute;
+      color: #ffffff;
+      border-radius: 20px;
+      padding: 3px;
+      width: 18px;
+      height: 18px;
+      font-size: 12px;
+      right: 0px;
+      bottom: 0px;
+      background: var(--mk-sys-color);
+    }
+  }
+
+  .card-pic-cell.active, .card-color-cell.active {
+    .anticon-check {
+      display: inline-block;
+    }
+  }
+}
+
+.check-card-form-wrap.mutile-line {
+  .card-cell {
+    margin-bottom: 12px;
+  }
+  .card-pic-cell {
+    margin-bottom: 12px;
+  }
+  .card-color-cell {
+    margin-bottom: 12px;
+  }
+}
+
+.check-card-form-wrap {
+  .card-cell.mk-background:hover {
+    border-color: var(--mk-sys-color);
+    background: var(--mk-sys-color);
+    span {
+      color: #ffffff!important;
+    }
+  }
+  .card-cell.mk-font:hover {
+    border-color: var(--mk-sys-color);
+    span {
+      color: var(--mk-sys-color)!important;
+    }
+  }
+
+  .card-cell.mk-custom:not(.active):hover {
+    .bg-mask {
+      opacity: 0.8;
+    }
+  }
+  .card-pic-cell:hover {
+    border-color: var(--mk-sys-color);
+    box-shadow: 0px 0px 4px var(--mk-sys-color);
+  }
+}
+.check-card-form-wrap.border-hide {
+  .card-cell {
+    border: 0px;
+  }
+}
+.mk-search-card {
+  .ant-dropdown-menu-item {
+    min-width: 80px;
+  }
+  .ant-dropdown-menu-item.active {
+    color: var(--mk-sys-color);
+  }
+}
\ No newline at end of file
diff --git a/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx b/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
index 859be1a..c086876 100644
--- a/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
+++ b/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
@@ -94,7 +94,11 @@
     } else if (mode === 'week') {
       return <WeekPicker value={value} onChange={this.onChange}/>
     } else if (mode === 'daterange') {
-      return <RangePicker dropdownClassName={'mk-date-picker ' + precision} placeholder={['寮�濮嬫棩鏈�', '缁撴潫鏃ユ湡']} showTime={format !== 'YYYY-MM-DD'} format={format} value={value} onChange={this.onChange}/>
+      return <RangePicker ranges={format === 'YYYY-MM-DD' ? {
+        '浠婂ぉ': [moment(), moment()],
+        '褰撴湀': [moment().startOf('month'), moment().endOf('month')],
+        '涓婃湀': [moment().subtract(1, 'months').startOf('month'), moment().subtract(1, 'months').endOf('month')],
+      } : null} dropdownClassName={'mk-date-picker ' + precision} placeholder={['寮�濮嬫棩鏈�', '缁撴潫鏃ユ湡']} showTime={format !== 'YYYY-MM-DD'} format={format} value={value} onChange={this.onChange}/>
     }
   }
 }
diff --git a/src/tabviews/zshare/topSearch/mkRadio/index.jsx b/src/tabviews/zshare/topSearch/mkRadio/index.jsx
new file mode 100644
index 0000000..dd5b7e6
--- /dev/null
+++ b/src/tabviews/zshare/topSearch/mkRadio/index.jsx
@@ -0,0 +1,77 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Radio } from 'antd'
+
+class MKRadio extends Component {
+  static propTpyes = {
+    config: PropTypes.object,
+    onChange: PropTypes.func
+  }
+
+  state = {
+    value: '',
+    config: null,
+    options: []
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+    let value = config.initval
+
+    if (value) {
+      let option = null
+      option= config.oriOptions[0]
+      if (typeof(value) === 'string' && option && typeof(option.value) === 'number') {
+        value = +value
+        if (isNaN(value)) {
+          value = config.initval
+        }
+      }
+    }
+
+    this.setState({
+      config: fromJS(config).toJS(),
+      options: fromJS(config.options).toJS(),
+      value,
+    })
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    const { config } = this.state
+
+    if (!is(fromJS(config.oriOptions), fromJS(nextProps.config.oriOptions))) {
+      this.setState({
+        config: fromJS(nextProps.config).toJS(),
+        options: fromJS(nextProps.config.options).toJS()
+      })
+    }
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  onChange = (val) => {
+    this.props.onChange(val)
+    this.setState({value: val})
+  }
+
+  render() {
+    const { value, options } = this.state
+
+    return (
+      <Radio.Group value={value} onChange={(e) => this.onChange(e.target.value)}>
+        {options.map(option => <Radio key={option.key} value={option.Value}>{option.Text}</Radio>)}
+      </Radio.Group>
+    )
+  }
+}
+
+export default MKRadio
\ No newline at end of file
diff --git a/src/templates/calendarconfig/tabcomponent/tabform/index.scss b/src/tabviews/zshare/topSearch/mkRadio/index.scss
similarity index 100%
rename from src/templates/calendarconfig/tabcomponent/tabform/index.scss
rename to src/tabviews/zshare/topSearch/mkRadio/index.scss
diff --git a/src/tabviews/zshare/topSearch/mkSelect/index.jsx b/src/tabviews/zshare/topSearch/mkSelect/index.jsx
index a090007..be6c57b 100644
--- a/src/tabviews/zshare/topSearch/mkSelect/index.jsx
+++ b/src/tabviews/zshare/topSearch/mkSelect/index.jsx
@@ -84,7 +84,7 @@
     const { config } = this.state
 
     if (config.type === 'multiselect') {
-      this.props.onChange(val.join(','))
+      this.props.onChange(val.join(','), true)
     } else {
       config.linkFields && config.linkFields.forEach((m, i) => {
         setTimeout(() => {
diff --git a/src/templates/calendarconfig/calcomponent/calendarform/index.jsx b/src/templates/calendarconfig/calcomponent/calendarform/index.jsx
deleted file mode 100644
index 2d1f32a..0000000
--- a/src/templates/calendarconfig/calcomponent/calendarform/index.jsx
+++ /dev/null
@@ -1,156 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Select, Checkbox, Tooltip, Radio } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-// import './index.scss'
-
-class MainTab extends Component {
-  static propTpyes = {
-    config: PropTypes.object,    // 椤甸潰閰嶇疆
-    calendar: PropTypes.any      // 鏃ュ巻閰嶇疆淇℃伅
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  render() {
-    const { getFieldDecorator } = this.props.form
-    const { calendar, config } = this.props
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 10 }
-      }
-    }
-    return (
-      <Form {...formItemLayout}>
-        <Row gutter={24}>
-          <Col span={24}>
-            <Form.Item label="寮�濮嬫椂闂�">
-              {getFieldDecorator('startfield', {
-                initialValue: calendar.startfield,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨寮�濮嬫椂闂�!'
-                  }
-                ]
-              })(
-                <Select>
-                  {config.columns.map(option =>
-                    <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="缁撴潫鏃堕棿">
-              {getFieldDecorator('endfield', {
-                initialValue: calendar.endfield,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨缁撴潫鏃堕棿!'
-                  }
-                ]
-              })(
-                <Select>
-                  {config.columns.map(option =>
-                    <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="淇℃伅瀛楁">
-              {getFieldDecorator('remarkfield', {
-                initialValue: calendar.remarkfield,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨淇℃伅瀛楁!'
-                  }
-                ]
-              })(
-                <Select>
-                  {config.columns.map(option =>
-                    <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="棰滆壊瀛楁">
-              {getFieldDecorator('colorfield', {
-                initialValue: calendar.colorfield,
-                rules: [
-                  {
-                    required: false,
-                    message: '璇烽�夋嫨棰滆壊瀛楁!'
-                  }
-                ]
-              })(
-                <Select>
-                  {config.columns.map(option =>
-                    <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="鏃ュ巻绛夌骇">
-              {getFieldDecorator('levels', {
-                initialValue: calendar.levels,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鏃ュ巻绛夌骇!'
-                  }
-                ]
-              })(
-                <Checkbox.Group options={[{ value: 'day', label: '鏃�' }, { value: 'month', label: '鏈�' }, { value: 'year', label: '骞�' }]}/>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="寮�鍚悗锛屼娇鐢ㄧ郴缁熷嚱鏁版椂浼氳嚜鍔ㄦ浛鎹㈡暟鎹簮鍙婅嚜瀹氫箟鑴氭湰涓殑calendarDate涓巆alendarDate1锛屽叾鍊煎垎鍒负閫夋嫨骞翠唤鐨勫紑濮嬪拰缁撴潫鏃堕棿锛屼娇鐢ㄨ嚜瀹氫箟鍑芥暟鏃讹紝浼氬鍔燾alendarDate浼犲弬锛屽叾鍊间负閫夋嫨骞翠唤銆�">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鏁版嵁鍒锋柊
-              </Tooltip>
-            }>
-              {getFieldDecorator('refresh', {
-                initialValue: calendar.refresh || 'false',
-              })(
-                <Radio.Group>
-                  <Radio key="true" value="true">寮�鍚�</Radio>
-                  <Radio key="false" value="false">鍏抽棴</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(MainTab)
\ No newline at end of file
diff --git a/src/templates/calendarconfig/calcomponent/calendarform/index.scss b/src/templates/calendarconfig/calcomponent/calendarform/index.scss
deleted file mode 100644
index e69de29..0000000
--- a/src/templates/calendarconfig/calcomponent/calendarform/index.scss
+++ /dev/null
diff --git a/src/templates/calendarconfig/calcomponent/index.jsx b/src/templates/calendarconfig/calcomponent/index.jsx
deleted file mode 100644
index 4a475c3..0000000
--- a/src/templates/calendarconfig/calcomponent/index.jsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Modal } from 'antd'
-import { EditOutlined } from '@ant-design/icons'
-
-import CalendarForm from './calendarform'
-
-import './index.scss'
-
-class SettingComponent extends Component {
-  static propTpyes = {
-    config: PropTypes.any,         // 鏍囩
-    updateConfig: PropTypes.func,
-  }
-
-  state = {
-    calendar: null,  // 鏃ュ巻璁剧疆
-    visible: false,  // 妯℃�佹鎺у埗
-  }
-
-  /**
-   * @description 淇濆瓨椤甸潰閰嶇疆淇℃伅
-   */
-  calendarSave = () => {
-    const { config } = this.props
-
-    this.calendarRef.handleConfirm().then(res => {
-      this.setState({
-        visible: false
-      })
-      this.props.updateConfig({...config, calendar: res})
-    })
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-  }
-
-  /**
-   * @description 娣诲姞鎴栦慨鏀规爣绛�
-   */
-  handleTab = (e) => {
-    const { config } = this.props
-    e.stopPropagation()
-
-    let calendar = fromJS(config.calendar).toJS()
-
-    this.setState({
-      visible: true,
-      calendar
-    })
-  }
-
-  render() {
-    const { config } = this.props
-    const { visible, calendar } = this.state
-
-    return (
-      <div className="model-calendar-setting">
-        <EditOutlined onClick={this.handleTab} />
-        {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */}
-        <Modal
-          wrapClassName="model-calendar-setting-modal"
-          title="鏃ュ巻鍏宠仈瀛楁"
-          visible={visible}
-          width={700}
-          maskClosable={false}
-          onCancel={() => { this.setState({ visible: false })}}
-          onOk={this.calendarSave}
-          destroyOnClose
-        >
-          <CalendarForm
-            config={config}
-            calendar={calendar}
-            wrappedComponentRef={(inst) => this.calendarRef = inst}
-          />
-        </Modal>
-      </div>
-    )
-  }
-}
-
-export default SettingComponent
\ No newline at end of file
diff --git a/src/templates/calendarconfig/calcomponent/index.scss b/src/templates/calendarconfig/calcomponent/index.scss
deleted file mode 100644
index 5065e8f..0000000
--- a/src/templates/calendarconfig/calcomponent/index.scss
+++ /dev/null
@@ -1,41 +0,0 @@
-.model-calendar-setting {
-  position: absolute;
-  right: 0;
-  top: 0;
-  z-index: 2;
-  >.anticon-edit {
-    font-size: 18px;
-    padding: 5px;
-    margin-right: 10px;
-    color: #1890ff;
-    cursor: pointer;
-  }
-}
-
-.model-calendar-setting-modal {
-  .ant-modal {
-    top: 50px;
-    padding-bottom: 5px;
-    .ant-modal-body {
-      max-height: calc(100vh - 190px);
-      overflow-y: auto;
-    }
-    .ant-modal-body::-webkit-scrollbar {
-      width: 7px;
-    }
-    .ant-modal-body::-webkit-scrollbar-thumb {
-      border-radius: 5px;
-      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-      background: rgba(0, 0, 0, 0.13);
-    }
-    .ant-modal-body::-webkit-scrollbar-track {
-      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-      border-radius: 3px;
-      border: 1px solid rgba(0, 0, 0, 0.07);
-      background: rgba(0, 0, 0, 0);
-    }
-    .ant-empty-normal {
-      margin: 5px 0px;
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/templates/calendarconfig/index.jsx b/src/templates/calendarconfig/index.jsx
deleted file mode 100644
index 34f957a..0000000
--- a/src/templates/calendarconfig/index.jsx
+++ /dev/null
@@ -1,842 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { DndProvider } from 'react-dnd'
-import HTML5Backend from 'react-dnd-html5-backend'
-import { Button, Card, Modal, Collapse, notification, Spin, Switch } from 'antd'
-import { RedoOutlined } from '@ant-design/icons'
-import moment from 'moment'
-
-import Api from '@/api'
-import Utils from '@/utils/utils.js'
-
-import asyncComponent from '@/utils/asyncComponent'
-import SearchComponent from '@/templates/sharecomponent/searchcomponent'
-
-import MenuForm from '@/templates/comtableconfig/menuform'
-import SourceElement from '@/templates/zshare/dragsource'
-import Source from './source'
-import './index.scss'
-
-const { Panel } = Collapse
-const { confirm } = Modal
-
-const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent'))
-const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent'))
-const SettingComponent = asyncComponent(() => import('@/templates/sharecomponent/settingcalcomponent'))
-const TabComponent = asyncComponent(() => import('./tabcomponent'))
-const CalComponent = asyncComponent(() => import('./calcomponent'))
-const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
-const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
-const CalendarComponent = asyncComponent(() => import('@/tabviews/zshare/calendar'))
-
-class SubTableConfig extends Component {
-  static propTpyes = {
-    menu: PropTypes.any,
-    reloadmenu: PropTypes.func,
-    handleView: PropTypes.func
-  }
-
-  state = {
-    config: null,            // 椤甸潰閰嶇疆
-    visible: false,          // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪锛屾ā鎬佹鏄剧ず鎺у埗
-    fields: null,            // 鎼滅储鏉′欢鍙婃樉绀哄垪锛屽彲閫夊瓧娈�
-    formlist: null,          // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪琛ㄥ崟瀛楁
-    menuloading: false,      // 鑿滃崟淇濆瓨涓�
-    menucloseloading: false, // 鑿滃崟鍏抽棴鏃讹紝閫夋嫨淇濆瓨
-    loading: false,          // 鍔犺浇涓紝椤甸潰spin
-    closeVisible: false,     // 鍏抽棴妯℃�佹
-    originConfig: null,      // 鍘熼厤缃�
-    tabviews: [],            // 鎵�鏈夋爣绛鹃〉
-    activeKey: '0',          // 榛樿灞曞紑鍩烘湰淇℃伅
-    openEdition: '',         // 缂栬緫鐗堟湰鏍囪锛岄槻姝㈠浜烘搷浣�
-    mockdata: [],            // 娴嬭瘯鏁版嵁
-  }
-
-  /**
-   * @description 鏁版嵁棰勫鐞�
-   * 1銆佽缃〉闈㈤厤缃俊鎭紝鏂板缓鎴栨棤閰嶇疆淇℃伅鏃讹紙鍒囨崲妯℃澘鍚庢棤閰嶇疆淇℃伅锛夛紝浣跨敤妯℃澘榛樿閰嶇疆
-   * 2銆佽缃搷浣滅被鍨嬨�佸師濮嬭彍鍗曚俊鎭紙姣忔淇濆瓨鍚庨噸缃級銆佸凡浣跨敤琛ㄥ強鍩烘湰淇℃伅琛ㄥ崟
-   */
-  UNSAFE_componentWillMount () {
-    const { menu } = this.props
-    let _LongParam = menu.LongParam
-    let _config = ''
-
-    if (!_LongParam) {
-      _config = fromJS(Source.baseConfig).toJS()
-      _config.isAdd = true
-    } else {
-      _config = _LongParam
-    }
-
-    if (_config.type === 'user') {
-      if (_config.tab) {
-        _config.tab.linkTab = ''
-      }
-    }
-
-    // 椤甸潰閰嶇疆涓繚鐣欒彍鍗曚俊鎭紝鍙敤浜庢暟鎹紶閫�
-    _config.ParentId = menu.ParentId
-    _config.fstMenuId = menu.fstMenuId
-    _config.MenuName = menu.MenuName || ''
-    _config.MenuNo = menu.MenuNo || ''
-    _config.OpenType = menu.PageParam ? menu.PageParam.OpenType : ''
-    _config.easyCode = _config.easyCode || ''
-
-    // 鏁版嵁婧�
-    if (_config.setting.interType === 'inner' && !_config.setting.innerFunc) {
-      _config.setting.interType = 'system'
-    }
-
-    this.setState({
-      openEdition: menu.open_edition || '',
-      activeKey: menu.activeKey || '0',
-      config: _config,
-      originMenu: fromJS(_config).toJS(),
-      mockdata: this.getMockData(moment().format('YYYY'))
-    })
-  }
-
-  /**
-   * @description 鍔犺浇瀹屾垚鍚�
-   * 1銆佽幏鍙栫郴缁熷彲浣跨敤琛�
-   * 2銆佹牴鎹厤缃俊鎭腑宸蹭娇鐢ㄨ〃鑾峰彇鐩稿叧瀛楁淇℃伅
-   */
-  componentDidMount () {
-    this.reloadTab(false)
-    document.onkeydown = (event) => {
-      let e = event || window.event
-      let keyCode = e.keyCode || e.which || e.charCode
-      let preKey = ''
-
-      if (e.ctrlKey) {
-        preKey = 'ctrl'
-      }
-      if (e.shiftKey) {
-        preKey = 'shift'
-      } else if (e.altKey) {
-        preKey = 'alt'
-      }
-      
-      if (!preKey || !keyCode) return
-      
-      let _shortcut = `${preKey}+${keyCode}`
-
-      if (_shortcut === 'ctrl+83') {
-        let modals = document.querySelectorAll('.mk-pop-modal')
-        let msg = null
-        for (let i = 0; i < modals.length; i++) {
-          if (msg) {
-            break
-          }
-
-          let node = modals[i].querySelector('.mk-com-name')
-
-          if (node) {
-            msg = node.innerText
-          }
-        }
-        if (msg) {
-          notification.warning({
-            top: 92,
-            message: '璇蜂繚瀛�' + msg,
-            duration: 5
-          })
-          return false
-        }
-
-        let node = document.getElementById('save-config')
-        if (node && node.click) {
-          node.click()
-        }
-        return false
-      }
-    }
-  }
-
-  getMockData = (year) => {
-    let msgs = [
-      {color: 'red', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭紒'},
-      {color: 'orange', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭紒'},
-      {color: 'yellow', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭紒'},
-      {color: 'green', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭��'},
-      {color: 'cyan', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭��'},
-      {color: 'blue', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭紒'},
-      {color: 'purple', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭��'},
-      {color: 'gray', remark: '鎮ㄦ湁涓�鏉℃柊鐨勬秷鎭��'}
-    ]
-    let mockdata = []
-
-    for (let i = 1; i <= 12; i++) {
-      if (Math.random() > 0.5) {
-        let cell = {uuid: Utils.getuuid()}
-        let msg = msgs[Math.floor(Math.random() * 8)]
-        let day = Math.floor(Math.random() * 28 + 1)
-
-        cell.color = msg.color
-        cell.remark = msg.remark
-        cell.start = `${year}-${i < 10 ? '0' + i : i}-${day < 10 ? '0' + day : day}`
-        cell.end = moment(cell.start, 'YYYY-MM-DD').add(Math.floor(Math.random() * 10), 'days').format('YYYY-MM-DD')
-
-        mockdata.push(cell)
-
-        if (Math.random() > 0.5) {
-          let _cell = {uuid: Utils.getuuid()}
-          let _msg = msgs[Math.floor(Math.random() * 8)]
-          let _day = Math.floor(Math.random() * 28 + 1)
-
-          _cell.color = _msg.color
-          _cell.remark = _msg.remark
-          _cell.start = `${year}-${i < 10 ? '0' + i : i}-${_day < 10 ? '0' + _day : _day}`
-          _cell.end = moment(_cell.start, 'YYYY-MM-DD').add(Math.floor(Math.random() * 10), 'days').format('YYYY-MM-DD')
-
-          mockdata.push(_cell)
-        }
-      }
-    }
-
-    return mockdata
-  }
-
-  /**
-   * @description 鍔犺浇鎴栧埛鏂版爣绛句俊鎭�
-   */
-  reloadTab = (type) => {
-    this.setState({
-      loading: type,
-      tabviews: []
-    })
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
-      if (res.status) {
-        let _tabviews = []
-        res.UserTemp.forEach(temp => {
-          let item = {
-            uuid: temp.MenuID,
-            value: temp.MenuID,
-            text: temp.MenuName,
-            type: temp.Template,
-            MenuNo: temp.MenuNo
-          }
-
-          _tabviews.push(item)
-        })
-
-        this.setState({
-          loading: false,
-          tabviews: _tabviews
-        })
-
-        if (type) {
-          notification.success({
-            top: 92,
-            message: '鍒锋柊鎴愬姛銆�',
-            duration: 2
-          })
-        }
-      } else {
-        this.setState({
-          loading: false
-        })
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    document.onkeydown = () => {}
-  }
-
-  // 椤甸潰杩斿洖
-  handleViewBack = () => {
-    let param = {
-      editMenu: null,
-      editTab: null,
-      tabConfig: null,
-      subTabConfig: null,
-      btnTab: null,
-      btnTabConfig: null,
-      editAction: null,
-      subConfig: null,
-      tabview: ''
-    }
-
-    this.props.handleView(param)
-  }
-
-  getFuncNames = (data, funcNames, tableNames) => {
-    data.forEach(item => {
-      // if (item.subfuncs) {
-      //   this.getFuncNames(item.subfuncs, funcNames, tableNames)
-      //   return
-      // }
-
-      if (item.tableName) {
-        tableNames.push(item.tableName)
-      }
-      if (item.innerFunc) {
-        funcNames.push({func: item.innerFunc, label: item.label || ''})
-      }
-
-      if (item.callbackFunc) {
-        funcNames.push({func: item.callbackFunc, label: item.label || ''})
-      }
-    })
-
-    return {
-      func: funcNames,
-      table: tableNames
-    }
-  }
-
-  /**
-   * @description 涓夌骇鑿滃崟淇濆瓨
-   */
-  submitConfig = () => {
-    const { menu } = this.props
-    const { openEdition } = this.state
-
-    let _config = fromJS(this.state.config).toJS()
-
-    // 鍩烘湰淇℃伅楠岃瘉
-    if (!_config.fstMenuId || !_config.ParentId || !_config.MenuName || !_config.MenuNo) {
-      notification.warning({
-        top: 92,
-        message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
-        duration: 5
-      })
-      this.setState({activeKey: '0'})
-      return
-    }
-
-    if (_config.isAdd) {
-      _config.search = _config.search.filter(item => !item.origin)
-    }
-
-    if (_config.type === 'user') { // 浣跨敤宸叉湁鑿滃崟鏃讹紝榛樿娣诲姞鍏宠仈鏍囩id
-      if (_config.tab && !_config.tab.linkTab) {
-        _config.tab.linkTab = Utils.getuuid()
-      }
-    }
-
-    // 鏈缃暟鎹簮鎴栨爣绛句笉鍚堟硶鏃讹紝鍚敤鐘舵�佷负false
-    let vresult = this.verifyconfig(_config)
-    if (vresult !== true) {
-      _config.enabled = false
-    }
-
-    _config.funcs = [] // 椤甸潰鍙婂瓙椤甸潰瀛樺偍杩囩▼闆�
-
-    _config.funcs.push({
-      type: 'view',
-      subtype: 'view',
-      uuid: menu.MenuID,
-      intertype: _config.setting.interType || 'system',
-      interface: _config.setting.interface || '',
-      tableName: _config.setting.tableName || '',
-      innerFunc: _config.setting.innerFunc || '',
-      outerFunc: _config.setting.outerFunc || ''
-    })
-
-    if (_config.tab) {
-      _config.funcs.push({
-        type: 'tab',
-        subtype: 'tab',
-        uuid: _config.tab.uuid,
-        label: _config.tab.label,
-        linkTab: _config.tab.linkTab
-      })
-    }
-
-    if (this.state.closeVisible) { // 鏄剧ず鍏抽棴瀵硅瘽妗嗘椂锛屾ā鎬佹涓繚瀛樻寜閽紝鏄剧ず淇濆瓨涓姸鎬�
-      this.setState({
-        menucloseloading: true
-      })
-    } else {
-      this.setState({
-        menuloading: true
-      })
-    }
-
-    new Promise(resolve => {
-      // if (_config.tab) {
-      //   Api.getSystemConfig({
-      //     func: 'sPC_Get_LongParam',
-      //     MenuID: _config.tab.linkTab
-      //   }).then(result => {
-      //     if (result.status && result.LongParam) {
-      //       let _LongParam = ''
-  
-      //       if (result.LongParam) {
-      //         try {
-      //           _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-      //         } catch (e) {
-      //           console.warn('Parse Failure')
-      //           _LongParam = ''
-      //         }
-      //       }
-
-      //       if (_LongParam) {
-      //         _config.funcs[1].menuNo = _LongParam.tabNo || ''
-      //         _config.funcs[1].subfuncs = _LongParam.funcs || []
-      //       }
-      //     }
-      //     resolve()
-      //   })
-      // } else {
-      //   resolve()
-      // }
-      resolve()
-    }).then(() => {
-      // 淇濆瓨鏃跺垹闄ら厤缃被鍨嬶紝system 銆乽ser
-      delete _config.type
-      delete _config.isAdd
-
-      let _LongParam = ''
-
-      try {
-        _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
-      } catch (e) {
-        notification.warning({
-          top: 92,
-          message: '缂栬瘧閿欒',
-          duration: 5
-        })
-        this.setState({
-          menucloseloading: false,
-          menuloading: false
-        })
-        return
-      }
-
-      // let tabParam = { // 娣诲姞鑿滃崟tab椤�
-      //   func: 'sPC_sMenusTab_AddUpt',
-      //   MenuID: menu.MenuID
-      // }
-
-      // if (_config.tab) {
-      //   tabParam.LText = Utils.formatOptions(`select '${menu.MenuID}' as MenuID ,'${_config.tab.linkTab}' as Tabid,'${_config.tab.label}' as TabName ,'0' as Sort`)
-      // } else {
-      //   tabParam.LText = Utils.formatOptions(`select '${menu.MenuID}' as MenuID ,'' as Tabid,'' as TabName ,'0' as Sort`)
-      // }
-
-      // tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      // tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp)
-
-      let _vals = this.getFuncNames(_config.funcs, [], [])
-      let _tables = Array.from(new Set(_vals.table))
-
-      let param = {
-        func: 'sPC_TrdMenu_AddUpt',
-        FstID: _config.fstMenuId,
-        SndID: _config.ParentId,
-        ParentID: _config.ParentId,
-        MenuID: menu.MenuID,
-        MenuNo: _config.MenuNo,
-        EasyCode: _config.easyCode || '',
-        Template: _config.Template || '',
-        MenuName: _config.MenuName,
-        PageParam: JSON.stringify({...menu.PageParam, Template: _config.Template, OpenType: _config.OpenType}),
-        LongParam: _LongParam,
-        LText: _vals.func.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`),
-        LTexttb: _tables.map(item => `select '${menu.MenuID}' as MenuID,'${item}' as tbName`)
-      }
-
-      if (menu.menuSort) { // 鑿滃崟鏂板缓鏃惰缃帓搴�
-        param.Sort = menu.menuSort
-      }
-
-      param.LText = param.LText.join(' union all ')
-      param.LText = Utils.formatOptions(param.LText)
-      param.LTexttb = param.LTexttb.join(' union all ')
-      param.LTexttb = Utils.formatOptions(param.LTexttb)
-      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-
-      if (openEdition) { // 鐗堟湰绠$悊
-        param.open_edition = openEdition
-      }
-
-      // 淇濆瓨鏈湴
-      let localParam = fromJS(param).toJS()
-
-      Api.getSystemConfig(param).then(response => {
-        if (response.status) {
-          this.setState({
-            config: _config,
-            openEdition: response.open_edition || '',
-            originMenu: fromJS(_config).toJS(),
-            menuloading: false,
-            menucloseloading: false
-          })
-
-          this.props.reloadmenu()
-
-          localParam.func = 'sPC_TrdMenu_AddUpt_For_Local'
-          delete localParam.LongParam
-          delete localParam.PageParam
-          delete localParam.Template
-          delete localParam.Sort
-          delete localParam.EasyCode
-          delete localParam.open_edition
-
-          Api.genericInterface(localParam)
-
-          notification.success({
-            top: 92,
-            message: '淇濆瓨鎴愬姛',
-            duration: 2
-          })
-          
-          if (this.state.closeVisible) {
-            this.handleViewBack()
-          }
-        } else {
-          this.setState({
-            menuloading: false,
-            menucloseloading: false
-          })
-          notification.warning({
-            top: 92,
-            message: response.message,
-            duration: 5
-          })
-        }
-      })
-    })
-  }
-
-  cancelConfig = () => {
-    const { config, originMenu } = this.state
-    let _this = this
-
-    if (config.isAdd) {
-      confirm({
-        content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
-        onOk() {
-          _this.props.handleView()
-        },
-        onCancel() {}
-      })
-    } else {
-      if (!is(fromJS(originMenu), fromJS(config))) {
-        this.setState({
-          closeVisible: true
-        })
-      } else {
-        this.props.handleView()
-      }
-    }
-  }
-
-  /**
-   * @description 璁剧疆鍙厤缃寜閽�
-   */
-  setSubConfig = () => {
-    const { menu } = this.props
-    const { config, originMenu, activeKey, openEdition } = this.state
-
-    if (config.isAdd) { // 鏂板缓鑿滃崟锛屾彁绀鸿彍鍗曞皻鏈繚瀛�
-      notification.warning({
-        top: 92,
-        message: '鑿滃崟灏氭湭淇濆瓨锛岃鍏堜繚瀛樿彍鍗曢厤缃紒',
-        duration: 5
-      })
-    } else {
-      // 鍩烘湰淇℃伅楠岃瘉
-      if (!config.fstMenuId || !config.ParentId || !config.MenuName || !config.MenuNo) {
-        notification.warning({
-          top: 92,
-          message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
-          duration: 5
-        })
-        this.setState({activeKey: '0'})
-        return
-      }
-
-      if (!is(fromJS(originMenu), fromJS(config))) { // 鑿滃崟淇℃伅鍙樺寲鏃讹紝鎻愮ず淇濆瓨
-        notification.warning({
-          top: 92,
-          message: '鑿滃崟閰嶇疆宸蹭慨鏀癸紝璇蜂繚瀛橈紒',
-          duration: 5
-        })
-        return
-      }
-
-      let submenu = menu.fstMenuList.filter(item => item.MenuID === config.fstMenuId)[0]
-      let _Menu = {
-        ...menu,
-        LongParam: config,
-        PageParam: {...menu.PageParam, Template: config.Template, OpenType: config.OpenType},
-        MenuName: config.MenuName,
-        MenuNo: config.MenuNo,
-        ParentId: config.ParentId,
-        fstMenuId: config.fstMenuId,
-        supMenuList: submenu ? submenu.options : []
-      }
-
-      // 鑿滃崟淇℃伅楠岃瘉閫氳繃鍚庯紝璺宠浆瀛愰厤缃〉闈�
-      _Menu.activeKey = activeKey       // 淇濆瓨褰撳墠鎵撳紑椤电
-      _Menu.open_edition = openEdition  // 鏇存柊鐗堟湰鍙�
-
-      let param = {
-        editMenu: _Menu,
-        editTab: fromJS(config.tab).toJS(),
-        tabConfig: null,
-        editSubTab: null,
-        subTabConfig: null,
-        btnTab: null,
-        btnTabConfig: null,
-        editAction: '',
-        subConfig: '',
-        tabview: config.tab.type
-      }
-      
-      // 褰撳瓙琛ㄤ娇鐢ㄤ富椤垫悳绱㈡潯浠舵椂锛屽皢涓婚〉鎼滅储鍚戜笅浼犻��
-      if (param.editTab && param.editTab.searchPass === 'true') {
-        param.editTab.mainsearch = fromJS(config.search).toJS()
-      }
-
-      this.setState({
-        loading: true
-      })
-
-      Api.getSystemConfig({
-        func: 'sPC_Get_LongParam',
-        MenuID: config.tab.linkTab
-      }).then(res => {
-        if (res.status) {
-          this.setState({
-            loading: false
-          })
-          let _LongParam = ''
-          if (res.LongParam) {
-            try {
-              _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
-            } catch (e) {
-              console.warn('Parse Failure')
-              _LongParam = ''
-            }
-          }
-
-          if (_LongParam && param.tabview === 'SubTable' && _LongParam.Template === 'SubTable') {
-            param.subConfig = _LongParam
-          }
-
-          if (param.editTab) {
-            param.editTab.open_edition = res.open_edition || ''
-          }
-
-          this.props.handleView(param)
-        } else {
-          this.setState({
-            loading: false
-          })
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-        }
-      })
-    }
-  }
-
-  /**
-   * @description 鍒囨崲鏍囩鏄惁鍚敤
-   */
-  onEnabledChange = () => {
-    const { config } = this.state
-
-    let _enabled = !config.enabled
-    let result = this.verifyconfig(config)
-
-    if (_enabled && result !== true) {
-      notification.warning({
-        top: 92,
-        message: result,
-        duration: 5
-      })
-      return
-    }
-
-    this.setState({
-      config: {...config, enabled: _enabled}
-    })
-  }
-
-  /**
-   * @description 鏍¢獙閰嶇疆淇℃伅鐨勫悎娉曟��
-   */
-  verifyconfig = (config) => {
-    let cols = []
-    config.columns.forEach(col => {
-      if (col.field) {
-        cols.push(col.field)
-      }
-    })
-
-    if (config.setting.interType === 'system' && config.setting.default !== 'false' && !config.setting.dataresource) {
-      return '鑿滃崟灏氭湭璁剧疆鏁版嵁婧愶紝涓嶅彲鍚敤锛�'
-    } else if (config.columns.length === 0) {
-      return '鑿滃崟灏氭湭璁剧疆瀛楁闆嗭紝涓嶅彲鍚敤锛�'
-    } else if (!config.calendar.startfield) {
-      return '鏃ュ巻鍏宠仈瀛楁鏈缃紝涓嶅彲鍚敤锛�'
-    } else if (!cols.includes(config.calendar.startfield)) {
-      return '寮�濮嬫椂闂村瓧娈靛凡鍒犻櫎锛屼笉鍙惎鐢紒'
-    } else if (!cols.includes(config.calendar.endfield)) {
-      return '缁撴潫鏃堕棿瀛楁宸插垹闄わ紝涓嶅彲鍚敤锛�'
-    } else if (config.calendar.colorfield && !cols.includes(config.calendar.colorfield)) {
-      return '棰滆壊瀛楁宸插垹闄わ紝涓嶅彲鍚敤锛�'
-    } else if (!cols.includes(config.calendar.remarkfield)) {
-      return '淇℃伅瀛楁宸插垹闄わ紝涓嶅彲鍚敤锛�'
-    } else {
-      return true
-    }
-  }
-
-  /**
-   * @description 缂栬緫鍔熻兘瀹屾垚鏇存柊锛屽寘鎷В鍐绘寜閽�佺矘璐淬�佹浛鎹㈢瓑
-   */
-  updateConfig = (res) => {
-    if (res.type === 'thaw') {
-      this.setState({
-        config: res.config
-      })
-    } else if (res.type === 'paste') {
-      this.setState({config: res.config})
-    }
-  }
-
-  /**
-   * @description 鏇存柊鎼滅储鏉′欢閰嶇疆淇℃伅
-   */
-  updatesearch = (config) => {
-
-    this.setState({
-      config: config
-    })
-  }
-
-  /**
-   * @description 鏇存柊鏄剧ず鍒楅厤缃俊鎭�
-   */
-  updateconfig = (config) => {
-    this.setState({
-      config: config
-    })
-  }
-
-  // 骞村垏鎹㈡椂閲嶆柊鐢熸垚鏁版嵁
-  changeDate = (year) => {
-    this.setState({
-      mockdata: this.getMockData(year)
-    })
-  }
-
-  render () {
-    const { menu } = this.props
-    const { activeKey, config, tabviews, mockdata } = this.state
-
-    return (
-      <div className="model-calendar-board">
-        <DndProvider backend={HTML5Backend}>
-          {/* 宸ュ叿鏍� */}
-          <div className="tools">
-            <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
-              {/* 鍩烘湰淇℃伅 */}
-              <Panel forceRender={true} header="鍩烘湰淇℃伅" key="0" id="subtable-basedata">
-                {/* 鑿滃崟淇℃伅 */}
-                <MenuForm
-                  menu={menu}
-                  config={config}
-                  updatemenu={this.updateconfig}
-                />
-                {config ? <UrlFieldComponent
-                  config={config}
-                  updateConfig={this.updateconfig}
-                /> : null}
-                {/* 琛ㄥ悕娣诲姞 */}
-                <TableComponent
-                  config={config}
-                  containerId="subtable-basedata"
-                  updatetable={this.updateconfig}
-                />
-              </Panel>
-              {/* 鎼滅储鏉′欢娣诲姞 */}
-              <Panel header="鎼滅储" key="1">
-                <div className="search-element">
-                  {Source.searchItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
-                </div>
-                <FieldsComponent config={config} type="search" />
-              </Panel>
-            </Collapse>
-          </div>
-          <div className="setting">
-            <Card title={
-              <div>
-                鏃ュ巻椤甸潰閰嶇疆 
-                <RedoOutlined style={{marginLeft: '10px'}} title="鍒锋柊鏍囩鍒楄〃" onClick={() => this.reloadTab(true)} />
-              </div>
-            } bordered={false} extra={
-              <div>
-                <EditComponent type="table" options={['search', 'form']} config={this.state.config}/>
-                <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={this.state.config.enabled} onChange={this.onEnabledChange} />
-                <Button type="primary" id="save-config" onClick={this.submitConfig} loading={this.state.menuloading}>淇濆瓨</Button>
-                <Button onClick={this.cancelConfig}>鍏抽棴</Button>
-              </div>
-            } style={{ width: '100%' }}>
-              <SettingComponent
-                config={config}
-                MenuID={menu.MenuID}
-                updateConfig={this.updateconfig}
-              />
-              <SearchComponent
-                menu={{MenuID: menu.MenuID, MenuName: config.MenuName}}
-                config={config}
-                updatesearch={this.updatesearch}
-              />
-              <div className="calendar-wrap">
-                <TabComponent config={config} updateConfig={this.updateconfig} tabviews={tabviews} setSubConfig={this.setSubConfig} />
-                <CalComponent config={config} updateConfig={this.updateconfig} />
-                <CalendarComponent calendar={{
-                  levels: config.calendar.levels, startfield: 'start', endfield: 'end', colorfield: 'color', remarkfield: 'remark', refresh: config.calendar.refresh
-                }} data={mockdata} changeDate={this.changeDate}/>
-              </div>
-            </Card>
-          </div>
-        </DndProvider>
-        <Modal
-          bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
-          closable={false}
-          maskClosable={false}
-          visible={this.state.closeVisible}
-          onCancel={() => { this.setState({closeVisible: false}) }}
-          footer={[
-            <Button key="save" className="mk-btn mk-green" loading={this.state.menucloseloading} onClick={this.submitConfig}>淇濆瓨</Button>,
-            <Button key="confirm" className="mk-btn mk-yellow" onClick={this.handleViewBack}>涓嶄繚瀛�</Button>,
-            <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>鍙栨秷</Button>
-          ]}
-          destroyOnClose
-        >
-          閰嶇疆宸蹭慨鏀癸紝鏄惁淇濆瓨閰嶇疆淇℃伅锛�
-        </Modal>
-        {this.state.loading && <Spin size="large" />}
-      </div>
-    )
-  }
-}
-
-export default SubTableConfig
diff --git a/src/templates/calendarconfig/index.scss b/src/templates/calendarconfig/index.scss
deleted file mode 100644
index d40120f..0000000
--- a/src/templates/calendarconfig/index.scss
+++ /dev/null
@@ -1,159 +0,0 @@
-.model-calendar-board {
-  position: fixed;
-  z-index: 1;
-  padding-top: 48px;
-  top: 0px;
-  left: 0px;
-  right: 0px;
-  bottom: 0px;
-  background: rgba(0, 0, 0, 0.35);
-  display: flex;
-  .tools {
-    flex: 1;
-    background: #ffffff;
-    border-right: 1px solid #d9d9d9;
-    height: 100%;
-    overflow-y: hidden;
-    padding-bottom: 30px;
-    .ant-collapse-borderless {
-      background-color: #ffffff;
-    }
-    .ant-collapse-item {
-      position: relative;
-      border: 0;
-    }
-    .ant-input-search {
-      margin-top: 10px;
-    }
-    .ant-collapse-item.ant-collapse-item-active {
-      border-bottom: 1px solid #d9d9d9;
-    }
-    .ant-collapse .ant-collapse-header {
-      padding: 11px 16px 10px 40px;
-      border-bottom: 1px solid #d9d9d9;
-      background: #1890ff;
-      color: #ffffff;
-    }
-    .ant-collapse-content-box {
-      .ant-form-item {
-        margin-bottom: 10px;
-        .ant-form-item-label {
-          text-align: left;
-          height: 25px;
-          line-height: 25px;
-        }
-      }
-    }
-    .search-element {
-      padding-top: 10px;
-      li {
-        padding: 0px 16px 10px;
-        div {
-          cursor: move;
-        }
-      }
-    }
-    
-    .config-button {
-      min-width: 65px;
-    }
-  }
-  .tools:hover {
-    overflow-y: auto;
-  }
-  .tools::-webkit-scrollbar {
-    width: 7px;
-  }
-  .tools::-webkit-scrollbar-thumb {
-    border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
-  }
-  .tools::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
-  }
-  .tools:hover::-webkit-scrollbar-thumb {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-  }
-  .tools:hover::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-    border: 1px solid rgba(0, 0, 0, 0.07);
-  }
-  .setting {
-    position: relative;
-    width: calc(100vw - 235px);
-    height: 100%;
-    background: #ffffff;
-    .ant-switch.big {
-      min-width: 60px;
-      height: 28px;
-      line-height: 28px;
-      margin-top: -2px;
-      .ant-switch-inner {
-        font-size: 14px;
-      }
-    }
-    .ant-switch.big::after {
-      width: 24px;
-      height: 24px;
-    }
-    .ant-card-head {
-      min-height: 44px;
-    }
-    .ant-card-head-title {
-      padding: 5px 0;
-      color: #1890ff;
-    }
-    .ant-card-extra {
-      padding: 5px 0;
-      button {
-        margin-left: 20px;
-      }
-    }
-    .ant-card-body {
-      position: relative;
-      padding: 0;
-      
-      > .anticon-setting {
-        position: absolute;
-        font-size: 18px;
-        right: 7px;
-        top: 10px;
-      }
-      .calendar-wrap {
-        position: relative;
-        padding-top: 10px;
-      }
-    }
-  }
-  .setting {
-    overflow-y: scroll;
-  }
-  .setting::-webkit-scrollbar {
-    width: 7px;
-  }
-  .setting::-webkit-scrollbar-thumb {
-    border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-    display: none;
-  }
-  .setting::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0.07);
-    background: rgba(0, 0, 0, 0);
-  }
-  .setting:hover::-webkit-scrollbar-thumb {
-    display: block;
-  }
-  .ant-spin {
-    position: absolute;
-    margin-left: calc(50vw - 22px);
-    margin-top: 30vh;
-  }
-}
diff --git a/src/templates/calendarconfig/source.jsx b/src/templates/calendarconfig/source.jsx
deleted file mode 100644
index 9638d63..0000000
--- a/src/templates/calendarconfig/source.jsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import Utils from '@/utils/utils.js'
-
-class CalendarBaseData {
-  baseConfig = {
-    version: '1.0',
-    type: 'system',
-    Template: 'CalendarPage',
-    enabled: false,
-    tabName: '',
-    tabNo: '',
-    Remark: '',
-    uuid: Utils.getuuid(),
-    setting: {
-      tableName: '',
-      primaryKey: '',
-      dataresource: '',
-      interType: 'system',
-      innerFunc: '',
-      interface: '',
-      outerFunc: ''
-    },
-    columns: [],
-    scripts: [],
-    tables: [],
-    tab: null,
-    calendar: {
-      levels: ['day', 'month', 'year'],
-      startfield: '',
-      endfield: '',
-      colorfield: '',
-      remarkfield: '',
-      refresh: 'false'
-    },
-    search: []
-  }
-
-  searchItems = [
-    {
-      type: 'search',
-      label: '鏂囨湰',
-      subType: 'text',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '涓嬫媺閫夋嫨',
-      subType: 'select',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '涓嬫媺澶氶��',
-      subType: 'multiselect',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鑱斿姩鑿滃崟',
-      subType: 'link',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '閫夐」鍗�',
-      subType: 'checkcard',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃ユ湡锛堝ぉ锛�',
-      subType: 'date',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃ユ湡锛堝懆锛�',
-      subType: 'dateweek',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃ユ湡锛堟湀锛�',
-      subType: 'datemonth',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃ユ湡锛堝尯闂达級',
-      subType: 'daterange',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃ユ湡锛堢粍鍚堬級',
-      subType: 'group',
-      url: ''
-    }
-  ]
-}
-
-export default new CalendarBaseData()
diff --git a/src/templates/calendarconfig/tabcomponent/index.jsx b/src/templates/calendarconfig/tabcomponent/index.jsx
deleted file mode 100644
index f85bba9..0000000
--- a/src/templates/calendarconfig/tabcomponent/index.jsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Modal } from 'antd'
-import { EditOutlined, CloseOutlined, PlusOutlined } from '@ant-design/icons'
-
-import { getTabForm } from '@/templates/zshare/formconfig'
-import TabForm from './tabform'
-import './index.scss'
-
-const { confirm } = Modal
-
-class SettingComponent extends Component {
-  static propTpyes = {
-    config: PropTypes.any,         // 鏍囩
-    tabviews: PropTypes.array,     // 鏍囩闆�
-    updateConfig: PropTypes.func,
-    setSubConfig: PropTypes.func
-  }
-
-  state = {
-    menu: null,          // 鑿滃崟淇℃伅
-    formlist: null,      // 琛ㄥ崟淇℃伅
-    visible: false       // 妯℃�佹鎺у埗
-  }
-
-  /**
-   * @description 淇濆瓨椤甸潰閰嶇疆淇℃伅
-   */
-  tabSave = () => {
-    const { config } = this.props
-
-    this.tabRef.handleConfirm().then(res => {
-      this.setState({
-        visible: false
-      })
-      this.props.updateConfig({...config, tab: res})
-    })
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props.config.tab), fromJS(nextProps.config.tab))
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-  }
-
-  /**
-   * @description 娣诲姞鎴栦慨鏀规爣绛�
-   */
-  handleTab = (e) => {
-    e.stopPropagation()
-    const { config } = this.props
-
-    this.setState({
-      visible: true,
-      formlist: getTabForm(config.tab || {}, '', [], '', [], config.Template)
-    })
-  }
-
-  closeTab = (e) => {
-    const { config } = this.props
-    const _this = this
-    e.stopPropagation()
-
-    confirm({
-      content: '纭畾鍒犻櫎鏍囩鍚楋紵',
-      onOk() {
-        _this.props.updateConfig({...config, tab: ''})
-      },
-      onCancel() {}
-    })
-  }
-
-  render() {
-    const { tabviews, config } = this.props
-    const { visible } = this.state
-
-    return (
-      <div className="model-calendar-tab">
-        {config.tab ? <div className="tab-control">
-          <span onDoubleClick={this.props.setSubConfig}>{config.tab.label}</span>
-          <EditOutlined onClick={this.handleTab} />
-          <CloseOutlined onClick={this.closeTab} />
-        </div> : <PlusOutlined title="娣诲姞鏍囩" onClick={this.handleTab} />}
-        {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */}
-        <Modal
-          wrapClassName="model-calendar-tab-modal"
-          title="缂栬緫"
-          visible={visible}
-          width={700}
-          maskClosable={false}
-          onCancel={() => { this.setState({ visible: false })}}
-          onOk={this.tabSave}
-          destroyOnClose
-        >
-          <TabForm
-            tabs={tabviews}
-            inputSubmit={this.tabSave}
-            formlist={this.state.formlist}
-            wrappedComponentRef={(inst) => this.tabRef = inst}
-          />
-        </Modal>
-      </div>
-    )
-  }
-}
-
-export default SettingComponent
\ No newline at end of file
diff --git a/src/templates/calendarconfig/tabcomponent/index.scss b/src/templates/calendarconfig/tabcomponent/index.scss
deleted file mode 100644
index 9bb7caf..0000000
--- a/src/templates/calendarconfig/tabcomponent/index.scss
+++ /dev/null
@@ -1,86 +0,0 @@
-.model-calendar-tab {
-  position: absolute;
-  top: 0;
-  z-index: 2;
-  >.anticon-plus {
-    position: absolute;
-    font-size: 18px;
-    left: 10px;
-    top: 10px;
-    color: #26c281;
-    cursor: pointer;
-  }
-  .tab-control {
-    position: absolute;
-    padding: 15px 0px 0px 10px;
-    left: 0px;
-    top: 0px;
-
-    span:not(.anticon) {
-      display: inline-block;
-      white-space: nowrap;
-      font-size: 16px;
-      cursor: pointer;
-      padding: 0 10px;
-      border-bottom: 2px solid #1890ff;
-    }
-
-    .anticon-edit {
-      position: absolute;
-      font-size: 14px;
-      left: 10px;
-      top: 2px;
-      color: #1890ff;
-      cursor: pointer;
-      display: none;
-    }
-    .anticon-close {
-      position: absolute;
-      font-size: 14px;
-      left: 35px;
-      top: 2px;
-      color: #ff4d4f;
-      cursor: pointer;
-      display: none;
-    }
-  }
-  .tab-control:hover {
-    .anticon-edit {
-      display: inline-block;
-    }
-    .anticon-close {
-      display: inline-block;
-    }
-  }
-}
-
-.model-calendar-tab-modal {
-  .ant-modal {
-    top: 50px;
-    padding-bottom: 5px;
-    .ant-modal-body {
-      max-height: calc(100vh - 190px);
-      overflow-y: auto;
-      // .ant-empty {
-      //   margin: 15vh 8px;
-      // }
-    }
-    .ant-modal-body::-webkit-scrollbar {
-      width: 7px;
-    }
-    .ant-modal-body::-webkit-scrollbar-thumb {
-      border-radius: 5px;
-      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-      background: rgba(0, 0, 0, 0.13);
-    }
-    .ant-modal-body::-webkit-scrollbar-track {
-      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-      border-radius: 3px;
-      border: 1px solid rgba(0, 0, 0, 0.07);
-      background: rgba(0, 0, 0, 0);
-    }
-    .ant-empty-normal {
-      margin: 5px 0px;
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/templates/calendarconfig/tabcomponent/tabform/index.jsx b/src/templates/calendarconfig/tabcomponent/tabform/index.jsx
deleted file mode 100644
index 0584c22..0000000
--- a/src/templates/calendarconfig/tabcomponent/tabform/index.jsx
+++ /dev/null
@@ -1,230 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, Tooltip, Radio } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-
-import { formRule } from '@/utils/option.js'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-class MainTab extends Component {
-  static propTpyes = {
-    tabs: PropTypes.array,       // 鍙叧鑱旀爣绛鹃泦
-    formlist: PropTypes.any,     // 琛ㄥ崟
-    inputSubmit: PropTypes.any   // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    formlist: null // 琛ㄥ崟
-  }
-
-  /**
-   * @description 琛ㄥ崟棰勫鐞�
-   */
-  UNSAFE_componentWillMount () {
-    const { formlist } = this.props
-
-    let _tabs = this.props.tabs.filter(tab => tab.type === 'SubTable')
-
-    this.setState({
-      formlist: formlist.map(item => {
-        if (item.key === 'linkTab') {
-          item.options = [
-            {
-              value: '',
-              text: '鏂板缓'
-            },
-            ..._tabs
-          ]
-        }
-
-        return item
-      })
-    })
-  }
-
-  /**
-   * @description 鏍囩椤电被鍨嬪垏鎹�
-   */
-  openTypeChange = (key, value) => {
-    const { formlist } = this.state
-
-    if (key === 'type') {
-      let _tabs = this.props.tabs.filter(tab => tab.type === value)
-
-      this.setState({
-        formlist: formlist.map(item => {
-          if (item.key === 'linkTab') {
-            item.options = [
-              {
-                value: '',
-                text: '鏂板缓'
-              },
-              ..._tabs
-            ]
-            item.initVal = ''
-          }
-          return item
-        })
-      }, () => {
-        if (this.props.form.getFieldValue('linkTab') !== undefined) {
-          this.props.form.setFieldsValue({linkTab: ''})
-        }
-      })
-    }
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  getFields() {
-    const { getFieldDecorator } = this.props.form
-    const fields = []
-    
-    this.state.formlist.forEach((item, index) => {
-      if (item.hidden || item.forbid) return
-
-      if (item.type === 'text') {
-        let rules = []
-
-        if (item.key === 'foreignKey') {
-          rules.push({
-            pattern: /^[a-zA-Z_]*$/ig,
-            message: item.label + '瀛楁鍙厑璁稿寘鍚瓧姣嶅強涓嬪垝绾匡紒'
-          })
-        }
-        fields.push(
-          <Col span={24} 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 + '!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  },
-                  ...rules
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'select') { // 涓嬫媺鎼滅储
-        fields.push(
-          <Col span={24} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: '璇烽�夋嫨' + item.label + '!'
-                  }
-                ]
-              })(
-                <Select
-                  showSearch
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  onChange={(value) => {this.openTypeChange(item.key, value)}}
-                >
-                  {item.options.map((option, i) =>
-                    <Select.Option id={'mk' + i} title={option.text} key={'mk' + i} value={option.value}>
-                      {option.text}
-                    </Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'radio') {
-        fields.push(
-          <Col span={24} 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>
-                  {
-                    item.options.map(option => {
-                      return (
-                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
-                      )
-                    })
-                  }
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      }
-    })
-
-    return fields
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-
-          if (!values.linkTab) { // 娌℃湁鍏宠仈鏍囩锛堟柊寤烘椂锛夛紝鍒涘缓鏂版爣绛綢d
-            values.linkTab = Utils.getuuid()
-          }
-          values.type = 'SubTable' // 绫诲瀷涓哄瓙琛�
-
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  render() {
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 12 }
-      }
-    }
-    return (
-      <Form {...formItemLayout} style={{minHeight: '180px'}}>
-        <Row gutter={24}>{this.getFields()}</Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(MainTab)
\ No newline at end of file
diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx
index 44a0274..7c55fb4 100644
--- a/src/templates/comtableconfig/index.jsx
+++ b/src/templates/comtableconfig/index.jsx
@@ -210,7 +210,7 @@
       loading: type,
       tabviews: []
     })
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
       if (res.status) {
         this.setState({
           loading: false,
@@ -498,7 +498,7 @@
             }
 
             return new Promise(resolve => {
-              Api.getSystemConfig(_param).then(response => {
+              Api.getCloudConfig(_param).then(response => {
                 resolve(response)
               })
             })
@@ -552,8 +552,7 @@
         }
       }).then(resp => {
         if (resp === false) return
-        let localParam = fromJS(param).toJS()
-        Api.getSystemConfig(param).then(response => {
+        Api.getCloudConfig(param).then(response => {
           if (response.status) {
             this.setState({
               config: _config,
@@ -561,15 +560,7 @@
               originMenu: fromJS(_config).toJS()
             })
 
-            localParam.func = 'sPC_TrdMenu_AddUpt_For_Local'
-            delete localParam.LongParam
-            delete localParam.PageParam
-            delete localParam.Template
-            delete localParam.Sort
-            delete localParam.EasyCode
-            delete localParam.open_edition
-
-            this.submitAction(btnParam, localParam)
+            this.submitAction(btnParam)
           } else {
             this.setState({
               menuloading: false,
@@ -589,12 +580,12 @@
   /**
    * @description 淇濆瓨鎴栦慨鏀硅彍鍗曟寜閽泦
    */
-  submitAction = (btnParam, localParam) => {
+  submitAction = (btnParam) => {
     const { config } = this.state
 
     new Promise(resolve => {
       if (btnParam.LText) {
-        Api.getSystemConfig(btnParam).then(result => {
+        Api.getCloudConfig(btnParam).then(result => {
           if (result.status) {
             this.setState({ // 淇濆瓨鎴愬姛鍚庢竻绌哄鍒跺垪琛�
               copyActions: []
@@ -635,7 +626,7 @@
       oriActions.forEach(action => {
         if (!action.prebtn || !action.prebtn.uuid) return
 
-        Api.getSystemConfig({
+        Api.getCloudConfig({
           func: 'sPC_Get_LongParam',
           MenuID: action.prebtn.uuid
         }).then(result => {
@@ -663,7 +654,7 @@
               PageParam: JSON.stringify({Template: _temp}),
               LongParam: result.LongParam
             }
-            Api.getSystemConfig(param).then(() => {})
+            Api.getCloudConfig(param).then(() => {})
           }
         })
       })
@@ -685,7 +676,6 @@
           })
         }
         this.props.reloadmenu()
-        Api.genericInterface(localParam)
       } else {
         this.setState({
           menuloading: false,
@@ -804,7 +794,7 @@
         loading: true
       })
 
-      Api.getSystemConfig({
+      Api.getCloudConfig({
         func: 'sPC_Get_LongParam',
         MenuID: uuid
       }).then(res => {
@@ -964,7 +954,7 @@
         func: 'sPC_MainMenu_Del',
         MenuID: item
       }
-      Api.getSystemConfig(_param)
+      Api.getCloudConfig(_param)
     })
     this.props.handleView()
   }
@@ -1027,7 +1017,7 @@
       MenuID: menu.MenuID
     }
 
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       if (res.status) {
         let _config = ''
         if (res.LongParam) {
diff --git a/src/templates/comtableconfig/updatetable/index.jsx b/src/templates/comtableconfig/updatetable/index.jsx
index 82d0052..3ce78d5 100644
--- a/src/templates/comtableconfig/updatetable/index.jsx
+++ b/src/templates/comtableconfig/updatetable/index.jsx
@@ -87,14 +87,13 @@
     let formActions = []
     let popActions = []
     let errors = []
-    let formTabs = []
     let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false', isMain: true}
 
     let oldtabs = {
       mainTable: mainTb.uuid
     }
 
-    let tbl = this.getTable(config, mainTb, errors, formActions, formTabs, popActions, oldtabs)
+    let tbl = this.getTable(config, mainTb, errors, formActions, popActions, oldtabs)
 
     if (config.autoMatic && config.autoMatic.enable === 'true') {
       if (tbl.action.filter(item => item.uuid === config.autoMatic.action && (['pop', 'prompt', 'exec'].includes(item.OpenType) || (item.OpenType === 'funcbutton' && item.funcType === 'print'))).length === 0) {
@@ -111,7 +110,11 @@
     let _tbs = []
     if (config.tabgroups && config.tabgroups.length > 0) {
       config.tabgroups.forEach(m => {
-        if (!m.sublist || m.sublist.length === 0) return
+        if (!m.sublist) return
+
+        m.sublist = m.sublist.filter(c => !!c.linkTab)
+        
+        if (m.sublist.length === 0) return
 
         let tabs = {
           uuid: Utils.getuuid(),
@@ -120,7 +123,7 @@
           setting: {},
           style: {},
           subtabs: m.sublist.map(n => {
-            let tab = { uuid: Utils.getuuid(), label: n.label, icon: n.icon, permission: 'false', components: [
+            let tab = { uuid: Utils.getuuid(), label: n.label, icon: n.icon, permission: 'true', components: [
               {
                 uuid: Utils.getuuid(),
                 linkTab: n.linkTab,
@@ -147,7 +150,7 @@
       let defers = _tbs.map((item, i) => {
         return new Promise((resolve) => {
           setTimeout(() => {
-            Api.getSystemConfig({
+            Api.getCloudConfig({
               func: 'sPC_Get_LongParam',
               MenuID: item.linkTab
             }).then(res => {
@@ -188,10 +191,12 @@
           }
         })
 
+        let supIds = []
         _config.components = _config.components.map(item => {
           if (item.type === 'tabs') {
             item.subtabs = item.subtabs.map(tab => {
-              tab.components[0] = this.getTable(menus[tab.components[0].linkTab], tab.components[0], errors, formActions, formTabs, popActions, oldtabs)
+              tab.components[0] = this.getTable(menus[tab.components[0].linkTab], tab.components[0], errors, formActions, popActions, oldtabs)
+              supIds.push([item.uuid, tab.uuid, tab.components[0].uuid])
 
               return tab
             })
@@ -199,19 +204,35 @@
           return item
         })
 
-        this.setPopView(_resolve, _config, formActions, formTabs, popActions, errors)
+        _config.components = _config.components.map(item => {
+          if (item.type === 'tabs') {
+            item.subtabs = item.subtabs.map(tab => {
+              if (tab.components[0].setting.supModule && tab.components[0].setting.supModule.length === 1) {
+                supIds.forEach(ids => {
+                  if (ids[2] === tab.components[0].setting.supModule[0]) {
+                    tab.components[0].setting.supModule = ids
+                  }
+                })
+              }
+              return tab
+            })
+          }
+          return item
+        })
+
+        this.setPopView(_resolve, _config, formActions, popActions, errors)
       })
     } else {
-      this.setPopView(_resolve, _config, formActions, formTabs, popActions, errors)
+      this.setPopView(_resolve, _config, formActions, popActions, errors)
     }
   }
 
-  setPopView = (_resolve, _config, formActions, formTabs, popActions, errors) => {
+  setPopView = (_resolve, _config, formActions, popActions, errors) => {
     if (popActions.length > 0) {
       let defers = popActions.map((item, i) => {
         return new Promise((resolve) => {
           setTimeout(() => {
-            Api.getSystemConfig({
+            Api.getCloudConfig({
               func: 'sPC_Get_LongParam',
               MenuID: item.linkTab
             }).then(res => {
@@ -267,7 +288,7 @@
                       MenuName: btn.label,
                       tables: _config.tables || [],
                       Template: 'BaseTable',
-                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
                       viewType: 'popview',
                       style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
                     }
@@ -293,7 +314,7 @@
                         MenuName: btn.label,
                         tables: _config.tables || [],
                         Template: 'BaseTable',
-                        components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
+                        components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
                         viewType: 'popview',
                         style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
                       }
@@ -319,7 +340,7 @@
                     MenuName: btn.label,
                     tables: _config.tables || [],
                     Template: 'BaseTable',
-                    components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
+                    components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
                     viewType: 'popview',
                     style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
                   }
@@ -345,7 +366,7 @@
                       MenuName: btn.label,
                       tables: _config.tables || [],
                       Template: 'BaseTable',
-                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
                       viewType: 'popview',
                       style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
                     }
@@ -360,10 +381,10 @@
           }
         })
 
-        this.setPopForm(_resolve, _config, formActions, formTabs, errors)
+        this.setPopForm(_resolve, _config, formActions, errors)
       })
     } else {
-      this.setPopForm(_resolve, _config, formActions, formTabs, errors)
+      this.setPopForm(_resolve, _config, formActions, errors)
     }
   }
 
@@ -386,12 +407,12 @@
     return enabled
   }
 
-  setPopForm = (_resolve, _config, formActions, formTabs, errors) => {
+  setPopForm = (_resolve, _config, formActions, errors) => {
     if (formActions.length > 0) {
       let defers = formActions.map((item, i) => {
         return new Promise((resolve) => {
           setTimeout(() => {
-            Api.getSystemConfig({
+            Api.getCloudConfig({
               func: 'sPC_Get_LongParam',
               MenuID: item.origin
             }).then(res => {
@@ -512,10 +533,10 @@
           }
         })
 
-        this.saveConfig(_resolve, _config, errors, formTabs)
+        this.saveConfig(_resolve, _config, errors)
       })
     } else {
-      this.saveConfig(_resolve, _config, errors, formTabs)
+      this.saveConfig(_resolve, _config, errors)
     }
   }
 
@@ -554,7 +575,7 @@
     })
   }
 
-  saveConfig = (_resolve, _config, errors, formTabs) => {
+  saveConfig = (_resolve, _config, errors) => {
     let err = errors.join('锛�')
     let _this = this
 
@@ -565,17 +586,17 @@
         content: '',
         onOk() {
           return new Promise(resolve => {
-            _this.saveNewMenu(resolve, _config, formTabs)
+            _this.saveNewMenu(resolve, _config)
           })
         },
         onCancel() {}
       })
     } else {
-      this.saveNewMenu(_resolve, _config, formTabs)
+      this.saveNewMenu(_resolve, _config)
     }
   }
 
-  saveNewMenu = (_resolve, _config, formTabs) => {
+  saveNewMenu = (_resolve, _config) => {
     _config.components.forEach(item => {
       if (item.type === 'tabs') {
         item.subtabs.forEach(tab => {
@@ -616,82 +637,7 @@
       }
     })
 
-    // if (formTabs.length > 0) {
-    //   this.transformTabs(_resolve, _config, formTabs)
-    // } else {
-      this.submitConfig(_resolve, _config)
-    // }
-  }
-
-  transformTabs = (_resolve, _config, formTabs) => {
-    let tab = formTabs.shift()
-
-    Api.getSystemConfig({
-      func: 'sPC_Get_LongParam',
-      MenuID: tab.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 && (_LongParam.type === 'FormTab' || _LongParam.Template === 'FormTab') && _LongParam.enabled) {
-          if (!_LongParam.tabgroups) {
-            _LongParam.tabgroups = []
-          } else if (typeof(_LongParam.tabgroups[0]) === 'string') {
-            let _tabgroups = []
-            _LongParam.tabgroups.forEach(groupId => {
-              let _group = {
-                uuid: groupId,
-                sublist: fromJS(_LongParam[groupId]).toJS()
-              }
-      
-              delete _LongParam[groupId]
-      
-              _tabgroups.push(_group)
-            })
-      
-            _LongParam.tabgroups = _tabgroups
-          }
-
-          _LongParam.tabgroups = _LongParam.tabgroups.filter(group => group.sublist.length > 0)
-
-          _LongParam.tabgroups.forEach(group => {
-            group.sublist = group.sublist.map(tab => {
-              if (tab.supMenu === 'mainTable') {
-                tab.supMenu = ''
-              }
-              return tab
-            })
-          })
-
-          _LongParam.action = _LongParam.action.map(item => {
-            if (item.intertype === 'inner' && !item.innerFunc) {
-              item.intertype = 'system'
-            }
-            return item
-          })
-
-          delete _LongParam.funcs
-          delete _LongParam.tables
-        } else {
-          _config.components[0].action = _config.components[0].action.filter(btn => btn.uuid !== tab.uuid)
-        }
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-        _resolve()
-      }
-    })
+    this.submitConfig(_resolve, _config)
   }
 
   checkBtns = (card) => {
@@ -803,7 +749,7 @@
     let save = false
 
     new Promise(resolve => {
-      Api.getSystemConfig(param).then(res => {
+      Api.getCloudConfig(param).then(res => {
         resolve(res)
       })
     }).then(res => { // 鍒犻櫎鍘熻彍鍗�
@@ -814,7 +760,7 @@
 
       if (this.delButtons.length === 0) return res
 
-      return Api.getSystemConfig({
+      return Api.getCloudConfig({
         func: 'sPC_MainMenu_Del',
         up_type: 'Y',
         MenuID: this.delButtons.join(',')
@@ -854,7 +800,7 @@
     })
   }
 
-  getTable = (config, newCon, errors, formActions, formTabs, popActions, oldtabs) => { 
+  getTable = (config, newCon, errors, formActions, popActions, oldtabs) => { 
     let _card = {
       uuid: newCon.uuid,
       type: 'table',
@@ -866,7 +812,7 @@
       action: [],
       subtype: 'basetable',
       setting: { useMSearch: newCon.useMSearch },
-      wrap: {},
+      wrap: {name: newCon.name},
       style: {},
       headerStyle: {},
       columns: [],
@@ -895,7 +841,11 @@
     let lineMarks = []
     config.columns.forEach(col => {
       if (col.type === 'colspan') {
-        _colspan.push(...col.subfield.split(', '))
+        if (col.subfield) {
+          _colspan.push(...col.subfield.split(', '))
+        } else if (col.sublist && col.sublist.length > 0) {
+          _colspan.push(...col.sublist)
+        }
       }
       if (!col.field) return
 
@@ -966,7 +916,7 @@
         if (_colspan.includes(col.field)) {
           _col.Hide = 'true'
         }
-
+        _col.uuid = Utils.getuuid()
         _card.cols.push(_col)
       }
 
@@ -977,14 +927,21 @@
           label: col.label,
           marks: [],
           isSub: false,
-          uuid: col.uuid,
+          uuid: Utils.getuuid(),
           blacklist: []
         }
+        let _subs = []
+        if (col.subfield) {
+          _subs = col.subfield.split(', ')
+        } else if (col.sublist) {
+          _subs = col.sublist
+        }
+
         if (col.unfold === 'true') {
           ucol.type = 'colspan'
           ucol.subcols = []
 
-          col.subfield.split(', ').forEach(sub => {
+          _subs.forEach(sub => {
             if (_cols[sub]) {
               let _col = fromJS(_cols[sub]).toJS()
               _col.Hide = 'false'
@@ -1004,7 +961,7 @@
           ucol.elements = []
           ucol.style = {paddingTop: '12px', paddingLeft: '8px', paddingBottom: '12px', paddingRight: '8px'}
 
-          col.subfield.split(', ').forEach(sub => {
+          _subs.forEach(sub => {
             if (_cols[sub]) {
               let _col = {
                 copyable: 'false',
@@ -1155,27 +1112,6 @@
         if (btn.tabTemplate === 'FormTab') {
           errors.push(newCon.name + '涓寜閽��' + btn.label + '銆嬩笉鍦ㄦ敮鎸�')
           return
-          // if (newCon.isMain !== true) {
-          //   errors.push(newCon.name + '涓寜閽��' + btn.label + '銆嬩笉鍦ㄦ敮鎸�')
-          //   return
-          // }
-
-          // delete _btn.tabTemplate
-
-          // _btn.MenuID = 'tab' + md5(btn.uuid).substr(3)
-          // _btn.MenuName = this.baseMsg.MenuName + '-' + btn.label
-          // _btn.MenuNo = this.baseMsg.MenuNo + '_' + _btn.MenuID.substr(-4).toUpperCase()
-          // _btn.hidden = _btn.hidden || 'false'
-          // _btn.tabType = 'CustomPage'
-          // _btn.linkmenu = [this.baseMsg.fstMenuId, this.baseMsg.parentId, _btn.MenuID]
-          
-          // let _tab = {...btn}
-
-          // _tab.MenuID = _btn.MenuID
-          // _tab.MenuNo = _btn.MenuNo
-          // _tab.MenuName = _btn.MenuName
-
-          // formTabs.push(_tab)
         } else if (!btn.linkmenu || btn.linkmenu.length !== 3) {
 
           errors.push(newCon.name + '涓寜閽��' + btn.label + '銆嬩笉鍦ㄦ敮鎸�')
@@ -1220,7 +1156,7 @@
       })
     }
 
-    let sets = ['tableName', 'interType', 'sysInterface', 'innerFunc', 'interface', 'proInterface', 'outerFunc', 'dataresource', ['queryType', 'query'], 'primaryKey', 'order', 'execute', ['laypage', 'true'], ['pageSize', 10], ['onload', 'true']]
+    let sets = ['tableName', 'interType', 'sysInterface', 'innerFunc', 'interface', 'proInterface', 'outerFunc', 'dataresource', ['queryType', 'query'], 'primaryKey', 'order', ['laypage', 'true'], ['pageSize', 10], ['onload', 'true']]
     let wraps = ['tableType', ['bordered', 'true'], 'actionfixed', ['size', 'middle'], ['selected', 'false'], ['tableMode', 'compatible'], ['mask', 'show'], ['borderColor', '#e8e8e8'], 'height', 'controlField', 'controlVal']
 
     _card.scripts = config.setting.scripts || []
@@ -1253,6 +1189,8 @@
       _card.wrap.doubleClick = ''
     }
 
+    _card.setting.execute = config.setting.default || 'true'
+
     _card.errors = []
     let columns = _card.columns.map(c => c.field)
     if (_card.setting.interType === 'system' && _card.setting.execute !== 'false' && !_card.setting.dataresource) {
diff --git a/src/templates/formtabconfig/actionform/index.jsx b/src/templates/formtabconfig/actionform/index.jsx
deleted file mode 100644
index d275498..0000000
--- a/src/templates/formtabconfig/actionform/index.jsx
+++ /dev/null
@@ -1,442 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, Radio, notification, Tooltip, InputNumber } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-
-import { btnIcons, btnClasses, formRule } from '@/utils/option.js'
-import MkIcon from '@/components/mk-icon'
-import './index.scss'
-
-const { TextArea } = Input
-
-class MainSearch extends Component {
-  static propTpyes = {
-    formlist: PropTypes.any,     // 琛ㄥ崟淇℃伅
-    card: PropTypes.any,         // 鎸夐挳淇℃伅
-    tabs: PropTypes.array,       // 鎵�鏈夋爣绛鹃〉
-    inputSubmit: PropTypes.any   // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    formlist: null,  // 琛ㄥ崟淇℃伅
-    openType: null,  // 鎵撳紑鏂瑰紡
-    interType: null, // 鎺ュ彛绫诲瀷锛氬唴閮ㄣ�佸閮�
-    insertUpdateOptions: [{
-      value: 'insert',
-      text: '娣诲姞'
-    }, {
-      value: 'update',
-      text: '淇敼'
-    }, {
-      value: 'insertOrUpdate',
-      text: '娣诲姞鎴栦慨鏀�'
-    }],
-    returnoptions: [{ // 杩斿洖鍚�-涓嶅埛鏂般�佸埛鏂伴〉闈€�佸埛鏂拌〃鏍�
-      value: 'never',
-      text: '涓嶅埛鏂�'
-    }, {
-      value: 'grid',
-      text: '鍒锋柊'
-    }],
-    currentoptions: [{ // 涓嶈繑鍥炴椂-涓嶅埛鏂般�佸埛鏂�
-      value: 'never',
-      text: '涓嶅埛鏂�'
-    }, {
-      value: 'refresh',
-      text: '鍒锋柊'
-    }],
-    interTypeOptions: [{
-      value: 'system',
-      text: '绯荤粺'
-    }, {
-      value: 'inner',
-      text: '鍐呴儴'
-    }, {
-      value: 'outer',
-      text: '澶栭儴'
-    }, {
-      value: 'custom',
-      text: '鑷畾涔�'
-    }]
-  }
-
-  
-  UNSAFE_componentWillMount () {
-    const { card } = this.props
-    let _intertype = ''
-
-    this.props.formlist.forEach(form => {
-      if (form.key === 'intertype') {
-        _intertype = form.initVal
-        if (card.btnType !== 'confirm') {
-          form.options = this.state.interTypeOptions.filter(op => op.value !== 'system')
-        } else {
-          form.options = this.state.interTypeOptions
-        }
-      }
-    })
-
-    let _options = this.getOptions(card.btnType, _intertype)
-
-    let formlist = this.props.formlist.map(item => {
-      if (item.key === 'class') {
-        item.options = btnClasses
-      } else if (item.key === 'icon') {
-        item.options = btnIcons
-      } else if (item.key === 'resetPageIndex') {
-        item.tooltip = '椤甸潰鍏抽棴锛屼笖鎵ц鍒锋柊鏃剁敓鏁�'
-      } else if (item.key === 'sqlType') {
-        item.options = this.state.insertUpdateOptions
-      } else if (item.key === 'OpenType') {
-        item.options = [
-          {
-            value: 'prompt',
-            text: '鎻愮ず妗�'
-          }, {
-            value: 'exec',
-            text: '鐩存帴鎵ц'
-          }
-        ]
-        if (card.btnType === 'cancel') {
-          item.readonly = true
-        }
-      } else if (item.key === 'execSuccess' && card.btnType === 'cancel') {
-        item.label = '鍏抽棴鍚�'
-        item.options[1].text = '鍒锋柊'
-      } else if (item.key === 'execSuccess' || item.key === 'execError') {
-        item.options[1].text = '鍒锋柊'
-      } else if (item.key === 'innerFunc' && card.btnType !== 'confirm' && _intertype === 'inner') {
-        item.required = true
-      }
-
-      item.hidden = !_options.includes(item.key)
-      return item
-    })
-    formlist.push({
-      type: 'radio',
-      key: 'afterExecSuccess',
-      label: '鎴愬姛鍚�',
-      initVal: card.afterExecSuccess || 'close',
-      required: true,
-      options: [{
-        value: 'close',
-        text: '鍏抽棴'
-      }, {
-        value: 'notclose',
-        text: '涓嶅叧闂�'
-      }]
-    },
-    {
-      type: 'radio',
-      key: 'afterExecError',
-      label: '澶辫触鍚�',
-      initVal: card.afterExecError || 'notclose',
-      required: true,
-      options: [{
-        value: 'close',
-        text: '鍏抽棴'
-      }, {
-        value: 'notclose',
-        text: '涓嶅叧闂�'
-      }]
-    },)
-
-    this.setState({formlist})
-  }
-
-  componentDidMount () {
-    const { card } = this.props
-
-    if (card.focus) {
-      try {
-        let _form = document.getElementById('label')
-        _form.select()
-      } catch (e) {
-        console.warn('琛ㄥ崟focus澶辫触锛�')
-      }
-    }
-  }
-
-  getOptions = (btnType, intertype) => {
-    let _options = []
-
-    if (btnType === 'cancel') {
-      _options = ['label', 'OpenType', 'icon', 'class', 'execSuccess', 'resetPageIndex']
-    } else if (btnType === 'confirm') {
-      if (intertype === 'outer') {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError', 'resetPageIndex']
-      } else if (intertype === 'system') {
-        _options = ['label', 'OpenType', 'intertype', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType', 'afterExecSuccess', 'afterExecError', 'resetPageIndex']
-      } else {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError', 'resetPageIndex']
-      }
-    } else {
-      if (intertype === 'outer') {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError', 'resetPageIndex']
-      } else {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError', 'resetPageIndex']
-      }
-    }
-
-    return _options
-  }
-
-  onChange = (e, key) => {
-    const { card } = this.props
-
-    let value = e.target.value
-
-    if (key === 'intertype') {
-      let _options = this.getOptions(card.btnType, value)
-
-      this.setState({
-        interType: value,
-        formlist: this.state.formlist.map(item => {
-          item.hidden = !_options.includes(item.key)
-
-          if (item.key === 'interface') {
-            item.readonly = false
-          } else if (item.key === 'sysInterface') {
-            item.initVal = 'false'
-          } else if (item.key === 'innerFunc' && value === 'inner') {
-            item.required = true
-          } else if (item.key === 'innerFunc' && value === 'outer') {
-            item.required = false
-          }
-
-          return item
-        })
-      })
-    } else if (key === 'sysInterface') {
-      if (value === 'true') {
-        this.props.form.setFieldsValue({
-          interface: window.GLOB.mainSystemApi || ''
-        })
-      }
-      this.setState({
-        formlist: this.state.formlist.map(item => {
-          if (item.key === 'interface' && value === 'true') {
-            item.readonly = true
-          } else if (item.key === 'interface') {
-            item.readonly = false
-          }
-
-          return item
-        })
-      })
-    }
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  getFields() {
-    const { getFieldDecorator } = this.props.form
-    const fields = []
-
-    this.state.formlist.forEach((item, index) => {
-      if (item.hidden) return
-
-      if (item.type === 'text') {
-        let _rules = []
-        if (item.key === 'innerFunc') {
-          let str = '^(' + item.fields.join('|') + ')'
-          let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
-          _rules = [{
-            pattern: _patten,
-            message: formRule.func.innerMessage
-          }, {
-            max: formRule.func.max,
-            message: formRule.func.maxMessage
-          }]
-        } else if (item.key === 'outerFunc' || item.key === 'callbackFunc') {
-          _rules = [{
-            pattern: formRule.func.pattern,
-            message: formRule.func.message
-          }, {
-            max: formRule.func.max,
-            message: formRule.func.maxMessage
-          }]
-        } else {
-          _rules = [{
-            max: formRule.input.max,
-            message: formRule.input.message
-          }]
-        }
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: item.readonly ? false : !!item.required,
-                    message: '璇疯緭鍏�' + item.label + '!'
-                  },
-                  ..._rules
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'number') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal
-              })(<InputNumber min={1} max={10000} precision={0} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'select') { // 涓嬫媺鎼滅储
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: '璇烽�夋嫨' + item.label + '!'
-                  }
-                ]
-              })(
-                <Select
-                  getPopupContainer={() => document.getElementById('winter')}
-                  disabled={!!item.readonly}
-                >
-                  {item.options.map((option, index) =>
-                    <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}>
-                      {item.key === 'icon' && option.value && <MkIcon type={option.value} />} {option.text}
-                    </Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'radio') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.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 onChange={(e) => {this.onChange(e, item.key)}}>
-                  {
-                    item.options.map(option => {
-                      return (
-                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
-                      )
-                    })
-                  }
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'textarea') {
-        fields.push(
-          <Col span={24} key={index}>
-            <Form.Item label={item.label} className="textarea">
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: item.readonly ? false : !!item.required,
-                    message: '璇疯緭鍏�' + item.label + '!'
-                  }
-                ]
-              })(<TextArea rows={4} readOnly={item.readonly}/>)}
-            </Form.Item>
-          </Col>
-        )
-      }
-    })
-    return fields
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          values.uuid = this.props.card.uuid
-          values.verify = this.props.card.verify || null
-          values.btnType = this.props.card.btnType || 'tabFormBtn'
-
-
-          if (values.innerFunc === '' && values.sql === '') {
-            notification.warning({
-              top: 92,
-              message: '浣跨敤绯荤粺鍑芥暟鏃讹紝璇峰~鍐欒〃鍚嶏紝浣跨敤鑷畾涔夊嚱鏁版椂锛屽彲蹇界暐銆�',
-              duration: 5
-            })
-          } else if (values.innerFunc === '' && values.sql !== '' && values.sqlType === '') {
-            notification.warning({
-              top: 92,
-              message: '浣跨敤绯荤粺鍑芥暟鏃讹紝璇烽�夋嫨鎿嶄綔绫诲瀷锛屼娇鐢ㄨ嚜瀹氫箟鍑芥暟鏃讹紝鍙拷鐣ャ��',
-              duration: 5
-            })
-          } else {
-            resolve(values)
-          }
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  render() {
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 7 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 17 }
-      }
-    }
-    return (
-      <Form {...formItemLayout} className="formtab-action-list-form" id="winter">
-        <Row gutter={24}>{this.getFields()}</Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/templates/formtabconfig/actionform/index.scss b/src/templates/formtabconfig/actionform/index.scss
deleted file mode 100644
index 969304f..0000000
--- a/src/templates/formtabconfig/actionform/index.scss
+++ /dev/null
@@ -1,33 +0,0 @@
-.formtab-action-list-form {
-  min-height: 190px;
-  .superconfig {
-    color: #1890ff;
-    cursor: pointer;
-  }
-  .textarea {
-    .ant-col-sm-7 {
-      width: 14%;
-    }
-    .ant-col-sm-17 {
-      width: 86%;
-    }
-  }
-  .with-button {
-    .ant-form-item-control-wrapper {
-      padding-right: 63px;
-    }
-    .ant-btn {
-      position: absolute;
-      right: 12px;
-      top: 4.5px;
-    }
-  }
-  .ant-input:read-only {
-    background: #fafafa;
-    resize: none;
-  }
-  .ant-input:read-only:hover, .ant-input:read-only:focus {
-    border-color: #d9d9d9;
-    box-shadow: none;
-  }
-}
\ No newline at end of file
diff --git a/src/templates/formtabconfig/dragelement/card.jsx b/src/templates/formtabconfig/dragelement/card.jsx
deleted file mode 100644
index feab70f..0000000
--- a/src/templates/formtabconfig/dragelement/card.jsx
+++ /dev/null
@@ -1,161 +0,0 @@
-import React from 'react'
-import { useDrag, useDrop } from 'react-dnd'
-import { Button, Select, DatePicker, Input, InputNumber, Popover } from 'antd'
-import { EditOutlined, CopyOutlined, ProfileOutlined, CloseOutlined, UploadOutlined, TableOutlined } from '@ant-design/icons'
-import moment from 'moment'
-import ItemTypes from './itemtypes'
-import './index.scss'
-
-const { MonthPicker } = DatePicker
-const { TextArea } = Input
-
-const Card = ({ id, type, cols, card, moveCard, findCard, editCard, delCard, profileCard, copyCard }) => {
-  const originalIndex = findCard(id).index
-  const [{ isDragging }, drag] = useDrag({
-    item: { type: ItemTypes[type], id, originalIndex },
-    collect: monitor => ({
-      isDragging: monitor.isDragging(),
-    }),
-  })
-  const [, drop] = useDrop({
-    accept: ItemTypes[type],
-    canDrop: () => true,
-    drop: (item) => {
-      const { id: draggedId, originalIndex } = item
-
-      if (originalIndex === undefined) {
-        item.dropTargetId = id
-      } else if (draggedId && draggedId !== id) {
-        const { index: overIndex } = findCard(id)
-        moveCard(draggedId, overIndex)
-      }
-    }
-  })
-  const opacity = isDragging ? 0.5 : 1
-
-  const edit = () => {
-    editCard(id)
-  }
-  
-  const del = () => {
-    delCard(id)
-  }
-
-  const copy = () => {
-    copyCard(id)
-  }
-  
-  const profile = () => {
-    profileCard(id)
-  }
-
-  let _defaultValue = '' // 涓嬫媺鎼滅储銆佹椂闂磋寖鍥寸被鍨嬶紝鍒濆鍊奸渶瑕侀澶勭悊
-
-  if (type === 'search' && (card.type === 'multiselect' || card.type === 'select' || card.type === 'link')) {
-    if (card.initval) {
-      let _option = card.options.filter(option => option.Value === card.initval)[0]
-      if (_option) {
-        _defaultValue = _option.Text || ''
-      } else {
-        _defaultValue = ''
-      }
-    } else if (card.setAll === 'true') {
-      _defaultValue = card.emptyText || '绌�'
-    }
-  } else if (type === 'search' && card.type === 'daterange') {
-    _defaultValue = [null, null]
-    if (card.initval === 'week') {
-      _defaultValue = [moment().startOf('week'), moment().endOf('week')]
-    } else if (card.initval === 'month') {
-      _defaultValue = [moment().startOf('month'), moment().endOf('month')]
-    } else if (card.initval) {
-      try {
-        let _initval = JSON.parse(card.initval)
-        _defaultValue = [moment().subtract(_initval[0], 'days'), moment().subtract(_initval[1], 'days')]
-      } catch (e) {
-        _defaultValue = [null, null]
-      }
-    }
-  }
-
-  let labelCol = 'ant-col-sm-8'
-  let wrapCol = 'ant-col-sm-16'
-  if (card.type === 'textarea') {
-    if (cols === '2') {
-      labelCol = 'textarea-line ant-col-sm-4'
-      wrapCol = 'textarea-line ant-col-sm-20'
-    } else if (cols === '3') {
-      labelCol = 'textarea-line ant-col-cuslabel'
-      wrapCol = 'textarea-line ant-col-cuswrap'
-    } else if (cols === '4') {
-      labelCol = 'textarea-line ant-col-sm-2'
-      wrapCol = 'textarea-line ant-col-sm-22'
-    }
-  }
-
-  return (
-    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-      <div className="mk-popover-control">
-        <EditOutlined className="edit" title="缂栬緫" onClick={edit} />
-        {type === 'search' ? <CopyOutlined className="edit copy" title="澶嶅埗" onClick={copy} /> : null}
-        {type === 'action' && card.btnType !== 'cancel' ?
-          <ProfileOutlined className="edit profile" title="鏍¢獙瑙勫垯" onClick={profile} /> : null
-        }
-        {type === 'search' || (type === 'action' && card.btnType !== 'confirm' && card.btnType !== 'cancel') ? <CloseOutlined className="edit close" title="鍒犻櫎" onClick={del} /> : null}
-      </div>
-    } trigger="hover">
-      <div className="page-card" style={{ opacity: opacity}}>
-        <div ref={node => drag(drop(node))}>
-          {type === 'search' ?
-            <div className="ant-row ant-form-item">
-              <div className={'ant-col ant-form-item-label ant-col-xs-24 ' + labelCol}>
-                <label title={card.label}>{card.label}</label>
-              </div>
-              <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}>
-                {card.type === 'text' ?
-                  <Input style={{marginTop: '4px'}} value={card.initval} /> : null
-                }
-                {card.type === 'number' ?
-                  <InputNumber value={card.initval} precision={card.decimal} /> : null
-                }
-                {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
-                  <Select value={_defaultValue}></Select> : null
-                }
-                {card.type === 'date' ?
-                  <DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
-                }
-                {card.type === 'datemonth' ?
-                  <MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
-                }
-                {card.type === 'datetime' ?
-                  <DatePicker showTime value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
-                }
-                {card.type === 'textarea' ?
-                  <TextArea value={card.initval} autoSize={{ minRows: 2, maxRows: 6 }} /> : null
-                }
-                {card.type === 'funcvar' &&
-                  <Input style={{marginTop: '4px'}} value={card.linkfield} />
-                }
-                {card.type === 'fileupload' ?
-                  <Button>
-                    <UploadOutlined /> 鐐瑰嚮涓婁紶
-                  </Button> : null
-                }
-              </div>
-            </div> : null
-          }
-          {type === 'action' ?
-            <Button
-              className={'mk-btn mk-' + card.class}
-              icon={card.icon}
-              key={card.uuid}
-            >
-              {card.label}{card.position === 'grid' && <TableOutlined />}
-            </Button> : null
-          }
-        </div>
-      </div>
-    </Popover>
-  )
-}
-export default Card
diff --git a/src/templates/formtabconfig/dragelement/index.jsx b/src/templates/formtabconfig/dragelement/index.jsx
deleted file mode 100644
index 3621397..0000000
--- a/src/templates/formtabconfig/dragelement/index.jsx
+++ /dev/null
@@ -1,199 +0,0 @@
-import React, { useState } from 'react'
-import { useDrop } from 'react-dnd'
-import update from 'immutability-helper'
-import { is, fromJS } from 'immutable'
-import { Col } from 'antd'
-import Utils from '@/utils/utils.js'
-import Card from './card'
-import ItemTypes from './itemtypes'
-import './index.scss'
-
-const Container = ({list, type, groupId, setting, handleList, handleMenu, deleteMenu, profileMenu }) => {
-  const [cards, setCards] = useState(list)
-  const moveCard = (id, atIndex) => {
-    const { card, index } = findCard(id)
-
-    if (!card) return
-
-    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
-    if (type === 'action') {
-      handleList(type, _cards)
-    } else {
-      handleList(type, _cards, null, groupId)
-    }
-  }
-
-  if (!is(fromJS(cards), fromJS(list))) {
-    setCards(list)
-  }
-
-  const findCard = id => {
-    const card = cards.filter(c => `${c.uuid}` === id)[0]
-    return {
-      card,
-      index: cards.indexOf(card),
-    }
-  }
-
-  const editCard = id => {
-    const { card } = findCard(id)
-    handleMenu(card)
-  }
-
-  const copyCard = id => {
-    const { card } = findCard(id)
-
-    let _card = JSON.parse(JSON.stringify(card))
-
-    _card.originUuid = _card.uuid
-    _card.uuid = Utils.getuuid()
-    _card.iscopy = true
-    _card.focus = true
-
-    // 澶嶅埗鍒板壀鍒囨澘
-    let oInput = document.createElement('input')
-    let val = JSON.parse(JSON.stringify(_card))
-    val.copyType = 'form'
-    val.uuid = Utils.getuuid()
-
-    delete val.originUuid
-    delete val.iscopy
-
-    delete val.$srcId
-    
-    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'
-    document.body.removeChild(oInput)
-
-    handleMenu(_card)
-  }
-  
-  const profileCard = id => {
-    const { card } = findCard(id)
-    profileMenu(card)
-  }
-
-  const delCard = id => {
-    const { card } = findCard(id)
-    deleteMenu({card: card, type: type})
-  }
-
-  const [, drop] = useDrop({
-    accept: ItemTypes[type],
-    drop(item) {
-      if (item.hasOwnProperty('originalIndex') && groupId) {
-        const { card } = findCard(item.id)
-
-        if (!card) {
-          handleList(type, cards, null, groupId, item.id)
-        }
-      }
-
-      if (item.hasOwnProperty('originalIndex')) {
-        return
-      }
-
-      let newcard = {}
-      newcard.uuid = Utils.getuuid()
-      newcard.focus = true
-      
-      if (item.type === 'search') {
-        let _match = 'like'
-        if (item.subType === 'select' || item.subType === 'link') {
-          _match = '='
-        } else if (item.subType === 'date' || item.subType === 'datemonth') {
-          _match = '>='
-        } else if (item.subType === 'dateweek' || item.subType === 'daterange') {
-          _match = 'between'
-        }
-        
-        newcard.label = 'label'
-        newcard.field = ''
-        newcard.initval = ''
-        newcard.type = item.subType
-        newcard.resourceType = '0'
-        newcard.options = []
-        newcard.orderType = 'asc'
-        newcard.match = _match
-      } else if (item.type === 'action') {
-        newcard.label = 'button'
-        newcard.Ot = 'requiredSgl'
-        newcard.OpenType = item.subType
-        newcard.tabType = 'SubTable'
-        newcard.linkTab = ''
-        newcard.class = 'default'
-        newcard.intertype = 'inner'
-        newcard.position = 'toolbar'
-        newcard.execSuccess = 'grid'
-        newcard.execError = 'never'
-        newcard.popClose = 'never'
-        newcard.verify = null
-      }
-      
-      let targetId = ''
-
-      if (item.dropTargetId) {
-        targetId = item.dropTargetId
-        delete item.dropTargetId
-      } else if (cards.length > 0) {
-        targetId = cards.slice(-1)[0].uuid
-      }
-
-      const { index: overIndex } = findCard(`${targetId}`)
-      const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] })
-
-      handleList(type, _cards, newcard, groupId)
-    }
-  })
-
-  let _width = (setting && setting.width) || 100
-  
-  return (
-    <div ref={drop} className="ant-row" style={type === 'search' ? {margin: '0 auto', width: _width + '%'} : {}}>
-      {type === 'action' && cards.map(card => (
-        <Card
-          key={card.uuid}
-          id={card.uuid}
-          type={type}
-          card={card}
-          moveCard={moveCard}
-          editCard={editCard}
-          delCard={delCard}
-          profileCard={profileCard}
-          findCard={findCard}
-        />
-      ))}
-      {type === 'search' && cards.map(card => (
-        <Col key={card.uuid} span={card.type !== 'textarea' ? 24 / setting.cols : 24}>
-          <Card
-            id={card.uuid}
-            key={card.uuid}
-            type={type}
-            card={card}
-            cols={setting.cols}
-            moveCard={moveCard}
-            editCard={editCard}
-            delCard={delCard}
-            copyCard={copyCard}
-            findCard={findCard}
-          />
-        </Col>
-      ))}
-      {cards.length === 0 &&
-        <div className="common-drawarea-placeholder">
-          {type === 'action' ? '璇锋坊鍔犳寜閽�' : '璇锋坊鍔犺〃鍗�'}
-        </div>
-      }
-    </div>
-  )
-}
-export default Container
diff --git a/src/templates/formtabconfig/dragelement/index.scss b/src/templates/formtabconfig/dragelement/index.scss
deleted file mode 100644
index 38776f9..0000000
--- a/src/templates/formtabconfig/dragelement/index.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-.common-source-item {
-  display: block;
-  box-shadow: 0px 0px 2px #bcbcbc;
-  padding: 0.4rem 0.7rem;
-  background-color: white;
-  margin: 0px 0px 10px;
-  cursor: move;
-  border-radius: 4px;
-}
-.common-drawarea-placeholder {
-  width: 100%;
-  line-height: 65px;
-  text-align: center;
-  color: #bcbcbc;
-}
\ No newline at end of file
diff --git a/src/templates/formtabconfig/dragelement/itemtypes.js b/src/templates/formtabconfig/dragelement/itemtypes.js
deleted file mode 100644
index 9ea1f2c..0000000
--- a/src/templates/formtabconfig/dragelement/itemtypes.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
-  CARD: 'card',
-  form: 'form',
-  search: 'search',
-  action: 'action',
-  columns: 'columns',
-  tab: 'tab'
-}
diff --git a/src/templates/formtabconfig/dragelement/source.jsx b/src/templates/formtabconfig/dragelement/source.jsx
deleted file mode 100644
index ab22158..0000000
--- a/src/templates/formtabconfig/dragelement/source.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react'
-import { useDrag } from 'react-dnd'
-import './index.scss'
-
-const SourceElement = ({content}) => {
-  const [, drag] = useDrag({ item: content })
-  return (
-    <div ref={drag} className="common-source-item">
-      {content.label}
-    </div>
-  )
-}
-export default SourceElement
\ No newline at end of file
diff --git a/src/templates/formtabconfig/groupform/index.jsx b/src/templates/formtabconfig/groupform/index.jsx
deleted file mode 100644
index ed21eb8..0000000
--- a/src/templates/formtabconfig/groupform/index.jsx
+++ /dev/null
@@ -1,129 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, InputNumber } from 'antd'
-import { formRule } from '@/utils/option.js'
-import TransferForm from '../transferform'
-// import Utils from '@/utils/utils.js'
-// import './index.scss'
-
-class GroupForm extends Component {
-  static propTpyes = {
-    group: PropTypes.object,    // 褰撳墠鍒嗙粍
-    groups: PropTypes.array,    // 鎵�鏈夊垎缁�
-    inputSubmit: PropTypes.any  // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    source: null,
-    selectds: null,
-    default: null
-  }
-
-  UNSAFE_componentWillMount () {
-    const { groups, group } = this.props
-    let defaultgroup = groups.filter(item => item.isDefault)[0]
-    let _source = defaultgroup.sublist.filter(item => !item.origin)
-    let _selectds = group.sublist.map(item => item.uuid )
-
-    _source = [..._source, ...group.sublist]
-
-    this.setState({
-      source: _source,
-      selectds: _selectds,
-    })
-  }
-
-  handleConfirm = () => {
-    const { groups, group } = this.props
-    let defaultgroup = groups.filter(item => item.isDefault)[0]
-
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          values.uuid = group.uuid
-
-          if (group.isDefault) {
-            values.isDefault = true
-            values.sublist = group.sublist
-            
-            resolve(values)
-          } else {
-            let targetKeys = this.refs['fields-transfer'].state.targetKeys
-            let defaultlist = this.state.source.filter(item => !targetKeys.includes(item.uuid))
-
-            values.sublist = targetKeys.map(item => {
-              return this.state.source.filter(cell => cell.uuid === item)[0]
-            })
-
-            resolve({
-              default: {...defaultgroup, sublist: defaultlist},
-              target: values
-            })
-          }
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  render() {
-    const { group, groups } = this.props
-    const { getFieldDecorator } = this.props.form
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-    return (
-      <Form {...formItemLayout}>
-        <Row gutter={24}>
-          <Col span={12}>
-            <Form.Item label="鍒嗙粍鍚嶇О">
-              {getFieldDecorator('label', {
-                initialValue: group.label,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ュ垎缁勫悕绉�!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="鎺掑簭">
-              {getFieldDecorator('sort', {
-                initialValue: group.hasOwnProperty('sort') ? group.sort : groups.length
-              })(<InputNumber min={0} max={100} precision={0} />)}
-            </Form.Item>
-          </Col>
-          {!group.isDefault ? <Col span={24}>
-            <TransferForm fields={this.state.source} ref="fields-transfer" selected={this.state.selectds}/>
-          </Col> : null}
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(GroupForm)
\ No newline at end of file
diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx
deleted file mode 100644
index d9b92c4..0000000
--- a/src/templates/formtabconfig/index.jsx
+++ /dev/null
@@ -1,1771 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { DndProvider } from 'react-dnd'
-import HTML5Backend from 'react-dnd-html5-backend'
-import moment from 'moment'
-import { Button, Card, Modal, Collapse, notification, Spin, Switch, Tooltip } from 'antd'
-import { QuestionCircleOutlined, RedoOutlined, SettingOutlined, PlusOutlined, DeleteOutlined, EditOutlined, SnippetsOutlined } from '@ant-design/icons'
-
-import Api from '@/api'
-import Utils, { FuncUtils } from '@/utils/utils.js'
-import { getModalForm, getActionForm } from '@/templates/zshare/formconfig'
-import { queryTableSql } from '@/utils/option.js'
-
-import TabsComponent from '@/templates/sharecomponent/tabscomponent'
-
-import PasteForm from '@/templates/zshare/pasteform'
-import ActionForm from './actionform'
-import SettingForm from './settingform'
-import DragElement from './dragelement'
-import GroupForm from './groupform'
-
-import MenuForm from '@/templates/zshare/menuform'
-import SourceElement from '@/templates/zshare/dragsource'
-import asyncComponent from '@/utils/asyncComponent'
-import Source from './source'
-import './index.scss'
-
-const { Panel } = Collapse
-const { confirm } = Modal
-const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
-const CreateFunc = asyncComponent(() => import('@/templates/zshare/createfunc'))
-const VerifyCard = asyncComponent(() => import('@/templates/zshare/verifycard'))
-
-class ComTableConfig extends Component {
-  static propTpyes = {
-    menu: PropTypes.any,
-    btnTab: PropTypes.object,
-    config: PropTypes.any,
-    handleView: PropTypes.func
-  }
-
-  state = {
-    config: null,            // 椤甸潰閰嶇疆
-    modaltype: '',           // 妯℃�佹绫诲瀷锛屾帶鍒舵ā鎬佹鏄剧ず
-    tableColumns: [],        // 琛ㄦ牸鏄剧ず鍒�
-    fields: null,            // 鎼滅储鏉′欢鍙婃樉绀哄垪锛屽彲閫夊瓧娈�
-    menuformlist: null,      // 鍩烘湰淇℃伅琛ㄥ崟瀛楁
-    formlist: null,          // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪琛ㄥ崟瀛楁
-    card: null,              // 缂栬緫鍏冪礌
-    menuloading: false,      // 鑿滃崟淇濆瓨涓�
-    menucloseloading: false, // 鑿滃崟鍏抽棴鏃讹紝閫夋嫨淇濆瓨
-    loading: false,          // 鍔犺浇涓紝椤甸潰spin
-    settingVisible: false,   // 鍏ㄥ眬閰嶇疆妯℃�佹
-    closeVisible: false,     // 鍏抽棴妯℃�佹
-    tables: [],              // 鍙敤琛ㄥ悕
-    originMenu: null,        // 鍘熷鑿滃崟
-    delActions: [],          // 鍒犻櫎鎸夐挳鍒楄〃
-    tabviews: [],            // 鎵�鏈夋爣绛鹃〉
-    profileVisible: false,   // 楠岃瘉淇℃伅妯℃�佹
-    editgroup: null,         // 褰撳墠缂栬緫缁�
-    groupVisible: false,     // 缂栬緫缁勬ā鎬佹
-    activeKey: '0',          // 榛樿灞曞紑鍩烘湰淇℃伅
-    pasteVisible: false,     // 绮樿创妯℃�佹
-    sqlVerifing: false,      // sql楠岃瘉
-    openEdition: ''          // 缂栬緫鐗堟湰鏍囪锛岄槻姝㈠浜烘搷浣�
-  }
-
-  /**
-   * @description 鏁版嵁棰勫鐞�
-   * 1銆佽缃〉闈㈤厤缃俊鎭紝鏂板缓鎴栨棤閰嶇疆淇℃伅鏃讹紙鍒囨崲妯℃澘鍚庢棤閰嶇疆淇℃伅锛夛紝浣跨敤妯℃澘榛樿閰嶇疆
-   * 2銆佽缃搷浣滅被鍨嬨�佸師濮嬭彍鍗曚俊鎭紙姣忔淇濆瓨鍚庨噸缃級銆佸凡浣跨敤琛ㄥ強鍩烘湰淇℃伅琛ㄥ崟
-   */
-  UNSAFE_componentWillMount () {
-    const { menu, btnTab, config } = this.props
-
-    let _config = ''
-    let columns = []
-
-    if (!config) {
-      _config = JSON.parse(JSON.stringify(Source.baseConfig))
-      _config.isAdd = true
-      if (menu && menu.LongParam && menu.LongParam.setting) {
-        _config.setting.tableName = menu.LongParam.setting.tableName
-        _config.setting.primaryKey = menu.LongParam.setting.primaryKey
-        _config.setting.dataresource = menu.LongParam.setting.dataresource
-        _config.setting.interType = menu.LongParam.setting.interType
-        _config.setting.interface = menu.LongParam.setting.interface
-        _config.setting.outerFunc = menu.LongParam.setting.outerFunc
-        _config.setting.innerFunc = menu.LongParam.setting.innerFunc
-        _config.setting.sysInterface = menu.LongParam.setting.sysInterface
-      }
-    } else {
-      _config = config
-
-      if (menu && menu.LongParam && menu.LongParam.setting) {
-        _config.setting.primaryKey = menu.LongParam.setting.primaryKey
-      }
-    }
-
-    if (!_config.tabgroups) {
-      _config.tabgroups = [{ uuid: 'tabs', sublist: [] }]
-    } else if (typeof(_config.tabgroups[0]) === 'string') {
-      let _tabgroups = []
-      _config.tabgroups.forEach(groupId => {
-        let _group = {
-          uuid: groupId,
-          sublist: fromJS(_config[groupId]).toJS()
-        }
-
-        delete _config[groupId]
-
-        _tabgroups.push(_group)
-      })
-
-      _config.tabgroups = _tabgroups
-    }
-
-    if (menu && menu.LongParam && menu.LongParam.columns) {
-      columns = menu.LongParam.columns
-    }
-
-    // 閰嶇疆榛樿鍊硷紝鍏煎
-    _config.Template = 'FormTab'
-    _config.action = _config.action.map(item => {
-      if (item.intertype === 'inner' && !item.innerFunc) {
-        item.intertype = 'system'
-      }
-      return item
-    })
-
-    this.setState({
-      config: _config,
-      activeKey: btnTab.activeKey || '0',
-      openEdition: btnTab.open_edition || '',
-      columns: columns,
-      originMenu: JSON.parse(JSON.stringify(_config)),
-      menuformlist: [
-        {
-          type: 'text',
-          key: 'menuName',
-          label: '鑿滃崟鍚嶇О',
-          initVal: menu.MenuName,
-          readonly: true
-        },
-        {
-          type: 'text',
-          key: 'actionName',
-          label: '鎸夐挳鍚嶇О',
-          initVal: btnTab.label,
-          readonly: true
-        }
-      ]
-    })
-  }
-
-  /**
-   * @description 鍔犺浇瀹屾垚鍚�
-   * 1銆佽幏鍙栫郴缁熷彲浣跨敤琛�
-   * 2銆佹牴鎹厤缃俊鎭腑宸蹭娇鐢ㄨ〃鑾峰彇鐩稿叧瀛楁淇℃伅
-   * 3銆佽幏鍙栨墍鏈夋爣绛鹃〉淇℃伅
-   */
-  componentDidMount () {
-    let param = {
-      func: 'sPC_Get_SelectedList',
-      LText: queryTableSql,
-      obj_name: 'data',
-      arr_field: 'TbName,Remark'
-    }
-
-    param.LText = Utils.formatOptions(param.LText)
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-
-    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
-
-    Api.getSystemConfig(param).then(res => {
-      if (res.status) {
-        this.setState({
-          tables: res.data
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
-      if (res.status) {
-        this.setState({
-          tabviews: res.UserTemp.map(temp => {
-            return {
-              uuid: temp.MenuID,
-              value: temp.MenuID,
-              text: temp.MenuName,
-              type: temp.Template,
-              MenuNo: temp.MenuNo
-            }
-          })
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-  }
-  
-  /**
-   * @description 鍔犺浇鎴栧埛鏂版爣绛句俊鎭�
-   */
-  reloadTab = () => {
-    this.setState({
-      loading: true,
-      tabviews: []
-    })
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
-      if (res.status) {
-        this.setState({
-          loading: false,
-          tabviews: res.UserTemp.map(temp => {
-            return {
-              uuid: temp.MenuID,
-              value: temp.MenuID,
-              text: temp.MenuName,
-              type: temp.Template,
-              MenuNo: temp.MenuNo
-            }
-          })
-        })
-        notification.success({
-          top: 92,
-          message: '鍒锋柊鎴愬姛銆�',
-          duration: 2
-        })
-      } else {
-        this.setState({
-          loading: false
-        })
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-  }
-
-  // 椤甸潰杩斿洖
-  handleViewBack = () => {
-    const { menu } = this.props
-    let _tabview = menu ? menu.LongParam.Template : ''
-    let param = {
-      editMenu: menu,
-      editTab: null,
-      tabConfig: null,
-      editSubTab: null,
-      subTabConfig: null,
-      btnTab: null,
-      btnTabConfig: null,
-      editAction: null,
-      subConfig: null,
-      tabview: _tabview
-    }
-
-    this.props.handleView(param)
-  }
-
-  handleList = (type, list, card, groupId, elementId) => {
-    const { config } = this.state
-
-    if (type === 'action') {
-      if (list.length > config.action.length) {
-  
-        this.handleAction(card)
-      }
-
-      this.setState({config: {...config, action: list}})
-    } else if (type === 'search') {
-      let _groups = null
-
-      if (card) {
-        // 鍏冪礌娣诲姞
-        if (config.groups.length === 1) {
-          _groups = config.groups.map(group => {
-            let _list = list.filter(item => !item.origin)
-            return {...group, sublist: _list}
-          })
-        } else {
-          _groups = config.groups.map(group => {
-            if (group.uuid === groupId) {
-              return {...group, sublist: list}
-            } else {
-              return group
-            }
-          })
-        }
-        this.handleSearch(card)
-      } else if (elementId) {
-        // 淇敼宸叉湁鍏冪礌鐨勫垎缁�
-        let element = null
-        _groups = config.groups.map(group => {
-          group.sublist = group.sublist.filter(item => {
-            if (item.uuid === elementId) {
-              element = item
-              return false
-            } else {
-              return true
-            }
-          })
-          return group
-        })
-
-        _groups = _groups.map(group => {
-          if (group.uuid === groupId) {
-            group.sublist.push(element)
-          }
-          return group
-        })
-      } else {
-        // 鍏冪礌绉诲姩
-        _groups = config.groups.map(group => {
-          if (group.uuid === groupId) {
-            return {...group, sublist: list}
-          } else {
-            return group
-          }
-        })
-      }
-
-      this.setState({
-        config: {...config, groups: _groups}
-      })
-    }
-  }
-
-  handleSearch = (card) => {
-    const { menu } = this.props
-    const { config } = this.state
-    let _inputfields = []
-    let _tabfields = []
-    let _linkableFields = []
-    let _linksupFields = []
-    let _formfields = []
-
-    // 璁剧疆涓嬫媺鑿滃崟鍙叧鑱斿瓧娈�
-    config.groups.forEach(group => {
-      _formfields = [..._formfields, ...group.sublist]
-    })
-
-    let uniq = new Map()
-    uniq.set(card.field, true)
-
-    _formfields.forEach(item => {
-      if (['text', 'number', 'textarea', 'color'].includes(item.type) && card.field !== item.field) {
-        _inputfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      if (card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
-        _tabfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (item.type !== 'select' && item.type !== 'link') return
-      if (item.field && !uniq.has(item.field)) {
-        uniq.set(item.field, true)
-
-        _linkableFields.push({
-          field: item.field,
-          label: item.label + '-琛ㄥ崟'
-        })
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-    })
-
-    if (card.linkSubField && card.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      card.linkSubField = card.linkSubField.filter(item => fields.includes(item))
-    }
-
-    if (menu.LongParam) {
-      menu.LongParam.columns.forEach(col => {
-        if (col.field && !uniq.has(col.field)) {
-          uniq.set(col.field, true)
-
-          _linkableFields.push({
-            field: col.field,
-            label: col.label + '-鏄剧ず鍒�'
-          })
-        }
-      })
-    }
-
-    this.setState({
-      modaltype: 'search',
-      card: card,
-      formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields).map(item => {
-        if (item.key === 'type') {
-          item.options = item.options.filter(option => !['switch', 'checkbox', 'radio', 'checkcard', 'hint'].includes(option.value))
-        }
-        return item
-      })
-    })
-  }
-
-  handleAction = (card) => {
-    let usefulFields = sessionStorage.getItem('permFuncField')
-    if (usefulFields) {
-      try {
-        usefulFields = JSON.parse(usefulFields)
-      } catch (e) {
-        usefulFields = []
-      }
-    } else {
-      usefulFields = []
-    }
-
-    this.setState({
-      modaltype: 'actionEdit',
-      card: card,
-      formlist: getActionForm(card, this.state.config, usefulFields)
-    })
-  }
-
-
-  /**
-   * @description 鎼滅储銆佹寜閽�佹樉绀哄垪淇敼鍚庢彁浜や繚瀛�
-   * 1銆佹悳绱㈡潯浠朵繚瀛橈紝褰撶被鍨嬩负涓嬫媺妗嗕笖瀛樺湪鏁版嵁婧愭椂锛屽皢鏌ヨ鏉′欢鎷兼帴涓簊ql锛屽苟鐢╞ase64杞爜
-   * 2銆佹寜閽寘鎷甯哥紪杈戝拰澶嶅埗锛屽鍒舵椂,鎸夐挳鍒楁湯灏炬坊鍔�
-   * 3銆佹坊鍔犳垨缂栬緫鍒楋紝淇濆瓨鏃讹紝濡傛寜閽綅缃缃负琛ㄦ牸锛屽垯淇敼鎿嶄綔鍒楁樉绀虹姸鎬�
-   */
-  handleSubmit = () => {
-    const { config, modaltype, card } = this.state
-
-    if (modaltype === 'search') {
-      this.modalFormRef.handleConfirm().then(res => {
-        let _config = JSON.parse(JSON.stringify(config))
-
-        if (_config.setting.primaryKey && _config.setting.primaryKey.toLowerCase() === res.field.toLowerCase()) {
-          notification.warning({
-            top: 92,
-            message: '琛ㄥ崟涓瓧娈靛悕涓嶅彲涓庝富閿噸澶嶏紒',
-            duration: 5
-          })
-          return
-        }
-
-        let _groups = null
-        let fieldrepet = false  // 瀛楁閲嶅
-
-        if (card.iscopy) {
-          _groups = _config.groups.map(group => {
-            let _index = null
-            group.sublist.forEach((item, index) => {
-              if (item.uuid === card.originUuid) {
-                _index = index
-              }
-
-              if (item.uuid !== res.uuid && item.field === res.field) {
-                fieldrepet = true
-              }
-            })
-
-            if (_index !== null) {
-              group.sublist.splice(_index + 1, 0, res)
-            }
-
-            if (group.isDefault) {
-              group.sublist = group.sublist.filter(item => !item.origin)
-            }
-            return group
-          })
-        } else {
-          _groups = _config.groups.map(group => {
-            group.sublist = group.sublist.map(item => {
-              if (item.uuid !== res.uuid && item.field === res.field) {
-                fieldrepet = true
-              }
-
-              if (item.uuid === res.uuid) {
-                return res
-              } else {
-                return item
-              }
-            })
-            if (group.isDefault) {
-              group.sublist = group.sublist.filter(item => !item.origin)
-            }
-            return group
-          })
-        }
-
-        if (fieldrepet) {
-          notification.warning({
-            top: 92,
-            message: '瀛楁宸插瓨鍦紒',
-            duration: 5
-          })
-          return
-        }
-
-        if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) {
-          this.setState({
-            sqlVerifing: true
-          })
-  
-          let param = {
-            func: 's_debug_sql',
-            exec_type: 'y',
-            LText: `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-              ${res.dataSource}`
-          }
-
-          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-          param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${param.timestamp}'`)
-          param.LText = param.LText.replace(/\n/g, ' ')
-
-          param.LText = Utils.formatOptions(param.LText)
-          param.secretkey = Utils.encrypt('', param.timestamp)
-  
-          if (window.GLOB.mainSystemApi && res.database === 'sso') {
-            param.rduri = window.GLOB.mainSystemApi
-          }
-          
-          Api.genericInterface(param).then(result => {
-            if (result.status) {
-              this.setState({
-                sqlVerifing: false,
-                config: {..._config, groups: _groups},
-                modaltype: ''
-              })
-            } else {
-              this.setState({sqlVerifing: false})
-
-              Modal.error({
-                title: result.message
-              })
-            }
-          })
-        } else {
-          this.setState({
-            config: {..._config, groups: _groups},
-            modaltype: ''
-          })
-        }
-      })
-    } else if (modaltype === 'actionEdit') {
-      this.actionFormRef.handleConfirm().then(res => {
-        let _action = config.action.map(item => {
-          if (item.uuid === res.uuid) {
-            return res
-          } else {
-            return item
-          }
-        })
-
-        this.setState({
-          config: {...config, action: _action},
-          modaltype: ''
-        })
-      })
-    }
-  }
-
-  editModalCancel = () => {
-    const { config, card, modaltype } = this.state
-
-    if (card.focus) {
-      let _config = null
-      if (modaltype === 'search') {
-        let _groups = config.groups.map(group => {
-          group.sublist = group.sublist.filter(item => item.uuid !== card.uuid)
-          return group
-        })
-        _config = {...config, groups: _groups}
-      } else if (modaltype === 'actionEdit') {
-        let _action = config.action.filter(item => item.uuid !== card.uuid)
-        _config = {...config, action: _action}
-      } else {
-        _config = config
-      }
-
-      this.setState({
-        card: null,
-        config: _config,
-        modaltype: ''
-      })
-    } else {
-      this.setState({
-        card: null,
-        modaltype: ''
-      })
-    }
-  }
-
-  /**
-   * @description 鍒涘缓鎸夐挳瀛樺偍杩囩▼
-   */
-  creatFunc = () => {
-    const { menu } = this.props
-    let _config = JSON.parse(JSON.stringify(this.state.config))
-
-    this.actionFormRef.handleConfirm().then(res => {
-      let btn = res         // 鎸夐挳淇℃伅
-      let newLText = ''     // 鍒涘缓瀛樺偍杩囩▼sql
-      let DelText = ''      // 鍒犻櫎瀛樺偍杩囩▼sql
-
-      // 鍒涘缓瀛樺偍杩囩▼锛屽繀椤诲~鍐欏唴閮ㄥ嚱鏁板悕
-      if (!btn.innerFunc) {
-        notification.warning({
-          top: 92,
-          message: '璇峰~鍐欏唴閮ㄥ嚱鏁帮紒',
-          duration: 5
-        })
-        return
-      }
-
-      let fields = []
-      _config.groups.forEach(group => {
-        fields = [...fields, ...group.sublist]
-      })
-
-      let _param = {
-        funcName: btn.innerFunc,
-        name: _config.setting.tableName || '',
-        fields: fields,
-        menuNo: menu.MenuNo
-      }
-
-      newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config))
-      DelText = Utils.formatOptions(FuncUtils.dropfunc(_param.funcName))
-
-      this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText)
-    })
-  }
-
-  /**
-   * @description 鍒涘缓琛ㄦ牸瀛樺偍杩囩▼
-   */
-  tableCreatFunc = () => {
-    const { menu } = this.props
-    const { config } = this.state
-
-    this.settingRef.handleConfirm().then(setting => {
-
-      if (!(setting.interType === 'inner') || !setting.innerFunc) {
-        notification.warning({
-          top: 92,
-          message: '鎺ュ彛绫诲瀷涓�-鍐呴儴锛屼笖瀛樺湪鍐呴儴鍑芥暟鏃讹紝鎵嶅彲浠ュ垱寤哄瓨鍌ㄨ繃绋嬶紒',
-          duration: 5
-        })
-        return
-      }
-
-      if (/[^\s]+\s+[^\s]+/ig.test(setting.dataresource) && config.setting.dataresource !== setting.dataresource) {
-        let param = {
-          func: 's_DataSrc_Save',
-          LText: setting.dataresource,
-          MenuID: menu.MenuID
-        }
-
-        param.LText = Utils.formatOptions(param.LText)
-        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-
-        Api.genericInterface(param)
-      }
-
-      let _config = {...config, setting: setting}
-      let newLText = Utils.formatOptions(FuncUtils.getTableFunc(setting.innerFunc, menu, _config)) // 鍒涘缓瀛樺偍杩囩▼sql
-      let DelText = Utils.formatOptions(FuncUtils.dropfunc(setting.innerFunc))          // 鍒犻櫎瀛樺偍杩囩▼sql
-
-      this.refs.tableCreatFunc.exec(setting.innerFunc, newLText, DelText)
-    })
-  }
-
-  deleteElement = (element) => {
-    let _this = this
-    confirm({
-      content: `纭畾鍒犻櫎<<${element.card.label}>>鍚楋紵`,
-      onOk() {
-        let _config = JSON.parse(JSON.stringify(_this.state.config))
-        let _delActions = _this.state.delActions
-
-        if (element.type === 'search') {
-          _config.groups = _config.groups.map(group => {
-            group.sublist = group.sublist.filter(item => item.uuid !== element.card.uuid)
-            return group
-          })
-        } else {
-          _config[element.type] = _config[element.type].filter(item => {
-            if (item.uuid === element.card.uuid) {
-              return false
-            } else {
-              return true
-            }
-          })
-          _delActions.push(element.card.uuid)
-        }
-
-        _this.setState({
-          config: _config,
-          delActions: _delActions
-        })
-      },
-      onCancel() {}
-    })
-  }
-
-  /**
-   * @description 楠岃瘉淇℃伅閰嶇疆
-   */
-  profileAction = (element) => {
-    this.setState({
-      profileVisible: true,
-      card: element
-    })
-  }
-
-  /**
-   * @description 楠岃瘉淇℃伅淇濆瓨
-   */
-  verifySubmit = () => {
-    const { card } = this.state
-    let config = JSON.parse(JSON.stringify(this.state.config))
-
-    this.verifyRef.handleConfirm().then(res => {
-      config.action = config.action.map(item => {
-        if (item.uuid === card.uuid) {
-          item.verify = res
-        }
-  
-        return item
-      })
-  
-      this.setState({
-        profileVisible: false,
-        config: config,
-        card: ''
-      })
-    })
-  }
-
-  /**
-   * @description 鑿滃崟淇濆瓨
-   */
-  submitConfig = () => {
-    const { menu, btnTab } = this.props
-    const { delActions, openEdition } = this.state
-
-    let config = JSON.parse(JSON.stringify(this.state.config))
-
-    this.menuformRef.handleConfirm().then(res => {
-      if (config.isAdd) {
-        if (config.groups[0] && config.groups[0].sublist[0] && config.groups[0].sublist[0].origin) {
-          config.groups[0].sublist = config.groups[0].sublist.filter(item => !item.origin)
-        }
-        config.tabgroups[0].sublist = config.tabgroups[0].sublist.filter(item => !item.origin)
-      }
-
-      let btnNames = config.action.map(item => item.label)
-      btnNames = Array.from(new Set(btnNames))
-      if (btnNames.length < config.action.length) {
-        notification.warning({
-          top: 92,
-          message: '鎸夐挳鍚嶇О涓嶅彲鐩稿悓锛�',
-          duration: 5
-        })
-        return
-      }
-
-      let _LongParam = ''
-      let _config = {...config}
-
-      // 鏁版嵁鏉ユ簮涓烘煡璇笖鏈缃富閿椂锛屽惎鐢ㄤ负false
-      if (_config.setting.datatype === 'query' && !_config.setting.primaryKey) {
-        _config.enabled = false
-      } else if (_config.setting.datatype === 'query' && _config.setting.interType === 'inner' && !_config.setting.innerFunc && !_config.setting.dataresource) {
-        _config.enabled = false
-      }
-
-      // 鏍囩涓嶅悎娉曟椂锛屽惎鐢ㄧ姸鎬佷负false
-      if (_config.tabgroups.length > 1) {
-        _config.tabgroups.forEach(group => {
-          if (group.sublist.length === 0) {
-            _config.enabled = false
-          }
-        })
-      }
-
-      // 瀛樺湪澶氫綑鐨勭┖琛ㄥ崟缁�
-      let _ismutil = _config.groups.length > 1
-      let _primary = _config.setting.primaryKey ? _config.setting.primaryKey.toLowerCase() : ''
-
-      _config.groups.forEach(group => {
-        if (_ismutil && group.sublist.length === 0) {
-          _config.enabled = false
-        }
-        let arr = group.sublist.filter(item => item.field && item.field.toLowerCase() === _primary)
-
-        if (arr.length > 0) {
-          _config.enabled = false
-        }
-      })
-
-      _config.funcs = [] // 椤甸潰鍙婂瓙椤甸潰瀛樺偍杩囩▼闆�
-
-      if (_config.setting.datatype === 'query') {
-        _config.funcs.push({
-          type: 'view',
-          subtype: 'view',
-          uuid: btnTab.uuid,
-          intertype: _config.setting.interType || 'inner',
-          interface: _config.setting.interface || '',
-          tableName: _config.setting.tableName || '',
-          innerFunc: _config.setting.innerFunc || '',
-          outerFunc: _config.setting.outerFunc || ''
-        })
-      }
-
-      _config.action.forEach(item => {
-        if (item.btnType !== 'cancel') {
-          _config.funcs.push({
-            type: 'button',
-            subtype: 'btn',
-            uuid: item.uuid,
-            label: item.label,
-            tableName: item.sql || '',
-            intertype: item.intertype,
-            interface: item.interface || '',
-            innerFunc: item.innerFunc || '',
-            outerFunc: item.outerFunc || '',
-            callbackFunc: item.callbackFunc || ''
-          })
-        }
-      })
-
-      _config.tabgroups.forEach(group => {
-        group.sublist.forEach(tab => {
-          _config.funcs.push({
-            type: 'tab',
-            subtype: 'tab',
-            uuid: tab.uuid,
-            label: tab.label,
-            linkTab: tab.linkTab
-          })
-        })
-      })
-
-      if (this.state.closeVisible) { // 鏄剧ず鍏抽棴瀵硅瘽妗嗘椂锛屾ā鎬佹涓繚瀛樻寜閽紝鏄剧ず淇濆瓨涓姸鎬�
-        this.setState({
-          menucloseloading: true
-        })
-      } else {
-        this.setState({
-          menuloading: true
-        })
-      }
-
-      new Promise(resolve => {
-        let deffers = []
-        _config.funcs.forEach(item => {
-          if (item.type === 'tab') {
-            let deffer = new Promise(resolve => {
-              Api.getSystemConfig({
-                func: 'sPC_Get_LongParam',
-                MenuID: item.linkTab
-              }).then(result => {
-                if (result.status && result.LongParam) {
-                  let _LongParam = ''
-        
-                  if (result.LongParam) {
-                    try {
-                      _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-                    } catch (e) {
-                      console.warn('Parse Failure')
-                      _LongParam = ''
-                    }
-                  }
-      
-                  if (_LongParam) {
-                    item.menuNo = _LongParam.tabNo
-                    item.subfuncs = _LongParam.funcs || []
-                  }
-                }
-                resolve()
-              })
-            })
-
-            deffers.push(deffer)
-          }
-        })
-
-        if (deffers.length === 0) {
-          resolve()
-        } else {
-          Promise.all(deffers).then(() => {
-            resolve()
-          })
-        }
-      }).then(() => {
-        
-        // 鍒犻櫎娣诲姞鏍囪瘑
-        delete _config.isAdd
-  
-        try {
-          _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
-        } catch (e) {
-          notification.warning({
-            top: 92,
-            message: '缂栬瘧閿欒',
-            duration: 5
-          })
-
-          this.setState({
-            menucloseloading: false,
-            menuloading: false
-          })
-          return
-        }
-  
-        let _sort = 0 // 鎸夐挳鍙婃爣绛炬帓搴�
-
-        let btnParam = { // 娣诲姞鑿滃崟鎸夐挳
-          func: 'sPC_Button_AddUpt',
-          Type: 60,      // 娣诲姞鎸夐挳琛ㄥ崟椤典笅鐨勬寜閽�
-          ParentID: btnTab.uuid,
-          MenuNo: menu.MenuNo,
-          Template: menu.PageParam.Template || '',
-          PageParam: '',
-          LongParam: '',
-          LText: config.action.map((item, index) => {
-            _sort++
-            return `select '${item.uuid}' as menuid, '${item.label}' as menuname, '${_sort * 10}' as Sort`
-          })
-        }
-  
-        btnParam.LText = btnParam.LText.join(' union all ')
-        btnParam.LText = Utils.formatOptions(btnParam.LText)
-        btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
-        
-        // let tabParam = { // 娣诲姞鑿滃崟tab椤�
-        //   func: 'sPC_sMenusTab_AddUpt',
-        //   MenuID: btnTab.uuid
-        // }
-        
-        // let _LText = []
-
-        // config.tabgroups.forEach(group => {
-        //   group.sublist.forEach(item => {
-        //     _sort++
-        //     _LText.push(`select '${btnTab.uuid}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${_sort * 10}' as Sort`)
-        //   })
-        // })
-
-        // _LText = _LText.join(' union all ')
-
-        // tabParam.LText = Utils.formatOptions(_LText)
-
-        // tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        // tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp)
-  
-        let param = {
-          func: 'sPC_ButtonParam_AddUpt',
-          ParentID: menu.MenuID,
-          MenuID: btnTab.uuid,
-          MenuNo: menu.MenuNo,
-          Template: 'FormTab',
-          MenuName: btnTab.label,
-          PageParam: JSON.stringify({Template: 'FormTab'}),
-          LongParam: _LongParam
-        }
-
-        if (openEdition) {
-          param.open_edition = openEdition
-        }
-
-        // 鏈夋寜閽垨鏍囩鍒犻櫎鏃讹紝鍏堣繘琛屽垹闄ゆ搷浣�
-        // 鍒犻櫎鎴愬姛鍚庯紝淇濆瓨椤甸潰閰嶇疆
-        new Promise(resolve => {
-          if (delActions.length > 0) {
-            let deffers = delActions.map(item => {
-              let _param = {
-                func: 'sPC_MainMenu_Del',
-                MenuID: item
-              }
-              return new Promise(resolve => {
-                Api.getSystemConfig(_param).then(response => {
-                  resolve(response)
-                })
-              })
-            })
-            Promise.all(deffers).then(result => {
-              let error = null
-              result.forEach(response => {
-                if (!response.status) {
-                  error = response
-                }
-              })
-    
-              if (error) {
-                this.setState({
-                  menuloading: false,
-                  menucloseloading: false
-                })
-                notification.warning({
-                  top: 92,
-                  message: error.message,
-                  duration: 5
-                })
-                resolve(false)
-              } else {
-                this.setState({
-                  delActions: []
-                })
-                resolve(true)
-              }
-            })
-          } else if (delActions.length === 0) {
-            resolve(true)
-          }
-        }).then(resp => {
-          if (resp === false) return
-    
-          Api.getSystemConfig(param).then(response => {
-            if (response.status) {
-              this.setState({
-                openEdition: response.open_edition || '',
-                config: _config,
-                originMenu: _config
-              })
-    
-              this.submitAction(btnParam)
-            } else {
-              this.setState({
-                menuloading: false,
-                menucloseloading: false
-              })
-              notification.warning({
-                top: 92,
-                message: response.message,
-                duration: 5
-              })
-            }
-          })
-        })
-      })
-    }, () => {
-      notification.warning({
-        top: 92,
-        message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
-        duration: 5
-      })
-    })
-  }
-
-  /**
-   * @description 淇濆瓨鎴栦慨鏀硅彍鍗曟寜閽�
-   */
-  submitAction = (btnParam) => {
-    new Promise(resolve => {
-      if (btnParam.LText) {
-        Api.getSystemConfig(btnParam).then(result => {
-          if (!result.status) {
-            notification.warning({
-              top: 92,
-              message: result.message,
-              duration: 5
-            })
-            resolve(false)
-          } else {
-            resolve(true)
-          }
-        })
-      } else {
-        resolve(true)
-      }
-    }).then(response => {
-      this.setState({
-        menuloading: false,
-        menucloseloading: false
-      })
-
-      if (response) {
-        notification.success({
-          top: 92,
-          message: '淇濆瓨鎴愬姛',
-          duration: 2
-        })
-        if (this.state.closeVisible) {
-          this.handleViewBack()
-        }
-      }
-    })
-  }
-
-  cancelConfig = () => {
-    const { config, originMenu } = this.state
-
-    let _this = this
-
-    if (config.isAdd) {
-      confirm({
-        content: '鎸夐挳閰嶇疆灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
-        onOk() {
-          _this.handleViewBack()
-        },
-        onCancel() {}
-      })
-    } else {
-      let _config = {...config}
-
-      if (!is(fromJS(_config), fromJS(originMenu))) {
-        this.setState({
-          closeVisible: true
-        })
-      } else {
-        this.handleViewBack()
-      }
-    }
-  }
-
-  changeSetting = () => {
-    this.setState({
-      settingVisible: true
-    })
-  }
-
-  settingSave = () => {
-    const { menu } = this.props
-    const {config} = this.state
-
-    this.settingRef.handleConfirm().then(res => {
-      if (
-        res.interType === 'inner' &&
-        !res.innerFunc &&
-        /[^\s]+\s+[^\s]+/ig.test(res.dataresource) &&
-        config.setting.dataresource !== res.dataresource
-      ) {
-        let param = {
-          func: 's_DataSrc_Save',
-          LText: res.dataresource,
-          MenuID: menu.MenuID
-        }
-
-        param.LText = Utils.formatOptions(param.LText)
-        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-
-        Api.genericInterface(param)
-      }
-
-      if (res.interType === 'inner' && !res.innerFunc && res.dataresource && /\s/.test(res.dataresource)) {
-        this.setState({
-          sqlVerifing: true
-        })
-
-        let param = {
-          func: 's_debug_sql',
-          exec_type: 'y',
-          LText: res.dataresource
-        }
-
-        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${param.timestamp}'`)
-        param.LText = param.LText.replace(/\n/g, ' ')
-        
-        param.LText = Utils.formatOptions(param.LText)
-        param.secretkey = Utils.encrypt('', param.timestamp)
-        
-        Api.genericInterface(param).then(result => {
-          if (result.status) {
-            this.setState({
-              sqlVerifing: false,
-              config: {...config, setting: res},
-              settingVisible: false
-            })
-          } else {
-            this.setState({sqlVerifing: false})
-            
-            Modal.error({
-              title: result.message
-            })
-          }
-        })
-      } else {
-        this.setState({
-          config: {...config, setting: res},
-          settingVisible: false
-        })
-      }
-    })
-  }
-
-  /**
-   * @description 璁剧疆鍙厤缃爣绛�
-   */
-  setSubConfig = (btn) => {
-    const {menu, btnTab} = this.props
-    const { config, originMenu, activeKey, openEdition } = this.state
-
-    if (config.isAdd) {
-      notification.warning({
-        top: 92,
-        message: '鑿滃崟灏氭湭淇濆瓨锛岃淇濆瓨鑿滃崟閰嶇疆锛�',
-        duration: 5
-      })
-    } else {
-      this.menuformRef.handleConfirm().then(res => {
-        let _config = {...config}
-
-        if (!is(fromJS(originMenu), fromJS(_config))) {
-          notification.warning({
-            top: 92,
-            message: '鑿滃崟閰嶇疆宸蹭慨鏀癸紝璇蜂繚瀛橈紒',
-            duration: 5
-          })
-        } else {
-          this.setState({
-            loading: true
-          })
-
-          btnTab.activeKey = activeKey       // 淇濆瓨褰撳墠鎵撳紑椤电
-          btnTab.open_edition = openEdition  // 鏇存柊鐗堟湰鍙�
-
-          let param = {
-            editMenu: menu,
-            editTab: btn,
-            tabConfig: null,
-            editSubTab: null,
-            subTabConfig: null,
-            btnTab: btnTab,
-            btnTabConfig: _config,
-            editAction: null,
-            subConfig: '',
-            tabview: btn.type
-          }
-
-          Api.getSystemConfig({
-            func: 'sPC_Get_LongParam',
-            MenuID: btn.linkTab
-          }).then(res => {
-            if (res.status) {
-              this.setState({
-                loading: false
-              })
-              let _LongParam = ''
-              if (res.LongParam) {
-                try {
-                  _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
-                } catch (e) {
-                  console.warn('Parse Failure')
-                  _LongParam = ''
-                }
-              }
-
-              if (_LongParam && param.tabview === 'SubTable' && _LongParam.Template === 'SubTable') {
-                param.subConfig = _LongParam
-              }
-
-              if (param.editTab) {
-                param.editTab.open_edition = res.open_edition || ''
-              }
-
-              this.props.handleView(param)
-            } else {
-              this.setState({
-                loading: false
-              })
-              notification.warning({
-                top: 92,
-                message: res.message,
-                duration: 5
-              })
-            }
-          })
-        }
-      }, () => {
-        notification.warning({
-          top: 92,
-          message: '鑿滃崟鍩烘湰淇℃伅宸蹭慨鏀癸紝璇蜂繚瀛橈紒',
-          duration: 5
-        })
-      })
-    }
-  }
-
-  onEnabledChange = () => {
-    const { config } = this.state
-
-    let tabinvalid = true
-    if (config.tabgroups.length > 1) {
-      config.tabgroups.forEach(group => {
-        if (group.sublist.length === 0) {
-          tabinvalid = false
-        }
-      })
-    }
-    let forminvalid = true
-    if (config.groups.length > 1) {
-      config.groups.forEach(group => {
-        if (group.sublist.length === 0) {
-          forminvalid = false
-        }
-      })
-    }
-
-    let _primary = config.setting.primaryKey ? config.setting.primaryKey.toLowerCase() : ''
-    let primaryrepeat = false
-
-    config.groups.forEach(group => {
-      let arr = group.sublist.filter(item => item.field && item.field.toLowerCase() === _primary)
-
-      if (arr.length > 0) {
-        primaryrepeat = true
-      }
-    })
-
-    if (config.setting.datatype === 'query' && config.setting.interType === 'inner' && !config.setting.innerFunc && !config.setting.dataresource) {
-      notification.warning({
-        top: 92,
-        message: '灏氭湭璁剧疆鏁版嵁婧愶紝涓嶅彲鍚敤锛�',
-        duration: 5
-      })
-    } else if (config.setting.datatype === 'query' && !config.setting.primaryKey) {
-      notification.warning({
-        top: 92,
-        message: '灏氭湭璁剧疆涓婚敭锛屼笉鍙惎鐢紒',
-        duration: 5
-      })
-    } else if (!tabinvalid) {
-      notification.warning({
-        top: 92,
-        message: '瀛樺湪澶氫綑鏍囩缁勶紝涓嶅彲鍚敤锛�',
-        duration: 5
-      })
-    } else if (!forminvalid) {
-      notification.warning({
-        top: 92,
-        message: '瀛樺湪澶氫綑绌鸿〃鍗曠粍锛屼笉鍙惎鐢紒',
-        duration: 5
-      })
-    } else if (primaryrepeat) {
-      notification.warning({
-        top: 92,
-        message: '琛ㄥ崟瀛楁涓庝富閿噸澶嶏紝涓嶅彲鍚敤锛�',
-        duration: 5
-      })
-    } else {
-      this.setState({
-        config: {...config, enabled: !config.enabled}
-      })
-    }
-  }
-
-
-
-  handleGroup = (group) => {
-    let editgroup = {
-      label: '',
-      sort: 0,
-      uuid: Utils.getuuid(),
-      sublist: []
-    }
-
-    if (group) {
-      editgroup = group
-    }
-
-    this.setState({
-      groupVisible: true,
-      editgroup: editgroup
-    })
-  }
-
-  closeGroup = (group) => {
-    const { config } = this.state
-    let _this = this
-
-    confirm({
-      content: `纭畾鍒犻櫎鍒嗙粍<<${group.label}>>鍚楋紵`,
-      onOk() {
-        let groups = config.groups.filter(item => !(item.uuid === group.uuid))
-        groups = groups.map(item => {
-          if (item.isDefault) {
-            item.sublist = [...item.sublist, ...group.sublist]
-          }
-
-          return item
-        })
-
-        _this.setState({
-          config: {...config, groups: groups},
-        })
-      },
-      onCancel() {}
-    })
-  }
-
-  handleGroupSave = () => {
-    const { editgroup, config } = this.state
-    let groups = config.groups.filter(item => !item.isDefault && item.uuid !== editgroup.uuid)
-
-    this.groupRef.handleConfirm().then(res => {
-      if (editgroup.isDefault) {
-        groups.push(res)
-      } else {
-        groups.push(res.default, res.target)
-      }
-
-      groups = groups.sort((a, b) => {
-        return a.sort - b.sort
-      })
-
-      this.setState({
-        config: {...config, groups: groups},
-        editgroup: '',
-        groupVisible: false,
-      })
-    })
-  }
-
-
-  pasteSubmit = () => {
-    let _config = JSON.parse(JSON.stringify(this.state.config))
-
-    this.pasteFormRef.handleConfirm().then(res => {
-      if (res.copyType === 'form') {
-        _config.groups.forEach(group => {
-          if (group.isDefault) {
-            group.sublist.push(res)
-          }
-        })
-
-        if (res.type === 'linkMain') {
-          notification.warning({
-            top: 92,
-            message: '涓嶆敮鎸佹琛ㄥ崟绫诲瀷锛�',
-            duration: 5
-          })
-          return
-        }
-
-        this.setState({
-          config: _config,
-          pasteVisible: null
-        }, () => {
-          this.handleSearch(res)
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�',
-          duration: 5
-        })
-      }
-    })
-  }
-
-  /**
-   * @description 鏇存柊鏍囩閰嶇疆淇℃伅
-   */
-  updatetabs = (config, delcards) => {
-    const { delActions } = this.state
-
-    this.setState({
-      config: config,
-      delActions: delcards ? [...delActions, ...delcards.map(item => item.uuid)] : delActions
-    })
-  }
-
-  render () {
-    const { config, modaltype, activeKey } = this.state
-    let _length = config.groups.length
-
-    let configTabs = []
-    config.tabgroups.forEach(group => {
-      configTabs.push(...group.sublist)
-    })
-
-    return (
-      <div className="form-tab-board">
-        <DndProvider backend={HTML5Backend}>
-          {/* 宸ュ叿鏍� */}
-          <div className="tools">
-            <Collapse accordion defaultActiveKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
-              {/* 鍩烘湰淇℃伅 */}
-              <Panel forceRender={true} header="鍩烘湰淇℃伅" key="0" id="common-basedata">
-                {/* 鑿滃崟淇℃伅 */}
-                <MenuForm
-                  formlist={this.state.menuformlist}
-                  wrappedComponentRef={(inst) => this.menuformRef = inst}
-                />
-              </Panel>
-              {/* 鎼滅储鏉′欢娣诲姞 */}
-              <Panel header="琛ㄥ崟" key="1">
-                <div className="search-element">
-                  {Source.searchItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
-                </div>
-              </Panel>
-              {/* 鎸夐挳娣诲姞 */}
-              <Panel header="鎸夐挳" key="2">
-                <div className="search-element">
-                  {Source.actionItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
-                </div>
-              </Panel>
-              {/* 娣诲姞鏍囩 */}
-              <Panel header="鏍囩椤�" key="4">
-                <div className="search-element">
-                  {Source.tabItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
-                </div>
-                {configTabs.length > 0 ?
-                  <p className="config-btn-title">
-                    <Tooltip placement="topLeft" title="鐐瑰嚮鎸夐挳锛屽彲瀹屾垚鎴栨煡鐪嬫爣绛鹃厤缃俊鎭��">
-                      <QuestionCircleOutlined className="mk-form-tip" />
-                    </Tooltip>
-                    鏍囩閰嶇疆
-                  </p> : null
-                }
-                {configTabs.map((item, index) => {
-                  return (
-                    <div key={index}>
-                      <Button
-                        className="config-button"
-                        icon={item.icon}
-                        style={{marginBottom: '10px'}}
-                        onClick={() => this.setSubConfig(item, 'tab')}
-                      >{item.label}</Button>
-                    </div>
-                  )
-                })}
-              </Panel>
-            </Collapse>
-          </div>
-          <div className="setting">
-            <Card title={
-              <div>
-                椤甸潰閰嶇疆 
-                <RedoOutlined style={{marginLeft: '10px'}} title="鍒锋柊鏍囩鍒楄〃" onClick={this.reloadTab} />
-              </div>
-            } bordered={false} extra={
-              <div>
-                <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={this.state.config.enabled} onChange={this.onEnabledChange} />
-                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>淇濆瓨</Button>
-                <Button onClick={this.cancelConfig}>杩斿洖</Button>
-              </div>
-            } style={{ width: '100%' }}>
-              <SettingOutlined onClick={this.changeSetting} />
-              <Collapse
-                activeKey={config.groups.map(group => group.uuid)}
-                expandIconPosition={'right'}
-              >
-                {config.groups.map((group, index) => (
-                  <Panel showArrow={false} header={group.label} key={group.uuid} extra={(
-                    <span>
-                      {index === _length - 1 ? <PlusOutlined
-                        onClick={() => { this.handleGroup()}}
-                      /> : null}
-                      {_length > 1 && index !== _length - 1 ? <DeleteOutlined
-                        onClick={() => { this.closeGroup(group) }}
-                      /> : null}
-                      <EditOutlined onClick={() => { this.handleGroup(group) }}/>
-                    </span>
-                  )}>
-                    {group.isDefault ? <SnippetsOutlined title="绮樿创" onClick={() => {this.setState({pasteVisible: true})}} /> : null}
-                    <DragElement
-                      type="search"
-                      groupId={group.uuid}
-                      list={group.sublist}
-                      handleList={this.handleList}
-                      setting={config.setting}
-                      handleMenu={this.handleSearch}
-                      deleteMenu={this.deleteElement}
-                    />
-                  </Panel>
-                ))}
-              </Collapse>
-              <div className="action-list">
-                <DragElement
-                  type="action"
-                  list={this.state.config.action}
-                  handleList={this.handleList}
-                  handleMenu={this.handleAction}
-                  deleteMenu={this.deleteElement}
-                  profileMenu={this.profileAction}
-                />
-              </div>
-              {/* 鏍囩缁� */}
-              <TabsComponent
-                config={config}
-                tabs={this.state.tabviews}
-                setSubConfig={(item) => this.setSubConfig(item, 'tab')}
-                updatetabs={this.updatetabs}
-              />
-            </Card>
-          </div>
-        </DndProvider>
-        {/* 缂栬緫琛ㄥ崟 */}
-        <Modal
-          title={this.state.card && this.state.card.iscopy ? '琛ㄥ崟-澶嶅埗' : '琛ㄥ崟-缂栬緫'}
-          visible={modaltype === 'search'}
-          width={950}
-          maskClosable={false}
-          onOk={this.handleSubmit}
-          confirmLoading={this.state.sqlVerifing}
-          onCancel={this.editModalCancel}
-          destroyOnClose
-        >
-          <ModalForm
-            card={this.state.card}
-            formlist={this.state.formlist}
-            inputSubmit={this.handleSubmit}
-            wrappedComponentRef={(inst) => this.modalFormRef = inst}
-          />
-        </Modal>
-        {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
-        <Modal
-          title="鎸夐挳缂栬緫"
-          visible={modaltype === 'actionEdit'}
-          width={920}
-          maskClosable={false}
-          onCancel={this.editModalCancel}
-          footer={[
-            this.state.card && this.state.card.btnType !== 'cancel' ?
-            <CreateFunc key="create" ref="btnCreatFunc" trigger={this.creatFunc}/> : null,
-            <Button key="cancel" onClick={this.editModalCancel}>鍙栨秷</Button>,
-            <Button key="confirm" type="primary" onClick={this.handleSubmit}>纭畾</Button>
-          ]}
-          destroyOnClose
-        >
-          <ActionForm
-            card={this.state.card}
-            tabs={this.state.tabviews}
-            formlist={this.state.formlist}
-            inputSubmit={this.handleSubmit}
-            wrappedComponentRef={(inst) => this.actionFormRef = inst}
-          />
-        </Modal>
-        {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */}
-        <Modal
-          wrapClassName="mk-pop-modal"
-          visible={this.state.profileVisible}
-          width={'90vw'}
-          maskClosable={false}
-          okText="鎻愪氦"
-          onOk={this.verifySubmit}
-          onCancel={() => {
-            if (this.verifyRef.handleCancel) {
-              this.verifyRef.handleCancel().then(() => {
-                this.setState({ profileVisible: false })
-              })
-            } else {
-              this.setState({ profileVisible: false })
-            }
-          }}
-          destroyOnClose
-        >
-          <VerifyCard
-            card={this.state.card}
-            btnTab={this.props.btnTab}
-            config={this.state.config}
-            columns={this.state.columns}
-            wrappedComponentRef={(inst) => this.verifyRef = inst}
-          />
-        </Modal>
-        {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */}
-        <Modal
-          title="缂栬緫"
-          visible={this.state.settingVisible}
-          width={700}
-          maskClosable={false}
-          onCancel={() => { // 鍙栨秷淇敼
-            this.setState({
-              settingVisible: false
-            })
-          }}
-          footer={[
-            <CreateFunc key="create" ref="tableCreatFunc" trigger={this.tableCreatFunc}/>,
-            <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>鍙栨秷</Button>,
-            <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>纭畾</Button>
-          ]}
-          destroyOnClose
-        >
-          <SettingForm
-            menu={this.props.menu}
-            config={this.state.config}
-            inputSubmit={this.settingSave}
-            wrappedComponentRef={(inst) => this.settingRef = inst}
-          />
-        </Modal>
-        <Modal
-          bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
-          closable={false}
-          maskClosable={false}
-          visible={this.state.closeVisible}
-          onCancel={() => { this.setState({closeVisible: false}) }}
-          footer={[
-            <Button key="save" className="mk-btn mk-green" loading={this.state.menucloseloading} onClick={this.submitConfig}>淇濆瓨</Button>,
-            <Button key="confirm" className="mk-btn mk-yellow" onClick={this.handleViewBack}>涓嶄繚瀛�</Button>,
-            <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>鍙栨秷</Button>
-          ]}
-          destroyOnClose
-        >
-          閰嶇疆宸蹭慨鏀癸紝鏄惁淇濆瓨閰嶇疆淇℃伅锛�
-        </Modal>
-        <Modal
-          title="鍒嗙粍绠$悊"
-          visible={this.state.groupVisible}
-          width={700}
-          maskClosable={false}
-          onOk={this.handleGroupSave}
-          onCancel={() => { this.setState({ groupVisible: false }) }}
-          destroyOnClose
-        >
-          <GroupForm
-            groups={config.groups}
-            group={this.state.editgroup}
-            inputSubmit={this.handleGroupSave}
-            wrappedComponentRef={(inst) => this.groupRef = inst}
-          />
-        </Modal>
-        {/* 鎸夐挳閰嶇疆淇℃伅绮樿创澶嶅埗 */}
-        <Modal
-          title="绮樿创"
-          visible={this.state.pasteVisible}
-          width={600}
-          maskClosable={false}
-          onOk={this.pasteSubmit}
-          onCancel={() => {this.setState({pasteVisible: null})}}
-          destroyOnClose
-        >
-          <PasteForm
-            wrappedComponentRef={(inst) => this.pasteFormRef = inst}
-            inputSubmit={this.pasteSubmit}
-          />
-        </Modal>
-        {this.state.loading && <Spin size="large" />}
-      </div>
-    )
-  }
-}
-
-export default ComTableConfig
diff --git a/src/templates/formtabconfig/index.scss b/src/templates/formtabconfig/index.scss
deleted file mode 100644
index cb73f81..0000000
--- a/src/templates/formtabconfig/index.scss
+++ /dev/null
@@ -1,394 +0,0 @@
-.form-tab-board {
-  position: fixed;
-  z-index: 1070;
-  padding-top: 48px;
-  top: 0px;
-  left: 0px;
-  right: 0px;
-  bottom: 0px;
-  background: rgba(0, 0, 0, 0.35);
-  display: flex;
-  .tools {
-    flex: 1;
-    background: #ffffff;
-    border-right: 1px solid #d9d9d9;
-    height: 100%;
-    overflow-y: auto;
-    padding-bottom: 30px;
-    .ant-collapse-borderless {
-      background-color: #ffffff;
-    }
-    .ant-collapse-item {
-      position: relative;
-      border: 0;
-    }
-    .ant-input-search {
-      margin-top: 10px;
-    }
-    .ant-collapse-item.ant-collapse-item-active {
-      border-bottom: 1px solid #d9d9d9;
-    }
-    .ant-collapse .ant-collapse-header {
-      padding: 11px 16px 10px 40px;
-      border-bottom: 1px solid #d9d9d9;
-      background: #1890ff;
-      color: #ffffff;
-    }
-    .ant-collapse-content-box {
-      .ant-form-item {
-        margin-bottom: 10px;
-        .ant-form-item-label {
-          text-align: left;
-          height: 25px;
-          line-height: 25px;
-        }
-      }
-    }
-    .search-element {
-      padding-top: 10px;
-      li {
-        padding: 0px 16px 10px;
-        div {
-          cursor: move;
-        }
-      }
-    }
-    .config-btn-title {
-      margin-top: 20px;
-      margin-bottom: 10px;
-      color: #1890ff;
-      border-bottom: 1px solid #e8e8e8;
-    }
-    .config-button {
-      min-width: 65px;
-    }
-  }
-  .tools::-webkit-scrollbar {
-    width: 4px;
-  }
-  .tools::-webkit-scrollbar-thumb {
-    border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
-    background: rgba(0, 0, 0, 0.08);
-  }
-  .tools::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0.07);
-    background: rgba(0, 0, 0, 0);
-  }
-  .setting {
-    position: relative;
-    width: calc(100vw - 235px);
-    height: 100%;
-    background: #ffffff;
-    .ant-switch.big {
-      min-width: 60px;
-      height: 28px;
-      line-height: 28px;
-      margin-top: -2px;
-      .ant-switch-inner {
-        font-size: 14px;
-      }
-    }
-    .ant-switch.big::after {
-      width: 24px;
-      height: 24px;
-    }
-    .ant-card-head {
-      min-height: 44px;
-    }
-    .ant-card-head-title {
-      padding: 5px 0;
-      color: #1890ff;
-    }
-    .ant-card-extra {
-      padding: 5px 0;
-      button {
-        margin-left: 20px;
-      }
-    }
-    .ant-card-body {
-      position: relative;
-      padding: 0 0 40px;
-
-      > .anticon-setting {
-        position: absolute;
-        font-size: 18px;
-        right: 7px;
-        top: 10px;
-        padding: 10px;
-        z-index: 1;
-      }
-
-      >.ant-collapse {
-        border-radius: 0;
-        border: 0;
-        margin-top: 45px;
-        .ant-collapse-header {
-          cursor: default;
-          border-radius: 0;
-          background: #1890ff;
-          color: #ffffff;
-          padding-left: 30px;
-          padding-right: 20px;
-          .anticon {
-            font-size: 16px;
-          }
-          .ant-collapse-extra {
-            .anticon-edit {
-              position: absolute;
-              left: 5px;
-              top: 2px;
-            }
-          }
-        }
-        .ant-collapse-item:last-child {
-          border-radius: 0;
-          .ant-collapse-content {
-            border-radius: 0;
-          }
-        }
-        .ant-collapse-content-box {
-          position: relative;
-          padding: 16px 30px;
-          > .ant-row {
-            min-height: 90px;
-            padding-bottom: 30px;
-            .page-card {
-              position: relative;
-              background: #ffffff;
-              border-radius: 2px;
-              padding-top: 15px;
-              .ant-form-item {
-                cursor: move;
-                display: flex;
-                margin-bottom: 0px;
-                .ant-form-item-label {
-                  overflow: visible;
-                  label {
-                    width: 100%;
-                    cursor: move;
-                    overflow: hidden;
-                    display: inline-block;
-                    text-overflow: ellipsis;
-                    white-space: nowrap;
-                  }
-                }
-                .ant-form-item-label.ant-col-cuslabel {
-                  width: 11%;
-                }
-                .ant-form-item-control-wrapper.ant-col-cuswrap {
-                  width: 89%;
-                }
-                .ant-form-item-control-wrapper {
-                  position: relative;
-                  .ant-input-number {
-                    margin-top: 4px;
-                  }
-                  .ant-select {
-                    width: 100%;
-                    margin-top: 4px;
-                  }
-                  .ant-calendar-picker {
-                    margin-top: 4px;
-                  }
-                  .ant-btn {
-                    margin-top: 4px;
-                  }
-                  .data-range .ant-calendar-picker-input {
-                    padding: 4px 20px 4px 5px;
-                    font-size: 13px;
-                  }
-                }
-                .ant-form-item-control-wrapper::after {
-                  content: '';
-                  position: absolute;
-                  top: 0;
-                  left: 0;
-                  right: 0;
-                  bottom: 0;
-                  opacity: 0;
-                  z-index: 1;
-                }
-              }
-            }
-            .ant-calendar-picker {
-              min-width: 100px!important;
-              width: 100%;
-            }
-          }
-          .anticon-snippets {
-            position: absolute;
-            font-size: 14px;
-            right: 10px;
-            top: 0px;
-            padding: 10px;
-            z-index: 1;
-          }
-        }
-      }
-      
-      .action-list {
-        position: relative;
-        padding: 0px 20px 15px;
-        min-height: 82px;
-        text-align: center;
-        > .ant-row {
-          min-height: 67px;
-        }
-        .page-card {
-          display: inline-block;
-          padding: 0px;
-          margin: 15px 10px 0 0;
-          position: relative;
-          div {
-            cursor: move;
-          }
-          
-          button {
-            cursor: move;
-            min-width: 70px;
-            margin-right: 10px;
-            height: 35px;
-            font-size: 15px;
-            padding: 5px 20px;
-            .anticon-table {
-              font-size: 10px;
-              position: absolute;
-              right: 1px;
-              bottom: 0px;
-            }
-          }
-        }
-      }
-      .tab-list {
-        position: relative;
-        padding: 30px 20px 0px;
-        .ant-switch {
-          position: absolute;
-          right: 20px;
-          top: 20px;
-        }
-        > .ant-row {
-          min-height: 47px;
-          .page-card {
-            position: relative;
-            padding: 0px;
-            > div {
-              padding: 12px 0px 0px;
-              cursor: move;
-            }
-          }
-          .ant-tabs-tab {
-            cursor: default;
-          }
-          .ant-tabs-bar {
-            min-height: 55px;
-          }
-          .ant-tabs-content {
-            .ant-tabs-tabpane img {
-              width: 100%;
-            }
-          }
-        }
-        > .anticon-plus {
-          position: absolute;
-          font-size: 18px;
-          right: 25px;
-          top: 50px;
-          z-index: 1;
-          color: #26C281;
-          cursor: pointer;
-        }
-        > .anticon-delete {
-          position: absolute;
-          font-size: 19px;
-          right: 25px;
-          top: 50px;
-          z-index: 1;
-          color: #ff4d4f;
-          cursor: pointer;
-        }
-        > .anticon-arrow-up {
-          position: absolute;
-          right: 55px;
-          font-size: 19px;
-          z-index: 1;
-          top: 50px;
-          color: #1890ff;
-          cursor: pointer;
-        }
-        > .anticon-arrow-down {
-          position: absolute;
-          right: 55px;
-          font-size: 19px;
-          z-index: 1;
-          top: 50px;
-          color: purple;
-          cursor: pointer;
-        }
-        > .anticon-arrow-down + .anticon-arrow-up {
-          right: 85px;
-        }
-        .ant-tabs-nav-container-scrolling {
-          margin-right: 50px;
-        }
-      }
-    }
-  }
-  .setting {
-    overflow-y: scroll;
-  }
-  .setting::-webkit-scrollbar {
-    width: 7px;
-  }
-  .setting::-webkit-scrollbar-thumb {
-    border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-    display: none;
-  }
-  .setting::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0.07);
-    background: rgba(0, 0, 0, 0);
-  }
-  .setting:hover::-webkit-scrollbar-thumb {
-    display: block;
-  }
-  .ant-spin {
-    position: absolute;
-    margin-left: calc(50vw - 22px);
-    margin-top: 30vh;
-  }
-}
-
-.common-table-fields-modal {
-  .ant-modal {
-    top: 50px;
-    padding-bottom: 5px;
-    .ant-modal-body {
-      max-height: calc(100vh - 190px);
-      overflow-y: auto;
-      .ant-empty {
-        margin: 15vh 8px;
-      }
-    }
-    .ant-modal-body::-webkit-scrollbar {
-      width: 7px;
-    }
-    .ant-modal-body::-webkit-scrollbar-thumb {
-      border-radius: 5px;
-      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-      background: rgba(0, 0, 0, 0.13);
-    }
-    .ant-modal-body::-webkit-scrollbar-track {
-      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-      border-radius: 3px;
-      border: 1px solid rgba(0, 0, 0, 0.07);
-      background: rgba(0, 0, 0, 0);
-    }
-  }
-}
diff --git a/src/templates/formtabconfig/settingform/index.jsx b/src/templates/formtabconfig/settingform/index.jsx
deleted file mode 100644
index 7330244..0000000
--- a/src/templates/formtabconfig/settingform/index.jsx
+++ /dev/null
@@ -1,361 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Radio, Select, Tooltip, notification, InputNumber } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-
-import { formRule } from '@/utils/option.js'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const { TextArea } = Input
-
-class SettingForm extends Component {
-  static propTpyes = {
-    menu: PropTypes.object,
-    config: PropTypes.object,
-    inputSubmit: PropTypes.any     // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    interType: (this.props.config.setting && this.props.config.setting.interType) || 'inner',
-    columns: null,
-    usefulFields: [],
-    interReadonly: false,
-  }
-
-  UNSAFE_componentWillMount() {
-    const { config } = this.props
-
-    let _columns = []
-    let _setting = config.setting
-    
-    try {
-      config.groups.forEach(group => {
-        let list = group.sublist.filter(item => item.field)
-        _columns = [..._columns, ...list]
-      })
-
-      let _colMap = new Map()
-      _columns = _columns.filter(item => {
-        if (_colMap.has(item.field)) {
-          return false
-        } else {
-          _colMap.set(item.field, true)
-          return true
-        }
-      })
-    } catch (e) {
-      notification.warning({
-        top: 92,
-        message: '鑿滃崟淇℃伅閿欒锛�',
-        duration: 5
-      })
-    }
-
-    let usefulFields = sessionStorage.getItem('permFuncField')
-    if (usefulFields) {
-      try {
-        usefulFields = JSON.parse(usefulFields)
-      } catch (e) {
-        usefulFields = []
-      }
-    } else {
-      usefulFields = []
-    }
-
-    this.setState({
-      columns: _columns,
-      setting: _setting,
-      interType: _setting.interType || 'inner',
-      interReadonly: _setting.sysInterface === 'true',
-      datatype: _setting.datatype || 'maintable',
-      usefulFields
-    })
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          let error = Utils.verifySql(values.dataresource)
-
-          if (error) {
-            notification.warning({
-              top: 92,
-              message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error,
-              duration: 5
-            })
-            return
-          }
-
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  onSysChange = (e) => {
-    if (e.target.value === 'true') {
-      this.props.form.setFieldsValue({
-        interface: window.GLOB.mainSystemApi || ''
-      })
-      this.setState({
-        interReadonly: true
-      })
-    } else {
-      this.setState({
-        interReadonly: false
-      })
-    }
-  }
-
-  onChange = (e) => {
-    this.setState({
-      interType: e.target.value
-    }, () => {
-      if (e.target.value === 'inner') return
-
-      let _type = this.props.form.getFieldValue('sysInterface')
-      if (_type === 'true') {
-        this.props.form.setFieldsValue({
-          interface: window.GLOB.mainSystemApi || ''
-        })
-        this.setState({
-          interReadonly: true
-        })
-      } else {
-        this.setState({
-          interReadonly: false
-        })
-      }
-    })
-  }
-
-  sourceChange = (e) => {
-    const { interType } = this.state
-
-    this.setState({
-      datatype: e.target.value
-    }, () => {
-      if (interType === 'inner') return
-
-      let _type = this.props.form.getFieldValue('sysInterface')
-      if (_type === 'true') {
-        this.props.form.setFieldsValue({
-          interface: window.GLOB.mainSystemApi || ''
-        })
-        this.setState({
-          interReadonly: true
-        })
-      } else {
-        this.setState({
-          interReadonly: false
-        })
-      }
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  render() {
-    const { menu } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { interType, setting, datatype, usefulFields } = this.state
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    let str = '^(' + usefulFields.join('|') + ')'
-    let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
-
-    return (
-      <Form {...formItemLayout} className="ant-advanced-search-form commontable-setting-form" id="commontable-setting-form">
-        <Row gutter={24}>
-          <Col span={12}>
-            <Form.Item label="琛ㄥ悕">
-              {getFieldDecorator('tableName', {
-                initialValue: setting.tableName,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ヨ〃鍚�!'
-                  },
-                  {
-                    max: 50,
-                    message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!'
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="鍒楁暟">
-              {getFieldDecorator('cols', {
-                initialValue: setting.cols || '2'
-              })(
-                <Select>
-                  <Select.Option value="1">1鍒�</Select.Option>
-                  <Select.Option value="2">2鍒�</Select.Option>
-                  <Select.Option value="3">3鍒�</Select.Option>
-                  <Select.Option value="4">4鍒�</Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="鏁版嵁鏉ユ簮">
-              {getFieldDecorator('datatype', {
-                initialValue: setting.datatype || 'query'
-              })(
-                <Radio.Group onChange={this.sourceChange}>
-                  <Radio value="maintable">涓昏〃</Radio>
-                  <Radio value="query">鏌ヨ</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="涓婚敭">
-              {getFieldDecorator('primaryKey', {
-                initialValue: setting.primaryKey
-              })(<Input placeholder="" autoComplete="off" disabled/>)}
-            </Form.Item>
-          </Col>
-          {datatype === 'query' ? <Col span={12}>
-            <Form.Item label="鎺ュ彛绫诲瀷">
-              {getFieldDecorator('interType', {
-                initialValue: interType
-              })(
-                <Radio.Group onChange={this.onChange}>
-                  <Radio value="inner">鍐呴儴</Radio>
-                  <Radio value="outer">澶栭儴</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          {datatype === 'query' && interType === 'outer' ? <Col span={12}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鍗曠偣鐧诲綍绯荤粺">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                绯荤粺鎺ュ彛
-              </Tooltip>
-            }>
-              {getFieldDecorator('sysInterface', {
-                initialValue: setting.sysInterface || 'false'
-              })(
-                <Radio.Group onChange={this.onSysChange}>
-                  <Radio value="true">鏄�</Radio>
-                  <Radio value="false">鍚�</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          {datatype === 'query' && interType === 'outer' ? <Col span={12}>
-            <Form.Item label="鎺ュ彛鍦板潃">
-              {getFieldDecorator('interface', {
-                initialValue: setting.sysInterface === 'true' ? (window.GLOB.mainSystemApi || '') : (setting.interface || ''),
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ユ帴鍙e湴鍧�!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={this.state.interReadonly} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {datatype === 'query' && interType !== 'outer' ? <Col span={12}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" overlayClassName="middle" title={`鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠�${usefulFields.join(', ')}绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愩�俙}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鍐呴儴鍑芥暟
-              </Tooltip>
-            }>
-              {getFieldDecorator('innerFunc', {
-                initialValue: setting.innerFunc || '',
-                rules: [
-                  {
-                    pattern: _patten,
-                    message: formRule.func.innerMessage
-                  }, {
-                    max: formRule.func.max,
-                    message: formRule.func.maxMessage
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {datatype === 'query' && interType !== 'outer' ? <Col span={24}>
-            <Form.Item help={'鏁版嵁ID锛�' + menu.MenuID} label={
-              <Tooltip placement="topLeft" title="浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愶紝鑷畾涔夊嚱鏁版椂锛屽彲蹇界暐銆�">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鏁版嵁婧�
-              </Tooltip>
-            } className="textarea">
-              {getFieldDecorator('dataresource', {
-                initialValue: setting.dataresource
-              })(<TextArea rows={4} />)}
-            </Form.Item>
-          </Col> : null}
-          {datatype === 'query' && interType === 'outer' ? <Col span={12}>
-            <Form.Item label="澶栭儴鍑芥暟">
-              {getFieldDecorator('outerFunc', {
-                initialValue: setting.outerFunc || '',
-                rules: [
-                  {
-                    pattern: formRule.func.pattern,
-                    message: formRule.func.message
-                  }, {
-                    max: formRule.func.max,
-                    message: formRule.func.maxMessage
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          <Col span={12}>
-            <Form.Item label="瀹藉害">
-              {getFieldDecorator('width', {
-                initialValue: setting.width || 100
-              })(<InputNumber min={10} max={100} precision={0} />)}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="鍒濆鍖�">
-              {getFieldDecorator('onload', {
-                initialValue: setting.onload || 'true'
-              })(
-                <Select>
-                  <Select.Option value="true">鍔犺浇鏁版嵁</Select.Option>
-                  <Select.Option value="false">涓嶅姞杞芥暟鎹�</Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/templates/formtabconfig/settingform/index.scss b/src/templates/formtabconfig/settingform/index.scss
deleted file mode 100644
index bf9fa12..0000000
--- a/src/templates/formtabconfig/settingform/index.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-.ant-advanced-search-form.commontable-setting-form {
-  .textarea {
-    .ant-form-item-label {
-      width: 16.3%;
-    }
-    .ant-form-item-control-wrapper {
-      width: 83.33333333%;
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/templates/formtabconfig/source.jsx b/src/templates/formtabconfig/source.jsx
deleted file mode 100644
index 57eeafd..0000000
--- a/src/templates/formtabconfig/source.jsx
+++ /dev/null
@@ -1,184 +0,0 @@
-import Utils from '@/utils/utils.js'
-
-class CommonTableBaseData {
-  baseConfig = {
-    Template: 'FormTab',
-    enabled: false,
-    setting: {
-      datatype: 'query',
-      cols: '2',
-      width: 90
-    },
-    tables: [],
-    groups: [
-      {
-        isDefault: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        sort: 101,
-        sublist: [
-          {
-            origin: true,
-            uuid: Utils.getuuid(),
-            label: 'label',
-            field: '',
-            initval: '',
-            type: 'text',
-            resourceType: '0',
-            options: [],
-            orderType: 'asc'
-          }, {
-            origin: true,
-            uuid: Utils.getuuid(),
-            label: 'label',
-            field: '',
-            initval: '',
-            type: 'select',
-            resourceType: '0',
-            options: [],
-            orderType: 'asc'
-          }, {
-            origin: true,
-            uuid: Utils.getuuid(),
-            label: 'label',
-            field: '',
-            initval: '',
-            type: 'date',
-            resourceType: '0',
-            options: [],
-            orderType: 'asc'
-          }
-        ]
-      }
-    ],
-    action: [
-      {
-        btnType: 'confirm',
-        uuid: Utils.getuuid(),
-        label: '纭畾',
-        intertype: 'system',
-        innerFunc: '',
-        interface: '',
-        outerFunc: '',
-        sql: '',
-        sqlType: '',
-        callbackFunc: '',
-        Ot: 'notRequired',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'exec',
-        icon: '',
-        class: 'border-primary',
-        verify: null
-      }, {
-        btnType: 'cancel',
-        uuid: Utils.getuuid(),
-        label: '鍏抽棴',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'exec',
-        pageTemplate: '',
-        url: '',
-        icon: '',
-        class: 'border-danger'
-      }
-    ],
-    tabgroups: [{
-      uuid: 'tabs',
-      sublist: [
-        {
-          origin: true,          // 鏄惁涓虹ず渚�
-          uuid: Utils.getuuid(),
-          label: 'tab1',
-          type: 'SubTable',
-          linkTab: '',
-          supMenu: ''
-        },
-        {
-          origin: true,
-          uuid: Utils.getuuid(),
-          label: 'tab2',
-          type: 'SubTable',
-          linkTab: '',
-          supMenu: ''
-        }
-      ]
-    }]
-  }
-
-  searchItems = [
-    {
-      type: 'search',
-      label: '鏂囨湰',
-      subType: 'text',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏁板瓧',
-      subType: 'number',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '涓嬫媺閫夋嫨',
-      subType: 'select',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏂囦欢涓婁紶',
-      subType: 'fileupload',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃堕棿锛堝ぉ锛�',
-      subType: 'date',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃堕棿锛堟湀锛�',
-      subType: 'datemonth',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '鏃堕棿锛堢锛�',
-      subType: 'datetime',
-      url: ''
-    },
-    {
-      type: 'search',
-      label: '澶氳鏂囨湰',
-      subType: 'textarea',
-      url: ''
-    }
-  ]
-
-  actionItems = [
-    {
-      type: 'action',
-      label: '鎻愮ず妗�',
-      subType: 'prompt',
-      url: ''
-    },
-    {
-      type: 'action',
-      label: '鐩存帴鎵ц',
-      subType: 'exec',
-      url: ''
-    }
-  ]
-
-  tabItems = [
-    {
-      type: 'tabs',
-      label: '瀛愯〃',
-      subType: 'SubTable',
-    }
-  ]
-}
-
-export default new CommonTableBaseData()
diff --git a/src/templates/formtabconfig/transferform/index.jsx b/src/templates/formtabconfig/transferform/index.jsx
deleted file mode 100644
index 3ff7f65..0000000
--- a/src/templates/formtabconfig/transferform/index.jsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Transfer } from 'antd'
-import './index.scss'
-
-class TransferForm extends Component {
-  static propTypes = {
-    fields: PropTypes.array,
-    selected: PropTypes.array
-  }
-
-  state = {
-    data: [],
-    targetKeys: [],
-    selectedKeys: []
-  }
-
-  handleChange = (nextTargetKeys, direction, moveKeys) => {
-    this.setState({ targetKeys: nextTargetKeys })
-  }
-
-  handleSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
-    this.setState({ selectedKeys: [...sourceSelectedKeys, ...targetSelectedKeys] })
-  }
-  
-  UNSAFE_componentWillMount() {
-    let datas = new Map()
-    this.props.fields.forEach(item => {
-      if (!item.origin) {
-        datas.set(item.uuid, item)
-      }
-    })
-
-    let selecteds = []
-
-    this.props.selected.forEach(item => {
-      if (datas.has(item)) {
-        selecteds.push(item)
-      }
-    })
-
-    this.setState({
-      data: [...datas.values()].map(item => {
-        return {
-          key: item.uuid,
-          title: item.label,
-          description: ''
-        }
-      }),
-      targetKeys: selecteds
-    })
-  }
-
-  render() {
-    const { data, targetKeys, selectedKeys } = this.state
-
-    return (
-      <div className="modal-fields-transfer">
-        <Transfer
-          dataSource={data}
-          targetKeys={targetKeys}
-          selectedKeys={selectedKeys}
-          onChange={this.handleChange}
-          onSelectChange={this.handleSelectChange}
-          render={item => item.title}
-        />
-      </div>
-    )
-  }
-}
-
-export default TransferForm
diff --git a/src/templates/formtabconfig/transferform/index.scss b/src/templates/formtabconfig/transferform/index.scss
deleted file mode 100644
index fcb7ff4..0000000
--- a/src/templates/formtabconfig/transferform/index.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-.modal-fields-transfer {
-  padding-left: 18px;
-  .ant-transfer-list {
-    width: 296px;
-  }
-}
\ No newline at end of file
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index 5291743..0ce29b4 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -245,23 +245,22 @@
     let _linkableFields = []
     let _linksupFields = []
     let standardform = null
-
-    let uniq = new Map()
     let index = null
-    uniq.set(card.field, true)
 
     config.fields.forEach((item, i) => {
       if (card.uuid === item.uuid) {
         index = i
       }
 
-      if (['text', 'number', 'textarea', 'color'].includes(item.type) && card.field !== item.field) {
+      if (!item.field || card.field === item.field) return
+
+      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
         _inputfields.push({
           field: item.field,
           label: item.label
         })
       }
-      if (card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
+      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
         _tabfields.push({
           field: item.field,
           label: item.label
@@ -275,20 +274,19 @@
         })
       }
 
-      if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return
-      if (item.type === 'checkcard' && item.multiple === 'true') return // 閫夐」鍗″閫�
-      if (item.field && !uniq.has(item.field)) {
-        uniq.set(item.field, true)
+      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
 
-        _linkableFields.push({
-          field: item.field,
-          label: item.label + '-琛ㄥ崟'
-        })
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
+      _linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+
+      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
+
+      _linkableFields.push({
+        field: item.field,
+        label: item.label + '-琛ㄥ崟'
+      })
     })
 
     if (index !== null) {
@@ -299,11 +297,10 @@
       }
     }
 
+    let _fields = _linkableFields.map(cell => cell.field)
     if (subTabConfig) {
       subTabConfig.columns.forEach(col => {
-        if (col.field && !uniq.has(col.field)) {
-          uniq.set(col.field, true)
-
+        if (col.field && !_fields.includes(col.field)) {
           _linkableFields.push({
             field: col.field,
             label: col.label + '-鏄剧ず鍒�'
@@ -312,9 +309,7 @@
       })
     } else if (tabConfig) {
       tabConfig.columns.forEach(col => {
-        if (col.field && !uniq.has(col.field)) {
-          uniq.set(col.field, true)
-
+        if (col.field && !_fields.includes(col.field)) {
           _linkableFields.push({
             field: col.field,
             label: col.label + '-鏄剧ず鍒�'
@@ -323,9 +318,7 @@
       })
     } else if (menu.LongParam) {
       menu.LongParam.columns.forEach(col => {
-        if (col.field && !uniq.has(col.field)) {
-          uniq.set(col.field, true)
-
+        if (col.field && !_fields.includes(col.field)) {
           _linkableFields.push({
             field: col.field,
             label: col.label + '-鏄剧ず鍒�'
@@ -515,7 +508,7 @@
       })
     }
 
-    Api.getSystemConfig(param).then(response => {
+    Api.getCloudConfig(param).then(response => {
       if (response.status) {
         this.setState({
           openEdition: response.open_edition || '',
@@ -662,7 +655,7 @@
       MenuID: editAction.uuid
     }
 
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       if (res.status) {
         let _config = ''
         if (res.LongParam) {
diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
index 0661538..227e56b 100644
--- a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Typography } from 'antd'
+import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import { formRule } from '@/utils/option.js'
@@ -12,7 +12,6 @@
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
 
 const { TextArea } = Input
-const { Paragraph } = Typography
 const actionTypeOptions = {
   pop: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'openmenu', 'output', 'tipTitle', 'hidden'],
   prompt: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'openmenu', 'output', 'tipTitle', 'hidden'],
@@ -665,15 +664,6 @@
       )
     })
 
-    if (window.debugger && this.props.card.uuid) {
-      fields.push(
-        <Col span={12} key="uuid">
-          <Form.Item label="鎸夐挳ID">
-            <Paragraph copyable>{this.props.card.uuid}</Paragraph>
-          </Form.Item>
-        </Col>
-      )
-    }
     return fields
   }
 
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index b871c62..8f66baa 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -5,14 +5,11 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import Utils, { FuncUtils } from '@/utils/utils.js'
+import Utils from '@/utils/utils.js'
 import { getActionForm } from '@/templates/zshare/formconfig'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 
 import ActionForm from './actionform'
-import CreateFunc from '@/templates/zshare/createfunc'
-import CreateInterface from '@/templates/zshare/createinterface'
-import { updateForm } from '@/utils/utils-update.js'
 import DragElement from './dragaction'
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
@@ -101,7 +98,7 @@
 
     param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
 
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       if (res.status) {
         let temps = res.data.map(temp => {
           return {
@@ -219,8 +216,7 @@
    * 4銆佷笅鎷夎彍鍗曟暟鎹簮璇硶楠岃瘉
    */
   handleSubmit = () => {
-    const { config, menu } = this.props
-    const { card } = this.state
+    const { config } = this.props
     let _actionlist = fromJS(this.state.actionlist).toJS()
 
     this.actionFormRef.handleConfirm().then(btn => {
@@ -248,373 +244,34 @@
         return
       }
 
-      this.setState({
-        copying: true
-      })
-
       let copyActionId = '' // 鎸夐挳涓哄鍒舵椂锛岃褰曞綋鍓嶆寜閽殑Id锛岃彍鍗曞彇娑堜繚瀛樻椂锛屽垹闄ゅ鍒舵寜閽厤缃俊鎭�
 
-      /**
-       * @description 鎸夐挳淇濆瓨鏍¢獙
-       * 1銆佹鏌ユ寜閽槸鍚︿负琛ㄥ崟鎴栬〃鍗曟爣绛鹃〉锛屽鍓嶅悗涓�鑷达紝鍒欏鍒跺叾鍐呭
-       * 2銆佹鏌ユ寜閽槸鍚︿负鏍囩椤碉紝濡傚墠鍚庝竴鑷达紝鍒欏鍒舵爣绛鹃〉
-       */
-      new Promise(resolve => {
-        if (
-          !card.originCard ||
-          (btn.OpenType !== card.originCard.OpenType) ||
-          (btn.OpenType === 'tab' && btn.tabTemplate !== 'FormTab') ||
-          (btn.OpenType === 'funcbutton' && btn.execMode !== 'pop')
-        ) { // 鎸夐挳涓嶆槸澶嶅埗锛屾垨鎸夐挳鍓嶅悗绫诲瀷涓嶄竴鑷存椂锛岀洿鎺ヤ繚瀛�
-          resolve('save')
-        } else if (btn.OpenType === 'pop' || btn.OpenType === 'tab' || btn.execMode === 'pop') {
-          resolve('subconf')
-        } else if (btn.OpenType === 'popview') {
-          resolve('subtab')
-        } else {
-          resolve('save')
-        }
-      }).then(result => { // 鏌ヨ鍘熸寜閽厤缃俊鎭�
-        if (result === 'save' || result === 'subtab') return result
+      // 鍒ゆ柇鏄惁瀛樺湪鎿嶄綔鍒�
+      let _hasGridbtn = _actionlist.filter(act => act.position === 'grid').length > 0
+      let _gridBtn = config.gridBtn ? fromJS(config.gridBtn).toJS() : null
 
-        return Api.getSystemConfig({
-          func: 'sPC_Get_LongParam',
-          MenuID: card.originCard.uuid,
-          appkey: card.originCard.appkey || ''
-        })
-      }).then(result => { // 澶嶅埗鎸夐挳閰嶇疆淇℃伅锛屼繚瀛樿嚦鏂版坊鍔犳寜閽�
-        if (result === 'save' || result === 'subtab') return result
-
-        if (result.status && result.LongParam) {
-          let _LongParam = ''
-
-          // 瑙f瀽閰嶇疆
-          if (result.LongParam) {
-            try {
-              _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-            } catch (e) {
-              console.warn('Parse Failure')
-              _LongParam = ''
-            }
-          }
-
-          if (!_LongParam) return 'save'
-
-          let _temp = '' // 閰嶇疆淇℃伅绫诲瀷
-
-          // 淇敼妯℃�佹鏍囬鍚嶇О
-          if ((btn.OpenType === 'pop' || btn.execMode === 'pop') && _LongParam.type === 'Modal') {
-            try {
-              _LongParam.setting.title = btn.label
-              _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam)))
-              _temp = 'Modal'
-            } catch (e) {
-              console.warn('Stringify Failure')
-              _temp = ''
-            }
-          } else if (btn.OpenType === 'tab' && _LongParam.type === 'FormTab') {
-            try {
-              _LongParam.action = _LongParam.action.map(_btn => {
-                _btn.uuid = Utils.getuuid()
-
-                return _btn
-              })
-              _LongParam.tabgroups.forEach(_groupId => {
-                _LongParam[_groupId] = _LongParam[_groupId].map(_tab => {
-                  _tab.uuid = Utils.getuuid()
-
-                  return _tab
-                })
-              })
-              _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam)))
-              _temp = 'FormTab'
-            } catch (e) {
-              console.warn('Stringify Failure')
-              _temp = ''
-            }
-          }
-
-          if (!_temp) return 'save'
-
-          let param = {
-            func: 'sPC_ButtonParam_AddUpt',
-            ParentID: menu.MenuID,
-            MenuID: btn.uuid,
-            MenuNo: menu.MenuNo,
-            Template: _temp,
-            MenuName: btn.label,
-            PageParam: JSON.stringify({Template: _temp}),
-            LongParam: _LongParam
-          }
-
-          return Api.getSystemConfig(param)
-        } else {
-          if (!result.status) {
-            notification.warning({
-              top: 92,
-              message: result.message,
-              duration: 5
-            })
-          }
-          return 'save'
-        }
-      }).then(result => {
-        if (result === 'save' || result === 'subtab') return result
-
-        if (!result.status) {
-          notification.warning({
-            top: 92,
-            message: result.message,
-            duration: 5
-          })
-        } else {
-          copyActionId = btn.uuid
-        }
-
-        return 'save'
-      }).then(result => { // 鏌ヨ鍘熸寜閽叧鑱旀爣绛句俊鎭�
-        if (result === 'save') return result
-
-        return Api.getSystemConfig({
-          func: 'sPC_Get_LongParam',
-          MenuID: card.originCard.linkTab,
-          appkey: card.originCard.appkey || ''
-        })
-      }).then(result => { // 鏍囩澶嶅埗
-        if (result === 'save') return result
-
-        let _LongParam = '' // 鏍囩閰嶇疆淇℃伅
-
-        if (!result.status) {
-          notification.warning({
-            top: 92,
-            message: result.message,
-            duration: 5
-          })
-        } else if (result.LongParam) {
-          // 瑙f瀽鏍囩閰嶇疆
-          try {
-            _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-          } catch (e) {
-            console.warn('Parse Failure')
-            _LongParam = ''
-          }
-        }
-
-        if (!_LongParam) {
-          return 'save'
-        } else {
-          copyActionId = btn.linkTab
-
-          return new Promise(resolve => {
-            this.copytab(btn, _LongParam, resolve)
-          })
-        }
-      }).then(() => {
-        // 鍒ゆ柇鏄惁瀛樺湪鎿嶄綔鍒�
-        let _hasGridbtn = _actionlist.filter(act => act.position === 'grid').length > 0
-        let _gridBtn = config.gridBtn ? fromJS(config.gridBtn).toJS() : null
-
-        if (_gridBtn) {
-          _gridBtn.display = _hasGridbtn
-        } else {
-          _gridBtn = {
-            display: _hasGridbtn,
-            Align: 'center',
-            IsSort: 'false',
-            uuid: Utils.getuuid(),
-            label: '鎿嶄綔',
-            type: 'action',
-            style: 'button',
-            show: 'horizontal',
-            Width: 120
-          }
-        }
-
-        this.setState({
-          actionlist: _actionlist,
-          copying: false,
-          visible: false
-        }, () => {
-          this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, copyActionId)
-        })
-      })
-    })
-  }
-
-  /**
-   * @description 鏍囩澶嶅埗
-   * 1銆佷繚瀛樻寜閽叧鑱旂殑鏂版爣绛�
-   * 2銆佷繚瀛樻爣绛炬寜閽俊鎭�
-   * 3銆佷繚瀛樻柊鏍囩涓寜閽殑瀛愰厤缃俊鎭�
-   */
-  copytab = (btn, _tab, _resolve) => {
-    let _LongParam = ''
-
-    _tab.uuid = btn.linkTab
-    _tab.tabName = _tab.tabName + moment().format('YYYY-MM-DD HH:mm:ss')
-    _tab.tabNo = _tab.tabNo + moment().format('YYYY-MM-DD HH:mm:ss')
-
-    let param = {
-      func: 'sPC_Tab_AddUpt',
-      MenuID: _tab.uuid,
-      MenuNo: _tab.tabNo,
-      Template: _tab.Template,
-      MenuName: _tab.tabName,
-      Remark: _tab.Remark,
-      PageParam: JSON.stringify({Template: _tab.Template}),
-      Sort: 0
-    }
-
-    let _oriActions = []
-
-    let btnParam = {
-      func: 'sPC_Button_AddUpt',
-      Type: 40,
-      ParentID: _tab.uuid,
-      MenuNo: _tab.tabNo,
-      Template: _tab.Template,
-      PageParam: '',
-      LongParam: '',
-      LText: ''
-    }
-
-    try {
-      let _linkchange = {}
-      btnParam.LText = []
-
-      _tab.action = _tab.action.map((item, index) => {
-        let uuid = Utils.getuuid()
-
-        if (item.OpenType === 'pop' || item.execMode === 'pop') {
-          _oriActions.push({
-            prebtn: JSON.parse(JSON.stringify(item)),
-            curuuid: uuid,
-            Template: 'Modal'
-          })
-        } else if (item.OpenType === 'popview') {
-          _linkchange[item.linkTab] = Utils.getuuid()
-
-          item.linkTab = _linkchange[item.linkTab]
-        }
-
-        item.uuid = uuid
-
-        btnParam.LText.push(`select '${item.uuid}' as menuid, '${item.label}' as menuname, '${(index + 1) * 10}' as Sort`)
-
-        return item
-      })
-
-      if (_tab.funcs && _tab.funcs.length > 0) {
-        _tab.funcs = _tab.funcs.map(item => {
-          if (item.type === 'tab') {
-            item.linkTab = _linkchange[item.linkTab]
-            item.menuNo = ''
-            item.subfuncs = []
-          }
-
-          return item
-        })
-      }
-
-      btnParam.LText = btnParam.LText.join(' union all ')
-      btnParam.LText = Utils.formatOptions(btnParam.LText)
-      btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
-
-      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_tab)))
-    } catch (e) {
-      console.warn('Stringify Failure')
-      _LongParam = ''
-      _resolve('save')
-      return
-    }
-
-    param.LongParam = _LongParam
-
-    new Promise(resolve => {
-      Api.getSystemConfig(param).then(response => {
-        if (response.status) {
-          resolve(true)
-        } else {
-          notification.warning({
-            top: 92,
-            message: response.message,
-            duration: 5
-          })
-          resolve(false)
-        }
-      })
-    }).then(result => {
-      if (!result) return result
-      if (!btnParam.LText) return true
-
-      return Api.getSystemConfig(btnParam)
-    }).then(result => {
-      if (result === false || result === true) return result
-
-      if (result.status) {
-        return true
+      if (_gridBtn) {
+        _gridBtn.display = _hasGridbtn
       } else {
-        notification.warning({
-          top: 92,
-          message: result.message,
-          duration: 5
-        })
-        return false
+        _gridBtn = {
+          display: _hasGridbtn,
+          Align: 'center',
+          IsSort: 'false',
+          uuid: Utils.getuuid(),
+          label: '鎿嶄綔',
+          type: 'action',
+          style: 'button',
+          show: 'horizontal',
+          Width: 120
+        }
       }
-    }).then(result => {
-      if (!result) return result
-      if (_oriActions.length === 0) return true
 
-      let deffers = _oriActions.map(item => {
-        return new Promise(resolve => {
-          Api.getSystemConfig({
-            func: 'sPC_Get_LongParam',
-            MenuID: item.prebtn.uuid
-          }).then(response => {
-            if (!response.status || !response.LongParam) {
-              resolve(response)
-            } else {
-              let _param = {
-                func: 'sPC_ButtonParam_AddUpt',
-                ParentID: _tab.uuid,
-                MenuID: item.curuuid,
-                MenuNo: _tab.tabNo,
-                Template: item.Template,
-                MenuName: item.prebtn.label,
-                PageParam: JSON.stringify({Template: item.Template}),
-                LongParam: response.LongParam
-              }
-              Api.getSystemConfig(_param).then(resp => {
-                resolve(resp)
-              })
-            }
-          })
-        })
+      this.setState({
+        actionlist: _actionlist,
+        visible: false
+      }, () => {
+        this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, copyActionId)
       })
-
-      return Promise.all(deffers)
-    }).then(result => {
-      let error = ''
-
-      if (typeof(result) === 'object') {
-        result.forEach(resul => {
-          if (!resul.status && !error) {
-            error = resul
-          }
-        })
-      }
-      
-      if (error) {
-        notification.warning({
-          top: 92,
-          message: error.message,
-          duration: 5
-        })
-      }
-
-      _resolve('save')
     })
   }
 
@@ -705,126 +362,6 @@
   }
 
   /**
-   * @description 鍒涘缓鎸夐挳瀛樺偍杩囩▼
-   */
-  creatFunc = () => {
-    const { menu } = this.props
-    let _config = fromJS(this.props.config).toJS()
-
-    this.actionFormRef.handleConfirm().then(res => {
-      let btn = res         // 鎸夐挳淇℃伅
-      let newLText = ''     // 鍒涘缓瀛樺偍杩囩▼sql
-      let DelText = ''      // 鍒犻櫎瀛樺偍杩囩▼sql
-
-      // 鍒涘缓瀛樺偍杩囩▼锛屽繀椤诲~鍐欏唴閮ㄥ嚱鏁板悕
-      if (btn.intertype !== 'inner') {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤鍐呴儴鍑芥暟鏃讹紝鎵嶅彲浠ュ垱寤哄瓨鍌ㄨ繃绋嬶紒',
-          duration: 5
-        })
-        return
-      }
-
-      new Promise(resolve => {
-        // 寮圭獥锛堣〃鍗曪級绫绘寜閽紝鍏堣幏鍙栨寜閽厤缃俊鎭紝濡傛灉灏氭湭閰嶇疆鎸夐挳鍒欎細鎶ラ敊骞剁粓姝€��
-        // 鑾峰彇淇℃伅鍚庣敓鎴愬垹闄ゅ拰鍒涘缓瀛樺偍杩囩▼鐨勮鍙�
-        if (btn.OpenType === 'pop') {
-          Api.getSystemConfig({
-            func: 'sPC_Get_LongParam',
-            MenuID: btn.uuid
-          }).then(res => {
-            let _LongParam = ''
-            if (res.status && res.LongParam) {
-              try {
-                _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
-              } catch (e) {
-                console.warn('Parse Failure')
-                _LongParam = ''
-              }
-            }
-
-            if (_LongParam) {
-              _LongParam = updateForm(_LongParam)
-
-              let _param = {
-                funcName: btn.innerFunc,
-                name: _config.setting.tableName || '',
-                fields: _LongParam.fields,
-                menuNo: menu.MenuNo
-              }
-              newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config))
-              DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-              resolve(true)
-            } else {
-              notification.warning({
-                top: 92,
-                message: '寮圭獥锛堣〃鍗曪級鎸夐挳锛岃鍏堥厤缃〃鍗曚俊鎭紒',
-                duration: 5
-              })
-              resolve(false)
-            }
-          })
-        } else if (btn.OpenType === 'excelIn') {
-          if (btn.verify && btn.verify.sheet && btn.verify.columns && btn.verify.columns.length > 0) {
-            let _param = {
-              funcName: btn.innerFunc,
-              menuNo: menu.MenuNo
-            }
-            newLText = Utils.formatOptions(FuncUtils.getexcelInfunc(_param, btn, menu))
-            DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-            resolve(true)
-          } else {
-            notification.warning({
-              top: 92,
-              message: '璇峰畬鍠勫鍏xcel楠岃瘉淇℃伅锛�',
-              duration: 5
-            })
-            resolve(false)
-          }
-        } else if (btn.OpenType === 'excelOut') {
-          newLText = Utils.formatOptions(FuncUtils.getTableFunc(btn.innerFunc, menu, _config)) // 鍒涘缓瀛樺偍杩囩▼sql
-          DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-
-          resolve(true)
-        } else {
-          let _param = {
-            funcName: btn.innerFunc,
-            name: _config.setting.tableName || '',
-            fields: '',
-            menuNo: menu.MenuNo
-          }
-          newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config))
-          DelText = Utils.formatOptions(FuncUtils.dropfunc(btn.innerFunc))
-          resolve(true)
-        }
-      }).then(res => {
-        if (!res) return
-
-        this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText)
-      })
-    })
-  }
-
-  /**
-   * @description 鍒涘缓鎸夐挳鎺ュ彛锛堝啓鍏ワ級
-   */
-  btnCreatInterface = () => {
-    const { config, type, menu } = this.props
-
-    this.actionFormRef.handleConfirm().then(result => {
-      let _menu = {
-        type: type,
-        MenuID: menu.MenuID,
-        menuName: menu.MenuName,
-        menuNo: menu.MenuNo
-      }
-      
-      this.refs.btnCreatInterface.triggerInInterface(result, config, _menu)
-    })
-  }
-
-  /**
    * @description 鎸夐挳鍙屽嚮瑙﹀彂瀛愰厤缃�
    */
   btnDoubleClick = (el) => {
@@ -893,7 +430,7 @@
 
   render() {
     const { config } = this.props
-    const { actionlist, visible, card, copying, profVisible, record } = this.state
+    const { actionlist, visible, card, copying, profVisible } = this.state
 
     return (
       <div className="model-table-action-list" style={config.charts && config.charts.length > 1 ? {paddingTop: 25} : null}>
@@ -915,8 +452,6 @@
           maskClosable={false}
           onCancel={this.editModalCancel}
           footer={[
-            record && ['pop', 'exec', 'prompt'].includes(record.OpenType) && record.intertype === 'system' ? <CreateInterface key="interface" ref="btnCreatInterface" trigger={this.btnCreatInterface}/> : null,
-            record && record.intertype === 'inner' ? <CreateFunc key="create" ref="btnCreatFunc" trigger={this.creatFunc}/> : null,
             <Button key="cancel" onClick={this.editModalCancel}>鍙栨秷</Button>,
             <Button key="confirm" type="primary" loading={copying} onClick={this.handleSubmit}>纭畾</Button>
           ]}
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx
index 7724f6c..e3eda1e 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx
@@ -46,16 +46,9 @@
         }
 
         this.props.columnChange(values)
-        this.setState({
-          locked: false,
-          type: 'Nvarchar(50)'
-        })
         this.props.form.setFieldsValue({
           Column: '',
-          Text: '',
-          required: 'true',
-          import: 'true',
-          type: 'Nvarchar(50)'
+          Text: ''
         })
       }
     })
@@ -148,6 +141,7 @@
                 <Radio.Group>
                   <Radio value="true">鏄�</Radio>
                   <Radio value="false">鍚�</Radio>
+                  <Radio value="init">鍒濆鍖�</Radio>
                 </Radio.Group>
               )}
             </Form.Item>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
index 837dd40..07c8db4 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select } from 'antd'
+import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select, Switch } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -23,6 +23,7 @@
     editItem: null,
     usefulfields: null,
     loading: false,
+    skip: false,
     verifySql: ''
   }
 
@@ -44,12 +45,13 @@
     fields.push('jskey')
 
     let _dec = columns.map(item => item.Column + ' ' + item.type).join(',')
+    let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
 
     if (_dec) {
       _dec += ','
     }
 
-    let _sql = `Declare @${btn.sheet.replace(/@db@/ig, '')} table (${_dec}jskey nvarchar(50) )
+    let _sql = `create table #${sheet} (${_dec}jskey nvarchar(50),BID nvarchar(50) )
       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),@tbid Nvarchar(512)
       Select @ErrorCode='', @retmsg=''
     `
@@ -80,8 +82,8 @@
   }
 
   handleConfirm = () => {
-    const { type } = this.props
-    const { editItem } = this.state
+    const { type, btn } = this.props
+    const { editItem, skip } = this.state
 
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
@@ -160,8 +162,10 @@
           return
         }
 
+        let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
         let tail = `
-          aaa:
+          drop table #${sheet}
+          aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg
         `
 
         let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
@@ -215,7 +219,7 @@
         }
 
         param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|typename)@/ig, `'${param.timestamp}'`)
+        param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${param.timestamp}'`)
         param.LText = param.LText.replace(/\n/g, ' ')
         
         // 澶栬仈鏁版嵁搴撴浛鎹�
@@ -226,26 +230,38 @@
         param.LText = Utils.formatOptions(param.LText)
         param.secretkey = Utils.encrypt('', param.timestamp)
         
-        this.setState({loading: true})
-        Api.genericInterface(param).then(res => {
-          if (res.status) {
-            this.setState({
-              loading: false,
-              editItem: null
-            }, () => {
-              this.props.scriptsChange(values)
-            })
-            this.props.form.setFieldsValue({
-              sql: ' '
-            })
-          } else {
-            this.setState({loading: false})
-
-            Modal.error({
-              title: res.message
-            })
-          }
-        })
+        if (skip) {
+          this.setState({
+            skip: false,
+            editItem: null
+          }, () => {
+            this.props.scriptsChange(values)
+          })
+          this.props.form.setFieldsValue({
+            sql: ' '
+          })
+        } else {
+          this.setState({loading: true})
+          Api.genericInterface(param).then(res => {
+            if (res.status) {
+              this.setState({
+                loading: false,
+                editItem: null
+              }, () => {
+                this.props.scriptsChange(values)
+              })
+              this.props.form.setFieldsValue({
+                sql: ' '
+              })
+            } else {
+              this.setState({loading: false})
+  
+              Modal.error({
+                title: res.message
+              })
+            }
+          })
+        }
       }
     })
   }
@@ -277,7 +293,7 @@
 
       database = database ? (database[0] || '') : ''
 
-      _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From @${sheet}`
+      _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From #${sheet}`
     } else {
       _value = value
     }
@@ -305,7 +321,7 @@
 
   render() {
     const { systemScripts, btn, type } = this.props
-    const { usefulfields, editItem } = this.state
+    const { usefulfields, editItem, skip } = this.state
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
       labelCol: {
@@ -322,17 +338,17 @@
       <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
         <Row gutter={24}>
           {!type && btn.sheet ? <Col span={8}>
-            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
-              {btn.sheet}
+            <Form.Item label="琛ㄥ悕" style={{whiteSpace: 'nowrap', margin: 0}}>
+              {btn.sheet}锛堣〃鍙橀噺璇蜂娇鐢�#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')}锛�
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={10}>
-            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
+            <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
+              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={24} className="sqlfield">
-            <Form.Item label={'鍙敤瀛楁'}>
+            <Form.Item label="鍙敤瀛楁">
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id, typename</span></Tooltip>,&nbsp;
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
               {usefulfields}
@@ -340,7 +356,7 @@
           </Col> : null}
           {!type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
             <Form.Item style={{marginBottom: 0}} label={
-              <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}>
+              <Tooltip placement="bottomLeft" title="鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
                 鎵ц浣嶇疆
               </Tooltip>
@@ -356,8 +372,8 @@
               )}
             </Form.Item>
           </Col> : null}
-          {!type ? <Col span={10}>
-            <Form.Item style={{marginBottom: 0}} label={'蹇嵎娣诲姞'}>
+          {!type ? <Col span={8}>
+            <Form.Item style={{marginBottom: 0}} label="蹇嵎娣诲姞">
               <Select
                 showSearch
                 filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
@@ -378,7 +394,7 @@
               </Select>
             </Form.Item>
           </Col> : null}
-          <Col span={6} className="add">
+          <Col span={5} className="add" style={{paddingTop: '2px', whiteSpace: 'nowrap'}}>
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
             {type === 'fullscreen' && !editItem ? '娣诲姞' : '淇濆瓨'}
             </Button>
@@ -386,8 +402,12 @@
               鍙栨秷
             </Button>
           </Col>
+          <Col span={3} style={{paddingTop: '15px', fontSize: '12px', whiteSpace: 'nowrap'}}>
+            寮哄埗淇濆瓨锛�
+            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
+          </Col>
           <Col span={24} className="sql">
-            <Form.Item label={'sql'}>
+            <Form.Item label="sql">
               {getFieldDecorator('sql', {
                 initialValue: '',
                 rules: [
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
index a3460ed..38fdf04 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -38,6 +38,7 @@
         width: '14%',
         inputType: 'input',
         unique: true,
+        strict: true,
         editable: true
       },
       {
@@ -72,20 +73,32 @@
         ]
       },
       {
+        title: '瀵煎叆',
+        dataIndex: 'import',
+        width: '10%',
+        editable: true,
+        inputType: 'radio',
+        render: (text, record) => {
+          if (record.import === 'init') {
+            return '鍒濆鍖�'
+          } else if (record.import === 'false') {
+            return '鍚�'
+          }
+          return '鏄�'
+        },
+        options: [
+          { value: 'true', text: '鏄�' },
+          { value: 'false', text: '鍚�' },
+          { value: 'init', text: '鍒濆鍖�' }
+        ]
+      },
+      {
         title: '蹇呭~',
         dataIndex: 'required',
         width: '10%',
         editable: true,
         inputType: 'switch',
         render: (text, record) => record.required === 'true' ? '鏄�' : '鍚�'
-      },
-      {
-        title: '瀵煎叆',
-        dataIndex: 'import',
-        width: '10%',
-        editable: true,
-        inputType: 'switch',
-        render: (text, record) => record.import !== 'false' ? '鏄�' : '鍚�'
       },
       {
         title: '鏈�灏忓��',
@@ -254,8 +267,6 @@
     let _verify = fromJS(card.verify || {}).toJS()
     let _columns = _verify.columns || []
 
-    delete _verify.dataresource
-
     // 鏃ф暟鎹吋瀹�
     _columns = _columns.map(col => {
       col.required = col.required || 'true'
@@ -325,7 +336,7 @@
     _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
-    Api.getSystemConfig(_sParam).then(res => {
+    Api.getCloudConfig(_sParam).then(res => {
       if (res.status) {
         let _scripts = res.data.map(item => {
           return {
@@ -638,7 +649,7 @@
         if (!err) {
           let _verify = {...verify, ...values}
 
-          let cols = _verify.columns.map(col => col.Column)
+          let cols = _verify.columns.map(col => col.Column.toLowerCase())
           cols = Array.from(new Set(cols))
 
           if (_verify.columns.length === 0) {
@@ -666,6 +677,15 @@
               return
             }
           }
+
+          _verify.columns.sort((a, b) => {
+            if (a.import === 'init' && b.import !== 'init') {
+              return 1
+            } else if (a.import !== 'init' && b.import === 'init') {
+              return -1
+            }
+            return 0
+          })
 
           let _loading = false
           if (this.scriptsForm && this.scriptsForm.state.editItem) {
@@ -838,8 +858,8 @@
             <Button className="excel-col-add mk-red" title="娓呯┖Excel鍒�" onClick={this.clearField}>
               娓呯┖Excel鍒�
             </Button>
-            <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>娉細鏁板�肩被鍨嬶紙int 鎴� decimal锛夛紝鍐呭涓哄繀濉紱鏈�澶у�煎拰鏈�灏忓�煎湪绫诲瀷涓烘暟鍊兼椂鏈夋晥銆�</Col>
-            <EditTable actions={['edit', 'move', 'copy', 'del']} type="excelcolumn" data={verify.columns} columns={excelColumns} onChange={this.changeColumns}/>
+            <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>娉細鏁板�肩被鍨嬶紙int 鎴� decimal锛夛紝鍐呭涓哄繀濉紱鏈�澶у�煎拰鏈�灏忓�煎湪绫诲瀷涓烘暟鍊兼椂鏈夋晥銆傚鍏�-鍒濆鍖栵細鐢ㄤ簬excel涓笉瀛樺湪锛屽鍏ユ椂闇�瑕佸垵濮嬪寲鐨勫瓧娈�</Col>
+            <EditTable actions={['edit', 'move', 'copy', 'del', 'extra:required:鏄惁蹇呭~']} type="excelcolumn" data={verify.columns} columns={excelColumns} onChange={this.changeColumns}/>
           </TabPane>
           {card.intertype === 'system' ? <TabPane tab={
             <span>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
index bf43e2c..9f4f640 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
@@ -1,7 +1,8 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Button, notification, Tooltip, Select } from 'antd'
+import { Form, Row, Col, Button, notification, Tooltip, Select, Switch, Radio } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
 import Api from '@/api'
@@ -21,6 +22,7 @@
     systemScripts: [],
     usefulfields: null,
     loading: false,
+    skip: false
   }
 
   UNSAFE_componentWillMount () {
@@ -60,7 +62,7 @@
     _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
-    Api.getSystemConfig(_sParam).then(res => {
+    Api.getCloudConfig(_sParam).then(res => {
       if (res.status) {
         let _scripts = res.data.map(item => {
           return {
@@ -114,11 +116,13 @@
     })
 
     this.props.form.setFieldsValue({
-      sql: record.sql
+      sql: record.sql,
+      position: record.position || 'front'
     })
   }
 
   handleConfirm = () => {
+    const { skip } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
@@ -189,6 +193,7 @@
         this.props.scriptsChange(values, (status) => {
           if (status) {
             this.setState({
+              skip: false,
               loading: false,
               editItem: null
             })
@@ -200,7 +205,7 @@
               loading: false
             })
           }
-        })
+        }, skip)
       }
     })
   }
@@ -211,25 +216,13 @@
     })
     
     this.props.form.setFieldsValue({
-      sql: ' '
+      sql: ' ',
+      position: 'front'
     })
   }
 
   selectScript = (value, option) => {
-    const { usefulfields, sheet } = this.props
-
-    let _value = ''
-    if (value === 'default') {
-      let fields = usefulfields.filter(item => item.import !== 'false')
-      fields = fields.map(col => col.Column).join(',')
-
-      let _sheet = sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
-
-      _value = `Select ${fields} From ${_sheet}`
-    } else {
-      _value = value
-    }
-
+    let _value = value
     let _sql = this.props.form.getFieldValue('sql')
     if (/^\s+$/.test(_sql)) {
       _sql = ''
@@ -253,7 +246,7 @@
 
   render() {
     const { sheet, linefields } = this.props
-    const { usefulfields, systemScripts } = this.state
+    const { usefulfields, systemScripts, skip } = this.state
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
       labelCol: {
@@ -276,7 +269,7 @@
           </Col>
           <Col span={10}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
+              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
             </Form.Item>
           </Col>
           <Col span={24} className="sqlfield">
@@ -287,6 +280,23 @@
               {linefields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'琛ㄥ崟鍙婅鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}>,&nbsp;{linefields}</Tooltip> : null}
             </Form.Item>
           </Col>
+          <Col span={8} style={{whiteSpace: 'nowrap'}}>
+            <Form.Item style={{marginBottom: 0}} label={
+              <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌鏁版嵁婧愪綅缃叧绯汇��'}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鎵ц浣嶇疆
+              </Tooltip>
+            }>
+              {getFieldDecorator('position', {
+                initialValue: 'front'
+              })(
+                <Radio.Group>
+                  <Radio value="front">鍓嶇疆</Radio>
+                  <Radio value="back">鍚庣疆</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
           <Col span={8}>
             <Form.Item style={{marginBottom: 0}} label="蹇嵎娣诲姞">
               <Select
@@ -295,9 +305,6 @@
                 onSelect={this.selectScript}
                 getPopupContainer={() => document.getElementById('verify-excelin-custom-scripts')}
               >
-                <Select.Option key="default" value={'default'}>
-                  榛樿sql
-                </Select.Option>
                 <Select.Option key="debugger" value={`z_debug: select @ErrorCode='E',@retmsg='娴嬭瘯鏂偣' goto aaa`}>
                   娴嬭瘯鏂偣
                 </Select.Option>
@@ -309,7 +316,7 @@
               </Select>
             </Form.Item>
           </Col>
-          <Col span={6} className="add">
+          <Col span={5} className="add" style={{whiteSpace: 'nowrap'}}>
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
               淇濆瓨
             </Button>
@@ -317,6 +324,10 @@
               鍙栨秷
             </Button>
           </Col>
+          <Col span={3} style={{paddingTop: '15px', fontSize: '12px', whiteSpace: 'nowrap'}}>
+            寮哄埗淇濆瓨锛�
+            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
+          </Col>
           <Col span={24} className="sql">
             <Form.Item label="sql">
               {getFieldDecorator('sql', {
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
index 04fa4a8..6d1b718 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
@@ -216,15 +216,25 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            {/* {dataType === 'custom' && defaultSql === 'true' ? <Col className="short-label" span={8}>
-              <Form.Item label="涓婚敭">
+            {btnType !== 'print' && dataType === 'custom' && defaultSql === 'true' ? <Col className="short-label" span={8}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鍙嚜瀹氫箟涓婚敭锛岀┖鏃堕粯璁や负鏁版嵁婧愪富閿�傛敞锛氶�夎瀵煎嚭鏃朵娇鐢ㄣ��">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  涓婚敭
+                </Tooltip>
+              }>
                 {getFieldDecorator('primaryKey', {
-                  initialValue: setting.primaryKey || 'ID',
+                  initialValue: setting.primaryKey || '',
                 })(<Input placeholder={''} autoComplete="off" />)}
               </Form.Item>
-            </Col> : null} */}
+            </Col> : null}
             {dataType === 'custom' && defaultSql === 'true' ? <Col className="short-label" span={8}>
-              <Form.Item label="鎺掑簭鏂瑰紡">
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="濡傛灉鍦ㄨ嚜瀹氫箟鑴氭湰涓娇鐢ㄤ簡@pageSize@鎴朄orderBy@锛岃鍦ㄦ暟鎹簮涓崟鐙啓鎺掑簭璇彞銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鎺掑簭鏂瑰紡
+                </Tooltip>
+              }>
                 {getFieldDecorator('order', {
                   initialValue: setting.order || '',
                   rules: [
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
index 86d94de..ebce7e5 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Radio, Spin, Typography, Popconfirm } from 'antd'
+import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Spin, Typography, Popconfirm } from 'antd'
 import { EditOutlined, StopOutlined, CheckCircleOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import md5 from 'md5'
@@ -12,7 +12,6 @@
 import ColumnForm from './columnform'
 import DataSource from './datasource'
 import CustomScript from './customscript'
-import CodeMirror from '@/templates/zshare/codemirror'
 import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
@@ -31,7 +30,6 @@
     verify: {},
     debugId: '',
     activeKey: 'setting',
-    defaultscript: '', // 鑷畾涔夎剼鏈�
     excelColumns: [
       {
         title: '瀛楁',
@@ -135,7 +133,7 @@
         width: '10%',
         editable: true,
         inputType: 'radio',
-        render: (text, record) => record.required === 'true' ? '鏄�' : '鍚�',
+        render: (text, record) => record.required === 'true' ? <span style={{color: 'red'}}>鏄�</span> : '鍚�',
         options: [
           {value: 'true', text: '鏄�'},
           {value: 'false', text: '鍚�'}
@@ -160,20 +158,18 @@
           )
         }
       },
-      // {
-      //   title: '鎵ц浣嶇疆',
-      //   dataIndex: 'position',
-      //   width: '10%',
-      //   render: (text, record) => {
-      //     if (record.position === 'init') {
-      //       return <span style={{color: 'orange'}}>鍒濆鍖�</span>
-      //     } else if (record.position === 'front') {
-      //       return <span style={{color: '#26C281'}}>sql鍓�</span>
-      //     } else {
-      //       return <span style={{color: '#1890ff'}}>sql鍚�</span>
-      //     }
-      //   }
-      // },
+      {
+        title: '鎵ц浣嶇疆',
+        dataIndex: 'position',
+        width: '10%',
+        render: (text, record) => {
+          if (record.position === 'back') {
+            return <span style={{color: '#1890ff'}}>鍚庣疆</span>
+          } else {
+            return <span style={{color: '#26C281'}}>鍓嶇疆</span>
+          }
+        }
+      },
       {
         title: '鐘舵��',
         dataIndex: 'status',
@@ -221,14 +217,10 @@
       _verify = fromJS(card.verify).toJS()
     }
 
-    _verify.enable = _verify.enable || 'false'
     _verify.dataType = _verify.dataType || 'default'
     _verify.columns = _verify.columns || []
     _verify.scripts = _verify.scripts || []
 
-    if (card.intertype !== 'system') {
-      _verify.enable = 'false'
-    }
     _verify.columns = _verify.columns.map(col => {
       col.type = col.type || 'text'
       col.output = col.output || 'true'
@@ -244,16 +236,6 @@
 
       return col
     })
-
-    let defaultscript = ''
-    if (!_verify.script && card.intertype === 'system') {
-      let search = this.formatSearch(config.search)
-      search = Utils.joinMainSearchkey(search)
-      search = search.replace(/@\$@/ig, '')
-      search = search ? 'where ' + search : ''
-      
-      defaultscript = `update ${config.setting.tableName || ''} set idefine5= idefine5+1 ,modifydate=getdate(),cdefine5='宸插鍑�',modifyuserid=@userid@ ${search}`
-    }
 
     let appType = sessionStorage.getItem('appType')
     let searches = []
@@ -318,62 +300,54 @@
 
       searches = search
     } else {
-      let search = []
-  
+      searches = fromJS(config.search || []).toJS()
+
       if (config.setting && config.setting.useMSearch === 'true' && window.GLOB.customMenu) {
         let menu = fromJS(window.GLOB.customMenu).toJS()
-        let _search = null
-        let filterComponent = (box) => {
+        let filterComponent = (box, mainSearch) => {
           box.components.forEach(item => {
-            if (_search) return
-    
-            if (item.type === 'search') {
-              box.slist = [...box.slist, item.search]
-            } else if (item.uuid === config.uuid) {
-              _search = box.slist.pop()
+            if (item.type !== 'search') return
+            mainSearch = item.search
+          })
+          let has = false
+          box.components.forEach(item => {
+            if (item.uuid === config.uuid) {
+              has = true
             } else if (item.type === 'group') {
               item.components.forEach(m => {
                 if (m.uuid !== config.uuid) return
-                _search = box.slist.pop()
-              })
-            } else if (item.type === 'tabs') {
-              item.subtabs.forEach(tab => {
-                tab.slist = [...box.slist]
-                filterComponent(tab)
+                has = true
               })
             }
           })
-        }
-        menu.slist = []
-        filterComponent(menu)
-    
-        if (_search) {
-          search = _search
-        } else {
-          menu.components.forEach(item => {
-            if (item.type !== 'search') return
-            search = item.search
-          })
-        }
-      }
-  
-      searches = fromJS(config.search || []).toJS()
-  
-      if (search.length > 0) {
-        let keys = searches.map(item => (item.field ? item.field.toLowerCase() : ''))
-        search.forEach(item => {
-          if (item.field && !keys.includes(item.field.toLowerCase())) {
-            searches.push(item)
+
+          if (has) {
+            if (mainSearch) {
+              let keys = searches.map(item => (item.field ? item.field.toLowerCase() : ''))
+              mainSearch.forEach(item => {
+                if (item.field && !keys.includes(item.field.toLowerCase())) {
+                  searches.push(item)
+                }
+              })
+            }
+          } else {
+            box.components.forEach(item => {
+              if (item.type !== 'tabs') return
+
+              item.subtabs.forEach(tab => {
+                filterComponent(tab, mainSearch)
+              })
+            })
           }
-        })
+        }
+        filterComponent(menu, null)
       }
     }
 
     this.setState({
       verify: _verify,
       searches: searches,
-      activeKey: card.intertype === 'system' && _verify.dataType === 'custom' ? 'setting' : 'columns',
-      defaultscript: defaultscript
+      activeKey: card.intertype === 'system' && _verify.dataType === 'custom' ? 'setting' : 'columns'
     })
   }
 
@@ -417,53 +391,6 @@
     this.setState({
       verify: verify
     })
-  }
-
-  /**
-   * @description 鑾峰彇鍏ㄩ儴鎼滅储鏉′欢
-   * @param {Array} searches 鎼滅储鏉′欢鏁扮粍
-   */
-  formatSearch (searches) {
-    if (!searches || searches.length === 0) return []
-
-    let newsearches = []
-    searches.forEach(search => {
-      if (!search.field) return
-      
-      let item = {
-        key: search.field,
-        match: search.match,
-        type: search.type,
-        label: search.label,
-        value: search.initval,
-        required: search.required === 'true'
-      }
-      if (item.type === 'group') {
-        item.key = search.datefield
-        item.type = 'daterange'
-        item.match = 'between'
-        item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',')
-
-        newsearches.push(item)
-        return
-      } else if (item.type === 'date') {
-        item.value = moment().format('YYYY-MM-DD')
-      } else if (item.type === 'datemonth') {
-        item.value = moment().format('YYYY-MM')
-      } else if (item.type === 'dateweek') {
-        item.value = moment().format('YYYY-MM-DD')
-      } else if (item.type === 'daterange') {
-        item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',')
-      } else if (item.type === 'multiselect' || (item.type === 'checkcard' && search.multiple === 'true')) {
-        item.type = 'multi'
-        item.value = '@$@'
-      } else {
-        item.value = '@$@'
-      }
-      newsearches.push(item)
-    })
-    
-    return newsearches
   }
 
   columnChange = (values) => {
@@ -582,9 +509,7 @@
         return
       }
 
-      if (activeKey === 'backscript' && verify.enable === 'true') {
-        this.checkScript(resolve, reject)
-      } else if (activeKey === 'setting') {
+      if (activeKey === 'setting') {
         this.settingForm.handleConfirm().then(res => {
           let _verify = {...verify, ...res}
 
@@ -667,111 +592,6 @@
       } else {
         resolve(verify)
       }
-    })
-  }
-
-  checkScript = (_resolve, _reject) => {
-    this.props.form.validateFieldsAndScroll((err, values) => {
-      if (!err) {
-        values.sql = values.sql || ''
-
-        let _quot = values.sql.match(/'{1}/g)
-        let _lparen = values.sql.match(/\({1}/g)
-        let _rparen = values.sql.match(/\){1}/g)
-
-        _quot = _quot ? _quot.length : 0
-        _lparen = _lparen ? _lparen.length : 0
-        _rparen = _rparen ? _rparen.length : 0
-
-        if (_quot % 2 !== 0) {
-          notification.warning({
-            top: 92,
-            message: 'sql涓璡'蹇呴』鎴愬鍑虹幇',
-            duration: 5
-          })
-          return
-        } else if (_lparen !== _rparen) {
-          notification.warning({
-            top: 92,
-            message: 'sql涓�()蹇呴』鎴愬鍑虹幇',
-            duration: 5
-          })
-          return
-        } else if (/--/ig.test(values.sql)) {
-          notification.warning({
-            top: 92,
-            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
-            duration: 5
-          })
-          return
-        } else if (/,,/ig.test(values.sql)) {
-          notification.warning({
-            top: 92,
-            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇杩炵画鐨勮嫳鏂囬�楀彿锛�,,锛�',
-            duration: 5
-          })
-          return
-        }
-
-        let error = Utils.verifySql(values.sql, 'customscript')
-
-        if (error) {
-          notification.warning({
-            top: 92,
-            message: 'sql涓笉鍙娇鐢�' + error,
-            duration: 5
-          })
-          return
-        }
-
-        let param = {
-          func: 's_debug_sql',
-          exec_type: 'y',
-          LText: values.sql
-        }
-
-        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${param.timestamp}'`)
-        param.LText = param.LText.replace(/\n/g, ' ')
-        
-        param.LText = Utils.formatOptions(param.LText)
-        param.secretkey = Utils.encrypt('', param.timestamp)
-        
-        this.setState({
-          loading: true
-        })
-        Api.genericInterface(param).then(res => {
-          this.setState({
-            loading: false
-          })
-          if (res.status) {
-            let verify = {...this.state.verify, script: values.sql}
-
-            this.setState({verify: verify}, () => {
-              _resolve(verify)
-            })
-          } else {
-            Modal.error({
-              title: res.message
-            })
-          }
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: '鑷畾涔夎剼鏈笉鍙负绌猴紒',
-          duration: 5
-        })
-        _reject()
-      }
-    })
-  }
-
-  changeEnable = (e) => {
-    const { verify } = this.state
-
-    this.setState({
-      verify: {...verify, enable: e.target.value}
     })
   }
 
@@ -896,13 +716,7 @@
     const { card } = this.props
     const { activeKey, verify } = this.state
 
-    if (activeKey === 'backscript' && verify.enable === 'true') {
-      this.checkScript(() => {
-        this.setState({
-          activeKey: val
-        })
-      }, () => {})
-    } else if (card.intertype !== 'system' || verify.dataType !== 'custom') {
+    if (card.intertype !== 'system' || verify.dataType !== 'custom') {
       this.setState({activeKey: val})
       return
     } else if (activeKey === 'setting') {
@@ -975,7 +789,7 @@
     }
   }
 
-  scriptsChange = (values, callback) => {
+  scriptsChange = (values, callback, skip) => {
     let verify = JSON.parse(JSON.stringify(this.state.verify))
 
     if (values.uuid) {
@@ -991,20 +805,27 @@
       verify.scripts.push(values)
     }
 
-    this.setState({loading: true})
-
-    this.sqlverify(() => { // 楠岃瘉鎴愬姛
+    if (skip) {
       this.setState({
-        loading: false,
         verify: verify
       })
       callback(true)
-    }, () => {             // 楠岃瘉澶辫触
-      this.setState({
-        loading: false
-      })
-      callback(false)
-    }, verify.scripts)
+    } else {
+      this.setState({loading: true})
+  
+      this.sqlverify(() => { // 楠岃瘉鎴愬姛
+        this.setState({
+          loading: false,
+          verify: verify
+        })
+        callback(true)
+      }, () => {             // 楠岃瘉澶辫触
+        this.setState({
+          loading: false
+        })
+        callback(false)
+      }, verify.scripts)
+    }
   }
 
   sqlverify = (_resolve, _reject, scripts) => {
@@ -1068,8 +889,7 @@
 
   render() {
     const { card } = this.props
-    const { verify, excelColumns, defaultscript, scriptsColumns, activeKey, loading, searches } = this.state
-    const { getFieldDecorator } = this.props.form
+    const { verify, excelColumns, scriptsColumns, activeKey, loading, searches } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -1119,39 +939,6 @@
               wrappedComponentRef={(inst) => this.scriptsForm = inst}
             />
             <EditTable actions={['move']} data={verify.scripts} columns={scriptsColumns} onChange={(scripts) => {this.setState({verify: {...verify, scripts}})}}/>
-          </TabPane> : null}
-          {card.intertype === 'system' ? <TabPane tab={
-            <span>
-              鍥炶皟鑴氭湰
-              {verify.enable === 'true' ? <span className="count-tip">1</span> : null}
-            </span>
-          } key="backscript">
-            <Form {...formItemLayout} className="verify-form">
-              <Row gutter={24}>
-                <Col span={8}>
-                  <Form.Item style={{marginBottom: 10}} label={'鍚敤'}>
-                    <Radio.Group defaultValue={verify.enable || 'false'} onChange={this.changeEnable}>
-                      <Radio value="true">鏄�</Radio>
-                      <Radio value="false">鍚�</Radio>
-                    </Radio.Group>
-                  </Form.Item>
-                </Col>
-                <div style={{color: '#959595', fontSize: '13px', paddingTop: '30px', float: 'right'}}>鎵ц鎴愬姛鍚庣殑鍥炶皟鍑芥暟銆�</div>
-                <Col span={24} className="sql">
-                  <Form.Item label={'sql'}>
-                    {getFieldDecorator('sql', {
-                      initialValue: verify.script || defaultscript,
-                      rules: [
-                        {
-                          required: true,
-                          message: '璇疯緭鍏ql!'
-                        }
-                      ]
-                    })(<CodeMirror />)}
-                  </Form.Item>
-                </Col>
-              </Row>
-            </Form>
           </TabPane> : null}
           <TabPane tab="淇℃伅鎻愮ず" key="message">
             <Form {...formItemLayout}>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
index 6e71f40..0d8cbf7 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
@@ -28,50 +28,55 @@
     }
 
     let _customScript = ''
+    let _tailScript = ''
     scripts && scripts.forEach(script => {
       if (script.status === 'false') return
-      _customScript += `
-      ${script.sql}
-      `
+      if (script.position !== 'back') {
+        _customScript += `
+        ${script.sql}
+        `
+      } else {
+        _tailScript += `
+        ${script.sql}
+        `
+      }
     })
 
-    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}
-      `
-    }
+    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 =''`
 
     if (verify.defaultSql === 'false') {
       _dataresource = ''
     }
+
+    if (/\s/.test(_dataresource)) {
+      _dataresource = '(' + _dataresource + ') tb'
+    }
     
-    _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|typename)@/ig, `'${timestamp}'`)
-    _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|typename)@/ig, `'${timestamp}'`)
+    _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${timestamp}'`)
+    _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${timestamp}'`)
+    _tailScript = _tailScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${timestamp}'`)
     _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
     _customScript = _customScript.replace(/@\$|\$@/ig, '')
+    _tailScript = _tailScript.replace(/@\$|\$@/ig, '')
 
     // 澶栬仈鏁版嵁搴撴浛鎹�
     if (window.GLOB.externalDatabase !== null) {
       _dataresource = _dataresource.replace(/@db@/ig, window.GLOB.externalDatabase)
       _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase)
+      _tailScript = _tailScript.replace(/@db@/ig, window.GLOB.externalDatabase)
     }
+
+    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
     
     // 姝e垯鏇挎崲
     let _regoptions = regoptions.map(item => {
       return {
         reg: new RegExp('@' + item.key + '@', 'ig'),
-        value: `'0'`,
-        type: item.type || ''
+        value: `'0'`
       }
     })
 
     _regoptions.push({
-      reg: new RegExp('@userName@', 'ig'),
-      value: `''`
-    }, {
-      reg: new RegExp('@fullName@', 'ig'),
-      value: `''`
-    }, {
       reg: new RegExp('@orderBy@', 'ig'),
       value: verify.order
     }, {
@@ -82,48 +87,46 @@
       value: 1
     })
 
+    _regoptions.forEach(item => {
+      _dataresource = _dataresource.replace(item.reg, item.value)
+      _customScript = _customScript.replace(item.reg, item.value)
+      _tailScript = _tailScript.replace(item.reg, item.value)
+    })
+
     if (verify.queryType === 'statistics' && _dataresource) {
-      _regoptions.forEach(item => {
-        _dataresource = _dataresource.replace(item.reg, item.value)
-      })
       _search = ''
-    } else if (_dataresource) {
-      _regoptions.forEach(item => {
-        if (item.type !== 'url') return
-        _dataresource = _dataresource.replace(item.reg, item.value)
-      })
     }
 
-    if (_customScript) {
-      _regoptions.forEach(item => {
-        _customScript = _customScript.replace(item.reg, item.value)
-      })
-    }
-
-    // 鏁版嵁婧愬鐞�, 瀛樺湪鏄剧ず鍒楁椂 
+    // 鏁版嵁婧愬鐞�, 瀛樺湪鏄剧ず鍒楁椂
     if (_dataresource) {
-      if (/\s/.test(_dataresource)) {
-        _dataresource = '(' + _dataresource + ') tb'
-      }
-
-      if (verify.order) {
-        _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${verify.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows`
-      } else {
+      if (custompage || !verify.order) {
         _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search}`
+      } else {
+        _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${verify.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
       }
     }
 
     if (_customScript) {
       sql = `/* sql 楠岃瘉 */
+        ${declare}
         ${_customScript}
         ${_dataresource}
+        ${_tailScript}
         aaa:
         if @ErrorCode!=''
           insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
       `
+    } else if (_tailScript) {
+      sql = `${declare}
+        ${_dataresource}
+        ${_tailScript}
+        aaa:
+        if @ErrorCode!=''
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+      `
     } else {
       sql = `/* 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 =''
+        ${declare}
         ${_dataresource}`
     }
     sql = sql.replace(/\n\s{8}/ig, '\n')
diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
index 90ff096..5a622de 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -66,12 +66,10 @@
         dataIndex: 'position',
         width: '10%',
         render: (text, record) => {
-          if (record.position === 'init') {
-            return <span style={{color: 'orange'}}>鍒濆鍖�</span>
-          } else if (record.position === 'front') {
-            return <span style={{color: '#26C281'}}>sql鍓�</span>
+          if (record.position === 'back') {
+            return <span style={{color: '#1890ff'}}>鍚庣疆</span>
           } else {
-            return <span style={{color: '#1890ff'}}>sql鍚�</span>
+            return <span style={{color: '#26C281'}}>鍓嶇疆</span>
           }
         }
       },
@@ -297,7 +295,7 @@
 
     param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
 
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       if (res.status) {
         let temps = res.data.map(temp => {
           return {
@@ -335,6 +333,29 @@
     })
   }
 
+  handleEdit = (record, type) => {
+    let node = null
+
+    if (type === 'scripts') {
+      this.scriptsForm.edit(record)
+      node = document.getElementById('mk-exout-script')
+    }
+
+
+    if (node && node.scrollTop) {
+      let inter = Math.ceil(node.scrollTop / 10)
+
+      let timer = setInterval(() => {
+        if (node.scrollTop - inter > 0) {
+          node.scrollTop = node.scrollTop - inter
+        } else {
+          node.scrollTop = 0
+          clearInterval(timer)
+        }
+      }, 10)
+    }
+  }
+
   showError = (errorType) => {
     if (errorType === 'S') {
       notification.success({
diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
index 19c1db3..969fa63 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
@@ -5,11 +5,18 @@
     let _dataresource = setting.dataresource || ''
 
     let _customScript = ''
+    let _tailScript = ''
     scripts && scripts.forEach(script => {
       if (script.status === 'false') return
-      _customScript += `
-      ${script.sql}
-      `
+      if (script.position !== 'back') {
+        _customScript += `
+        ${script.sql}
+        `
+      } else {
+        _tailScript += `
+        ${script.sql}
+        `
+      }
     })
 
     if (_customScript) {
@@ -22,16 +29,22 @@
     if (setting.defaultSql === 'false') {
       _dataresource = ''
     }
+    if (/\s/.test(_dataresource)) {
+      _dataresource = '(' + _dataresource + ') tb'
+    }
     
-    _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|typename)@/ig, `'${timestamp}'`)
-    _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|typename)@/ig, `'${timestamp}'`)
+    _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${timestamp}'`)
+    _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${timestamp}'`)
+    _tailScript = _tailScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${timestamp}'`)
     _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
     _customScript = _customScript.replace(/@\$|\$@/ig, '')
+    _tailScript = _tailScript.replace(/@\$|\$@/ig, '')
 
     // 澶栬仈鏁版嵁搴撴浛鎹�
     if (window.GLOB.externalDatabase !== null) {
       _dataresource = _dataresource.replace(/@db@/ig, window.GLOB.externalDatabase)
       _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase)
+      _tailScript = _tailScript.replace(/@db@/ig, window.GLOB.externalDatabase)
     }
 
     let arr_field = columns.map(col => col.field)
@@ -43,10 +56,6 @@
 
     // 鏁版嵁婧愬鐞�, 瀛樺湪鏄剧ず鍒楁椂 
     if (_dataresource) {
-      if (/\s/.test(_dataresource)) {
-        _dataresource = '(' + _dataresource + ') tb'
-      }
-
       if (setting.order) {
         _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows`
       } else {
@@ -58,10 +67,21 @@
       sql = `/* sql 楠岃瘉 */
         ${_customScript}
         ${_dataresource}
+        ${_tailScript}
         aaa:
         if @ErrorCode!=''
           insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
       `
+    } else if (_tailScript) {
+      sql = `/* 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 =''
+        ${declareSql}
+        ${_dataresource}
+        ${_tailScript}
+        aaa:
+        if @ErrorCode!=''
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+      `
     } else {
       sql = `/* 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 =''
diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx
index c493ccd..5cc4bf4 100644
--- a/src/templates/sharecomponent/fieldscomponent/index.jsx
+++ b/src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -3,6 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { Button, Modal, Empty, notification } from 'antd'
 
+import Api from '@/api'
 import Utils from '@/utils/utils.js'
 import EditCard from './editcard'
 
@@ -11,8 +12,8 @@
 
 class FieldsComponent extends Component {
   static propTpyes = {
-    type: PropTypes.string,          // 鎼滅储鏉′欢娣诲姞銆佹樉绀哄垪娣诲姞
-    config: PropTypes.object,        // 瀹瑰櫒Id
+    type: PropTypes.string,
+    config: PropTypes.object,
     updatefield: PropTypes.func
   }
 
@@ -23,10 +24,8 @@
     selectCards: []
   }
 
-  queryField = () => {
-    const { type, config } = this.props
-    // 鍒ゆ柇鏄惁宸查�夋嫨琛ㄥ悕
-    if (!window.GLOB.tableFields || window.GLOB.tableFields.length === 0) {
+  checkField = () => {
+    if (!window.GLOB.publicTables || window.GLOB.publicTables.length === 0) {
       notification.warning({
         top: 92,
         message: '璇烽�夋嫨琛ㄥ悕锛�',
@@ -35,9 +34,101 @@
       return
     }
 
+    window.GLOB.tableFields = window.GLOB.tableFields || []
+
+    let index = 0
+
+    let deffers = window.GLOB.publicTables.map(item => {
+      let tb = window.GLOB.tableFields.filter(tab => tab.tableName === item.TbName)[0]
+
+      if (tb) {
+        return Promise.resolve(fromJS(tb).toJS())
+      }
+
+      return new Promise(resolve => {
+        setTimeout(() => {
+          Api.getCloudConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => {
+            let tabmsg = {
+              status: res.status,
+              message: res.message,
+              tableName: item.TbName,
+              columns: []
+            }
+
+            if (res.FDName && res.FDName.length > 0) {
+              tabmsg.columns = res.FDName.map(item => {
+                let _type = item.FieldType.toLowerCase()
+                let _decimal = 0
+                let _length = 50
+                if (/^nvarchar/.test(_type)) {
+                  try { // 瀛樺湪max
+                    _length = +_type.match(/\d+/)[0] || 50
+                  } catch (e) {
+                    _length = 2048
+                  }
+                  _type = 'text'
+                } else if (/^int/.test(_type)) {
+                  _type = 'number'
+                } else if (/^decimal/.test(_type)) {
+                  _decimal = _type.split(',')[1]
+                  _decimal = parseInt(_decimal)
+                  _type = 'number'
+                } else if (/^datetime/.test(_type)) {
+                  _type = 'datetime'
+                } else if (/^date/.test(_type)) {
+                  _type = 'date'
+                } else {
+                  _type = 'text'
+                }
+    
+                return {
+                  field: item.FieldName || '',
+                  label: item.FieldDec,
+                  type: _type,
+                  datatype: _type,
+                  decimal: _decimal,
+                  length: _length,
+                  $datatype: item.FieldType.toLowerCase()
+                }
+              })
+            }
+
+            resolve(tabmsg)
+          })
+        }, index * 50)
+
+        index++
+      })
+    })
+    Promise.all(deffers).then(response => {
+      let error = false
+      let _columns = response
+
+      response.forEach(item => {
+        if (!item.status) {
+          error = item.message || '瀛楁鏌ヨ澶辫触锛�'
+        }
+      })
+
+      if (error) {
+        notification.warning({
+          top: 92,
+          message: error,
+          duration: 5
+        })
+      } else {
+        window.GLOB.tableFields = _columns
+        this.queryField(_columns)
+      }
+    })
+  }
+
+  queryField = (tableFields) => {
+    const { type, config } = this.props
+
     // 琛ㄥ瓧娈甸泦杞负map鏁版嵁
     let columns = new Map()
-    window.GLOB.tableFields.forEach(table => {
+    tableFields.forEach(table => {
       table.columns.forEach(column => {
         columns.set(column.field.toLowerCase(), column)
       })
@@ -281,7 +372,7 @@
 
     return (
       <div className="quickly-add">
-        <Button type="primary" block onClick={this.queryField}>{label}</Button>
+        <Button type="primary" block onClick={this.checkField}>{label}</Button>
         {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */}
         <Modal
           wrapClassName="model-table-fieldmanage-modal"
diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
index f65bb50..b5bd01f 100644
--- a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
+++ b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
@@ -55,6 +55,8 @@
       _defaultValue = [moment().startOf('week'), moment().endOf('week')]
     } else if (card.initval === 'month') {
       _defaultValue = [moment().startOf('month'), moment().endOf('month')]
+    } else if (card.initval === 'lastMonth') {
+      _defaultValue = [moment().subtract(1, 'months').startOf('month'), moment().subtract(1, 'months').endOf('month')]
     } else if (card.initval) {
       try {
         let _initval = JSON.parse(card.initval)
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index 6d282da..6eb1a3b 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -354,6 +354,7 @@
         {/* 缂栬緫鎼滅储鏉′欢 */}
         <Modal
           title={card && card.copyType === 'search' ?  '鎼滅储鏉′欢-澶嶅埗' : '鎼滅储鏉′欢-缂栬緫'}
+          wrapClassName="mk-scroll-modal"
           visible={visible}
           width={850}
           maskClosable={false}
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
index 67cb5a2..34b71e8 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -84,6 +84,7 @@
       {value: '[3, 0]', label: '杩戜笁澶�'},
       {value: '[7, 0]', label: '杩戜竷澶�'},
       {value: '[30, 0]', label: '杩�30澶�'},
+      {value: '[90, 0]', label: '杩�90澶�'},
       {value: '[7, -7]', label: '鍓嶅悗涓冨ぉ'},
       {value: '[30, -30]', label: '鍓嶅悗30澶�'},
       {value: '[90, -90]', label: '鍓嶅悗90澶�'},
@@ -98,6 +99,7 @@
 const searchTypeOptions = {
   text: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'inputType', 'advanced', 'query', 'labelwidth'],
   select: ['label', 'field', 'resourceType', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'setAll', 'dropdown', 'query', 'labelwidth'],
+  radio: ['label', 'field', 'resourceType', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'setAll', 'query', 'labelwidth'],
   multiselect: ['label', 'field', 'resourceType', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'query', 'labelwidth'],
   link: ['label', 'field', 'resourceType', 'initval', 'type', 'linkField', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'setAll', 'dropdown', 'query', 'labelwidth'],
   date: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'query', 'precision', 'labelwidth'],
@@ -119,11 +121,7 @@
   }
 
   state = {
-    openType: null,          // 鎼滅储鏉′欢鏄剧ず绫诲瀷
-    resourceType: null,      // 涓嬫媺鎼滅储鏃讹紝閫夐」鏉ユ簮绫诲瀷
-    formlist: null,          // 琛ㄥ崟
-    cFields: [],
-    textTooltip: '瀛楁鍚嶅彲浠ヤ娇鐢ㄩ�楀彿鍒嗛殧锛岃繘琛岀患鍚堟悳绱�',
+    formlist: null
   }
 
   record = {}
@@ -183,7 +181,7 @@
     let reRequired = {}
     let reLabel = {}
 
-    if (['multiselect', 'select', 'link'].includes(type)) {
+    if (['multiselect', 'select', 'link', 'radio'].includes(type)) {
       reRequired.linkField = true
       if (this.record.resourceType === '0') {        // 鑷畾涔夎祫婧�
         shows.push('options')
@@ -213,6 +211,9 @@
         }
         if (this.record.selectStyle === 'custom') {
           shows.push('backgroundColor')
+        }
+        if (this.record.multiple === 'dropdown' && this.record.resourceType === '1') {
+          shows.push('mark', 'parentField')
         }
       }
       shows.push('linkField')
@@ -319,7 +320,7 @@
               uuid: key
             }]
           }
-        } else if (['multiselect', 'select', 'link'].includes(value)) {
+        } else if (['multiselect', 'select', 'link', 'radio'].includes(value)) {
           if (!this.record.options[0].Text && this.record.fields.length > 0) {
             let field = this.record.fields[0].field
     
@@ -487,7 +488,7 @@
             <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />
           </AutoComplete>
         } else {
-          content = <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />
+          content = <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} onChange={(e) => {this.optionChange(item.key, e.target.value)}}/>
         }
       } else if (item.type === 'number') {
         rules = [
@@ -554,7 +555,7 @@
           if (this.record.linkField) {
             type = 'link'
           }
-          content = <DataTable type={type} display={this.record.display} linkSubFields={[]} transfield={{}} fields={this.record.fields || []} onChange={this.changeOptions}/>
+          content = <DataTable type={type} multiple={this.record.multiple} display={this.record.display} linkSubFields={[]} transfield={{}} fields={this.record.fields || []} onChange={this.changeOptions}/>
         }
       } else if (item.type === 'fields') {
         span = 24
@@ -619,7 +620,7 @@
         if (!err) {
           values.uuid = this.props.card.uuid
           // 涓嬫媺鑿滃崟鎴栬仈鍔ㄨ彍鍗�
-          if (['multiselect', 'select', 'link'].includes(values.type)) {
+          if (['multiselect', 'select', 'link', 'radio'].includes(values.type)) {
             if (values.resourceType === '0') {
               values.options = values.options || []
               values.dataSource = ''
@@ -665,10 +666,15 @@
               values.options = []
             }
           } else if (values.type === 'checkcard') {
+            if (values.multiple === 'dropdown' && values.display !== 'text') {
+              values.multiple = 'false'
+            }
+
             if (values.resourceType === '0') {
               values.options = values.options || []
               values.options = values.options.map(m => {
                 m.ParentID = m.ParentID || ''
+                m.pid = m.pid || ''
                 return m
               })
 
@@ -750,7 +756,7 @@
 
           ['linkField', 'valueField', 'valueText', 'orderBy'].forEach(item => {
             if (values[item]) {
-              values[item] = values[item].replace(/\s* | \t* | \v* | \r*/ig, '')
+              values[item] = values[item].replace(/\s+|\t+|\v+|\r+/ig, '')
             }
           })
 
diff --git a/src/templates/sharecomponent/searchcomponent/settingform/index.jsx b/src/templates/sharecomponent/searchcomponent/settingform/index.jsx
index 1adb220..913d5a6 100644
--- a/src/templates/sharecomponent/searchcomponent/settingform/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/settingform/index.jsx
@@ -12,14 +12,16 @@
   }
 
   state = {
-    advanceType: ''
+    advanceType: '',
+    show: ''
   }
 
   UNSAFE_componentWillMount () {
     const { setting } = this.props
 
     this.setState({
-      advanceType: setting.advanceType || 'modal'
+      advanceType: setting.advanceType || 'modal',
+      show: setting.show || 'true'
     })
   }
 
@@ -39,7 +41,7 @@
   render() {
     const { setting } = this.props
     const { getFieldDecorator } = this.props.form
-    const { advanceType } = this.state
+    const { advanceType, show } = this.state
 
     const formItemLayout = {
       labelCol: {
@@ -60,7 +62,7 @@
               {getFieldDecorator('show', {
                 initialValue: setting.show || 'true'
               })(
-                <Radio.Group>
+                <Radio.Group onChange={(e) => this.setState({show: e.target.value})}>
                   <Radio value="true">鏄剧ず</Radio>
                   <Radio value="false">闅愯棌</Radio>
                 </Radio.Group>
@@ -152,6 +154,18 @@
               })(<InputNumber min={0} precision={0} onPressEnter={this.props.inputSubmit}/>)}
             </Form.Item>
           </Col>
+          {show === 'true' ? <Col span={12}>
+            <Form.Item label="閲嶇疆鏃�">
+              {getFieldDecorator('resetContrl', {
+                initialValue: setting.resetContrl || 'init',
+              })(
+                <Radio.Group>
+                  <Radio value="init">鎭㈠鍒濆鍊�</Radio>
+                  <Radio value="clear">娓呯┖</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
         </Row>
       </Form>
     )
diff --git a/src/templates/sharecomponent/settingcalcomponent/index.jsx b/src/templates/sharecomponent/settingcalcomponent/index.jsx
deleted file mode 100644
index d1d7909..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/index.jsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Modal } from 'antd'
-import { SettingOutlined } from '@ant-design/icons'
-
-import VerifyCard from './verifycard'
-import './index.scss'
-
-class DataSource extends Component {
-  static propTpyes = {
-    config: PropTypes.any,
-    MenuID: PropTypes.string,
-    updateConfig: PropTypes.func
-  }
-
-  state = {
-    sourcelist: [],
-    visible: false,
-    loading: false,
-    setting: null
-  }
-
-  UNSAFE_componentWillMount () {
-    const { config } = this.props
-
-    this.setState({setting: fromJS(config.setting).toJS()})
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  editDataSource = () => {
-    this.setState({
-      visible: true
-    })
-  }
-
-  verifySubmit = () => {
-    const { config } = this.props
-
-    this.setState({loading: true})
-    this.verifyRef.submitDataSource().then(res => {
-      if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-        window.GLOB.funcs.forEach(m => {
-          let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
-          res.scripts.forEach(item => {
-            item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-          })
-          if (res.setting.dataresource) {
-            res.setting.dataresource = res.setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-          }
-        })
-      }
-
-      res.show = config.setting.show || 'true'
-      res.advanceType = config.setting.advanceType || 'modal'
-      res.advanceWidth = config.setting.advanceWidth || 1000
-      res.drawerPlacement = config.setting.drawerPlacement || 'right'
-      res.searchRatio = config.setting.searchRatio || 6
-      res.searchLwidth = config.setting.searchLwidth !== undefined ? config.setting.searchLwidth : 33.3
-
-      this.setState({loading: false, visible: false})
-      this.props.updateConfig({...config, ...res})
-    }, () => {
-      this.setState({loading: false})
-    })
-  }
-
-  render () {
-    const { config } = this.props
-    const { visible, loading } = this.state
-
-    return (
-      <div className="model-datasource">
-        <SettingOutlined onClick={() => this.editDataSource()} />
-        <Modal
-          wrapClassName="mk-pop-modal"
-          visible={visible}
-          width={'75vw'}
-          maskClosable={false}
-          okText="鎻愪氦"
-          onOk={this.verifySubmit}
-          confirmLoading={loading}
-          onCancel={() => { this.setState({ visible: false }) }}
-          destroyOnClose
-        >
-          <VerifyCard
-            config={config}
-            menuId={this.props.config.uuid}
-            searches={config.search}
-            wrappedComponentRef={(inst) => this.verifyRef = inst}
-          />
-        </Modal>
-      </div>
-    )
-  }
-}
-
-export default DataSource
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcalcomponent/index.scss b/src/templates/sharecomponent/settingcalcomponent/index.scss
deleted file mode 100644
index fdc03f8..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/index.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.model-datasource {
-  position: absolute;
-  right: 7px;
-  top: 5px;
-  z-index: 1;
-
-  >.anticon-setting {
-    font-size: 18px;
-    padding: 10px;
-  }
-}
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/columnform/index.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/columnform/index.jsx
deleted file mode 100644
index 2539ee3..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/columnform/index.jsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Select, Button, Input } from 'antd'
-import './index.scss'
-
-
-class UniqueForm extends Component {
-  static propTpyes = {
-    columnChange: PropTypes.func  // 淇敼鍑芥暟
-  }
-
-  state = {
-    editItem: null // 缂栬緫鍏冪礌
-  }
-
-  edit = (record) => {
-    this.setState({
-      editItem: record
-    })
-
-    this.props.form.setFieldsValue({
-      label: record.label,
-      field: record.field,
-      datatype: record.datatype
-    })
-  }
-
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    this.props.form.validateFieldsAndScroll((err, values) => {
-      if (!err) {
-        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
-
-        this.setState({
-          editItem: null
-        }, () => {
-          this.props.columnChange(values)
-        })
-        this.props.form.setFieldsValue({
-          label: '',
-          field: ''
-        })
-      }
-    })
-  }
-
-  render() {
-    const { getFieldDecorator } = this.props.form
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <Form {...formItemLayout} className="verify-form" id="verifycard1">
-        <Row gutter={24}>
-          <Col span={7}>
-            <Form.Item label={'鍚嶇О'}>
-              {getFieldDecorator('label', {
-                initialValue: '',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ュ悕绉�!'
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" />)}
-            </Form.Item>
-          </Col>
-          <Col span={7}>
-            <Form.Item label={'瀛楁'}>
-              {getFieldDecorator('field', {
-                initialValue: '',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ュ瓧娈�!'
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" />)}
-            </Form.Item>
-          </Col>
-          <Col span={7}>
-            <Form.Item label="鏁版嵁绫诲瀷">
-              {getFieldDecorator('datatype', {
-                initialValue: '',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鏁版嵁绫诲瀷!'
-                  }
-                ]
-              })(
-                <Select>
-                  <Select.Option value="Nvarchar(50)"> Nvarchar(50) </Select.Option>
-                  <Select.Option value="Nvarchar(100)"> Nvarchar(100) </Select.Option>
-                  <Select.Option value="Nvarchar(512)"> Nvarchar(512) </Select.Option>
-                  <Select.Option value="Nvarchar(1024)"> Nvarchar(1024) </Select.Option>
-                  <Select.Option value="Nvarchar(2048)"> Nvarchar(2048) </Select.Option>
-                  <Select.Option value="Nvarchar(max)"> Nvarchar(max) </Select.Option>
-                  <Select.Option value="Int"> Int </Select.Option>
-                  <Select.Option value="Decimal(18,0)"> Decimal(18,0) </Select.Option>
-                  <Select.Option value="Decimal(18,1)"> Decimal(18,1) </Select.Option>
-                  <Select.Option value="Decimal(18,2)"> Decimal(18,2) </Select.Option>
-                  <Select.Option value="Decimal(18,3)"> Decimal(18,3) </Select.Option>
-                  <Select.Option value="Decimal(18,4)"> Decimal(18,4) </Select.Option>
-                  <Select.Option value="Decimal(18,5)"> Decimal(18,5) </Select.Option>
-                  <Select.Option value="Decimal(18,6)"> Decimal(18,6) </Select.Option>
-                  <Select.Option value="Decimal(18,7)"> Decimal(18,7) </Select.Option>
-                  <Select.Option value="Decimal(18,8)"> Decimal(18,8) </Select.Option>
-                  <Select.Option value="Decimal(18,9)"> Decimal(18,9) </Select.Option>
-                  <Select.Option value="Decimal(18,10)"> Decimal(18,10) </Select.Option>
-                  <Select.Option value="Decimal(18,11)"> Decimal(18,11) </Select.Option>
-                  <Select.Option value="Decimal(18,12)"> Decimal(18,12) </Select.Option>
-                  <Select.Option value="Decimal(18,13)"> Decimal(18,13) </Select.Option>
-                  <Select.Option value="Decimal(18,14)"> Decimal(18,14) </Select.Option>
-                  <Select.Option value="Decimal(18,15)"> Decimal(18,15) </Select.Option>
-                  <Select.Option value="Decimal(18,16)"> Decimal(18,16) </Select.Option>
-                  <Select.Option value="Decimal(18,17)"> Decimal(18,17) </Select.Option>
-                  <Select.Option value="Decimal(18,18)"> Decimal(18,18) </Select.Option>
-                  {/* <Select.Option value="date"> date </Select.Option> */}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={3} className="add">
-            <Button onClick={this.handleConfirm} type="primary" className="mk-green">
-              淇濆瓨
-            </Button>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(UniqueForm)
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/columnform/index.scss b/src/templates/sharecomponent/settingcalcomponent/verifycard/columnform/index.scss
deleted file mode 100644
index e69de29..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/columnform/index.scss
+++ /dev/null
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
deleted file mode 100644
index 1280859..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
+++ /dev/null
@@ -1,440 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { fromJS } from 'immutable'
-import { Form, Tabs, Table, Popconfirm, notification, Modal, Spin } from 'antd'
-import { EditOutlined, DeleteOutlined } from '@ant-design/icons'
-import moment from 'moment'
-
-import Api from '@/api'
-import Utils from '@/utils/utils.js'
-
-import asyncComponent from '@/utils/asyncComponent'
-import ColForm from './columnform'
-import SettingForm from './settingform'
-import SettingUtils from './utils'
-import './index.scss'
-
-const { TabPane } = Tabs
-
-const CustomScript = asyncComponent(() => import('@/templates/zshare/customscript'))
-const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
-
-class VerifyCard extends Component {
-  static propTpyes = {
-    config: PropTypes.object,        // 鏁版嵁婧愪俊鎭�
-    menuId: PropTypes.string,        // 鑿滃崟Id
-    searches: PropTypes.array,       // 鎼滅储鏉′欢
-  }
-
-  state = {
-    columns: [],
-    activeKey: 'setting',
-    loading: false,
-    usefulfields: '',
-    defaultsql: '',         // 榛樿Sql
-    colColumns: [
-      {
-        title: '鍚嶇О',
-        dataIndex: 'label',
-        width: '25%'
-      },
-      {
-        title: '瀛楁',
-        dataIndex: 'field',
-        width: '25%'
-      },
-      {
-        title: '鏁版嵁绫诲瀷',
-        dataIndex: 'datatype',
-        width: '25%',
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        width: '25%',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          (<div>
-            <span className="operation-btn" title="缂栬緫" onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><EditOutlined /></span>
-            <Popconfirm
-              overlayClassName="popover-confirm"
-              title="纭畾鍒犻櫎鍚�?"
-              onConfirm={() => this.deleteColumn(record)
-            }>
-              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
-            </Popconfirm>
-          </div>)
-      }
-    ]
-  }
-
-  UNSAFE_componentWillMount() {
-    const { config } = this.props
-
-    let _setting = fromJS(config.setting).toJS()
-    let _scripts = fromJS(config.scripts).toJS()
-
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(m => {
-        let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
-        _scripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-        if (_setting.dataresource) {
-          _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
-        }
-      })
-    }
-
-    this.setState({
-      setting: _setting,
-      columns: fromJS(config.columns).toJS(),
-      scripts: _scripts
-    })
-  }
-
-  columnChange = (values) => {
-    let columns = fromJS(this.state.columns).toJS()
-
-    if (values.uuid) {
-      columns = columns.map(item => {
-        if (item.uuid === values.uuid) {
-          return values
-        } else {
-          return item
-        }
-      })
-    } else {
-      values.uuid = Utils.getuuid()
-      columns.push(values)
-    }
-
-    this.setState({ columns })
-  }
-
-  deleteColumn = (record) => {
-    this.setState({ columns: this.state.columns.filter(item => item.uuid !== record.uuid) })
-  }
-
-  handleEdit = (record) => {
-    this.contrastForm.edit(record)
-  }
-
-  changeTab = (val) => {
-    const { activeKey, setting } = this.state
-
-    if (activeKey === 'setting') {
-      this.settingForm.handleConfirm().then(res => {
-        if (res.interType !== 'system' && val === 'scripts') {
-          notification.warning({
-            top: 92,
-            message: '浣跨敤绯荤粺鎺ュ彛鏃讹紝鎵嶅彲浠ヨ缃嚜瀹氫箟鑴氭湰锛�',
-            duration: 5
-          })
-          return
-        }
-
-        this.setState({
-          setting: res
-        }, () => {
-          if (res.interType === 'system') { // 绯荤粺鎺ュ彛锛宻ql楠岃瘉
-            this.setState({loading: true})
-
-            this.sqlverify(() => { // 楠岃瘉鎴愬姛
-              this.setState({
-                activeKey: val,
-                loading: false
-              })
-            }, () => {             // 楠岃瘉澶辫触
-              this.setState({
-                activeKey: val,
-                loading: false
-              })
-            }, activeKey)
-          } else {
-            this.setState({
-              activeKey: val
-            })
-          }
-        })
-      })
-    } else if (activeKey === 'columns') {
-      if (setting.interType !== 'system' && val === 'scripts') {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤绯荤粺鎺ュ彛鏃讹紝鎵嶅彲浠ヨ缃嚜瀹氫箟鑴氭湰锛�',
-          duration: 5
-        })
-        return
-      }
-
-      this.setState({
-        activeKey: val
-      })
-    } else if (activeKey === 'scripts') {
-      let _loading = false
-      if (this.scriptsForm && this.scriptsForm.state.editItem) {
-        _loading = true
-      } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
-        _loading = true
-      }
-
-      if (_loading) {
-        notification.warning({
-          top: 92,
-          message: '瀛樺湪鏈繚瀛樿剼鏈紒',
-          duration: 5
-        })
-      }
-
-      this.setState({loading: true})
-      this.sqlverify(() => { // 楠岃瘉鎴愬姛
-        this.setState({
-          activeKey: val,
-          loading: false
-        })
-      }, () => {             // 楠岃瘉澶辫触
-        this.setState({
-          activeKey: val,
-          loading: false
-        })
-      }, activeKey)
-    }
-  }
-
-  submitDataSource = () => {
-    const { activeKey, setting, columns, scripts } = this.state
-
-    return new Promise((resolve, reject) => {
-      if (activeKey === 'setting') {
-        this.settingForm.handleConfirm().then(res => {
-          this.setState({
-            setting: res
-          }, () => {
-            this.sqlverify(() => { resolve({setting: res, columns, scripts }) }, reject, 'submit')
-          })
-        }, () => {
-          reject()
-        })
-      } else if (activeKey === 'columns') {
-        this.sqlverify(() => { resolve({setting, columns, scripts }) }, reject, 'submit')
-      } else if (activeKey === 'scripts') {
-        let _loading = false
-        if (this.scriptsForm && this.scriptsForm.state.editItem) {
-          _loading = true
-        } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
-          _loading = true
-        }
-
-        if (_loading) {
-          notification.warning({
-            top: 92,
-            message: '瀛樺湪鏈繚瀛樿剼鏈紝璇风偣鍑荤‘瀹氫繚瀛橈紝鎴栫偣鍑诲彇娑堟斁寮冧慨鏀癸紒',
-            duration: 5
-          })
-          reject()
-          return
-        }
-
-        this.sqlverify(() => { resolve({setting, columns, scripts }) }, reject, 'submit')
-      }
-    })
-  }
-
-  sqlverify = (resolve, reject, type, testScripts) => {
-    const { searches, config } = this.props
-    const { columns, setting, scripts } = this.state
-
-    if (setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熸帴鍙f椂锛屼笉闇�瑕乻ql楠岃瘉
-      resolve()
-      return
-    }
-
-    let _scripts = []
-
-    if (testScripts) {
-      _scripts = testScripts.filter(item => item.status !== 'false')
-    } else {
-      _scripts = scripts.filter(item => item.status !== 'false')
-    }
-
-    if (type === 'submit' && setting.execute === 'false' && _scripts.length === 0) {
-      notification.warning({
-        top: 92,
-        message: '涓嶆墽琛岄粯璁ql鏃讹紝璇锋坊鍔犺嚜瀹氫箟鑴氭湰锛�',
-        duration: 5
-      })
-      reject()
-      return
-    }
-
-    // 涓嶄娇鐢ㄩ粯璁ql鍒囨崲
-    if (type === 'setting' && setting.execute === 'false') {
-      resolve()
-    } else if (type === 'scripts' && _scripts.length === 0) {
-      resolve()
-    } else if (setting.execute !== 'false' || _scripts.length > 0) {
-      let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      let param = {
-        func: 's_debug_sql',
-        exec_type: 'y',
-        LText: SettingUtils.getDebugSql(setting, _scripts, columns, this.getRegOptions(searches), config.calendar, config.urlFields, timestamp)
-      }
-      param.LText = Utils.formatOptions(param.LText)
-      param.timestamp = timestamp
-      param.secretkey = Utils.encrypt('', timestamp)
-      
-      Api.genericInterface(param).then(result => {
-        if (result.status) {
-          resolve()
-        } else {
-          reject()
-          Modal.error({
-            title: result.message
-          })
-        }
-      })
-    } else {
-      resolve()
-    }
-  }
-
-  getRegOptions = (searches) => {
-    if (!searches || searches.length === 0) return []
-
-    let options = []
-    let fieldmap = new Map()
-    searches.forEach(search => {
-      let item = {
-        key: search.field,
-        value: '0'
-      }
-
-      if (fieldmap.has(item.key)) {
-        item.key = item.key + '1'
-      }
-
-      fieldmap.set(item.key, true)
-
-      if (search.type === 'group') {
-        options.push({
-          key: search.field,
-          value: '0'
-        })
-        options.push({
-          key: search.datefield,
-          value: '0'
-        })
-        options.push({
-          key: search.datefield + '1',
-          value: '0'
-        })
-        options.push(item)
-      } else if (['datemonth', 'dateweek', 'daterange'].includes(search.type)) {
-        options.push(item)
-        options.push({
-          key: item.key + '1',
-          value: '0'
-        })
-      } else if (search.type === 'text' || search.type === 'select') {
-        item.key.split(',').forEach(field => {
-          let cell = JSON.parse(JSON.stringify(item))
-          cell.key = field
-
-          options.push(cell)
-        })
-      } else {
-        options.push(item)
-      }
-    })
-
-    return options
-  }
-
-  updatefields = (columns) => {
-    this.setState({
-      columns: columns
-    })
-  }
-
-  // 鑷畾涔夎剼鏈慨鏀�
-  scriptsChange = (scripts) => {
-    return new Promise((resolve, reject) => {
-      this.sqlverify(resolve, reject, 'verify', scripts)
-    })
-  }
-
-  // 鑷畾涔夎剼鏈洿鏂�
-  scriptsUpdate = (scripts) => {
-    this.setState({scripts})
-  }
-
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-  }
-
-  render() {
-    const { config } = this.props
-    const { columns, setting, scripts, colColumns, activeKey, loading } = this.state
-
-    return (
-      <div className="model-verify-card-box-tab">
-        {loading && <Spin size="large" />}
-        <Tabs activeKey={activeKey} className="verify-card-box" onChange={this.changeTab}>
-          <TabPane tab="鏁版嵁婧�" key="setting">
-            <SettingForm
-              menuId={this.props.menuId}
-              columns={columns}
-              setting={setting}
-              scripts={scripts}
-              wrappedComponentRef={(inst) => this.settingForm = inst}
-            />
-          </TabPane>
-          <TabPane tab="瀛楁闆�" key="columns">
-            <ColForm
-              columnChange={this.columnChange}
-              wrappedComponentRef={(inst) => this.contrastForm = inst}
-            />
-            <FieldsComponent
-              config={{...config, columns}}
-              type="fields"
-              updatefield={this.updatefields}
-            />
-            <Table
-              bordered
-              rowKey="uuid"
-              className="custom-table"
-              dataSource={columns}
-              columns={colColumns}
-              pagination={false}
-            />
-          </TabPane>
-          <TabPane tab={
-            <span>
-              鑷畾涔夎剼鏈�
-              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
-            </span>
-          } key="scripts" id="mk-setting-scripts">
-            <CustomScript
-              setting={setting}
-              scripts={scripts}
-              urlFields={config.urlFields}
-              defaultSql={this.state.defaultsql}
-              searches={this.props.searches}
-              scriptsChange={this.scriptsChange}
-              scriptsUpdate={this.scriptsUpdate}
-              wrappedComponentRef={(inst) => this.scriptsForm = inst}
-            />
-          </TabPane>
-        </Tabs>
-      </div>
-    )
-  }
-}
-
-export default Form.create()(VerifyCard)
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss
deleted file mode 100644
index 420b3ef..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss
+++ /dev/null
@@ -1,80 +0,0 @@
-.model-verify-card-box-tab {
-  .ant-spin {
-    position: absolute;
-    left: calc(50% - 16px);
-    top: 220px;
-    z-index: 1;
-  }
-  .verify-card-box {
-    .count-tip {
-      position: absolute;
-      top: 0px;
-      color: #1890ff;
-      font-size: 12px;
-    }
-    .ant-tabs-nav-scroll {
-      text-align: center;
-    }
-    .ant-tabs-content {
-      min-height: 40vh;
-    }
-    table tr td {
-      word-wrap: break-word;
-      word-break: break-word;
-    }
-    .quickly-add {
-      position: relative;
-      width: 100px;
-      float: right;
-      top: -5px;
-      z-index: 2;
-    }
-    .verify-form {
-      .sql {
-        .ant-col-sm-8 {
-          width: 10.5%;
-        }
-        .ant-col-sm-16 {
-          width: 89.5%;
-          padding-top: 4px;
-        }
-      }
-      .sqlfield {
-        .ant-form-item {
-          margin-bottom: 5px;
-        }
-        .ant-form-item-control {
-          line-height: 24px;
-        }
-        .ant-form-item-label {
-          line-height: 25px;
-        }
-        .ant-form-item-children {
-          line-height: 22px;
-        }
-        .ant-col-sm-8 {
-          width: 10.5%;
-        }
-        .ant-col-sm-16 {
-          width: 89.5%;
-        }
-      }
-      .add {
-        padding-top: 4px;
-      }
-    }
-    .custom-table .ant-empty {
-      margin: 20px 8px!important;
-    }
-    .errorval {
-      display: inline-block;
-      width: 30px;
-    }
-    .operation-btn {
-      display: inline-block;
-      font-size: 16px;
-      padding: 0 5px;
-      cursor: pointer;
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx
deleted file mode 100644
index 6b8f830..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx
+++ /dev/null
@@ -1,330 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Radio, Tooltip, notification } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-import moment from 'moment'
-
-import Api from '@/api'
-import { formRule } from '@/utils/option.js'
-import Utils from '@/utils/utils.js'
-import CodeMirror from '@/templates/zshare/codemirror'
-// import './index.scss'
-
-const { TextArea } = Input
-
-class SettingForm extends Component {
-  static propTpyes = {
-    menuId: PropTypes.string,     // 鑿滃崟Id
-    setting: PropTypes.object,    // 鏁版嵁婧愰厤缃�
-    columns: PropTypes.array,     // 鍒楄缃�
-    scripts: PropTypes.array,     // 鑷畾涔夎剼鏈�
-  }
-
-  state = {
-    interType: this.props.setting.interType || 'system',
-    usefulFields: []
-  }
-
-  UNSAFE_componentWillMount() {
-    let usefulFields = sessionStorage.getItem('permFuncField')
-    if (usefulFields) {
-      try {
-        usefulFields = JSON.parse(usefulFields)
-      } catch (e) {
-        usefulFields = []
-      }
-    } else {
-      usefulFields = []
-    }
-
-    this.setState({
-      usefulFields
-    })
-  }
-
-  handleConfirm = () => {
-    const { setting } = this.props
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          // 鏁版嵁婧愬墠绔獙璇�
-          if (values.interType === 'system' && values.execute !== 'false' && !values.dataresource) {
-            notification.warning({
-              top: 92,
-              message: '璇峰~鍐欐暟鎹簮锛�',
-              duration: 5
-            })
-            reject()
-            return
-          } else if (values.interType === 'system' && values.execute !== 'false' && values.dataresource) {
-            let _quot = values.dataresource.match(/'{1}/g)
-            let _lparen = values.dataresource.match(/\({1}/g)
-            let _rparen = values.dataresource.match(/\){1}/g)
-
-            _quot = _quot ? _quot.length : 0
-            _lparen = _lparen ? _lparen.length : 0
-            _rparen = _rparen ? _rparen.length : 0
-
-            if (_quot % 2 !== 0) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑\'蹇呴』鎴愬鍑虹幇',
-                duration: 5
-              })
-              reject()
-              return
-            } else if (_lparen !== _rparen) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑()蹇呴』鎴愬鍑虹幇',
-                duration: 5
-              })
-              reject()
-              return
-            } else if (/--/ig.test(values.dataresource)) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜板瓧绗� -- 锛屾敞閲婅鐢� /*鍐呭*/',
-                duration: 5
-              })
-              reject()
-              return
-            } else if (/,,/ig.test(values.dataresource)) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜拌繛缁殑鑻辨枃閫楀彿锛�,,锛�',
-                duration: 5
-              })
-              reject()
-              return
-            }
-
-            let error = Utils.verifySql(values.dataresource)
-
-            if (error) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error,
-                duration: 5
-              })
-              reject()
-              return
-            }
-          }
-
-          // 鏁版嵁婧愪繚瀛�
-          if (
-            values.interType === 'system' && values.execute !== 'false' &&
-            /[^\s]+\s+[^\s]+/ig.test(values.dataresource) && setting.dataresource !== values.dataresource
-          ) {
-            let param = {
-              func: 's_DataSrc_Save',
-              LText: values.dataresource,
-              MenuID: this.props.menuId
-            }
-    
-            param.LText = Utils.formatOptions(param.LText)
-            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-            param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-    
-            Api.genericInterface(param)
-          }
-
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  onRadioChange = (e, key) => {
-    let value = e.target.value
-
-    if (key === 'interType') {
-      this.setState({
-        interType: value
-      })
-    }
-  }
-
-  render() {
-    const { setting } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { interType, usefulFields } = this.state
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    let tooltip = null
-    let rules = []
-
-    if (usefulFields.length > 0) {
-      tooltip = '寮�澶村彲鐢ㄥ瓧绗︼細' + usefulFields.join(', ')
-      let str = '^(' + usefulFields.join('|') + ')'
-      let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
-
-      rules.push({
-        required: true,
-        message: '璇疯緭鍏ュ唴閮ㄥ嚱鏁�!'
-      }, {
-        pattern: _patten,
-        message: formRule.func.innerMessage
-      })
-    }
-
-    return (
-      <Form {...formItemLayout}>
-        <Row gutter={24}>
-          <Col span={8}>
-            <Form.Item label="琛ㄥ悕">
-              {getFieldDecorator('tableName', {
-                initialValue: setting.tableName,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ヨ〃鍚�!'
-                  },
-                  {
-                    max: 50,
-                    message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!'
-                  }
-                ]
-              })(<Input placeholder={''} autoComplete="off" />)}
-            </Form.Item>
-          </Col>
-          <Col span={8}>
-            <Form.Item label="鎺ュ彛绫诲瀷">
-              {getFieldDecorator('interType', {
-                initialValue: interType,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鎺ュ彛绫诲瀷!'
-                  },
-                ]
-              })(
-              <Radio.Group onChange={(e) => {this.onRadioChange(e, 'interType')}}>
-                <Radio value="system">绯荤粺</Radio>
-                <Radio value="inner">鍐呴儴</Radio>
-                <Radio value="outer">澶栭儴</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col>
-          {interType === 'inner' ? <Col span={8}>
-            <Form.Item label={tooltip ?
-              <Tooltip placement="topLeft" title={tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鍐呴儴鍑芥暟
-              </Tooltip> : '鍐呴儴鍑芥暟'
-            }>
-              {getFieldDecorator('innerFunc', {
-                initialValue: setting.innerFunc || '',
-                rules: rules
-              })(<Input placeholder={''} autoComplete="off" />)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'outer' ? <Col span={8}>
-            <Form.Item label="澶栭儴鍑芥暟">
-              {getFieldDecorator('outerFunc', {
-                initialValue: setting.outerFunc || '',
-                rules: [
-
-                ]
-              })(<Input placeholder={''} autoComplete="off" />)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'outer' ? <Col span={24} className="mk-through-line3">
-            <Form.Item label="鎺ュ彛鍦板潃">
-              {getFieldDecorator('interface', {
-                initialValue: setting.interface || '',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ユ帴鍙e湴鍧�!'
-                  },
-                ]
-              })(<TextArea rows={2}/>)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'system' ? <Col span={24} className="mk-through-line3">
-            <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('dataresource', {
-                initialValue: setting.dataresource || ''
-              })(<CodeMirror />)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'system' ? <Col span={8}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title={'鏌ヨ鏃讹紝鎼滅储鏉′欢浠here鏉′欢鎷兼帴杩涘叆sql锛岀粺璁℃椂锛屽皢鏁版嵁婧愪腑浠モ�淍+鎼滅储瀛楁+@鈥濈殑鍐呭锛屼互鎼滅储鏉′欢涓殑鍊艰繘琛屾浛鎹㈠悗锛屾彁浜ゆ煡璇紝娉細鏌ヨ绫诲瀷浠呭湪浣跨敤绯荤粺鍑芥暟鏃舵湁鏁堛��'}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鏌ヨ绫诲瀷
-              </Tooltip>
-            }>
-              {getFieldDecorator('queryType', {
-                initialValue: setting.queryType || 'query'
-              })(
-              <Radio.Group>
-                <Radio value="query">鏌ヨ</Radio>
-                <Radio value="statistics">缁熻</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          {/* <Col span={8}>
-            <Form.Item label="涓婚敭">
-              {getFieldDecorator('primaryKey', {
-                initialValue: setting.primaryKey || ''
-              })(
-                <Select>
-                  {columns.map((option, i) =>
-                    <Select.Option key={i} value={option.field}>
-                      {option.label}
-                    </Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col> */}
-          {interType === 'system' ? <Col span={8}>
-            <Form.Item label="榛樿sql">
-              {getFieldDecorator('execute', {
-                initialValue: setting.execute || 'true'
-              })(
-              <Radio.Group>
-                <Radio value="true">鎵ц</Radio>
-                <Radio value="false">涓嶆墽琛�</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          <Col span={8}>
-            <Form.Item label="鍒濆鍖�">
-              {getFieldDecorator('onload', {
-                initialValue: setting.onload || 'true'
-              })(
-              <Radio.Group>
-                <Radio value="true">鍔犺浇鏁版嵁</Radio>
-                <Radio value="false">涓嶅姞杞芥暟鎹�</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.scss b/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.scss
deleted file mode 100644
index e69de29..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.scss
+++ /dev/null
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx
deleted file mode 100644
index 5eb0bce..0000000
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx
+++ /dev/null
@@ -1,145 +0,0 @@
-
-export default class SettingUtils {
-  /**
-   * @description 鐢熸垚椤甸潰鏌ヨ璇彞
-   * @return {String}  scripts       鑷畾涔夎剼鏈�
-   * @return {String}  searches      鎼滅储鏉′欢
-   * @return {Object}  setting       椤甸潰璁剧疆
-   * @return {Array}   columns       鏄剧ず瀛楁
-   */
-  static getDebugSql (setting, scripts, columns, searches, calendar, urlFields = [], timestamp) {
-    let sql = ''
-    let _dataresource = ''
-    let _customScript = ''
-    let arr_field = columns.map(item => item.field).join(',')
-
-    if (scripts.length > 0) {
-      scripts.forEach(item => {
-        _customScript += `
-          ${item.sql}
-        `
-      })
-    }
-
-    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}
-      `
-    }
-
-    if (setting.execute !== 'false') {
-      _dataresource = setting.dataresource || ''
-    }
-
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(item => {
-        let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
-        _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-        _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-      })
-    }
-    
-    _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${timestamp}'`)
-    _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${timestamp}'`)
-    _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
-    _customScript = _customScript.replace(/@\$|\$@/ig, '')
-    
-    // 澶栬仈鏁版嵁搴撴浛鎹�
-    if (window.GLOB.externalDatabase !== null) {
-      _dataresource = _dataresource.replace(/@db@/ig, window.GLOB.externalDatabase)
-      _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase)
-    }
-
-    urlFields.forEach(field => {
-      _dataresource = _dataresource.replace(new RegExp('@' + field + '@', 'ig'), `'0'`)
-      _customScript = _customScript.replace(new RegExp('@' + field + '@', 'ig'), `'0'`)
-    })
-    
-    // 姝e垯鏇挎崲
-    let _regoptions = []
-    let _search = ''
-
-    if (setting.queryType === 'statistics' || _customScript) {
-      _regoptions = searches.map(item => {
-        return {
-          reg: new RegExp('@' + item.key + '@', 'ig'),
-          value: `'0'`
-        }
-      })
-    }
-
-    // 鏃ュ巻涓殑骞翠唤鏇挎崲
-    if (calendar.refresh === 'true') {
-      _regoptions.push({
-        reg: new RegExp('@calendarDate@', 'ig'),
-        value: `'1970-01-01 00:00:00.000'`
-      }, {
-        reg: new RegExp('@calendarDate1@', 'ig'),
-        value: `'2030-12-31 23:59:59.999'`
-      })
-    }
-
-    _regoptions.push({
-      reg: new RegExp('@userName@', 'ig'),
-      value: `''`
-    }, {
-      reg: new RegExp('@fullName@', 'ig'),
-      value: `''`
-    })
-
-    if ((setting.queryType === 'statistics' || calendar.refresh === 'true') && _dataresource) {
-      _regoptions.forEach(item => {
-        _dataresource = _dataresource.replace(item.reg, item.value)
-      })
-
-      _search = ''
-    }
-
-    if (_customScript) {
-      _regoptions.push({
-        reg: new RegExp('@orderBy@', 'ig'),
-        value: setting.order
-      })
-      if (setting.laypage !== 'false') {
-        _regoptions.push({
-          reg: new RegExp('@pageSize@', 'ig'),
-          value: 10
-        }, {
-          reg: new RegExp('@pageIndex@', 'ig'),
-          value: 1
-        })
-      }
-      _regoptions.forEach(item => {
-        _customScript = _customScript.replace(item.reg, item.value)
-      })
-    }
-
-    // 鏁版嵁婧愬鐞�, 瀛樺湪鏄剧ず鍒楁椂 
-    if (arr_field && _dataresource) {
-      if (/\s/.test(_dataresource)) {
-        _dataresource = '(' + _dataresource + ') tb'
-      }
-
-      _dataresource = `/*system_query*/select ${setting.laypage !== 'false' ?  'top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage !== 'false' ?  'where rows > 0' : ''} order by tmptable.rows`
-    }
-
-    if (_customScript) {
-      sql = `/* sql 楠岃瘉 */
-        ${_customScript}
-        ${_dataresource}
-        aaa:
-        if @ErrorCode!=''
-          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
-      `
-    } else {
-      sql = `/* 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 =''
-        ${_dataresource}`
-    }
-    sql = sql.replace(/\n\s{8}/ig, '\n')
-    console.info(sql)
-    sql = sql.replace(/\n/g, ' ')
-    
-    return sql
-  }
-}
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcomponent/index.jsx b/src/templates/sharecomponent/settingcomponent/index.jsx
index 3f9e0ce..6d9bb70 100644
--- a/src/templates/sharecomponent/settingcomponent/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/index.jsx
@@ -4,10 +4,7 @@
 import { Modal, Button } from 'antd'
 import { SettingOutlined } from '@ant-design/icons'
 
-import Utils, { FuncUtils } from '@/utils/utils.js'
 import SettingForm from './settingform'
-import CreateFunc from '@/templates/zshare/createfunc'
-import CreateInterface from '@/templates/zshare/createinterface'
 
 // import './index.scss'
 
@@ -73,43 +70,26 @@
     })
   }
 
-  /**
-   * @description 鍒涘缓琛ㄦ牸瀛樺偍杩囩▼
-   */
-  tableCreatFunc = () => {
-    const { config } = this.props
-    const { menu } = this.state
+  // /**
+  //  * @description 鍒涘缓琛ㄦ牸鎺ュ彛锛堣鍑猴級
+  //  */
+  // tableCreatInterface = () => {
+  //   const { config } = this.props
+  //   const { menu } = this.state
 
-    this.settingRef.handleConfirm('loading').then(setting => {
-      let res = this.resetSetting(setting, config.setting)
-      let _config = {...config, setting: res}
-      let newLText = Utils.formatOptions(FuncUtils.getTableFunc(setting.innerFunc, menu, _config)) // 鍒涘缓瀛樺偍杩囩▼sql
-      let DelText = Utils.formatOptions(FuncUtils.dropfunc(setting.innerFunc))          // 鍒犻櫎瀛樺偍杩囩▼sql
+  //   this.settingRef.handleConfirm('loading').then(setting => {
+  //     let res = this.resetSetting(setting, config.setting)
+  //     let _config = {...config, setting: res}
+  //     let _menu = {
+  //       type: config.Template === 'CommonTable' ? 'main' : 'subtable',
+  //       MenuID: menu.MenuID,
+  //       menuName: menu.MenuName,
+  //       menuNo: menu.MenuNo
+  //     }
 
-      this.refs.funcCreatComponent.exec(setting.innerFunc, newLText, DelText)
-    })
-  }
-
-  /**
-   * @description 鍒涘缓琛ㄦ牸鎺ュ彛锛堣鍑猴級
-   */
-  tableCreatInterface = () => {
-    const { config } = this.props
-    const { menu } = this.state
-
-    this.settingRef.handleConfirm('loading').then(setting => {
-      let res = this.resetSetting(setting, config.setting)
-      let _config = {...config, setting: res}
-      let _menu = {
-        type: config.Template === 'CommonTable' ? 'main' : 'subtable',
-        MenuID: menu.MenuID,
-        menuName: menu.MenuName,
-        menuNo: menu.MenuNo
-      }
-
-      this.refs.tableCreatInterface.triggerOutInterface(_menu, _config)
-    })
-  }
+  //     this.refs.tableCreatInterface.triggerOutInterface(_menu, _config)
+  //   })
+  // }
 
   resetSetting = (s, ori) => {
     let setting = fromJS(s).toJS()
@@ -121,6 +101,7 @@
     setting.drawerPlacement = ori.drawerPlacement || 'right'
     setting.searchRatio = ori.searchRatio || 6
     setting.searchLwidth = ori.searchLwidth !== undefined ? ori.searchLwidth : 33.3
+    setting.resetContrl = ori.resetContrl || 'init'
 
     if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
       window.GLOB.funcs.forEach(m => {
@@ -178,7 +159,7 @@
 
   render() {
     const { config } = this.props
-    const { visible, search, menu, record } = this.state
+    const { visible, search, menu } = this.state
 
     return (
       <>
@@ -191,8 +172,6 @@
           maskClosable={false}
           onCancel={() => { this.setState({ visible: false, loading: false })}}
           footer={[
-            record && record.interType === 'system' ? <CreateInterface key="interface" loading={this.state.interloading} ref="tableCreatInterface" trigger={this.tableCreatInterface}/> : null,
-            record && record.interType === 'inner' ? <CreateFunc key="create" ref="funcCreatComponent" trigger={this.tableCreatFunc}/> : null,
             <Button key="cancel" onClick={() => { this.setState({ visible: false, loading: false }) }}>鍙栨秷</Button>,
             <Button key="confirm" type="primary" loading={this.state.loading} onClick={this.settingSave}>纭畾</Button>
           ]}
@@ -202,7 +181,7 @@
             menu={menu}
             config={config}
             search={search}
-            updRecord={(record) => this.setState({record: fromJS(record).toJS()})}
+            updRecord={() => {}}
             wrappedComponentRef={(inst) => this.settingRef = inst}
           />
         </Modal>
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
index 29f51db..30cbbed 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
@@ -2,9 +2,7 @@
 import PropTypes from 'prop-types'
 import { Form, Row, Col, Input, Radio, Tooltip, notification, Select, InputNumber } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
-import moment from 'moment'
 
-import Api from '@/api'
 import { formRule } from '@/utils/option.js'
 import Utils from '@/utils/utils.js'
 import asyncComponent from '@/utils/asyncComponent'
@@ -72,7 +70,6 @@
   }
 
   handleConfirm = () => {
-    const { setting } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
@@ -140,24 +137,6 @@
               reject()
               return
             }
-          }
-
-          // 鏁版嵁婧愪繚瀛�
-          if (
-            values.interType === 'system' && values.default !== 'false' &&
-            /[^\s]+\s+[^\s]+/ig.test(values.dataresource) && setting.dataresource !== values.dataresource
-          ) {
-            let param = {
-              func: 's_DataSrc_Save',
-              LText: values.dataresource,
-              MenuID: this.props.menu.MenuID
-            }
-    
-            param.LText = Utils.formatOptions(param.LText)
-            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-            param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-    
-            Api.genericInterface(param)
           }
 
           resolve(values)
@@ -355,7 +334,7 @@
           </Col> : null}
           {interType === 'system' ? <Col span={24} className="mk-through-line3">
             <Form.Item help={'鏁版嵁ID锛�' + menu.MenuID} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } label={
-              <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''锛涙煡璇㈡浛鎹㈢ $select@ -> /* 鎴� ''銆� @select$ -> */ 鎴� ''锛涚粺璁℃浛鎹㈢ $sum@ -> /* 鎴� ''銆� @sum$ -> */ 鎴� ''銆俙}>
+              <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''銆俙}>
                 <QuestionCircleOutlined className="mk-form-tip" />
                 鏁版嵁婧�
               </Tooltip>
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
index fbfb050..4b274f6 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
@@ -173,7 +173,7 @@
     _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
-    Api.getSystemConfig(_sParam).then(res => {
+    Api.getCloudConfig(_sParam).then(res => {
       if (res.status) {
         let _scripts = res.data.map(item => {
           return {
@@ -446,7 +446,7 @@
             </Col>
             <Col span={20}>
               <Form.Item labelCol={{span: 4}} wrapperCol={{span: 20}} label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
-                ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
+                ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
               </Form.Item>
             </Col>
             <Col span={24} className="sqlfield">
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
index 5f186cf..54a957d 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
@@ -151,7 +151,7 @@
       let arr = sql.match(/@[0-9a-zA-Z_]+@/ig)
 
       arr.forEach(item => {
-        let reg = new RegExp(item, 'ig')
+        let reg = new RegExp(item, 'i')
         if (reg.test(_dataresource)) {
           errors.push(`鏁版嵁婧愪腑瀛樺湪鏈浛鎹㈠��${item}`)
         }
diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx
index 15954e3..69e7a3b 100644
--- a/src/templates/sharecomponent/tablecomponent/index.jsx
+++ b/src/templates/sharecomponent/tablecomponent/index.jsx
@@ -6,7 +6,6 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import { queryTableSql } from '@/utils/option.js'
@@ -24,7 +23,6 @@
 
   state = {
     tables: [],          // 绯荤粺琛�
-    tableFields: [],     // 宸查�夎〃瀛楁闆�
     selectedTables: [],  // 宸查�夎〃
   }
 
@@ -40,8 +38,6 @@
 
     this.setState({
       selectedTables: tables
-    }, () => {
-      this.gettableFields()
     })
   }
 
@@ -74,8 +70,8 @@
     param.secretkey = Utils.encrypt(param.LText, param.timestamp)
     param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
 
-    if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
-      param.rduri = options.cloudServiceApi
+    if (window.GLOB.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
+      param.rduri = window.GLOB.cloudServiceApi
       param.userid = sessionStorage.getItem('CloudUserID') || ''
       param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
     }
@@ -97,163 +93,28 @@
     })
   }
 
-  gettableFields = () => {
-    let deffers = this.state.selectedTables.map((item, i) => {
-      return new Promise(resolve => {
-        let param = {func: 'sPC_Get_FieldName', TBName: item.TbName}
-        if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
-          param.rduri = options.cloudServiceApi
-          param.userid = sessionStorage.getItem('CloudUserID') || ''
-          param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
-        }
-
-        setTimeout(() => {
-          Api.getSystemCacheConfig(param).then(res => {
-            res.TBName = item.TbName
-            resolve(res)
-          })
-        }, (i + 1) * 100)
-      })
-    })
-    Promise.all(deffers).then(response => {
-      let _columns = []
-      response.forEach(res => {
-        if (res.status) {
-          let tabmsg = {
-            tableName: res.TBName,
-            columns: res.FDName.map(item => {
-              let _type = item.FieldType.toLowerCase()
-              let _decimal = 0
-              let _length = 50
-              if (/^nvarchar/.test(_type)) {
-                try { // 瀛樺湪max
-                  _length = +_type.match(/\d+/)[0] || 50
-                } catch (e) {
-                  _length = 2048
-                }
-                _type = 'text'
-              } else if (/^int/.test(_type)) {
-                _type = 'number'
-              } else if (/^decimal/.test(_type)) {
-                _decimal = _type.split(',')[1]
-                _decimal = parseInt(_decimal)
-                _type = 'number'
-              } else if (/^datetime/.test(_type)) {
-                _type = 'datetime'
-              } else if (/^date/.test(_type)) {
-                _type = 'date'
-              } else {
-                _type = 'text'
-              }
-  
-              return {
-                field: item.FieldName || '',
-                label: item.FieldDec,
-                type: _type,
-                datatype: _type,
-                decimal: _decimal,
-                length: _length,
-                $datatype: item.FieldType.toLowerCase()
-              }
-            })
-          }
-          _columns.push(tabmsg)
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-        }
-      })
-
-      this.setState({
-        tableFields: _columns
-      })
-      window.GLOB.tableFields = _columns
-    })
-  }
-
   /**
    * @description 娣诲姞琛ㄥ悕
    */
   onTableChange = (value) => {
     const { config } = this.props
-    const { tables, tableFields, selectedTables } = this.state
+    const { tables, selectedTables } = this.state
 
     let _table = tables.filter(item => item.TbName === value)[0]
-    let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0]
-    if (!isSelected) {
-      let _tables = [...selectedTables, _table]
 
-      window.GLOB.publicTables = _tables
+    if (selectedTables.findIndex(cell => cell.TbName === value) > -1) return
 
-      this.setState({
-        selectedTables: _tables
-      })
+    let _tables = [...selectedTables, _table]
 
-      let _config = {...config, tables: _tables}
-      
-      Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
-        if (res.status) {
-          let tabmsg = {
-            tableName: _table.TbName,
-            columns: res.FDName.map(item => {
-              let _type = item.FieldType.toLowerCase()
-              let _decimal = 0
-              let _length = 50
+    window.GLOB.publicTables = _tables
 
-              if (/^nvarchar/.test(_type)) {
-                try { // 瀛樺湪max
-                  _length = +_type.match(/\d+/)[0] || 50
-                } catch (e) {
-                  _length = 2048
-                }
-                _type = 'text'
-              } else if (/^int/.test(_type)) {
-                _type = 'number'
-              } else if (/^decimal/.test(_type)) {
-                _decimal = _type.split(',')[1]
-                _decimal = parseInt(_decimal)
-                _type = 'number'
-              } else if (/^datetime/.test(_type)) {
-                _type = 'datetime'
-              } else if (/^date/.test(_type)) {
-                _type = 'date'
-              } else {
-                _type = 'text'
-              }
+    this.setState({
+      selectedTables: _tables
+    })
 
-              return {
-                field: item.FieldName,
-                label: item.FieldDec,
-                type: _type,
-                datatype: _type,
-                decimal: _decimal,
-                length: _length,
-                $datatype: item.FieldType.toLowerCase()
-              }
-            })
-          }
-
-          let _columns = [...tableFields, tabmsg]
-
-          this.setState({
-            tableFields: _columns
-          })
-
-          window.GLOB.tableFields = _columns
-
-          this.props.updatetable(_config)
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-        }
-      })
-    }
+    let _config = {...config, tables: _tables}
+    
+    this.props.updatetable(_config)
   }
 
   /**
@@ -261,19 +122,15 @@
    */
   deleteTable = (table) => {
     const { config } = this.props
-    const { selectedTables, tableFields } = this.state
+    const { selectedTables } = this.state
 
     let _tables = selectedTables.filter(item => item.TbName !== table.TbName)
-    let _fields = tableFields.filter(item => item.tableName !== table.TbName)
 
     window.GLOB.publicTables = _tables
 
     this.setState({
       selectedTables: _tables,
-      tableFields: _fields
     })
-
-    window.GLOB.tableFields = _fields
 
     this.props.updatetable({...config, tables: _tables})
   }
diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
index 0a21e7d..6ac9645 100644
--- a/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
+++ b/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
@@ -2,9 +2,7 @@
 import PropTypes from 'prop-types'
 import { Form, Row, Col, Input, Radio, Tooltip, notification, InputNumber } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
-import moment from 'moment'
 
-import Api from '@/api'
 import { formRule } from '@/utils/option.js'
 import Utils from '@/utils/utils.js'
 import CodeMirror from '@/templates/zshare/codemirror'
@@ -61,7 +59,6 @@
   }
 
   handleConfirm = () => {
-    const { setting } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
@@ -129,24 +126,6 @@
               reject()
               return
             }
-          }
-
-          // 鏁版嵁婧愪繚瀛�
-          if (
-            values.interType === 'system' && values.default !== 'false' &&
-            /[^\s]+\s+[^\s]+/ig.test(values.dataresource) && setting.dataresource !== values.dataresource
-          ) {
-            let param = {
-              func: 's_DataSrc_Save',
-              LText: values.dataresource,
-              MenuID: this.props.menu.MenuID
-            }
-    
-            param.LText = Utils.formatOptions(param.LText)
-            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-            param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-    
-            Api.genericInterface(param)
           }
 
           resolve(values)
diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx
index 19bfb12..3459581 100644
--- a/src/templates/subtableconfig/index.jsx
+++ b/src/templates/subtableconfig/index.jsx
@@ -185,7 +185,7 @@
       loading: type,
       tabviews: []
     })
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
       if (res.status) {
         let _tabviews = []
         res.UserTemp.forEach(temp => {
@@ -273,7 +273,7 @@
         func: 'sPC_MainMenu_Del',
         MenuID: item
       }
-      Api.getSystemConfig(_param)
+      Api.getCloudConfig(_param)
     })
 
     this.props.handleView(param)
@@ -438,7 +438,7 @@
           }
 
           return new Promise(resolve => {
-            Api.getSystemConfig(_param).then(response => {
+            Api.getCloudConfig(_param).then(response => {
               resolve(response)
             })
           })
@@ -493,7 +493,7 @@
     }).then(resp => {
       if (resp === false) return
 
-      Api.getSystemConfig(param).then(response => {
+      Api.getCloudConfig(param).then(response => {
         if (response.status) {
           this.setState({
             openEdition: response.open_edition || '',
@@ -551,7 +551,7 @@
     if (oriActions.length === 0) return
 
     oriActions.forEach(action => {
-      Api.getSystemConfig({
+      Api.getCloudConfig({
         func: 'sPC_Get_LongParam',
         MenuID: action.prebtn ? action.prebtn.uuid : ''
       }).then(result => {
@@ -578,7 +578,7 @@
               PageParam: JSON.stringify({Template: _LongParam.type}),
               LongParam: result.LongParam
             }
-            Api.getSystemConfig(param).then(() => {})
+            Api.getCloudConfig(param).then(() => {})
           }
         }
       })
@@ -675,7 +675,7 @@
           loading: true
         })
 
-        Api.getSystemConfig({
+        Api.getCloudConfig({
           func: 'sPC_Get_LongParam',
           MenuID: btn.OpenType === 'popview' ? btn.linkTab : btn.uuid
         }).then(res => {
@@ -863,7 +863,7 @@
       MenuID: config.uuid
     }
 
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       if (res.status) {
         let _config = ''
         if (res.LongParam) {
diff --git a/src/templates/treepageconfig/index.jsx b/src/templates/treepageconfig/index.jsx
index f5c1eba..318adf1 100644
--- a/src/templates/treepageconfig/index.jsx
+++ b/src/templates/treepageconfig/index.jsx
@@ -19,6 +19,8 @@
 const { Panel } = Collapse
 const { confirm } = Modal
 const { TreeNode } = Tree
+
+const UpdateTable = asyncComponent(() => import('./updatetable'))
 const TreeSettingComponent = asyncComponent(() => import('@/templates/sharecomponent/treesettingcomponent'))
 const TabsComponent = asyncComponent(() => import('@/templates/sharecomponent/tabscomponent'))
 
@@ -68,9 +70,10 @@
     _config.MenuName = menu.MenuName || ''
     _config.MenuNo = menu.MenuNo || ''
     _config.OpenType = menu.PageParam ? menu.PageParam.OpenType : ''
+    _config.MenuID = menu.MenuID || ''
 
     // 閰嶇疆榛樿鍊硷紝鍏煎
-    _config.Template = 'TreePage'
+    // _config.Template = 'TreePage'
     _config.easyCode = _config.easyCode || ''
     
     if (_config.type === 'user') {
@@ -174,7 +177,7 @@
       loading: type,
       tabviews: []
     })
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
       if (res.status) {
         this.setState({
           loading: false,
@@ -364,7 +367,7 @@
           }
 
           return new Promise(resolve => {
-            Api.getSystemConfig(_param).then(response => {
+            Api.getCloudConfig(_param).then(response => {
               resolve(response)
             })
           })
@@ -400,16 +403,8 @@
       }
     }).then(resp => {
       if (resp === false) return
-      let localParam = fromJS(param).toJS()
-      localParam.func = 'sPC_TrdMenu_AddUpt_For_Local'
-      delete localParam.LongParam
-      delete localParam.PageParam
-      delete localParam.Template
-      delete localParam.Sort
-      delete localParam.EasyCode
-      delete localParam.open_edition
 
-      Api.getSystemConfig(param).then(response => {
+      Api.getCloudConfig(param).then(response => {
         if (response.status) {
           this.setState({
             config: _config,
@@ -426,7 +421,6 @@
           })
 
           this.props.reloadmenu()
-          Api.genericInterface(localParam)
 
           if (this.state.closeVisible) {
             this.props.handleView()
@@ -540,7 +534,7 @@
         loading: true
       })
 
-      Api.getSystemConfig({
+      Api.getCloudConfig({
         func: 'sPC_Get_LongParam',
         MenuID: item.linkTab
       }).then(res => {
@@ -715,6 +709,7 @@
               </div>
             } bordered={false} extra={
               <div>
+                <UpdateTable config={config}/>
                 <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={this.state.config.enabled} onChange={this.onEnabledChange} />
                 <Button type="primary" id="save-config" onClick={this.submitConfig} loading={this.state.menuloading}>淇濆瓨</Button>
                 <Button onClick={this.cancelConfig}>鍏抽棴</Button>
diff --git a/src/templates/treepageconfig/updatetable/index.jsx b/src/templates/treepageconfig/updatetable/index.jsx
new file mode 100644
index 0000000..231a7c6
--- /dev/null
+++ b/src/templates/treepageconfig/updatetable/index.jsx
@@ -0,0 +1,1259 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Modal, Button, notification } from 'antd'
+import { ArrowUpOutlined } from '@ant-design/icons'
+import moment from 'moment'
+import md5 from 'md5'
+
+import { colorTransform } from '@/utils/option.js'
+import { getTables } from '@/utils/utils-custom.js'
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+// import './index.scss'
+
+const { confirm } = Modal
+
+class UpdateTable extends Component {
+  static propTpyes = {
+    config: PropTypes.object
+  }
+
+  state = {}
+  delButtons = []
+  baseMsg = {}
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  trigger = () => {
+    const { config } = this.props
+    const _this = this
+
+    if (!config.enabled) {
+      notification.warning({
+        top: 92,
+        message: '鏈惎鐢ㄨ彍鍗曚笉鍙崌绾э紒',
+        duration: 5
+      })
+      return
+    }
+    
+    confirm({
+      title: '纭畾鍗囩骇褰撳墠鑿滃崟鍚楋紵',
+      content: '',
+      onOk() {
+        return new Promise(resolve => {
+          _this.execUpdate(resolve)
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  execUpdate = (_resolve) => {
+    const config = fromJS(this.props.config).toJS()
+    this.delButtons = []
+    this.baseMsg = {
+      fstMenuId: config.fstMenuId,
+      parentId: config.ParentId,
+      MenuName: config.MenuName,
+      MenuNo: config.MenuNo,
+    }
+
+    let _config = {
+      version: 1.0,
+      uuid: config.MenuID,
+      MenuID: config.MenuID,
+      fstMenuId: config.fstMenuId,
+      parentId: config.ParentId,
+      Template: 'CustomPage',
+      easyCode: config.easyCode,
+      enabled: false,
+      MenuName: config.MenuName,
+      MenuNo: config.MenuNo,
+      OpenType: 'newtab',
+      tables: config.tables || [],
+      urlFields: config.urlFields || [],
+      hidden: config.hidden || 'false',
+      Remark: config.Remark || '',
+      components: [],
+      viewType: 'menu',
+      style: { backgroundColor: '#ffffff', paddingTop: '16px', paddingBottom: '80px', paddingLeft: '16px', paddingRight: '16px'},
+    }
+
+    let formActions = []
+    let popActions = []
+    let errors = []
+
+    let mainTr = {
+      uuid: Utils.getuuid(),
+      type: 'tree',
+      format: 'array',    // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+      pageable: false,    // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+      switchable: true,   // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+      width: config.setting.width || 5,
+      name: config.setting.title || '缁撴瀯鏍�',
+      subtype: 'normaltree',
+      setting: {},
+      wrap: { name: config.setting.title || '缁撴瀯鏍�', title: config.setting.title || '', width: config.setting.width || 5, showIcon: config.setting.showIcon || 'false', showLine: config.setting.showLine || 'false', searchable: config.setting.searchable || 'false' },
+      style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
+      headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
+      columns: [],
+      scripts: [],
+      action: [],
+    }
+
+    mainTr.setting = {
+      interType: config.setting.interType || 'system',
+      innerFunc: config.setting.innerFunc || '',
+      interface: config.setting.interface || '',
+      dataresource: config.setting.dataresource || '',
+      tableName: config.setting.tableName || '',
+      sysInterface: config.setting.sysInterface || 'false',
+      order: config.setting.order || '',
+      execute: config.setting.default || 'true',
+      primaryKey: config.setting.valueField || '',
+      supModule: ['empty'],
+      sync: 'false',
+      onload: 'true'
+    }
+
+    mainTr.wrap.valueField = config.setting.valueField || ''
+    mainTr.wrap.labelField = config.setting.labelField || ''
+    mainTr.wrap.parentField = config.setting.parentField || ''
+    mainTr.wrap.mark = config.setting.mark || ''
+
+    mainTr.scripts = config.setting.scripts || []
+
+    let fields = [mainTr.wrap.valueField, mainTr.wrap.labelField, mainTr.wrap.parentField]
+
+    fields.forEach(col => {
+      mainTr.columns.push({
+        datatype: `Nvarchar(50)`,
+        field: col,
+        fieldlength: 50,
+        label: col,
+        type: 'text',
+        uuid: Utils.getuuid()
+      })
+    })
+
+    let oldtabs = {
+      mainTable: mainTr.uuid
+    }
+
+    _config.components.push(mainTr)
+
+    let _tbs = []
+    if (config.tabgroups && config.tabgroups.length > 0) {
+      config.tabgroups.forEach((m, i) => {
+        if (!m.sublist) return
+
+        m.sublist = m.sublist.filter(c => !!c.linkTab)
+        
+        if (m.sublist.length === 0) return
+
+        let tabs = {
+          uuid: Utils.getuuid(),
+          type: 'tabs',
+          subtype: 'tabs',
+          name: '鏍囩缁�' + (i + 1),
+          width: 24 - mainTr.width,
+          setting: {supModule: [mainTr.uuid], controlField: 'mk_floor', name: '鏍囩缁�' + (i + 1), width: 24 - mainTr.width, position: 'top'},
+          style: {paddingTop: '10px'},
+          subtabs: m.sublist.map(n => {
+            let level = ''
+            if (n.level === 0) {
+              level = '@pass_empty@,1,2,3,4,5'
+            } else if (!n.level) {
+              level = '@pass@'
+            } else {
+              if (n.level === 1) {
+                level = '2,3,4,5'
+              } else if (n.level === 2) {
+                level = '1,3,4,5'
+              } else if (n.level === 3) {
+                level = '1,2,4,5'
+              } else if (n.level === 4) {
+                level = '1,2,3,5'
+              } else if (n.level === 5) {
+                level = '1,2,3,4'
+              }
+            }
+
+            let tab = { uuid: Utils.getuuid(), controlVal: level, label: n.label, icon: n.icon, permission: 'true', components: [
+              {
+                uuid: Utils.getuuid(),
+                linkTab: n.linkTab,
+                name: n.label,
+                useMSearch: 'false',
+                supModule: n.supMenu || '',
+                equalTab: n.equalTab && n.equalTab.length > 0 ? n.equalTab[0] : ''
+              }
+            ]}
+            this.delButtons.push(n.linkTab)
+            oldtabs[n.uuid] = tab.components[0].uuid
+
+            _tbs.push(tab.components[0])
+
+            return tab
+          })
+        }
+        
+        _config.components.push(tabs)
+      })
+    }
+
+    if (_tbs.length > 0) {
+      let defers = _tbs.map((item, i) => {
+        return new Promise((resolve) => {
+          setTimeout(() => {
+            Api.getCloudConfig({
+              func: 'sPC_Get_LongParam',
+              MenuID: item.linkTab
+            }).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) {
+                  _LongParam.uuid = item.linkTab
+                  resolve(_LongParam)
+                } else {
+                  resolve({uuid: item.linkTab, $empty: true})
+                }
+              } else {
+                notification.warning({
+                  top: 92,
+                  message: res.message,
+                  duration: 5
+                })
+                resolve({uuid: item.linkTab, $empty: true})
+              }
+            })
+          }, i * 50)
+        })
+      })
+      Promise.all(defers).then(res => {
+        let menus = {}
+        res.forEach(item => {
+          if (item && !item.$empty) {
+            menus[item.uuid] = item
+          }
+        })
+
+        let supIds = []
+        _config.components = _config.components.map(item => {
+          if (item.type === 'tabs') {
+            item.subtabs = item.subtabs.map(tab => {
+              tab.components[0] = this.getTable(menus[tab.components[0].linkTab], tab.components[0], errors, formActions, popActions, oldtabs)
+              supIds.push([item.uuid, tab.uuid, tab.components[0].uuid])
+              return tab
+            })
+          }
+          return item
+        })
+
+        _config.components = _config.components.map(item => {
+          if (item.type === 'tabs') {
+            item.subtabs = item.subtabs.map(tab => {
+              if (tab.components[0].setting.supModule && tab.components[0].setting.supModule.length === 1) {
+                supIds.forEach(ids => {
+                  if (ids[2] === tab.components[0].setting.supModule[0]) {
+                    tab.components[0].setting.supModule = ids
+                  }
+                })
+              }
+              return tab
+            })
+          }
+          return item
+        })
+
+        this.setPopView(_resolve, _config, formActions, popActions, errors)
+      })
+    } else {
+      this.setPopView(_resolve, _config, formActions, popActions, errors)
+    }
+  }
+
+  setPopView = (_resolve, _config, formActions, popActions, errors) => {
+    if (popActions.length > 0) {
+      let defers = popActions.map((item, i) => {
+        return new Promise((resolve) => {
+          setTimeout(() => {
+            Api.getCloudConfig({
+              func: 'sPC_Get_LongParam',
+              MenuID: item.linkTab
+            }).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) {
+                  _LongParam.uuid = item.uuid
+                  resolve(_LongParam)
+                } else {
+                  resolve({uuid: item.uuid, $empty: true})
+                }
+              } else {
+                notification.warning({
+                  top: 92,
+                  message: res.message,
+                  duration: 5
+                })
+                resolve({uuid: item.uuid, $empty: true})
+              }
+            })
+          }, i * 50)
+        })
+      })
+      Promise.all(defers).then(res => {
+        let menus = {}
+        res.forEach(item => {
+          if (item && !item.$empty) {
+            menus[item.uuid] = item
+          }
+        })
+
+        _config.components.forEach(item => {
+          if (item.type === 'tabs') {
+            item.subtabs.forEach(tab => {
+              tab.components[0].action.forEach(btn => {
+                if (btn.OpenType === 'popview') {
+                  if (menus[btn.uuid]) {
+                    let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+
+                    btn.config = {
+                      uuid: btn.uuid,
+                      MenuID: btn.uuid,
+                      ParentId: tab.components[0].uuid,
+                      MenuName: btn.label,
+                      tables: _config.tables || [],
+                      Template: 'CustomPage',
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                      viewType: 'popview',
+                      style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                    }
+
+                    btn.config.enabled = this.setEnabled(btn.config)
+                  } else {
+                    errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+              tab.components[0].cols.forEach(col => {
+                if (col.type !== 'custom') return
+                col.elements.forEach(btn => {
+                  if (btn.eleType !== 'button') return
+                  if (btn.OpenType === 'popview') {
+                    if (menus[btn.uuid]) {
+                      let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+  
+                      btn.config = {
+                        uuid: btn.uuid,
+                        MenuID: btn.uuid,
+                        ParentId: tab.components[0].uuid,
+                        MenuName: btn.label,
+                        tables: _config.tables || [],
+                        Template: 'CustomPage',
+                        components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                        viewType: 'popview',
+                        style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                      }
+
+                      btn.config.enabled = this.setEnabled(btn.config)
+                    } else {
+                      errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                    }
+                  }
+                })
+              })
+            })
+          } else if (item.type !== 'tree') {
+            item.action.forEach(btn => {
+              if (btn.OpenType === 'popview') {
+                if (menus[btn.uuid]) {
+                  let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+
+                  btn.config = {
+                    uuid: btn.uuid,
+                    MenuID: btn.uuid,
+                    ParentId: item.uuid,
+                    MenuName: btn.label,
+                    tables: _config.tables || [],
+                    Template: 'CustomPage',
+                    components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                    viewType: 'popview',
+                    style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                  }
+
+                  btn.config.enabled = this.setEnabled(btn.config)
+                } else {
+                  errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                }
+              }
+            })
+            item.cols.forEach(col => {
+              if (col.type !== 'custom') return
+              col.elements.forEach(btn => {
+                if (btn.eleType !== 'button') return
+                if (btn.OpenType === 'popview') {
+                  if (menus[btn.uuid]) {
+                    let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+  
+                    btn.config = {
+                      uuid: btn.uuid,
+                      MenuID: btn.uuid,
+                      ParentId: item.uuid,
+                      MenuName: btn.label,
+                      tables: _config.tables || [],
+                      Template: 'CustomPage',
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                      viewType: 'popview',
+                      style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                    }
+
+                    btn.config.enabled = this.setEnabled(btn.config)
+                  } else {
+                    errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+            })
+          }
+        })
+
+        this.setPopForm(_resolve, _config, formActions, errors)
+      })
+    } else {
+      this.setPopForm(_resolve, _config, formActions, errors)
+    }
+  }
+
+  setEnabled = (config) => {
+    let enabled = true
+    config.components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          if (tab.components[0].errors.length > 0) {
+            enabled = false
+          }
+        })
+      } else {
+        if (item.errors.length > 0) {
+          enabled = false
+        }
+      }
+    })
+
+    return enabled
+  }
+
+  setPopForm = (_resolve, _config, formActions, errors) => {
+    if (formActions.length > 0) {
+      let defers = formActions.map((item, i) => {
+        return new Promise((resolve) => {
+          setTimeout(() => {
+            Api.getCloudConfig({
+              func: 'sPC_Get_LongParam',
+              MenuID: item.origin
+            }).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) {
+                  _LongParam.uuid = item.uuid
+                  resolve(_LongParam)
+                } else {
+                  resolve({uuid: item.uuid, $empty: true})
+                }
+              } else {
+                notification.warning({
+                  top: 92,
+                  message: res.message,
+                  duration: 5
+                })
+                resolve({uuid: item.uuid, $empty: true})
+              }
+            })
+          }, i * 50)
+        })
+      })
+      Promise.all(defers).then(res => {
+        let menus = {}
+        res.forEach(item => {
+          if (item && !item.$empty) {
+            menus[item.uuid] = item
+          }
+        })
+
+        _config.components.forEach(item => {
+          if (item.type === 'tabs') {
+            item.subtabs.forEach(tab => {
+              tab.components[0].action.forEach(btn => {
+                if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                  this.setTbForm(btn.config.components[0], menus, errors, tab.components[0].name + '-' + btn.label)
+                } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                  if (menus[btn.uuid]) {
+                    btn.modal = {
+                      setting: menus[btn.uuid].setting,
+                      tables: [],
+                      groups: [],
+                      fields: menus[btn.uuid].fields || []
+                    }
+                  } else {
+                    errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+              tab.components[0].cols.forEach(col => {
+                if (col.type !== 'custom') return
+                col.elements.forEach(btn => {
+                  if (btn.eleType !== 'button') return
+                  if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                    this.setTbForm(btn.config.components[0], menus, errors, tab.components[0].name + '-' + btn.label)
+                  } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                    if (menus[btn.uuid]) {
+                      btn.modal = {
+                        setting: menus[btn.uuid].setting,
+                        tables: [],
+                        groups: [],
+                        fields: menus[btn.uuid].fields || []
+                      }
+                    } else {
+                      errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                    }
+                  }
+                })
+              })
+            })
+          } else if (item.type !== 'tree') {
+            item.action.forEach(btn => {
+              if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                this.setTbForm(btn.config.components[0], menus, errors, item.name + '-' + btn.label)
+              } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                if (menus[btn.uuid]) {
+                  btn.modal = {
+                    setting: menus[btn.uuid].setting,
+                    tables: [],
+                    groups: [],
+                    fields: menus[btn.uuid].fields || []
+                  }
+                } else {
+                  errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                }
+              }
+            })
+
+            item.cols.forEach(col => {
+              if (col.type !== 'custom') return
+              col.elements.forEach(btn => {
+                if (btn.eleType !== 'button') return
+                if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                  this.setTbForm(btn.config.components[0], menus, errors, item.name + '-' + btn.label)
+                } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                  if (menus[btn.uuid]) {
+                    btn.modal = {
+                      setting: menus[btn.uuid].setting,
+                      tables: [],
+                      groups: [],
+                      fields: menus[btn.uuid].fields || []
+                    }
+                  } else {
+                    errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+            })
+          }
+        })
+
+        this.saveConfig(_resolve, _config, errors)
+      })
+    } else {
+      this.saveConfig(_resolve, _config, errors)
+    }
+  }
+
+  setTbForm = (item, menus, errors, name) => {
+    item.action.forEach(btn => {
+      if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+        if (menus[btn.uuid]) {
+          btn.modal = {
+            setting: menus[btn.uuid].setting,
+            tables: [],
+            groups: [],
+            fields: menus[btn.uuid].fields || []
+          }
+        } else {
+          errors.push(name + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+        }
+      }
+    })
+    item.cols.forEach(col => {
+      if (col.type !== 'custom') return
+      col.elements.forEach(btn => {
+        if (btn.eleType !== 'button') return
+        if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+          if (menus[btn.uuid]) {
+            btn.modal = {
+              setting: menus[btn.uuid].setting,
+              tables: [],
+              groups: [],
+              fields: menus[btn.uuid].fields || []
+            }
+          } else {
+            errors.push(name + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+          }
+        }
+      })
+    })
+  }
+
+  saveConfig = (_resolve, _config, errors) => {
+    let err = errors.join('锛�')
+    let _this = this
+
+    if (err) {
+      _resolve()
+      confirm({
+        title: err + '锛岀‘瀹氬崌绾у綋鍓嶈彍鍗曞悧锛�',
+        content: '',
+        onOk() {
+          return new Promise(resolve => {
+            _this.saveNewMenu(resolve, _config)
+          })
+        },
+        onCancel() {}
+      })
+    } else {
+      this.saveNewMenu(_resolve, _config)
+    }
+  }
+
+  saveNewMenu = (_resolve, _config) => {
+    _config.components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components[0].action.forEach(btn => {
+            if (btn.OpenType === 'popview' && btn.config) {
+              btn.config.$tables = getTables(btn.config.components[0])
+            }
+          })
+          tab.components[0].cols.forEach(col => {
+            if (col.type !== 'custom') return
+            col.elements.forEach(btn => {
+              if (btn.eleType !== 'button') return
+              if (btn.OpenType === 'popview' && btn.config) {
+                btn.config.$tables = getTables(btn.config.components[0])
+              }
+            })
+          })
+
+          tab.components[0].$tables = getTables(tab.components[0])
+        })
+      } else {
+        item.$tables = getTables(item)
+      }
+    })
+
+    this.submitConfig(_resolve, _config)
+  }
+
+  checkBtns = (card) => {
+    card.action.forEach(cell => {
+      if (cell.hidden === 'true') return
+      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+        if (!cell.modal || cell.modal.fields.length === 0) {
+          card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
+        }
+      } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
+        card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+      } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+        card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+      }
+    })
+
+    card.cols.forEach(col => {
+      if (col.type !== 'custom') return
+
+      col.elements.forEach(cell => {
+        if (cell.hidden === 'true' || cell.eleType !== 'button') return
+        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+          if (!cell.modal || cell.modal.fields.length === 0) {
+            card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
+          }
+        } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
+          card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+        } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+          card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+        }
+      })
+    })
+  }
+
+  submitConfig = (_resolve, config) => {
+    let tbs = []
+    config.components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          if (tab.components[0].$tables) {
+            tbs.push(...tab.components[0].$tables)
+          }
+
+          this.checkBtns(tab.components[0])
+        })
+      } else {
+        if (item.$tables) {
+          tbs.push(...item.$tables)
+        }
+      }
+    })
+
+    let arr = []
+    tbs = tbs.filter(tb => {
+      let _tb = tb.toLowerCase()
+
+      if (arr.includes(_tb)) return false
+      arr.push(_tb)
+
+      return true
+    })
+    tbs.sort()
+    if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
+      let names = sessionStorage.getItem('mk_tb_names')
+      tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
+    }
+    tbs = tbs.map(tb => `'${tb}'`).join(';')
+
+    let key = md5(config.uuid + tbs.toLowerCase())
+
+    let urlparam = {
+      FstId: config.fstMenuId,
+      ParentId: config.parentId,
+      MenuID: config.uuid,
+      MenuName: config.MenuName,
+      MenuNo: config.MenuNo,
+      EasyCode: config.easyCode,
+      type: 'admin',
+      OpenType: config.OpenType,
+      PageParam: {Template: 'CustomPage', OpenType: 'newtab', hidden: config.hidden},
+      MenuType: 'custom'
+    }
+    let url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+    config.tbkey = key
+
+    let param = {
+      func: 'sPC_TrdMenu_AddUpt',
+      FstID: config.fstMenuId || '',
+      SndID: config.parentId,
+      ParentID: config.parentId,
+      MenuID: config.uuid,
+      MenuNo: config.MenuNo || '',
+      EasyCode: config.easyCode || '',
+      Template: 'CustomPage',
+      MenuName: config.MenuName || '',
+      PageParam: JSON.stringify({Template: 'CustomPage', OpenType: config.OpenType, hidden: config.hidden}),
+      open_edition: '',
+      debug_md5: key,
+      debug_url: url,
+      debug_list: window.btoa(tbs),
+      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config)))
+    }
+
+    param.LText = Utils.formatOptions(param.LText)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    let save = false
+
+    new Promise(resolve => {
+      Api.getCloudConfig(param).then(res => {
+        resolve(res)
+      })
+    }).then(res => { // 鍒犻櫎鍘熻彍鍗�
+      if (!res || !res.status) return res
+
+      save = true
+      localStorage.setItem('menuUpdate', new Date().getTime() + ',' + config.uuid)
+
+      if (this.delButtons.length === 0) return res
+
+      return Api.getCloudConfig({
+        func: 'sPC_MainMenu_Del',
+        up_type: 'Y',
+        MenuID: this.delButtons.join(',')
+      })
+    }).then(res => {
+      if (!res) return
+
+      _resolve()
+
+      if (res.status) {
+        delete urlparam.type
+
+        let _param = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+
+        window.history.replaceState(null, null, window.location.href.split('#')[0] + `#/menudesign/${_param}`)
+        window.location.reload()
+      } else {
+        Modal.warning({
+          title: res.message,
+          okText: '鐭ラ亾浜�',
+          onOk: () => {
+            if (save) {
+              delete urlparam.type
+
+              let _param = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+
+              window.history.replaceState(null, null, window.location.href.split('#')[0] + `#/menudesign/${_param}`)
+              window.location.reload()
+            } else {
+              window.location.reload()
+            }
+          }
+        })
+      }
+    })
+  }
+
+  getTable = (config, newCon, errors, formActions, popActions, oldtabs) => { 
+    let _card = {
+      uuid: newCon.uuid,
+      type: 'table',
+      name: newCon.name,
+      format: 'array',
+      pageable: true,
+      switchable: true,
+      search: [],
+      action: [],
+      subtype: 'normaltable',
+      setting: { useMSearch: 'false', sync: 'false', onload: 'true' },
+      wrap: {name: newCon.name},
+      style: {},
+      headerStyle: {},
+      columns: [],
+      cols: [],
+      scripts: []
+    }
+
+    if (!config) {
+      errors.push(newCon.name + '閰嶇疆淇℃伅涓㈠け')
+      return _card
+    }
+
+    if (oldtabs && newCon.supModule && oldtabs[newCon.supModule]) {
+      _card.setting.supModule = [oldtabs[newCon.supModule]]
+    } else {
+      _card.setting.supModule = ['empty']
+    }
+
+    _card.search = config.search.map(item => {
+      item.uuid = Utils.getuuid()
+      return item
+    })
+
+    let _cols = {}
+    let _colspan = []
+    let lineMarks = []
+    config.columns.forEach(col => {
+      if (col.type === 'colspan') {
+        if (col.subfield) {
+          _colspan.push(...col.subfield.split(', '))
+        } else if (col.sublist && col.sublist.length > 0) {
+          _colspan.push(...col.sublist)
+        }
+      }
+      if (!col.field) return
+
+      let _col = fromJS(col).toJS()
+
+      if (_col.marks) {
+        _col.marks = []
+        col.marks.forEach(m => {
+          if (m.signType === 'card') return
+
+          let field = []
+          field.push(m.field)
+          field.push(m.contrastType)
+
+          if (m.contrastField) {
+            field.push(m.contrastField)
+          }
+          let color = '#1890ff'
+          if (m.color && m.color[1]) {
+            color = colorTransform[m.color[1]]
+          }
+          let signType = ['font']
+          if (m.signType === 'background') {
+            signType = ['background']
+          } else if (m.signType === 'icon') {
+            if (m.position === 'back') {
+              signType = ['iconback']
+            } else {
+              signType = ['iconfront']
+            }
+            signType.push(m.iconType)
+            signType.push(m.icon)
+          }
+
+          if (m.signType === 'line') {
+            lineMarks.push({
+              $index: lineMarks.length + 1,
+              uuid: Utils.getuuid(),
+              field: field,
+              color: color,
+              contrastValue: m.contrastValue || '',
+              match: m.match,
+              signType: ['background']
+            })
+          } else {
+            _col.marks.push({
+              $index: _col.marks.length + 1,
+              uuid: Utils.getuuid(),
+              field: field,
+              color: color,
+              contrastValue: m.contrastValue || '',
+              match: m.match,
+              signType: signType
+            })
+          }
+        })
+      }
+
+      _cols[col.field] = _col
+    })
+
+    config.columns.forEach(col => {
+      if (col.type === 'index') {
+        _card.cols.push(fromJS(col).toJS())
+      } else if (col.field && _cols[col.field]) {
+        let _col = fromJS(_cols[col.field]).toJS()
+
+        if (_colspan.includes(col.field)) {
+          _col.Hide = 'true'
+        }
+        _col.uuid = Utils.getuuid()
+        _card.cols.push(_col)
+      }
+
+      if (col.type === 'colspan') {
+        let ucol = {
+          Align: col.Align,
+          Hide: col.Hide,
+          label: col.label,
+          marks: [],
+          isSub: false,
+          uuid: Utils.getuuid(),
+          blacklist: []
+        }
+        let _subs = []
+        if (col.subfield) {
+          _subs = col.subfield.split(', ')
+        } else if (col.sublist) {
+          _subs = col.sublist
+        }
+        if (col.unfold === 'true') {
+          ucol.type = 'colspan'
+          ucol.subcols = []
+
+          _subs.forEach(sub => {
+            if (_cols[sub]) {
+              let _col = fromJS(_cols[sub]).toJS()
+              _col.Hide = 'false'
+              _col.isSub = true
+              _col.uuid = Utils.getuuid()
+
+              ucol.subcols.push(_col)
+            }
+          })
+
+          if (ucol.subcols.length > 0) {
+            _card.cols.push(ucol)
+          }
+        } else {
+          ucol.Width = 120
+          ucol.type = 'custom'
+          ucol.elements = []
+          ucol.style = {paddingTop: '12px', paddingLeft: '8px', paddingBottom: '12px', paddingRight: '8px'}
+
+          _subs.forEach(sub => {
+            if (_cols[sub]) {
+              let _col = {
+                copyable: 'false',
+                datatype: 'dynamic',
+                eleType: _cols[sub].type !== 'number' ? 'text' : 'number',
+                field: sub,
+                height: '',
+                innerHeight: 'auto',
+                marks: _cols[sub].marks || null,
+                noValue: 'show',
+                prefix: _cols[sub].prefix || '',
+                postfix: _cols[sub].postfix || '',
+                style: {},
+                width: 24,
+                uuid: Utils.getuuid()
+              }
+
+              ucol.elements.push(_col)
+            }
+          })
+
+          if (ucol.elements.length > 0) {
+            _card.cols.push(ucol)
+          }
+        }
+      }
+    })
+
+    _card.lineMarks = lineMarks
+    _card.columns = []
+    _card.absFields = []
+    _card.cols.forEach(col => {
+      if (!col.field) return
+      if (['text', 'picture', 'video', 'textarea'].includes(col.type)) {
+        _card.columns.push({
+          datatype: `Nvarchar(${col.fieldlength || 50})`,
+          field: col.field,
+          fieldlength: col.fieldlength || 50,
+          label: col.label,
+          type: 'text',
+          uuid: col.uuid
+        })
+      } else if (col.type === 'link') {
+        _card.columns.push({
+          datatype: `Nvarchar(${col.fieldlength || 50})`,
+          field: col.field,
+          fieldlength: col.fieldlength || 50,
+          label: col.label,
+          type: 'text',
+          uuid: col.uuid
+        })
+        if (col.nameField) {
+          _card.columns.push({
+            datatype: `Nvarchar(${col.fieldlength || 50})`,
+            field: col.nameField,
+            fieldlength: col.fieldlength || 50,
+            label: col.label + '(鍚嶇О)',
+            type: 'text',
+            uuid: col.uuid + 'name'
+          })
+        }
+      } else if (col.type === 'number') {
+        _card.columns.push({
+          datatype: `Decimal(18,${col.decimal || 0})`,
+          field: col.field,
+          decimal: col.decimal || 0,
+          label: col.label,
+          type: 'number',
+          uuid: col.uuid
+        })
+
+        if (col.format === 'abs') {
+          _card.absFields.push(col.field)
+        }
+      }
+    })
+
+    if (_card.absFields.length) {
+      _card.absFields = Array.from(new Set(_card.absFields))
+    } else {
+      _card.absFields = null
+    }
+
+    let colbtns = []
+    let colors = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#E7E7EF', default: 'rgba(0, 0, 0, 0.65)' }
+
+    let uuids = {}
+    config.action.forEach(btn => {
+      let _c = btn.class ? btn.class.replace('border-', '') : ''
+      let color = colors[_c] || '#1890ff'
+      let _btn = fromJS(btn).toJS()
+
+      delete _btn.position
+      delete _btn.linkTab
+
+      if (_btn.intertype === 'inner' && !_btn.innerFunc) {
+        _btn.intertype = 'system'
+      }
+      if ((_btn.intertype === 'outer' || _btn.intertype === 'custom') && !_btn.procMode) { // 鍏煎澶栭儴鍑芥暟鐩翠紶绫诲瀷
+        _btn.procMode = !_btn.innerFunc ? 'none' : 'inner'
+      }
+      if (_btn.funcType === 'print' && _btn.execMode) {
+        _btn.OpenType = 'funcbutton'
+      } else if (_btn.OpenType === 'blank') {
+        _btn.OpenType = 'tab'
+      }
+
+      this.delButtons.push(btn.uuid)
+
+      _btn.show = 'button'
+
+      if (_btn.execSuccess === 'equaltab') {
+        _btn.execSuccess = 'grid'
+        _btn.syncComponent = []
+
+        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
+          _btn.syncComponent.push(oldtabs[newCon.equalTab])
+        }
+      } else if (_btn.execSuccess === 'maingrid') {
+        _btn.execSuccess = 'mainline'
+      }
+
+      if (_btn.execError === 'equaltab') {
+        _btn.execError = 'grid'
+      } else if (_btn.execError === 'maingrid') {
+        _btn.execError = 'mainline'
+      }
+
+      if (_btn.popClose === 'equaltab') {
+        _btn.popClose = 'grid'
+        _btn.syncComponent = []
+
+        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
+          _btn.syncComponent.push(oldtabs[newCon.equalTab])
+        }
+      } else if (_btn.popClose === 'maingrid') {
+        _btn.popClose = 'mainline'
+      }
+
+      if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
+
+        formActions.push({origin: btn.uuid, uuid: _btn.uuid, name: newCon.name, label: btn.label})
+      } else if (_btn.OpenType === 'popview') {
+        if (!popActions) return
+
+        popActions.push({origin: btn.uuid, linkTab: btn.linkTab || '', uuid: _btn.uuid, name: newCon.name, label: btn.label})
+      } else if (_btn.OpenType === 'tab') {
+        if (btn.tabTemplate === 'FormTab') {
+          errors.push(newCon.name + '涓寜閽��' + btn.label + '銆嬩笉鍦ㄦ敮鎸�')
+          return
+        } else if (!btn.linkmenu || btn.linkmenu.length !== 3) {
+
+          errors.push(newCon.name + '涓寜閽��' + btn.label + '銆嬩笉鍦ㄦ敮鎸�')
+          return
+        }
+      }
+
+      uuids[btn.uuid] = true
+
+      if (_btn.tabType === 'CommonTable' || _btn.tabType === 'SubTable') {
+        _btn.tabType = 'BaseTable'
+      }
+
+      if (btn.position === 'grid') {
+        _btn.eleType = 'button'
+        _btn.width = 24
+        _btn.style = {color: color, backgroundColor: 'transparent', borderColor: 'transparent'}
+        colbtns.push(_btn)
+      } else {
+        if (btn.class === 'default') {
+          _btn.style = {color: 'rgba(0, 0, 0, 0.65)', backgroundColor: '#fff', borderColor: '#d9d9d9', marginRight: '15px'}
+        } else if (btn.class.indexOf('border') > -1) {
+          _btn.style = {color: color, backgroundColor: '#fff', borderColor: color, marginRight: '15px'}
+        } else {
+          _btn.style = {color: btn.class === 'gray' ? 'rgba(0, 0, 0, 0.65)' : '#fff', backgroundColor: color, borderColor: color, marginRight: '15px'}
+        }
+        _card.action.push(_btn)
+      }
+    })
+
+    if (colbtns.length > 0) {
+      _card.cols.push({
+        Align: 'left',
+        label: '鎿嶄綔',
+        marks: [],
+        isSub: false,
+        uuid: Utils.getuuid(),
+        type: 'custom',
+        Width: 120,
+        elements: colbtns,
+        style: {paddingTop: '12px', paddingLeft: '8px', paddingBottom: '12px', paddingRight: '8px'}
+      })
+    }
+
+    let sets = ['tableName', 'interType', 'sysInterface', 'innerFunc', 'interface', 'proInterface', 'outerFunc', 'dataresource', ['queryType', 'query'], 'primaryKey', 'order', ['laypage', 'true'], ['pageSize', 10], ['onload', 'true']]
+    let wraps = ['tableType', ['bordered', 'true'], 'actionfixed', ['size', 'middle'], ['selected', 'false'], ['tableMode', 'compatible'], ['mask', 'show'], ['borderColor', '#e8e8e8'], 'height', 'controlField', 'controlVal']
+
+    _card.scripts = config.setting.scripts || []
+
+    sets.forEach(n => {
+      if (n === 'interType') {
+        if (!['system', 'inner', 'outer'].includes(config.setting.interType)) {
+          _card.setting.interType = 'system'
+        } else if (config.setting.interType === 'inner' && !config.setting.innerFunc) {
+          _card.setting.interType = 'system'
+        } else {
+          _card.setting.interType = config.setting.interType
+        }
+      } else if (typeof(n) === 'string') {
+        _card.setting[n] = config.setting[n] || ''
+      } else {
+        _card.setting[n[0]] = config.setting[n[0]] || n[1]
+      }
+    })
+    wraps.forEach(w => {
+      if (typeof(w) === 'string') {
+        _card.wrap[w] = config.setting[w] || ''
+      } else {
+        _card.wrap[w[0]] = config.setting[w[0]] || w[1]
+      }
+    })
+
+    _card.wrap.doubleClick = config.setting.doubleClick || ''
+    if (_card.wrap.doubleClick && !uuids[_card.wrap.doubleClick]) {
+      _card.wrap.doubleClick = ''
+    }
+
+    _card.setting.execute = config.setting.default || 'true'
+
+    _card.errors = []
+    let columns = _card.columns.map(c => c.field)
+    if (_card.setting.interType === 'system' && _card.setting.execute !== 'false' && !_card.setting.dataresource) {
+      _card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
+    } else if (_card.setting.interType === 'system' && _card.setting.execute === 'false' && _card.scripts.filter(script => script.status !== 'false').length === 0) {
+      _card.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+    } else if (!_card.setting.primaryKey) {
+      _card.errors.push({ level: 0, detail: '鏈缃富閿紒'})
+    } else if (!columns.includes(_card.setting.primaryKey)) {
+      _card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
+    } else if (!_card.setting.supModule) {
+      _card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+    }
+
+    return _card
+  }
+
+  render() {
+    return (
+      <Button className="mk-border-purple" onClick={this.trigger}><ArrowUpOutlined /> 鍗囩骇</Button>
+    )
+  }
+}
+
+export default UpdateTable
\ No newline at end of file
diff --git a/src/templates/formtabconfig/groupform/index.scss b/src/templates/treepageconfig/updatetable/index.scss
similarity index 100%
rename from src/templates/formtabconfig/groupform/index.scss
rename to src/templates/treepageconfig/updatetable/index.scss
diff --git a/src/templates/zshare/createfunc/index.jsx b/src/templates/zshare/createfunc/index.jsx
index daa034f..d464a7f 100644
--- a/src/templates/zshare/createfunc/index.jsx
+++ b/src/templates/zshare/createfunc/index.jsx
@@ -4,203 +4,125 @@
 import moment from 'moment'
 
 import Utils from '@/utils/utils.js'
+import FuncUtils from './utils.js'
 import Api from '@/api'
 // import './index.scss'
 
 class CreateFunc extends Component {
   static propTypes = {
-    trigger: PropTypes.func
+    getMsg: PropTypes.func
   }
 
   state = {
-    loading: false,
+    loading: false
   }
 
-  exec = (innerFunc, newLText, DelText) => {
+  trigger = () => {
+    this.props.getMsg().then(config => {
+      let newLText = ''
+      let func = ''
+
+      if (config.$type === 'table') {
+        func = config.func
+        newLText = FuncUtils.getTableFunc(config)
+      } else if (config.$type === 'excelIn') {
+        func = config.func
+        newLText = FuncUtils.getexcelInfunc(config)
+      } else if (config.$type === 'btn') {
+        func = config.func
+        newLText = FuncUtils.getfunc(config)
+      }
+      
+      if (!newLText || !func) return
+
+      this.createExec(func, newLText)
+    })
+  }
+
+  createExec = (func, newLText) => {
+    let dropfunc = `IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('${func}') AND type in (N'P', N'PC'))  mdrpk PROCEDURE ${func}`
+    // 鍒犻櫎瀛樺偍杩囩▼
+    let droparam = {
+      func: 'sPC_TableData_InUpDe',
+      LText: Utils.formatOptions(dropfunc),
+      TypeCharOne: 'proc' // 鍒犻櫎鎴栧垱寤哄瓨鍌ㄨ繃绋嬫爣蹇�
+    }
+
+    droparam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    droparam.secretkey = Utils.encrypt(droparam.LText, droparam.timestamp)
+    droparam.open_key = Utils.encryptOpenKey(droparam.secretkey, droparam.timestamp)
+
+    // 鏂板缓瀛樺偍杩囩▼
+    let _param = {
+      func: 'sPC_TableData_InUpDe',
+      LText: Utils.formatOptions(newLText),
+      TypeCharOne: 'proc'
+    }
+    _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+    _param.open_key = Utils.encryptOpenKey(_param.secretkey, _param.timestamp)
+
+    let saveParam = {
+      func: 's_proc_save',
+      sql_script: window.btoa(window.encodeURIComponent(newLText)),
+      proc_name: func,
+      save_type: 'auto'
+    }
+
     this.setState({
       loading: true
     })
 
-    this.createExec(innerFunc, newLText, DelText)
-  }
-  
-  createExec = (innerFunc, newLText, DelText) => {
-    let isExist = false // 瀛樺偍杩囩▼鏄惁瀛樺湪
-    let cloudText = ''  // 浜戠瀛樺偍缁撴灉
-    let localfunc = ''  // 鏈湴瀛樺偍杩囩▼
-
-    new Promise(resolve => {
-      // 鑾峰彇浜戠瀛樺偍杩囩▼淇℃伅
-      Api.getSystemConfig({
-        func: 'sPC_Get_TVP',
-        TVPName: innerFunc
-      }).then(result => {
+    Api.genericInterface(droparam).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        this.setState({
+          loading: false
+        })
+        return
+      }
+      Api.genericInterface(_param).then(result => {
         if (!result.status) {
           notification.warning({
             top: 92,
             message: result.message,
             duration: 5
           })
-          resolve(false)
-        } else {
-          cloudText = result.TVPText
-          resolve(true)
-        }
-      })
-    }).then(res => {
-      if (!res) return res
-      // 鑾峰彇鏈湴瀛樺偍杩囩▼淇℃伅
-
-      let _param = {
-        func: 's_get_userproc',
-        LText: innerFunc
-      }
-      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
-      
-      return Api.genericInterface(_param)
-    }).then(res => {
-      if (!res) return res
-
-      // 澶勭悊鏈湴缁撴灉
-      if (!res.status) {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-        return false
-      } else {
-        isExist = true
-        localfunc = Utils.formatOptions(res.Ltext)
-        return true
-      }
-    }).then(res => {
-      if (!res) return res
-
-      // 鏍规嵁鏈湴鍙婅繙绔粨鏋滃垽鏂墽琛屽姩浣�
-      if ((newLText === localfunc) && (newLText === cloudText)) {
-        return 'drop'
-      } else if (!localfunc || (cloudText === localfunc)) {
-        // 鏈湴瀛樺偍杩囩▼涓嶅瓨鍦紝鎴栦簯绔拰鏈湴瀛樺偍杩囩▼涓�鑷存椂锛屽皢鏂扮殑瀛樺偍杩囩▼鏇存柊鑷充簯绔�
-        return Api.getSystemConfig({
-          func: 'sPC_TVP_InUp',
-          TVPName: innerFunc,
-          TVPText: newLText,
-          TypeName: 'P'
-        })
-      } else {
-        return new Promise(resolve => {
-          Api.getSystemConfig({ // 娣诲姞鐜版湁鐨勬湰鍦板瓨鍌ㄨ繃绋嬭嚦浜戠
-            func: 'sPC_TVP_InUp',
-            TVPName: innerFunc,
-            TVPText: localfunc,
-            TypeName: 'P'
-          }).then(result => {
-            if (result.status) {
-              Api.getSystemConfig({
-                func: 'sPC_TVP_InUp', // 娣诲姞鏈�鏂扮殑瀛樺偍杩囩▼鑷充簯绔�
-                TVPName: innerFunc,
-                TVPText: newLText,
-                TypeName: 'P'
-              }).then(response => {
-                resolve(response)
-              })
-            } else {
-              resolve(result)
-            }
+          this.setState({
+            loading: false
           })
+          return
+        }
+
+        Api.genericInterface(saveParam).then(response => {
+          this.setState({loading: false})
+          if (!response.status) {
+            notification.warning({
+              top: 92,
+              message: response.message,
+              duration: 5
+            })
+          } else {
+            notification.success({
+              top: 92,
+              message: '鍒涘缓鎴愬姛銆�',
+              duration: 5
+            })
+          }
         })
-      }
-    }).then(res => {
-      if (!res || res === 'drop') return res
-
-      // 澶勭悊浜戠鏇存柊缁撴灉
-      if (!res.status) {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-        return false
-      } else if (isExist) {
-        return 'drop'
-      } else {
-        return 'create'
-      }
-    }).then(res => {
-      if (!res || res === 'create') return res
-
-      // 鍒犻櫎瀛樺偍杩囩▼
-      let _param = {
-        func: 'sPC_TableData_InUpDe',
-        LText: DelText,
-        TypeCharOne: 'proc' // 鍒犻櫎鎴栧垱寤哄瓨鍌ㄨ繃绋嬫爣蹇�
-      }
-
-      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
-      _param.open_key = Utils.encryptOpenKey(_param.secretkey, _param.timestamp)
-
-      return Api.genericInterface(_param)
-    }).then(res => {
-      if (!res || res === 'create') return res
-      
-      // 鍒犻櫎缁撴灉澶勭悊
-      if (!res.status) {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-        return false
-      } else {
-        return true
-      }
-    }).then(res => {
-      if (!res) return res
-      
-      // 鏂板缓瀛樺偍杩囩▼
-      let _param = {
-        func: 'sPC_TableData_InUpDe',
-        LText: newLText,
-        TypeCharOne: 'proc'
-      }
-      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
-      _param.open_key = Utils.encryptOpenKey(_param.secretkey, _param.timestamp)
-
-      return Api.genericInterface(_param)
-    }).then(res => {
-      this.setState({
-        loading: false
       })
-
-      if (!res) return res
-      
-      // 澶勭悊鏂板缓缁撴灉
-      if (!res.status) {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      } else {
-        notification.success({
-          top: 92,
-          message: '鍒涘缓鎴愬姛',
-          duration: 2
-        })
-      }
     })
   }
 
   render() {
-
     return (
       <Button
         className="mk-btn mk-purple"
-        onClick={this.props.trigger}
+        onClick={this.trigger}
         loading={this.state.loading}
       >
         鍒涘缓瀛樺偍杩囩▼
diff --git a/src/templates/zshare/createfunc/utils.js b/src/templates/zshare/createfunc/utils.js
new file mode 100644
index 0000000..2e0c1b6
--- /dev/null
+++ b/src/templates/zshare/createfunc/utils.js
@@ -0,0 +1,454 @@
+/**
+ * @description 鍒涘缓瀛樺偍杩囩▼绫�
+ */
+export default class FuncUtils {
+  /**
+   * @description 鍒涘缓椤甸潰瀛樺偍杩囩▼
+   * @return {String}
+   */
+  static getTableFunc (config) {
+    let form = ''
+    let formParam = ''
+    let _vars = ['bid', 'pageindex', 'pagesize', 'ordercol', 'ordertype', 'exceltype', 'septmenuno', 'lang', 'debug', 'loginuid', 'sessionuid', 'userid', 'errorcode', 'retmsg']
+    let _columns = []
+    let primaryKey = config.setting.primaryKey || 'ID'
+
+    if (!_vars.includes(primaryKey.toLowerCase())) {
+      _vars.push(primaryKey.toLowerCase())
+      formParam = `mchr13k@${primaryKey} nvarchar(50)='',`
+    }
+
+    if (config.search && config.search.length > 0) {
+      let _fields = new Map()
+      config.search.forEach(item => {
+        if (item.field) {
+          let type = ''
+
+          if (item.type.match(/date/ig)) {
+            type = 'datetime=null'
+          } else {
+            type = 'nvarchar(50)=\'\''
+          }
+
+          item.field.split(',').forEach(cell => {
+            let _f = cell
+            if (_fields.has(cell)) {
+              _f = _f + '1'
+            }
+  
+            _fields.set(cell, true)
+
+            if (!_vars.includes(_f.toLowerCase())) {
+              _vars.push(_f.toLowerCase())
+              formParam = formParam + `mchr13k@${_f} ${type},`
+            }
+          })
+        }
+      })
+    }
+
+    if (config.columns && config.columns.length > 0) {
+      config.columns.forEach(item => {
+        if (item.field) {
+          _columns.push(`${item.field} as ${item.label}`)
+        }
+      })
+
+      form = `
+        declare @dc table (${_columns.join(',')})
+        
+        @tableid ='${config.MenuID}'
+      `
+    }
+
+    let Ltext = `create proc ${config.func}
+    ( /*${config.MenuName}*/
+    @appkey nvarchar(50)='',
+    @BID nvarchar(50)='',
+    @UserName nvarchar(50)='',
+    @FullName nvarchar(50)='',${formParam}
+    @PageIndex nvarchar(50)='',
+    @PageSize nvarchar(50)='',
+    @OrderCol nvarchar(50)='',
+    @OrderType nvarchar(50)='',
+    @exceltype nvarchar(50)='',
+    @sEPTMenuNo nvarchar(50)='${config.menuNo}',
+    @lang nvarchar(50)='',
+    @debug nvarchar(50)='',
+    @LoginUID nvarchar(50)='',
+    @SessionUid nvarchar(50)='',
+    @UserID nvarchar(50),
+    @dataM nvarchar(50),
+    @ErrorCode nvarchar(50) out,
+    @retmsg nvarchar(4000) out
+    )
+    as
+    begin
+    declare @BegindateTest datetime,@EnddateTest datetime
+    select @BegindateTest=getdate()
+    set @ErrorCode=''
+    set @retmsg=''
+    BEGIN TRY
+      /*浜嬪姟鎿嶄綔*/
+      BEGIN TRAN
+        /*鍏蜂綋涓氬姟鎿嶄綔*/
+        
+        /* 
+        select top 10 * from sProcExcep order by id desc
+
+        ${form}
+        if 1=2
+        begin
+          set @ErrorCode='E'
+          set @retmsg='鍦ㄦ鍐欐姤閿�'
+          goto GOTO_RETURN
+        end
+        
+        insert into sNote (remark,createuserid,CreateUser,CreateStaff)
+        select '鍦ㄦ鍐欐棩蹇�',@UserID,@UserName,@FullName
+        */
+        
+      COMMIT TRAN
+      SET NOCOUNT ON
+      RETURN
+    END TRY
+    BEGIN CATCH
+      /*閿欒澶勭悊*/
+      ROLLBACK TRAN
+      DECLARE @ErrorMessage NVARCHAR(4000);
+      DECLARE @ErrorSeverity INT;
+      DECLARE @ErrorState INT;
+      
+      /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/
+      set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
+      SET @retmsg=ERROR_MESSAGE();
+      SELECT @ErrorMessage=ERROR_MESSAGE(),
+        @ErrorSeverity=ERROR_SEVERITY(),
+        @ErrorState=ERROR_STATE();
+        
+      RAISERROR(@ErrorMessage, /*-- Message text.*/
+        @ErrorSeverity, /*-- Severity.*/
+        @ErrorState  /*-- State.*/
+      );
+    END CATCH
+    
+    GOTO_RETURN:
+      ROLLBACK TRAN
+      
+    END`
+
+    Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k')
+
+    return Ltext
+  }
+
+  /**
+   * @description 鍒涘缓瀛樺偍杩囩▼
+   * @return {String}
+   */
+  static getfunc (btn) {
+    let form = ''
+    let formParam = ''
+    let _vars = ['bid', 'septmenuno', 'lang', 'debug', 'loginuid', 'sessionuid', 'userid', 'errorcode', 'retmsg']
+    let columns = btn.columns
+    let primaryKey = btn.primaryKey
+
+    if (!_vars.includes(primaryKey.toLowerCase())) {
+      _vars.push(primaryKey.toLowerCase())
+      let _type = '50'
+      if (btn.Ot === 'requiredOnce') { // 澶氳鎷兼帴鏃讹紝涓婚敭璁句负max
+        _type = 'max'
+      }
+      formParam = `mchr13k@${primaryKey} nvarchar(${_type})='',`
+    }
+
+    if (btn.fields && btn.fields.length > 0) {
+      let _fields = []
+      btn.fields.forEach(item => {
+        if (item.field) {
+          let type = ''
+          if (item.type.match(/date/ig)) {
+            type = 'datetime=null'
+          } else if (item.type === 'number') {
+            type = `decimal(18,${item.decimal})=0`
+          } else if (item.type === 'rate') {
+            type = `decimal(18,2)=0`
+          } else {
+            type = 'nvarchar(50)=\'\''
+          }
+
+          if (!_vars.includes(item.field.toLowerCase())) {
+            _vars.push(item.field.toLowerCase())
+            formParam = formParam + `mchr13k@${item.field} ${type},`
+          }
+
+          _fields.push(item.field)
+        }
+      })
+
+      let field1 = _fields.join(',')
+      let field2 = _fields.join(',@')
+      let field3 = _fields.map(cell => {
+        return cell + '=@' + cell
+      })
+
+      field2 = field2 ? '@' + field2 : ''
+      field3 = field3.join(',')
+
+      form = `
+        insert into ${btn.name} (${field1},createuserid) select ${field2},@UserID
+        
+        update ${btn.name} set ${field3},modifydate=getdate(),modifyuser=@username,modifyuserid=@UserID
+      `
+    } else if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') {
+      form = `
+        update ${btn.name} set ModifyDate=getdate(),ModifyUserID=@UserID where ${primaryKey}=@${primaryKey}
+      `
+    }
+
+    if (columns) {
+      let _col = []
+      let _field = []
+      columns.forEach(col => {
+        if (col.field) {
+          if (col.type === 'number') {
+            _col.push(col.field + ' decimal(18,2)')
+          } else {
+            _col.push(col.field + ' nvarchar(50)')
+          }
+          _field.push(col.field)
+        }
+      })
+      _col = _col.join(',')
+      _field = _field.join(',')
+
+      form = form + `
+        declare @dc table (${_col})
+        
+        insert into @dc (${_field})
+
+        @tableid ='${btn.MenuID}'
+      `
+    }
+
+    // 鎵撳嵃鑷畾涔夋ā鏉垮瓧娈垫彁绀�
+    let _printRemark = ''
+    if (btn.funcType === 'print') {
+      _printRemark = '/* 鑷畾涔夋暟鎹墦鍗版ā鏉挎椂锛岃浣跨敤TemplateID瀛楁 */'
+    }
+
+    let Ltext = `create proc ${btn.func}
+    ( /*${btn.MenuName}  ${btn.label}*/
+    @appkey nvarchar(50)='',
+    @BID nvarchar(50)='',
+    @UserName nvarchar(50)='',
+    @FullName nvarchar(50)='',${formParam}
+    @sEPTMenuNo nvarchar(50)='${btn.menuNo}',
+    @lang nvarchar(50)='',
+    @debug nvarchar(50)='',
+    @LoginUID nvarchar(50)='',
+    @SessionUid nvarchar(50)='',
+    @UserID nvarchar(50),
+    @ErrorCode nvarchar(50) out,
+    @retmsg nvarchar(4000) out
+    )
+    as
+    begin
+    declare  @BegindateTest datetime,@EnddateTest datetime
+    select  @BegindateTest=getdate()
+    set @ErrorCode=''
+    set @retmsg=''
+    BEGIN TRY
+      /*浜嬪姟鎿嶄綔*/
+      BEGIN TRAN
+        /*鍏蜂綋涓氬姟鎿嶄綔*/
+        ${_printRemark}
+        /* 
+        select top 10 * from sProcExcep order by id desc
+
+        ${form}
+        if 1=2
+        begin
+          set @ErrorCode='E'
+          set @retmsg='鍦ㄦ鍐欐姤閿�'
+          goto GOTO_RETURN
+        end
+        
+        insert into sNote (remark,createuserid,CreateUser,CreateStaff)
+        select '鍦ㄦ鍐欐棩蹇�',@UserID,@UserName,@FullName
+        */
+        
+      COMMIT TRAN
+      SET NOCOUNT ON
+      RETURN
+    END TRY
+    BEGIN CATCH
+      /*閿欒澶勭悊*/
+      ROLLBACK TRAN
+      DECLARE @ErrorMessage NVARCHAR(4000);
+      DECLARE @ErrorSeverity INT;
+      DECLARE @ErrorState INT;
+      
+      /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/
+      set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
+      SET @retmsg=ERROR_MESSAGE();
+      SELECT @ErrorMessage=ERROR_MESSAGE(),
+        @ErrorSeverity=ERROR_SEVERITY(),
+        @ErrorState=ERROR_STATE();
+        
+      RAISERROR(@ErrorMessage, /* Message text.*/
+        @ErrorSeverity, /* Severity.*/
+        @ErrorState  /* State.*/
+      );
+    END CATCH
+    
+    GOTO_RETURN:
+      ROLLBACK TRAN
+      
+    END`
+
+    Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k')
+
+    return Ltext
+  }
+
+  /**
+   * @description 鍒涘缓瀵煎叆瀛樺偍杩囩▼
+   * @return {String}
+   */
+  static getexcelInfunc (btn) {
+    let _verify = btn.verify
+
+    let _uniquesql = ''
+    if (_verify.uniques && _verify.uniques.length > 0) {
+      _verify.uniques.forEach(unique => {
+        if (unique.status === 'false') return
+
+        let _fields = unique.field.split(',')
+        let _fields_ = _fields.map(_field => {
+          return `a.${_field}=b.${_field}`
+        })
+        _fields_ = _fields_.join(' and ')
+
+        if (unique.verifyType !== 'physical') {
+          _fields_ += ' and b.deleted=0'
+        }
+
+        _uniquesql += `
+        Set @tbid=''
+        Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${btn.sheet} ) a group by ${unique.field} having sum(n)>1
+
+        If @tbid!=''
+        Begin
+          select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 閲嶅'
+          goto aaa
+        end
+
+        Set @tbid=''
+        Select top 1 @tbid=${_fields.join('+\' \'+')} from  @${btn.sheet} a
+        Inner join ${btn.sheet} b on ${_fields_}
+
+        If @tbid!=''
+        Begin
+          select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
+          goto aaa
+        end
+        `
+      })
+
+      if (_uniquesql) {
+        _uniquesql = `
+        Declare @tbid Nvarchar(512)
+        ${_uniquesql}`
+      }
+    }
+
+    let declarefields = []
+    let fields = []
+
+    _verify.columns.forEach(col => {
+      declarefields.push(`${col.Column} ${col.type}`)
+      fields.push(col.Column)
+    })
+
+    fields = fields.join(',')
+
+    let _sql = `declare @${btn.sheet} table (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50))
+      
+      Insert into @${btn.sheet} (${fields},jskey,BID)
+
+      select @LText=dbo.urldecode(dbo.base64decode(@LText))
+
+      ${_uniquesql}
+      Insert into ${btn.sheet} (${fields},createuserid,createuser,createstaff,bid) 
+      Select ${fields},@userid,@username,@fullname,@BID From @${btn.sheet}
+
+      Delete @${btn.sheet}`
+
+    let Ltext = `create proc ${btn.func}
+    ( /*${btn.MenuName}  ${btn.label}*/
+      @appkey nvarchar(50)='',
+      @ID nvarchar(50)='',
+      @BID nvarchar(50)='',
+      @UserName nvarchar(50)='',
+      @FullName nvarchar(50)='',
+      @Ltext nvarchar(max)='',
+      @sEPTMenuNo nvarchar(50)='${btn.menuNo}', 
+      @secretkey nvarchar(50)='',
+      @timestamp nvarchar(50)='',
+      @lang nvarchar(50)='',
+      @LoginUID nvarchar(50)='',
+      @SessionUid nvarchar(50)='',
+      @UserID nvarchar(50), 
+      @ErrorCode nvarchar(50) out,
+      @retmsg nvarchar(4000) out
+    )
+    as
+    begin
+    declare @BegindateTest datetime,@EnddateTest datetime 
+    select @BegindateTest=getdate() 
+    set @ErrorCode=''
+    set @retmsg=''
+    BEGIN TRY
+      /*浜嬪姟鎿嶄綔*/
+      BEGIN TRAN
+        /*鍏蜂綋涓氬姟鎿嶄綔*/
+
+        /* 
+        ${_sql}
+        */
+        
+      COMMIT TRAN
+      SET NOCOUNT ON
+      RETURN
+    END TRY
+    BEGIN CATCH
+      /*閿欒澶勭悊*/
+      ROLLBACK TRAN
+      DECLARE @ErrorMessage NVARCHAR(4000);
+      DECLARE @ErrorSeverity INT;
+      DECLARE @ErrorState INT;
+      
+      /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/
+      set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
+      SET @retmsg=ERROR_MESSAGE();
+      SELECT @ErrorMessage=ERROR_MESSAGE(),
+        @ErrorSeverity=ERROR_SEVERITY(),
+        @ErrorState=ERROR_STATE();
+        
+      RAISERROR(@ErrorMessage, /* Message text.*/
+        @ErrorSeverity, /* Severity.*/
+        @ErrorState  /* State.*/
+      );
+    END CATCH
+    
+    GOTO_RETURN:
+      ROLLBACK TRAN
+      
+    END`
+
+    Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k')
+
+    return Ltext
+  }
+}
\ No newline at end of file
diff --git a/src/templates/zshare/createinterface/index.jsx b/src/templates/zshare/createinterface/index.jsx
index ab76039..b5d117a 100644
--- a/src/templates/zshare/createinterface/index.jsx
+++ b/src/templates/zshare/createinterface/index.jsx
@@ -6,7 +6,6 @@
 
 import MutilForm from './mutilform'
 import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
 import { updateForm } from '@/utils/utils-update.js'
 import Api from '@/api'
 import './index.scss'
@@ -335,7 +334,7 @@
       Ltexttableparam: '',
       Ltext: '',
       menuType: menu.type,
-      systemType: options.sysType
+      systemType: window.GLOB.sysType
     }
 
     this.setState({
@@ -406,7 +405,7 @@
 
     new Promise(resolve => {
       if (btn.OpenType === 'pop') {
-        Api.getSystemConfig({
+        Api.getCloudConfig({
           func: 'sPC_Get_LongParam',
           MenuID: btn.uuid
         }).then(result => {
diff --git a/src/templates/zshare/customscript/index.jsx b/src/templates/zshare/customscript/index.jsx
index 2cc6298..662e012 100644
--- a/src/templates/zshare/customscript/index.jsx
+++ b/src/templates/zshare/customscript/index.jsx
@@ -142,7 +142,7 @@
     _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
-    Api.getSystemConfig(_sParam).then(res => {
+    Api.getCloudConfig(_sParam).then(res => {
       if (res.status) {
         let _scripts = res.data.map(item => {
           let _item = {
diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx
index ad29e43..3f0e3fe 100644
--- a/src/templates/zshare/editTable/index.jsx
+++ b/src/templates/zshare/editTable/index.jsx
@@ -180,6 +180,15 @@
     const { data, actions } = this.props
     let columns = fromJS(this.props.columns).toJS()
     let operation = null
+    let extra = null
+    
+    if (actions) {
+      actions.forEach(item => {
+        if (/^extra/.test(item)) {
+          extra = item.split(':')
+        }
+      })
+    }
 
     if (actions && (actions.includes('edit') || actions.includes('copy') || actions.includes('del'))) {
       let _operation = null
@@ -217,9 +226,10 @@
             </div>
           ) : (
             <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px', whiteSpace: 'nowrap'}}>
-              {actions.includes('edit') ? <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><EditOutlined /></span> : null}
-              {actions.includes('copy') ? <span className="copy" onClick={() => {editingKey === '' && this.copy(record)}}><CopyOutlined /></span> : null}
-              {actions.includes('status') ? <span className="status" onClick={() => {editingKey === '' && this.handleStatus(record)}}><SwapOutlined /></span> : null}
+              {actions.includes('edit') ? <span className="primary" title="缂栬緫" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><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}
               {actions.includes('del') && editingKey === '' ? <Popconfirm
                 overlayClassName="popover-confirm"
                 title="纭畾鍒犻櫎鍚�?"
@@ -406,7 +416,9 @@
       columns.forEach(col => {
         if (col.unique !== true || !unique) return
 
-        if (col.strict) {
+        if (col.uniqueFunc) {
+          unique = col.uniqueFunc(data, res.data)
+        } else if (col.strict) {
           let key = res.data[col.dataIndex].toLowerCase()
           let _index = data.findIndex(item => key === item[col.dataIndex].toLowerCase())
 
@@ -445,7 +457,9 @@
         columns.forEach(col => {
           if (col.unique !== true || !unique) return
 
-          if (col.strict) {
+          if (col.uniqueFunc) {
+            unique = col.uniqueFunc(data, cell)
+          } else if (col.strict) {
             let _index = data.findIndex(item => cell[col.dataIndex].toLowerCase() === item[col.dataIndex].toLowerCase())
   
             if (_index > -1) {
@@ -474,10 +488,10 @@
     message.success('绮樿创鎴愬姛銆�')
   }
 
-  handleStatus = (record) => {
+  handleStatus = (record, type) => {
     const { data } = this.state
 
-    record.status = record.status === 'false' ? 'true' : 'false'
+    record[type] = record[type] === 'false' ? 'true' : 'false'
 
     let newData = data.map(item => {
       if (record.uuid === item.uuid) return record
@@ -508,15 +522,32 @@
     columns.forEach(col => {
       if (col.unique !== true || !unique) return
 
-      let _index = newData.findIndex(item => record.uuid !== item.uuid && record[col.dataIndex] === item[col.dataIndex])
+      if (col.uniqueFunc) {
+        unique = col.uniqueFunc(newData, record)
+        return
+      } else if (col.strict) {
+        let key = record[col.dataIndex].toLowerCase()
+        let _index = newData.findIndex(item => record.uuid !== item.uuid && key === item[col.dataIndex].toLowerCase())
 
-      if (_index > -1) {
-        notification.warning({
-          top: 92,
-          message: col.title + '涓嶅彲閲嶅锛�',
-          duration: 5
-        })
-        unique = false
+        if (_index > -1) {
+          notification.warning({
+            top: 92,
+            message: col.title + '涓嶅彲閲嶅锛�',
+            duration: 5
+          })
+          unique = false
+        }
+      } else {
+        let _index = newData.findIndex(item => record.uuid !== item.uuid && record[col.dataIndex] === item[col.dataIndex])
+  
+        if (_index > -1) {
+          notification.warning({
+            top: 92,
+            message: col.title + '涓嶅彲閲嶅锛�',
+            duration: 5
+          })
+          unique = false
+        }
       }
     })
 
@@ -547,31 +578,49 @@
       }
       const newData = [...this.state.data]
       const index = newData.findIndex(item => uuid === item.uuid)
+      if (index > -1) {
+        row = {...newData[index], ...row}
+      } else {
+        row.uuid = uuid
+      }
 
       let unique = true
       columns.forEach(col => {
         if (col.unique !== true || !unique) return
 
-        let _index = newData.findIndex(item => uuid !== item.uuid && row[col.dataIndex] === item[col.dataIndex])
-
-        if (_index > -1) {
-          notification.warning({
-            top: 92,
-            message: col.title + '涓嶅彲閲嶅锛�',
-            duration: 5
-          })
-          unique = false
+        if (col.uniqueFunc) {
+          unique = col.uniqueFunc(newData, row)
+          return
+        } else if (col.strict) {
+          let key = row[col.dataIndex].toLowerCase()
+          let _index = newData.findIndex(item => row.uuid !== item.uuid && key === item[col.dataIndex].toLowerCase())
+  
+          if (_index > -1) {
+            notification.warning({
+              top: 92,
+              message: col.title + '涓嶅彲閲嶅锛�',
+              duration: 5
+            })
+            unique = false
+          }
+        } else {
+          let _index = newData.findIndex(item => row.uuid !== item.uuid && row[col.dataIndex] === item[col.dataIndex])
+  
+          if (_index > -1) {
+            notification.warning({
+              top: 92,
+              message: col.title + '涓嶅彲閲嶅锛�',
+              duration: 5
+            })
+            unique = false
+          }
         }
       })
 
       if (!unique) return
 
       if (index > -1) {
-        const item = newData[index]
-        newData.splice(index, 1, {
-          ...item,
-          ...row,
-        })
+        newData.splice(index, 1, row)
         this.setState({ data: newData, editingKey: '' }, () => {
           this.props.onChange(newData)
         })
@@ -660,7 +709,7 @@
       return item
     })
 
-    let reg = searchKey ? new RegExp(searchKey, 'ig') : null
+    let reg = searchKey ? new RegExp(searchKey, 'i') : null
 
     return (
       <EditableContext.Provider value={this.props.form}>
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index d3ee589..db78cd8 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -359,6 +359,9 @@
       value: 'switch',
       text: '寮�鍏�'
     }, {
+      value: 'radio',
+      text: '鍗曢�夋'
+    }, {
       value: 'check',
       text: '鍕鹃�夋'
     }]
@@ -367,7 +370,7 @@
   if (card.focus) {
     if (['text', 'multiselect'].includes(card.type)) {
       card.match = 'like'
-    } else if (['select', 'link', 'checkcard'].includes(card.type)) {
+    } else if (['select', 'link', 'checkcard', 'radio'].includes(card.type)) {
       card.match = '='
     } else if (card.type === 'date') {
       card.match = '>='
@@ -384,6 +387,30 @@
       Text: '鍏ㄩ儴',
       ParentID: ''
     })
+  }
+
+  let muloptions = [{
+    value: 'false',
+    text: '鍗曢��'
+  }, {
+    value: 'true',
+    text: '澶氶��'
+  }, {
+    value: 'dropdown',
+    text: '涓嬫媺鑿滃崟'
+  }]
+
+  if (appType !== '') {
+    muloptions = [{
+      value: 'false',
+      text: '鍗曢��'
+    }, {
+      value: 'true',
+      text: '澶氶��'
+    }]
+    if (card.multiple === 'dropdown') {
+      card.multiple = 'false'
+    }
   }
 
   return [
@@ -573,14 +600,18 @@
       key: 'multiple',
       label: '閫夋嫨褰㈠紡',
       initVal: card.multiple || 'false',
+      // tooltip: appType === '' ? '浣跨敤涓嬫媺鑿滃崟鏃讹紝閫夐」浼氫緷鎹� pid 缁勭粐鏁版嵁鐨勪笂涓嬬骇鍏崇郴锛屼簩绾ч�夐」浼氫笅鎷夊睍绀恒�傛敞锛�1銆佹樉绀轰负鏂囨湰鏃舵湁鏁堬紱2銆佷娇鐢ㄦ暟鎹簮璇疯繑鍥� pid 瀛楁銆�' : '',
       required: true,
-      options: [{
-        value: 'false',
-        text: '鍗曢��'
-      }, {
-        value: 'true',
-        text: '澶氶��'
-      }]
+      options: muloptions
+    },
+    {
+      type: 'text',
+      key: 'parentField',
+      label: '涓婄骇瀛楁',
+      initVal: card.parentField || '',
+      tooltip: '鐢ㄤ簬缁勭粐鏁版嵁涓婁笅绾у叧绯伙紝璇锋敞鎰忓~鍐欓《绾ф爣璇嗐��',
+      required: true,
+      readonly: false
     },
     {
       type: 'select',
@@ -898,6 +929,14 @@
       initVal: card.backgroundColor || '',
       tooltip: '璁剧疆鑳屾櫙鑹插悗锛岄�変腑鏁堟灉鐢辫儗鏅鑹叉帶鍒躲��',
       required: true
+    },
+    {
+      type: 'text',
+      key: 'mark',
+      label: '椤剁骇鏍囪瘑',
+      initVal: card.mark || '',
+      tooltip: '涓婄骇瀛楁(pid)涓庨《绾ф爣璇嗙浉鍚屾椂锛岃涓洪《绾ц妭鐐广��',
+      required: false
     },
     {
       type: 'multiselect',
@@ -2885,7 +2924,7 @@
       key: 'dataSource',
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
-      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆�',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�硷細@ID@銆丂BID@銆�',
       required: true,
       readonly: false
     },
@@ -3029,7 +3068,20 @@
       }, {
         value: '-90',
         text: '鍓�90澶�'
+      }, {
+        value: 'custom',
+        text: '鑷畾涔�'
       }]
+    },
+    {
+      type: 'text',
+      key: 'minDateField',
+      label: '鏈�灏忓�硷紙瀛楁锛�',
+      initVal: card.minDateField || '',
+      tooltip: '鏈�灏忓�煎搴斿瓧娈碉紝涔熷彲鑷畾涔夊浐瀹氬�硷紝鏍煎紡涓篩YYY-MM-DD銆�',
+      required: true,
+      readonly: false,
+      options: columns
     },
     {
       type: 'select',
@@ -3079,7 +3131,20 @@
       }, {
         value: '-90',
         text: '鍓�90澶�'
+      }, {
+        value: 'custom',
+        text: '鑷畾涔�'
       }]
+    },
+    {
+      type: 'text',
+      key: 'maxDateField',
+      label: '鏈�澶у�硷紙瀛楁锛�',
+      initVal: card.maxDateField || '',
+      tooltip: '鏈�澶у�煎搴斿瓧娈碉紝涔熷彲鑷畾涔夊浐瀹氬�硷紝鏍煎紡涓篩YYY-MM-DD銆�',
+      required: true,
+      readonly: false,
+      options: columns
     },
     {
       type: 'radio',
@@ -3118,7 +3183,7 @@
       type: 'text',
       key: 'separator',
       label: '杩炴帴绗�',
-      initVal: card.separator === undefined ? '/' : card.separator,
+      initVal: card.separator === undefined ? ',' : card.separator,
       tooltip: '琛ㄥ崟鎻愪氦鏃朵俊鎭箣闂寸殑杩炴帴绗︺�傛敞锛氳繛鎺ョ涓虹┖鏃讹紝鍒濆鍖栨椂濉厖鍏朵粬琛ㄥ崟鏃犳晥銆�',
       required: false,
       readonly: false
@@ -3445,6 +3510,22 @@
       }, {
         value: 'hide',
         text: '闅愯棌'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'checkAll',
+      label: '鍏ㄩ��',
+      initVal: card.checkAll || 'hide',
+      tooltip: '鍙閫夌殑閫夐」鍗℃槸鍚︽樉绀哄叏閫夊紑鍏筹紝娉細褰撻�夐」澶т簬3涓椂鏈夋晥銆�',
+      required: false,
+      forbid: appType !== '',
+      options: [{
+        value: 'hide',
+        text: '闅愯棌'
+      }, {
+        value: 'show',
+        text: '鏄剧ず'
       }]
     },
     {
@@ -4013,7 +4094,7 @@
       type: 'multiselect',
       key: 'linkSubField',
       label: '濉厖琛ㄥ崟',
-      tooltip: '鍦ㄥ垏鎹㈤�夐」鏃朵細鎶婁俊鎭嚜鍔ㄥ~鍏ュ叧鑱旂殑琛ㄥ崟锛堟枃鏈垨鏁板瓧琛ㄥ崟锛変腑銆�',
+      tooltip: '鍦ㄥ垏鎹㈤�夐」鏃朵細鎶婁俊鎭嚜鍔ㄥ~鍏ュ叧鑱旂殑琛ㄥ崟锛堟枃鏈垨鏁板瓧琛ㄥ崟锛変腑锛屽紑鍏充細灏嗘彁绀烘枃鏈~鍏ユ琛ㄥ崟銆�',
       initVal: card.linkSubField || [],
       options: inputfields
     },
@@ -4108,8 +4189,7 @@
       key: 'icon',
       label: '鍥炬爣',
       initVal: card.icon || '',
-      required: false,
-      forbid: type === 'CalendarPage'
+      required: false
     },
     {
       type: 'select',
@@ -4117,8 +4197,7 @@
       label: '涓婄骇鏍囩',
       initVal: supMenu,
       required: false,
-      options: menus,
-      forbid: type === 'CalendarPage'
+      options: menus
     },
     {
       type: 'mutilselect',
@@ -4127,8 +4206,7 @@
       tooltip: '濡傛灉瀛愭爣绛句腑鍚湁鍒锋柊鍚岀骇鏍囩鐨勬寜閽紝鍦ㄦ澶勬坊鍔犻渶瑕佸埛鏂扮殑鏍囩銆�',
       initVal: equalTab,
       required: false,
-      options: equalTabs,
-      forbid: type === 'CalendarPage'
+      options: equalTabs
     },
     {
       type: 'text',
@@ -4136,8 +4214,7 @@
       label: '澶栭敭',
       tooltip: '澶栭敭鏃ㄥ湪鏍囩椤典腑鎵ц榛樿鍑芥暟锛堟坊鍔狅級鏃讹紝鏇挎崲BID瀛楁',
       initVal: card.foreignKey || '',
-      required: false,
-      forbid: type === 'CalendarPage'
+      required: false
     },
     {
       type: 'number',
@@ -4157,7 +4234,7 @@
       initVal: card.searchPass || 'false',
       tooltip: '浣跨敤涓昏〃鎼滅储鏉′欢鏃讹紝涓昏〃鐨勬悳绱㈡潯浠朵細浼犲叆瀛愯〃涓��',
       required: false,
-      forbid: type !== 'CommonTable' && type !== 'CalendarPage',
+      forbid: type !== 'CommonTable',
       options: [{
         value: 'true',
         text: '浣跨敤'
diff --git a/src/templates/zshare/modalform/datatable/index.jsx b/src/templates/zshare/modalform/datatable/index.jsx
index 75a9a67..8f3e62b 100644
--- a/src/templates/zshare/modalform/datatable/index.jsx
+++ b/src/templates/zshare/modalform/datatable/index.jsx
@@ -174,6 +174,7 @@
       !is(fromJS(this.props.fields), fromJS(nextProps.fields)) ||
       !is(fromJS(this.props.linkSubFields), fromJS(nextProps.linkSubFields)) ||
       this.props.display !== nextProps.display ||
+      (nextProps.multiple && this.props.multiple !== nextProps.multiple) ||
       this.props.type !== nextProps.type
     ) {
       this.setState({editingKey: ''}, () => {
@@ -185,9 +186,9 @@
   }
 
   getCloumns = () => {
-    const { display, fields, linkSubFields, transfield, type } = this.props
+    const { display, fields, linkSubFields, transfield, type, multiple } = this.props
     let columns = []
-    let keys = ['ParentID']
+    let keys = ['ParentID', 'pid']
 
     if (display === 'picture') {
       columns.push({
@@ -241,6 +242,14 @@
       editable: true,
     })
 
+    if (multiple === 'dropdown' && display === 'text') {
+      columns.unshift({
+        title: 'pid',
+        dataIndex: 'pid',
+        editable: true,
+      })
+    }
+
     if (type === 'link') {
       columns.unshift({
         title: 'ParentID',
diff --git a/src/templates/zshare/modalform/fieldtable/index.jsx b/src/templates/zshare/modalform/fieldtable/index.jsx
index d9100da..3b607cf 100644
--- a/src/templates/zshare/modalform/fieldtable/index.jsx
+++ b/src/templates/zshare/modalform/fieldtable/index.jsx
@@ -127,6 +127,26 @@
         this.setState({loading: false})
       })
       return
+    } else if (fields.filter(f => f.toLowerCase() === 'parentid').length > 0) {
+      notification.warning({
+        top: 92,
+        message: '瀛楁鍚嶄笉鍙娇鐢╬arentid锛�',
+        duration: 5
+      })
+      this.setState({loading: true}, () => {
+        this.setState({loading: false})
+      })
+      return
+    } else if (fields.filter(f => f.toLowerCase() === 'pid').length > 0) {
+      notification.warning({
+        top: 92,
+        message: '瀛楁鍚嶄笉鍙娇鐢╬id锛�',
+        duration: 5
+      })
+      this.setState({loading: true}, () => {
+        this.setState({loading: false})
+      })
+      return
     }
 
     this.setState({ data }, () => {
diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx
index 27260e3..3aaa932 100644
--- a/src/templates/zshare/modalform/index.jsx
+++ b/src/templates/zshare/modalform/index.jsx
@@ -28,11 +28,11 @@
   multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'marginTop', 'marginBottom', 'dropdown'],
   link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkField', 'linkSubField', 'span', 'place', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
   fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'tooltip', 'extra', 'compress', 'miniSet', 'splitline', 'marginTop', 'marginBottom', 'maxSize'],
-  switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom'],
+  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'],
   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'],
+  // datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline', 'marginTop', 'marginBottom', 'minDate', 'maxDate'],
   textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'span', 'labelwidth', 'maxRows', 'encryption', 'interception', 'tooltip', 'extra', 'place', 'count', 'placeholder', 'marginTop', 'marginBottom'],
   cascader: ['readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'marginTop', 'marginBottom', 'separator'],
   color: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'colorType', 'extra', 'marginTop', 'marginBottom'],
@@ -221,8 +221,8 @@
           shows.push('decimal')
         }
       } else {
-        shows.push('fieldlength')
-        reTooltip.initval = '娣诲姞澶氫釜鍒濆鍊艰浣跨敤閫楀彿鍒嗛殧銆�'
+        shows.push('fieldlength', 'checkAll')
+        reTooltip.initval = '娣诲姞澶氫釜鍒濆鍊艰浣跨敤閫楀彿鍒嗛殧銆�' 
       }
 
       shows.push('linkField')
@@ -234,9 +234,17 @@
       if (this.record.readonly === 'true' && this.record.hidden !== 'true') {
         shows.push('unchecked')
       }
-    } else if (['date', 'datemonth', 'datetime'].includes(type)) {
+    } else if (['date', 'datemonth'].includes(type)) {
       reOptions.initval = dateOptions[type]
       reTypes.initval = 'select'
+      if (type === 'date') {
+        if (this.record.minDate === 'custom') {
+          shows.push('minDateField')
+        }
+        if (this.record.maxDate === 'custom') {
+          shows.push('maxDateField')
+        }
+      }
     } else if (type === 'switch' || type === 'check') {
       reOptions.initval = [
         {value: true, text: '寮�'},
@@ -408,6 +416,8 @@
           this.record.resourceType = '0'
           _fieldval.resourceType = '0'
         }
+      } else if (this.record.type === 'funcvar' && value !== 'funcvar') {
+        this.record.readonly = 'false'
       }
 
       if (this.record.options.length > 0) {
@@ -588,7 +598,7 @@
     this.props.form.setFieldsValue({dataSource: resource})
   }
 
-  complete = (key, option) => {
+  complete = (option) => {
     let label = option.props.label
 
     this.props.form.setFieldsValue({label: label})
@@ -642,13 +652,13 @@
           })
         }
 
-        if (item.key === 'field' && item.options && item.options.length > 0) {
+        if (['field', 'minDateField', 'maxDateField'].includes(item.key) && item.options && item.options.length > 0) {
           content = <AutoComplete
             dataSource={item.options.map((cell) => <AutoComplete.Option label={cell.label} value={cell.field} key={cell.uuid}>
               {cell.field}
             </AutoComplete.Option>)}
             filterOption={(input, option) => option.props.children.indexOf(input) > -1}
-            onSelect={this.complete}
+            onSelect={(val, option) => item.key === 'field' && this.complete(option)}
             placeholder=""
           >
             <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />
@@ -986,7 +996,7 @@
 
           ['linkField', 'valueField', 'valueText', 'orderBy'].forEach(item => {
             if (values[item]) {
-              values[item] = values[item].replace(/\s*|\t*|\v*|\r*/ig, '')
+              values[item] = values[item].replace(/\s+|\t+|\v+|\r+/ig, '')
             }
           })
 
diff --git a/src/templates/zshare/modalform/modaleditable/index.jsx b/src/templates/zshare/modalform/modaleditable/index.jsx
index 053e370..b8ca161 100644
--- a/src/templates/zshare/modalform/modaleditable/index.jsx
+++ b/src/templates/zshare/modalform/modaleditable/index.jsx
@@ -4,7 +4,6 @@
 import { Table, Input, Popconfirm, Form, message } from 'antd'
 import { ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
 
-import { formRule } from '@/utils/option.js'
 import Utils from '@/utils/utils.js'
 import './index.scss'
 
@@ -35,16 +34,8 @@
   }
 
   save = e => {
-    const { record, handleSave, datatype } = this.props
+    const { record, handleSave } = this.props
     this.form.validateFields((error, values) => {
-      if (datatype === 'number') {
-        Object.keys(values).forEach(key => {
-          values[key] = parseFloat(values[key])
-          if (isNaN(values[key])) {
-            values[key] = 0
-          }
-        })
-      }
       handleSave({ ...record, ...values })
       if (error && error[e.currentTarget.id]) {
         return
@@ -55,16 +46,8 @@
 
   renderCell = form => {
     this.form = form
-    const { children, dataIndex, record, datatype } = this.props
+    const { children, dataIndex, record } = this.props
     const { editing } = this.state
-
-    let rules = []
-    if (datatype === 'number') {
-      rules.push({
-        pattern: /^(-?\d+)(\.\d+)?$/,
-        message: formRule.input.numbermsg
-      })
-    }
 
     return editing ? (
       <Form.Item style={{ margin: '0 -5px 0 -5px' }}>
@@ -73,8 +56,7 @@
             {
               required: dataIndex === 'Text',
               message: '涓嶅彲涓虹┖.',
-            },
-            ...rules
+            }
           ],
           initialValue: record[dataIndex]
         })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
@@ -139,52 +121,6 @@
       count: data.length
     })
   }
-
-  // changeDatatype = (column) => {
-  //   const { columns, dataSource } = this.state
-  //   let value = column.datatype !== 'number' ? 'number' : 'string'
-  //   let _data = dataSource.map(item => {
-  //     let val = item[column.dataIndex]
-  //     if (value === 'number') {
-  //       val = parseFloat(val)
-  //       if (isNaN(val)) {
-  //         val = 0
-  //       }
-  //     } else {
-  //       val = '' + val
-  //     }
-
-  //     item[column.dataIndex] = val
-
-  //     return item
-  //   })
-
-  //   this.setState({
-  //     dataSource: _data,
-  //     columns: columns.map(col => {
-  //       if (col.dataIndex === column.dataIndex) {
-  //         col.datatype = value
-  //       }
-
-  //       if (col.dataIndex !== 'operation') {
-  //         col.title = <div>
-  //           {col.$title}
-  //           {/* <Popconfirm
-  //             title={`纭畾鍒囨崲涓�${col.datatype === 'number' ? '鏂囨湰' : '鏁板��'}鍚楋紵`}
-  //             overlayClassName="popover-confirm"
-  //             onConfirm={() => this.changeDatatype(col)
-  //           }>
-  //             <SwapOutlined style={{ color: col.datatype === 'number' ? '#1890ff' : ''}} />
-  //           </Popconfirm> */}
-  //         </div>
-  //       }
-
-  //       return col
-  //     })
-  //   }, () => {
-  //     this.props.onChange(_data)
-  //   })
-  // }
 
   handleUpDown = (record, direction) => {
     const { dataSource } = this.state
@@ -292,7 +228,6 @@
 
     let _dataSource = fromJS(dataSource).toJS()
     let fields = []
-    let dataItem = ''
     let subFields = linkSubFields.filter(m => m !== 'Value' && m !== 'Text')
 
     if (subFields.length > 0) {
@@ -304,19 +239,14 @@
         return data
       })
 
-      dataItem = _dataSource ? _dataSource[0] : ''
-
       fields = subFields.map(field => {
         return {
           title: transfield[field] || field,
           $title: transfield[field] || field,
           dataIndex: field,
           editable: true,
-          datatype: dataItem && typeof(dataItem[field]) === 'number' ? 'number' : 'string'
         }
       })
-    } else {
-      dataItem = _dataSource ? _dataSource[0] : ''
     }
 
     let columns = [
@@ -324,15 +254,13 @@
         title: 'Value',
         $title: 'Value',
         dataIndex: 'Value',
-        editable: true,
-        datatype: dataItem && typeof(dataItem.Value) === 'number' ? 'number' : 'string'
+        editable: true
       },
       {
         title: 'Text',
         $title: 'Text',
         dataIndex: 'Text',
-        editable: true,
-        datatype: dataItem && typeof(dataItem.Text) === 'number' ? 'number' : 'string'
+        editable: true
       },
       ...fields,
       {
@@ -363,8 +291,7 @@
         title: 'ParentID',
         $title: 'ParentID',
         dataIndex: 'ParentID',
-        editable: true,
-        datatype: dataItem && typeof(dataItem.ParentID) === 'number' ? 'number' : 'string'
+        editable: true
       })
     }
 
@@ -373,13 +300,6 @@
         if (col.dataIndex !== 'operation') {
           col.title = <div>
             {col.$title}
-            {/* <Popconfirm
-              title={`纭畾鍒囨崲涓�${col.datatype === 'number' ? '鏂囨湰' : '鏁板��'}鍚楋紵`}
-              overlayClassName="popover-confirm"
-              onConfirm={() => this.changeDatatype(col)
-            }>
-              <SwapOutlined style={{ color: col.datatype === 'number' ? '#1890ff' : ''}} />
-            </Popconfirm> */}
           </div>
         }
         return col
@@ -460,8 +380,7 @@
           editable: col.editable,
           dataIndex: col.dataIndex,
           title: col.title,
-          datatype: col.datatype,
-          handleSave: this.handleSave,
+          handleSave: this.handleSave
         })
       }
     })
diff --git a/src/templates/zshare/unattended/settingform/index.jsx b/src/templates/zshare/unattended/settingform/index.jsx
index e30dd8d..4142a57 100644
--- a/src/templates/zshare/unattended/settingform/index.jsx
+++ b/src/templates/zshare/unattended/settingform/index.jsx
@@ -160,6 +160,7 @@
                 <Radio.Group>
                   <Radio value="first">绗竴琛�</Radio>
                   <Radio value="next">涓嬩竴琛�</Radio>
+                  <Radio value="refresh">鍒锋柊椤甸潰</Radio>
                 </Radio.Group>
               )}
             </Form.Item>
diff --git a/src/templates/zshare/verifycard/baseform/index.jsx b/src/templates/zshare/verifycard/baseform/index.jsx
index 00171d3..611e4ef 100644
--- a/src/templates/zshare/verifycard/baseform/index.jsx
+++ b/src/templates/zshare/verifycard/baseform/index.jsx
@@ -5,6 +5,7 @@
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
+import MkPrintTemps from '@/menu/components/share/actioncomponent/actionform/mkPrintTemps'
 import './index.scss'
 
 const sysTempsIds = ['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok']
@@ -15,13 +16,14 @@
     verify: PropTypes.object,
     unionFields: PropTypes.array,
     notes: PropTypes.array,
+    appType: PropTypes.any,
     onChange: PropTypes.func
   }
 
   state = {
     wxTemps: [],
     selectTemp: null,
-    miniTemps: [],
+    miniTemps: []
   }
 
   componentDidMount() {
@@ -126,6 +128,8 @@
     let error = ''
     if (verify.noteEnable === 'true' && !verify.noteCode) { // 寮�鍚煭淇℃椂锛岄渶瑕佹ā鏉跨紪鐮�
       error = '寮�鍚煭淇℃椂锛岄渶瑕侀�夋嫨鐭俊妯℃澘锛�'
+    } else if (verify.printEnable === 'true' && !verify.printTempId) {
+      error = '浣跨敤鍗曟嵁鎵撳嵃鏃讹紝闇�瑕侀�夋嫨鎵撳嵃妯℃澘锛�'
     } else if (verify.accountdate === 'true' && !verify.accountfield) {
       error = '寮�鍚处鏈熸椂锛岄渶瑕侀�夋嫨楠岃瘉鍏徃锛�'
     } else if (verify.wxNote === 'true') {
@@ -148,6 +152,9 @@
 
     if (_verify.noteEnable !== 'true') {
       _verify.noteCode = ''
+    }
+    if (_verify.printEnable !== 'true') {
+      _verify.printTempId = ''
     }
     if (_verify.accountdate !== 'true') {
       _verify.accountfield = ''
@@ -184,6 +191,14 @@
     const { verify } = this.props
 
     let _verify = {...verify, noteCode: val, noteId: option.props.id}
+
+    this.props.onChange(_verify)
+  }
+
+  onPrintIdChange = (val) => {
+    const { verify } = this.props
+
+    let _verify = {...verify, printTempId: val}
 
     this.props.onChange(_verify)
   }
@@ -264,7 +279,7 @@
   }
 
   render() {
-    const { unionFields, verify, notes, card } = this.props
+    const { unionFields, verify, notes, card, appType } = this.props
     const { wxTemps, selectTemp } = this.state
     const formItemLayout = {
       labelCol: {
@@ -393,6 +408,25 @@
             </Form.Item>
           </Col> : null}
           <Col span={24}></Col>
+          {appType !== 'mob' ? <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="浣跨敤鍗曟嵁鎵撳嵃鏃堕渶閫夋嫨鎵撳嵃妯℃澘锛岃烦杞墦鍗扮晫闈㈡椂ID浼樺厛浠庤繑鍥炲�间腑鑾峰彇锛岃繑鍥炲�兼病鏈夋椂浠庤閲岃幏鍙栥��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍗曟嵁鎵撳嵃
+              </Tooltip>
+            }>
+              <Radio.Group value={verify.printEnable} onChange={(e) => {this.onOptionChange(e.target.value, 'printEnable')}}>
+                <Radio value="true">寮�鍚�</Radio>
+                <Radio value="false">涓嶅紑鍚�</Radio>
+              </Radio.Group>
+            </Form.Item>
+          </Col> : null}
+          {verify.printEnable === 'true' ? <Col span={8}>
+            <Form.Item label="鎵撳嵃妯℃澘" required>
+              <MkPrintTemps value={verify.printTempId} onChange={this.onPrintIdChange}/>
+            </Form.Item>
+          </Col> : null}
+          <Col span={24}></Col>
           <Col span={8}>
             <Form.Item label={
               <Tooltip placement="bottomLeft" title={'璇峰湪鏈嶅姟鍣ㄥ畬鎴愬叕浼楀彿閰嶇疆銆�'}>
diff --git a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
index ce0b0fd..c0750c8 100644
--- a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
+++ b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select } from 'antd'
+import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select, Switch } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -21,7 +21,8 @@
 
   state = {
     editItem: null,
-    loading: false
+    loading: false,
+    skip: false
   }
 
   edit = (record) => {
@@ -36,7 +37,7 @@
   }
 
   handleConfirm = () => {
-    const { editItem } = this.state
+    const { editItem, skip } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
@@ -161,26 +162,38 @@
         param.LText = Utils.formatOptions(param.LText)
         param.secretkey = Utils.encrypt('', param.timestamp)
         
-        this.setState({loading: true})
-        Api.genericInterface(param).then(res => {
-          if (res.status) {
-            this.setState({
-              loading: false,
-              editItem: null
-            }, () => {
-              this.props.scriptsChange(values)
-            })
-            this.props.form.setFieldsValue({
-              sql: ' '
-            })
-          } else {
-            this.setState({loading: false})
-
-            Modal.error({
-              title: res.message
-            })
-          }
-        })
+        if (skip) {
+          this.setState({
+            skip: false,
+            editItem: null
+          }, () => {
+            this.props.scriptsChange(values)
+          })
+          this.props.form.setFieldsValue({
+            sql: ' '
+          })
+        } else {
+          this.setState({loading: true})
+          Api.genericInterface(param).then(res => {
+            if (res.status) {
+              this.setState({
+                loading: false,
+                editItem: null
+              }, () => {
+                this.props.scriptsChange(values)
+              })
+              this.props.form.setFieldsValue({
+                sql: ' '
+              })
+            } else {
+              this.setState({loading: false})
+  
+              Modal.error({
+                title: res.message
+              })
+            }
+          })
+        }
       }
     })
   }
@@ -198,6 +211,9 @@
   selectScript = (value, option) => {
     if (!value || !option) return
     let _sql = this.props.form.getFieldValue('sql')
+    if (/^\s+$/.test(_sql)) {
+      _sql = ''
+    }
     if (_sql) {
       _sql = _sql + ` 
 
@@ -218,6 +234,7 @@
   render() {
     const { usefulfields, systemScripts, btn } = this.props
     const { getFieldDecorator } = this.props.form
+    const { skip } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -241,7 +258,7 @@
           </Col>
           <Col span={10}>
             <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
+              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
             </Form.Item>
           </Col>
           <Col span={24} className="sqlfield">
@@ -269,7 +286,7 @@
               )}
             </Form.Item>
           </Col>
-          <Col span={10}>
+          <Col span={8}>
             <Form.Item label={'蹇嵎娣诲姞'} style={{marginBottom: 0}}>
               <Select
                 allowClear
@@ -285,7 +302,7 @@
               </Select>
             </Form.Item>
           </Col>
-          <Col span={6} className="add">
+          <Col span={5} className="add" style={{whiteSpace: 'nowrap'}}>
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
               淇濆瓨
             </Button>
@@ -293,6 +310,10 @@
               鍙栨秷
             </Button>
           </Col>
+          <Col span={3} style={{paddingTop: '15px', fontSize: '12px', whiteSpace: 'nowrap'}}>
+            寮哄埗淇濆瓨锛�
+            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
+          </Col>
           <Col span={24} className="sql">
             <Form.Item label="sql">
               {getFieldDecorator('sql', {
diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx
index fd2f022..cb530d4 100644
--- a/src/templates/zshare/verifycard/customscript/index.jsx
+++ b/src/templates/zshare/verifycard/customscript/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select } from 'antd'
+import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select, Switch } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -23,7 +23,8 @@
 
   state = {
     editItem: null,
-    loading: false
+    loading: false,
+    skip: false
   }
 
   edit = (record) => {
@@ -45,7 +46,7 @@
 
   handleConfirm = () => {
     const { type } = this.props
-    const { editItem } = this.state
+    const { editItem, skip } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (type === 'fullscreen' && err) {
@@ -195,7 +196,7 @@
         }
 
         param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-        param.LText = param.LText.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|typename)@/ig, `'${param.timestamp}'`)
+        param.LText = param.LText.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|typename)@/ig, `'${param.timestamp}'`)
 
         console.info(`/* sql 楠岃瘉 */\n${param.LText.replace(/\n\s{6,20}/ig, '\n')}`)
 
@@ -203,26 +204,38 @@
         param.LText = Utils.formatOptions(param.LText)
         param.secretkey = Utils.encrypt('', param.timestamp)
         
-        this.setState({loading: true})
-        Api.genericInterface(param).then(res => {
-          if (res.status) {
-            this.setState({
-              loading: false,
-              editItem: null
-            }, () => {
-              this.props.scriptsChange(values)
-            })
-            this.props.form.setFieldsValue({
-              sql: ' '
-            })
-          } else {
-            this.setState({loading: false})
-
-            Modal.error({
-              title: res.message
-            })
-          }
-        })
+        if (skip) {
+          this.setState({
+            skip: false,
+            editItem: null
+          }, () => {
+            this.props.scriptsChange(values)
+          })
+          this.props.form.setFieldsValue({
+            sql: ' '
+          })
+        } else {
+          this.setState({loading: true})
+          Api.genericInterface(param).then(res => {
+            if (res.status) {
+              this.setState({
+                loading: false,
+                editItem: null
+              }, () => {
+                this.props.scriptsChange(values)
+              })
+              this.props.form.setFieldsValue({
+                sql: ' '
+              })
+            } else {
+              this.setState({loading: false})
+  
+              Modal.error({
+                title: res.message
+              })
+            }
+          })
+        }
       }
     })
   }
@@ -241,6 +254,9 @@
     if (!value || !option) return
 
     let _sql = this.props.form.getFieldValue('sql')
+    if (/^\s+$/.test(_sql)) {
+      _sql = ''
+    }
     if (_sql) {
       _sql = _sql + ` 
 
@@ -261,7 +277,7 @@
   render() {
     const { usefulfields, systemScripts, btn, type } = this.props
     const { getFieldDecorator } = this.props.form
-    const { editItem } = this.state
+    const { editItem, skip } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -287,7 +303,7 @@
           </Col> : null}
           {!_type ? <Col span={10}>
             <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
+              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
             </Form.Item>
           </Col> : null}
           {!_type ? <Col span={24} className="sqlfield">
@@ -298,7 +314,7 @@
               {usefulfields ? <span>, {usefulfields}</span> : ''}
             </Form.Item>
           </Col> : null}
-          {!_type ?<Col span={8} style={{whiteSpace: 'nowrap'}}>
+          {!_type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
             <Form.Item style={{marginBottom: 0}} label={
               <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}>
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -316,7 +332,7 @@
               )}
             </Form.Item>
           </Col> : null}
-          {!_type ?<Col span={10}>
+          {!_type ? <Col span={8}>
             <Form.Item label={'蹇嵎娣诲姞'} style={{marginBottom: 0}}>
               <Select
                 showSearch
@@ -334,14 +350,18 @@
               </Select>
             </Form.Item>
           </Col> : null}
-          <Col span={6} className="add">
-            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
+          <Col span={5} className="add" style={{whiteSpace: 'nowrap'}}>
+            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 30}}>
               {_type === 'fullscreen' && !editItem ? '娣诲姞' : '淇濆瓨'}
             </Button>
             <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
               鍙栨秷
             </Button>
           </Col>
+          {!_type ? <Col span={3} style={{paddingTop: '15px', fontSize: '12px', whiteSpace: 'nowrap'}}>
+            寮哄埗淇濆瓨锛�
+            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
+          </Col> : null}
           <Col span={24} className="sql">
             <Form.Item label={
               <Tooltip placement="topLeft" overlayStyle={{width: '320px', maxWidth: '320px'}} title={<><div>{'璋冭瘯鏇挎崲绗� /*$breakpoint_begin_xxxx@ 銆丂breakpoint_end_xxxx$*/锛屽湪鎺у埗鍙颁腑杈撳叆 window.debug = \'xxxx\' 浼氬惎鐢ㄥ搴旂殑璋冭瘯璇彞锛屽揩鎹烽敭 ctrl+c 鎴栧湪鎺у埗鍙颁腑杈撳叆 window.debug = false 鍏抽棴璋冭瘯銆傛敞锛氳皟璇曟椂瀛楃 $breakpoint_proc@ 灏嗚鏇挎崲銆�'}</div><div style={{height: '5px'}}></div><div>{'鏁版嵁妫�鏌ユ浛鎹㈢ $check@ -> \'\'銆� @check$ -> \'\'锛孍rrorCode绛変簬C鏃朵細璇㈤棶鏄惁缁х画鎵ц锛岀‘瀹氭椂 $check@ -> /*銆� @check$ -> */銆傛敞锛�1銆侀渶浣跨敤绯荤粺鎺ュ彛 2銆佽璁剧疆涓衡�滈�夋嫨澶氳鈥濇椂鏃犳晥銆�'}</div></>}>
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index ade0e92..cffd4a9 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -9,7 +9,6 @@
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-import options from '@/store/options.js'
 import BaseForm from './baseform'
 import UniqueForm from './uniqueform'
 import ContrastForm from './contrastform'
@@ -538,6 +537,7 @@
 
   UNSAFE_componentWillMount() {
     const { columns, config, card, btnTab } = this.props
+    const { appType } = this.state
     let _verify = fromJS(card.verify || {}).toJS()
 
     let _invalid = _verify.invalid
@@ -554,10 +554,11 @@
     }
 
     _verify.default = _verify.default || 'true'
-    _verify.wxNote = _verify.wxNote || 'false'         // 鍏紬鍙锋秷鎭帹閫佹槸鍚﹀紑鍚�
-    _verify.noteEnable = _verify.noteEnable || 'false' // 鐭俊鍙戦�佹槸鍚﹀紑鍚�
-    _verify.noteType = _verify.noteType || 'N'         // 鐭俊鍙戦�佹ā寮忥細Y锛堝疄鏃讹級銆丯锛堝畾鏃讹級
-    _verify.noteTemp = _verify.noteTemp || 'Y'         // 鐭俊鍙戦�佹ā鏉匡細Y锛堢浉鍚岋級銆丯锛堜笉鍚岋級
+    _verify.wxNote = _verify.wxNote || 'false'           // 鍏紬鍙锋秷鎭帹閫佹槸鍚﹀紑鍚�
+    _verify.noteEnable = _verify.noteEnable || 'false'   // 鐭俊鍙戦�佹槸鍚﹀紑鍚�
+    _verify.printEnable = _verify.printEnable || 'false' // 鍗曟嵁鎵撳嵃鏄惁寮�鍚�
+    _verify.noteType = _verify.noteType || 'N'           // 鐭俊鍙戦�佹ā寮忥細Y锛堝疄鏃讹級銆丯锛堝畾鏃讹級
+    _verify.noteTemp = _verify.noteTemp || 'Y'           // 鐭俊鍙戦�佹ā鏉匡細Y锛堢浉鍚岋級銆丯锛堜笉鍚岋級
     _verify.invalid = _invalid
     _verify.uniques = _verify.uniques || []
     _verify.contrasts = _verify.contrasts || []
@@ -569,6 +570,11 @@
     _verify.voucher = _verify.voucher || {enabled: false}
     _verify.scripts = _verify.scripts || []
     _verify.cbScripts = _verify.cbScripts || []
+
+    if (appType === 'mob') {
+      _verify.printEnable = 'false'
+      _verify.printTempId = ''
+    }
 
     if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
       window.GLOB.funcs.forEach(m => {
@@ -632,7 +638,7 @@
         _fields = card.modal.fields || []
         resolve(_fields)
       } else if (card.OpenType === 'pop') {
-        Api.getSystemConfig({
+        Api.getCloudConfig({
           func: 'sPC_Get_LongParam',
           MenuID: card.uuid
         }).then(res => {
@@ -1059,8 +1065,8 @@
     mutilparam.secretkey = Utils.encrypt(mutilparam.LText, mutilparam.timestamp)
     mutilparam.open_key = Utils.encryptOpenKey(mutilparam.secretkey, mutilparam.timestamp)
 
-    if (options.cloudServiceApi) { // 浜戠璇锋眰
-      mutilparam.rduri = options.cloudServiceApi
+    if (window.GLOB.cloudServiceApi) { // 浜戠璇锋眰
+      mutilparam.rduri = window.GLOB.cloudServiceApi
       mutilparam.userid = sessionStorage.getItem('CloudUserID') || ''
       mutilparam.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
     }
@@ -1560,7 +1566,7 @@
               {verify.default === 'false' ? <span className="count-tip"><ExclamationOutlined style={{color: 'orange'}}/></span> : null}
             </span>
           } key="base">
-            <BaseForm card={card} unionFields={unionFields} setting={setting} verify={verify} notes={notes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
+            <BaseForm card={card} appType={appType} unionFields={unionFields} setting={setting} verify={verify} notes={notes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
           </TabPane> : null}
           {verifyInter === 'system' ? <TabPane tab={
             <span>
diff --git a/src/templates/zshare/verifycard/uniqueform/index.jsx b/src/templates/zshare/verifycard/uniqueform/index.jsx
index 2c1e3d2..5249e9c 100644
--- a/src/templates/zshare/verifycard/uniqueform/index.jsx
+++ b/src/templates/zshare/verifycard/uniqueform/index.jsx
@@ -97,7 +97,7 @@
           {btn.Ot !== 'requiredOnce' ? <Col span={7}>
             <Form.Item label="楠岃瘉绫诲瀷">
               {getFieldDecorator('verifyType', {
-                initialValue: 'physical',
+                initialValue: 'logic',
                 rules: [
                   {
                     required: true,
diff --git a/src/utils/option.js b/src/utils/option.js
index e771dfe..1652359 100644
--- a/src/utils/option.js
+++ b/src/utils/option.js
@@ -1,7 +1,6 @@
 import nortable from '@/assets/img/normaltable.jpg'
 // import mainsubtable from '@/assets/img/mainsubtable.jpg'
-import treepage from '@/assets/img/treepage.jpg'
-import calendar from '@/assets/img/calendar.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'
@@ -74,20 +73,13 @@
     baseconfig: '',
     isSystem: true
   },
-  {
-    title: '鏍戝舰椤甸潰',
-    type: 'TreePage',
-    url: treepage,
-    baseconfig: '',
-    isSystem: true
-  },
-  {
-    title: '鏃ュ巻',
-    type: 'CalendarPage',
-    url: calendar,
-    baseconfig: '',
-    isSystem: true
-  },
+  // {
+  //   title: '鏍戝舰椤甸潰',
+  //   type: 'TreePage',
+  //   url: treepage,
+  //   baseconfig: '',
+  //   isSystem: true
+  // },
   {
     title: '澶栭儴椤甸潰',
     type: 'NewPage',
@@ -154,6 +146,7 @@
     {value: '[3, 0]', text: '杩戜笁澶�'},
     {value: '[7, 0]', text: '杩戜竷澶�'},
     {value: '[30, 0]', text: '杩�30澶�'},
+    {value: '[90, 0]', text: '杩�90澶�'},
     {value: '[7, -7]', text: '鍓嶅悗涓冨ぉ'},
     {value: '[30, -30]', text: '鍓嶅悗30澶�'},
     {value: '[90, -90]', text: '鍓嶅悗90澶�'},
@@ -163,6 +156,7 @@
     {value: '[-2, -2]', text: '鍚庡ぉ'},
     {value: 'week', text: '鏈懆'},
     {value: 'month', text: '鏈湀'},
+    {value: 'lastMonth', text: '涓婃湀'},
   ],
   datetime: [
     {value: '', text: '绌�'},
@@ -911,3 +905,12 @@
 }
 
 export const queryTableSql = 'select top 999999 TbName,Remark from (select TbName,Remark from sDataDictb where appkey= @appkey@ and Deleted=0 union select a.TbName,Remark from (select TbName,Remark from sDataDictb where appkey= \'\' and Deleted=0 ) a left join (select TbName from sDataDictb where appkey= @appkey@ and Deleted=0 ) b on a.TbName=b.TbName where b.TbName is null ) t order by TbName'
+
+export const queryPrintSql = `select ID,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate 
+  where appkey= @appkey@ and Deleted=0 and typechartwo='web_print'
+  union select ID,Images,a.PrintTempNO+PrintTempName as PN 
+  from (select * from sPrintTemplate where appkey= '' and Deleted=0 and typechartwo='web_print') a 
+  left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@ and Deleted=0 ) b 
+  on a.PrintTempNO=b.PrintTempNO 
+  left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c 
+  on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null`
\ No newline at end of file
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index be4f888..5871f20 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -270,6 +270,7 @@
 
     if (interfaces && interfaces.length > 0) {
       interfaces.forEach(item => {
+        if (item.uuid === selfId) return
         modules.push({
           value: item.uuid,
           label: item.name
@@ -702,13 +703,13 @@
     // 閲嶇疆缁勪欢鍚嶇О
     let sign = this.getSignName()
     if (item.plot) { // 鍥捐〃
-      item.plot.name = item.plot.name + sign
+      item.plot.name = (item.plot.name || '') + sign
       item.name = item.plot.name
     } else if (item.wrap) { // 閫氱敤
-      item.wrap.name = item.wrap.name + sign
+      item.wrap.name = (item.wrap.name || '') + sign
       item.name = item.wrap.name
     } else if (item.setting) { // 鍒嗙粍銆佹爣绛鹃〉绛�
-      item.setting.name = item.setting.name + sign
+      item.setting.name = (item.setting.name || '') + sign
       item.name = item.setting.name
     }
 
diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js
index df476aa..a5cb08d 100644
--- a/src/utils/utils-datamanage.js
+++ b/src/utils/utils-datamanage.js
@@ -1,13 +1,11 @@
 import md5 from 'md5'
 import moment from 'moment'
-import options from '@/store/options.js'
 import Utils from './utils.js'
 
 export default class DataUtils {
   /**
    * @description 鏁版嵁婧愬悕绉帮紝鐢ㄤ簬缁熶竴鏌ヨ
    * @param {Object}   setting      鏁版嵁婧愯缃�
-   * @param {String}   arrFields    鏌ヨ瀛楁
    * @param {Array}    search       鎼滅储鏉′欢
    * @param {String}   orderBy      鎺掑簭鏂瑰紡
    * @param {Number}   pageIndex    椤电爜
@@ -15,13 +13,13 @@
    * @param {String}   BID          涓婄骇ID
    * @return {Object}  param
    */
-  static getQueryDataParams (setting, arrFields, search = [], orderBy = '', pageIndex = 1, pageSize = 10, BID, id) {
+  static getQueryDataParams (setting, search = [], orderBy = '', pageIndex = 1, pageSize = 10, BID, id, year) {
     let param = null
 
     if (setting.interType === 'system') {
-      param = this.getDefaultQueryParam(setting, arrFields, search, orderBy, pageIndex, pageSize, id, BID)
+      param = this.getDefaultQueryParam(setting, search, orderBy, pageIndex, pageSize, id, BID, year)
     } else {
-      param = this.getCustomQueryParam(setting, search, orderBy, pageIndex, pageSize, id)
+      param = this.getCustomQueryParam(setting, search, orderBy, pageIndex, pageSize, id, year)
     }
 
     if (BID) {
@@ -38,7 +36,7 @@
   /**
    * @description 鑾峰彇鐢ㄦ埛鑷畾涔夊瓨鍌ㄨ繃绋嬩紶鍙�
    */
-  static getCustomQueryParam (setting, search, orderBy, pageIndex, pageSize, id) {
+  static getCustomQueryParam (setting, search, orderBy, pageIndex, pageSize, id, year) {
     let param = Utils.formatCustomMainSearch(search)
 
     if (orderBy) {
@@ -50,14 +48,21 @@
     } else if (setting.laypage) {
       param.PageIndex = pageIndex
       param.PageSize = pageSize
+    } else if (setting.$re_year) {
+      param.mk_year = year
     }
 
     if (setting.interType === 'inner') {
       param.func = setting.innerFunc
+
+      if (setting.recordUser === 'true') {
+        param.username = sessionStorage.getItem('User_Name') || ''
+        param.fullname = sessionStorage.getItem('Full_Name') || ''
+      }
     } else {
       if (window.GLOB.mkHS) {
-        if (setting.sysInterface === 'true' && options.cloudServiceApi) {
-          param.rduri = options.cloudServiceApi
+        if (setting.sysInterface === 'true' && window.GLOB.cloudServiceApi) {
+          param.rduri = window.GLOB.cloudServiceApi
           param.userid = sessionStorage.getItem('CloudUserID') || ''
           param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         } else if (setting.sysInterface !== 'true') {
@@ -98,18 +103,14 @@
   /**
    * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼鐨勫弬鏁�
    */
-  static getDefaultQueryParam (setting, arrFields, search, orderBy, pageIndex, pageSize, id, BID) {
+  static getDefaultQueryParam (setting, search, orderBy, pageIndex, pageSize, id, BID, year) {
     let param = {
       func: 'sPC_Get_TableData',
       obj_name: 'data',
       exec_type: 'y',
-      arr_field: arrFields,
+      arr_field: setting.arr_field,
       default_sql: setting.execute ? 'true' : 'false'
     }
-
-    // if (setting.transaction === 'true') {
-    //   param.func = 'sPC_Get_TableData_try'
-    // }
 
     let userName = sessionStorage.getItem('User_Name') || ''
     let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -123,13 +124,9 @@
     let district = sessionStorage.getItem('district') || ''
     let address = sessionStorage.getItem('address') || ''
 
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
-
     let _dataresource = setting.dataresource
     let _customScript = ''
+    let _tailScript = setting.tailScript || ''
     
     if (setting.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)
@@ -138,74 +135,66 @@
       `
     }
 
-    _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
-    _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
-    _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
-    _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
-    _customScript = _customScript.replace(/\$sum@/ig, '/*')
-    _customScript = _customScript.replace(/@sum\$/ig, '*/')
+    let allSearch = Utils.getAllSearchOptions(search)
+    let regoptions = allSearch.map(item => {
+      return {
+        reg: new RegExp('@' + item.key + '@', 'ig'),
+        value: `'${item.value}'`
+      }
+    })
+    regoptions.push(
+      { reg: /@orderBy@/ig, value: orderBy },
+      { reg: /@pageSize@/ig, value: setting.laypage ? pageSize : '9999' },
+      { reg: /@pageIndex@/ig, value: pageIndex},
+      { reg: /@select\$|\$select@/ig, value: ''},
+      { reg: /\$sum@/ig, value: '/*'},
+      { reg: /@sum\$/ig, value: '*/'},
+      { reg: /@ID@/ig, value: `'${id || ''}'`},
+      { reg: /@BID@/ig, value: `'${BID || ''}'`},
+      { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
+      { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
+      { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
+      { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      { reg: /@typename@/ig, value: `'admin'`},
+    )
 
-    // _dataresource = _dataresource.replace(/@ID@/ig, `''`)
-    // _customScript = _customScript.replace(/@ID@/ig, `''`)
-    _dataresource = _dataresource.replace(/@BID@/ig, `'${BID || ''}'`)
-    _customScript = _customScript.replace(/@BID@/ig, `'${BID || ''}'`)
-    _dataresource = _dataresource.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    _customScript = _customScript.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    _dataresource = _dataresource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    _customScript = _customScript.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    _dataresource = _dataresource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    _customScript = _customScript.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    _dataresource = _dataresource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _customScript = _customScript.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _dataresource = _dataresource.replace(/@typename@/ig, `'admin'`)
-    _customScript = _customScript.replace(/@typename@/ig, `'admin'`)
-
-    let regoptions = null
-    if (setting.queryType === 'statistics' || _customScript) {
-      let allSearch = Utils.getAllSearchOptions(search)
-      regoptions = allSearch.map(item => {
-        return {
-          reg: new RegExp('@' + item.key + '@', 'ig'),
-          value: `'${item.value}'`
-        }
-      })
-      regoptions.push({
-        reg: new RegExp('@orderBy@', 'ig'),
-        value: orderBy
-      }, {
-        reg: new RegExp('@pageSize@', 'ig'),
-        value: setting.laypage ? pageSize : '9999'
-      }, {
-        reg: new RegExp('@pageIndex@', 'ig'),
-        value: pageIndex
-      })
+    if (setting.$re_year) {
+      regoptions.push({ reg: /@mk_year@/ig, value: year })
     }
+
+    regoptions.forEach(item => {
+      _dataresource = _dataresource.replace(item.reg, item.value)
+      _customScript = _customScript.replace(item.reg, item.value)
+      _tailScript = _tailScript.replace(item.reg, item.value)
+    })
 
     let _search = ''
     
     if (_dataresource) {
-      if (setting.queryType === 'statistics') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲
-        regoptions.forEach(item => {
-          _dataresource = _dataresource.replace(item.reg, item.value)
-        })
-        if (id) {
-          _dataresource = _dataresource + ` where ${setting.primaryKey || 'ID'}='${id}'`
+      let id_search = ''
+      if (id) {
+        if (/^excel:/.test(id)) {
+          id_search = `${setting.primaryKey} in (select ID from dbo.SplitComma('${id.replace(/^excel:/, '')}'))`
+        } else {
+          id_search = `${setting.primaryKey || 'ID'}='${id}'`
+          orderBy = ''
         }
-      } else if (!id) {
-        _search = Utils.joinMainSearchkey(search)
-        if (_search) {
-          _search = 'where ' + _search
+      }
+
+      if (setting.queryType === 'statistics') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲
+        if (id) {
+          _dataresource = _dataresource + ` where ${id_search}`
         }
       } else if (id) {
         _search = Utils.joinMainSearchkey(search)
-        _search = `where ${_search ? _search + ' AND ' : ''} ${setting.primaryKey || 'ID'}='${id}'`
+        _search = `where ${_search ? _search + ' AND ' : ''} ${id_search}`
+      } else {
+        _search = Utils.joinMainSearchkey(search)
+        _search = _search ? 'where ' + _search : ''
       }
     }
 
     if (_customScript) {
-      regoptions.forEach(item => {
-        _customScript = _customScript.replace(item.reg, item.value)
-      })
       if (window.GLOB.breakpoint) {
         _customScript = _customScript.replace(/\$breakpoint_proc@/ig, window.GLOB.breakpoint)
         param.func = 'sPC_Get_TableData_debug'
@@ -214,38 +203,50 @@
 
     let LText = ''
     let DateCount = ''
+    let arr_field = setting.all_field || setting.arr_field
 
-    if (setting.sub_field) {
-      arrFields = arrFields + ',' + setting.sub_field
-    }
-
-    if (_dataresource && setting.laypage && orderBy && !id) {
-      LText = `/*system_query*/select top ${pageSize} ${arrFields} from (select ${arrFields} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
-      if (setting.sub_field) {
-        DateCount = `/*system_query*/select count(1) as total from (select distinct ${setting.primaryKey} from ${_dataresource} ${_search})a`
+    if (_dataresource) {
+      if (setting.custompage) {
+        LText = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search} `
+      } else if (setting.laypage && orderBy) {
+        LText = `/*system_query*/select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
+        if (setting.sub_field) {
+          DateCount = `/*system_query*/select count(1) as total from (select distinct ${setting.primaryKey} from ${_dataresource} ${_search})a`
+        } else {
+          DateCount = `/*system_query*/select count(1) as total from ${_dataresource} ${_search}`
+        }
+      } else if (orderBy) {
+        LText = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
       } else {
-        DateCount = `/*system_query*/select count(1) as total from ${_dataresource} ${_search}`
+        LText = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search}  `
       }
-    } else if (_dataresource && orderBy) {
-      LText = `/*system_query*/select ${arrFields} from (select ${arrFields} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
-    } else if (_dataresource) {
-      LText = `/*system_query*/select ${arrFields} from ${_dataresource} ${_search}  `
     }
 
     if (_customScript) {
       if (LText) {
         LText = `${LText}
+          ${_tailScript}
           aaa:
           if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
         `
       } else {
         _customScript = `${_customScript}
+          ${_tailScript}
           aaa:
           if @ErrorCode!=''
-            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
         `
       }
+    } else if (_tailScript) {
+      LText = `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='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
+        ${LText}
+        ${_tailScript}
+        aaa:
+        if @ErrorCode!=''
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
+      `
     } else {
       LText = `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='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
@@ -254,7 +255,7 @@
     }
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+    if (window.GLOB.debugger === true) {
       _customScript && console.info(`${setting.$name ? `/*${setting.$name} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
       LText && console.info(`${setting.$name ? `/*${setting.$name} 鏁版嵁婧�*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
     }
@@ -279,6 +280,9 @@
     param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     param.secretkey = Utils.encrypt('', param.timestamp)
 
+    param.username = userName
+    param.fullname = fullName
+
     if (window.GLOB.probation) {
       param.s_debug_type = 'Y'
     }
@@ -287,8 +291,8 @@
       param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
 
       // special HS鑷畾涔夊嚱鏁版煡璇�
-      if (setting.tableName === 's_custom_script' && options.cloudServiceApi) {
-        param.rduri = options.cloudServiceApi
+      if (setting.tableName === 's_custom_script' && window.GLOB.cloudServiceApi) {
+        param.rduri = window.GLOB.cloudServiceApi
         param.userid = sessionStorage.getItem('CloudUserID') || ''
         param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
       }
@@ -308,10 +312,6 @@
       arr_field: statFields.map(col => col.field).join(','),
       default_sql: setting.execute ? 'true' : 'false'
     }
-
-    // if (setting.transaction === 'true') {
-    //   param.func = 'sPC_Get_TableData_try'
-    // }
     
     let _dataresource = setting.dataresource
     let _customScript = ''
@@ -326,11 +326,6 @@
     let city = sessionStorage.getItem('city') || ''
     let district = sessionStorage.getItem('district') || ''
     let address = sessionStorage.getItem('address') || ''
-
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
     
     if (setting.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)
@@ -339,66 +334,42 @@
       `
     }
 
-    _dataresource = _dataresource.replace(/@sum\$|\$sum@/ig, '')
-    _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '')
-    _dataresource = _dataresource.replace(/\$select@/ig, '/*')
-    _dataresource = _dataresource.replace(/@select\$/ig, '*/')
-    _customScript = _customScript.replace(/\$select@/ig, '/*')
-    _customScript = _customScript.replace(/@select\$/ig, '*/')
+    let allSearch = Utils.getAllSearchOptions(search)
+    let regoptions = allSearch.map(item => {
+      return {
+        reg: new RegExp('@' + item.key + '@', 'ig'),
+        value: `'${item.value}'`
+      }
+    })
 
-    // _dataresource = _dataresource.replace(/@ID@/ig, `''`)
-    // _customScript = _customScript.replace(/@ID@/ig, `''`)
-    _dataresource = _dataresource.replace(/@BID@/ig, `'${BID || ''}'`)
-    _customScript = _customScript.replace(/@BID@/ig, `'${BID || ''}'`)
-    _dataresource = _dataresource.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    _customScript = _customScript.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    _dataresource = _dataresource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    _customScript = _customScript.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    _dataresource = _dataresource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    _customScript = _customScript.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    _dataresource = _dataresource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _customScript = _customScript.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _dataresource = _dataresource.replace(/@typename@/ig, `'admin'`)
-    _customScript = _customScript.replace(/@typename@/ig, `'admin'`)
+    regoptions.push(
+      { reg: /@orderBy@/ig, value: orderBy },
+      { reg: /@pageSize@/ig, value: 999999 },
+      { reg: /@pageIndex@/ig, value: 1},
+      { reg: /\$select@/ig, value: '/*'},
+      { reg: /@select\$/ig, value: '*/'},
+      { reg: /@sum\$|\$sum@/ig, value: ''},
+      { reg: /@ID@/ig, value: `''`},
+      { reg: /@BID@/ig, value: `'${BID || ''}'`},
+      { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
+      { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
+      { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
+      { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      { reg: /@typename@/ig, value: `'admin'`},
+    )
 
-    let regoptions = null
-    if (setting.queryType === 'statistics' || _customScript) {
-      let allSearch = Utils.getAllSearchOptions(search)
+    regoptions.forEach(item => {
+      _dataresource = _dataresource.replace(item.reg, item.value)
+      _customScript = _customScript.replace(item.reg, item.value)
+    })
 
-      regoptions = allSearch.map(item => {
-        return {
-          reg: new RegExp('@' + item.key + '@', 'ig'),
-          value: `'${item.value}'`
-        }
-      })
-      regoptions.push({
-        reg: new RegExp('@orderBy@', 'ig'),
-        value: orderBy
-      }, {
-        reg: new RegExp('@pageSize@', 'ig'),
-        value: 999999
-      }, {
-        reg: new RegExp('@pageIndex@', 'ig'),
-        value: 1
-      })
-    }
-
-    let _search = Utils.joinMainSearchkey(search)
-    if (_search) {
-      _search = 'where ' + _search
-    }
+    let _search = ''
     
-    if (setting.queryType === 'statistics') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲
-      regoptions.forEach(item => {
-        _dataresource = _dataresource.replace(item.reg, item.value)
-      })
-      _search = ''
-    }
-
-    if (_customScript) {
-      regoptions.forEach(item => {
-        _customScript = _customScript.replace(item.reg, item.value)
-      })
+    if (setting.queryType !== 'statistics') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲
+      _search = Utils.joinMainSearchkey(search)
+      if (_search) {
+        _search = 'where ' + _search
+      }
     }
 
     let LText = ` /*system_query*/select ${statFields.map(col => `isnull(sum(${col.field}),0) as ${col.field}`).join(',')} from ${_dataresource} ${_search} `
@@ -407,7 +378,7 @@
       LText = `${LText}
         aaa:
         if @ErrorCode!=''
-          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
       `
     } else {
       LText = `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)
@@ -417,7 +388,7 @@
     }
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+    if (window.GLOB.debugger === true) {
       _customScript &&  console.info(`${setting.$name ? `/*${setting.$name} 鑷畾涔夎剼鏈� 缁熻鏌ヨ*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
       LText &&  console.info(`${setting.$name ? `/*${setting.$name} 鏁版嵁婧� 缁熻鏌ヨ*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
     }
@@ -432,6 +403,9 @@
 
     param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     param.secretkey = Utils.encrypt('', param.timestamp)
+
+    param.username = userName
+    param.fullname = fullName
 
     if (window.GLOB.mkHS) { // 浜戠鏁版嵁楠岃瘉
       param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
@@ -456,33 +430,28 @@
 export function getStructDefaultParam (component, searchlist, first) {
   const { columns, setting, dataName, format, uuid } = component
 
-  let arr_field = columns.map(col => col.field)
   let _dataresource = setting.dataresource
   let _customScript = setting.customScript
   
-  if (setting.queryType === 'statistics' || _customScript) {
-    let allSearch = Utils.getAllSearchOptions(searchlist)
-    let regoptions = allSearch.map(item => {
-      return {
-        reg: new RegExp('@' + item.key + '@', 'ig'),
-        value: `'${item.value}'`
-      }
-    })
+  let allSearch = Utils.getAllSearchOptions(searchlist)
+  let regoptions = allSearch.map(item => {
+    return {
+      reg: new RegExp('@' + item.key + '@', 'ig'),
+      value: `'${item.value}'`
+    }
+  })
 
-    regoptions.forEach(item => {
-      if (_dataresource && setting.queryType === 'statistics') {
-        _dataresource = _dataresource.replace(item.reg, item.value)
-      }
-      _customScript = _customScript.replace(item.reg, item.value)
-    })
-  }
+  regoptions.forEach(item => {
+    _dataresource = _dataresource.replace(item.reg, item.value)
+    _customScript = _customScript.replace(item.reg, item.value)
+  })
 
-  _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
-  _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
-  _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
-  _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
-  _customScript = _customScript.replace(/\$sum@/ig, '/*')
-  _customScript = _customScript.replace(/@sum\$/ig, '*/')
+  // _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
+  // _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
+  // _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
+  // _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
+  // _customScript = _customScript.replace(/\$sum@/ig, '/*')
+  // _customScript = _customScript.replace(/@sum\$/ig, '*/')
 
   let _search = ''
   if (setting.queryType !== 'statistics' && _dataresource) {
@@ -491,9 +460,9 @@
   }
 
   if (setting.order && _dataresource) {
-    _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
+    _dataresource = `select top 1000 ${setting.arr_field} from (select ${setting.arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
   } else if (_dataresource) {
-    _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} `
+    _dataresource = `select top 1000 ${setting.arr_field} from ${_dataresource} ${_search} `
   }
 
   if (first) {
@@ -508,11 +477,7 @@
     let city = sessionStorage.getItem('city') || ''
     let district = sessionStorage.getItem('district') || ''
     let address = sessionStorage.getItem('address') || ''
-  
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
+
     _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='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
       ${_customScript}
@@ -525,6 +490,7 @@
     $name: setting.$name,
     columns: columns,
     par_tablename: '',
+    order: setting.order || '',
     type: format === 'array' ? format : '',
     primaryKey: setting.primaryKey || '',
     foreign_key: '',
@@ -541,10 +507,18 @@
 export function getStructuredParams (params, config, BID) {
   let LText_field = []
   let diffUser = false
-  // let transaction = false
-  let loginId = `'${sessionStorage.getItem('LoginUID') || ''}'`
-  let sessionId = `'${localStorage.getItem('SessionUid') || ''}'`
-  let userId = `'${sessionStorage.getItem('UserID') || ''}'`
+
+  let regoptions = [
+    { reg: /@pageSize@/ig, value: 9999 },
+    { reg: /@pageIndex@/ig, value: 1},
+    { reg: /@ID@/ig, value: `''`},
+    { reg: /@BID@/ig, value: `'${BID || ''}'`},
+    { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
+    { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
+    { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
+    { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+    { reg: /@typename@/ig, value: `'admin'`},
+  ]
 
   let _LText = params.map((item, index) => {
     let _script = item.script
@@ -553,27 +527,17 @@
     if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) {
       diffUser = true
     }
-    // if (item.transaction) {
-    //   transaction = true
-    // }
 
-    _sql = _sql.replace(/@ID@/ig, `''`)
-    _script = _script.replace(/@ID@/ig, `''`)
-    _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
-    _script = _script.replace(/@BID@/ig, `'${BID || ''}'`)
-    _sql = _sql.replace(/@LoginUID@/ig, loginId)
-    _script = _script.replace(/@LoginUID@/ig, loginId)
-    _sql = _sql.replace(/@SessionUid@/ig, sessionId)
-    _script = _script.replace(/@SessionUid@/ig, sessionId)
-    _sql = _sql.replace(/@UserID@/ig, userId)
-    _script = _script.replace(/@UserID@/ig, userId)
-    _sql = _sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _script = _script.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    _sql = _sql.replace(/@typename@/ig, `'admin'`)
-    _script = _script.replace(/@typename@/ig, `'admin'`)
+    _sql = _sql.replace(/@orderBy@/ig, item.order)
+    _script = _script.replace(/@orderBy@/ig, item.order)
+    
+    regoptions.forEach(cell => {
+      _sql = _sql.replace(cell.reg, cell.value)
+      _script = _script.replace(cell.reg, cell.value)
+    })
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+    if (window.GLOB.debugger === true) {
       _script && console.info(`${item.$name ? `/*${item.$name} 鑷畾涔夎剼鏈紙鍚屾鏌ヨ锛�*/\n` : ''}${_sql ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_script}`)
       _sql && console.info(`${item.$name ? `/*${item.$name} 鏁版嵁婧愶紙鍚屾鏌ヨ锛�*/\n` : ''}` + _sql)
     }
@@ -588,15 +552,14 @@
     func: 'sPC_Get_structured_data',
     LText: _LText.join(' union all '),
     LText_field: LText_field.join(' union all '),
-    BID: BID
+    BID: BID,
+    username: sessionStorage.getItem('User_Name') || '',
+    fullName: sessionStorage.getItem('Full_Name') || ''
   }
 
   if (config.MenuName) {
     param.menuname = config.MenuName
   }
-  // if (transaction) {
-  //   param.func = 'sPC_Get_structured_data_try'
-  // }
 
   let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
 
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 5f9d942..4633e68 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -1,6 +1,5 @@
 import moment from 'moment'
 import md5 from 'md5'
-import options from '@/store/options.js'
 
 const formatKeys = [
   { key: 'select', value: ' msltk ' },
@@ -34,7 +33,8 @@
   { key: 'TRAN', value: ' mtrnk ' },
   { key: 'goto', value: ' mgtk ' },
   { key: 'set', value: ' mstk ' },
-  { key: 'ROLLBACK', value: ' mrlbkk ' }
+  { key: 'ROLLBACK', value: ' mrlbkk ' },
+  { key: 'drop', value: ' mdrpk ' },
 ]
 
 export default class Utils {
@@ -216,12 +216,6 @@
   //   value = window.atob(value)
   //   value = value.replace('minKe', '')
   //   value = window.decodeURIComponent(window.atob(value))
-
-  //   // 澶栬仈鏁版嵁搴撴浛鎹�
-  //   if (window.GLOB.externalDatabase !== null && window.GLOB.externalDatabase) {
-  //     value = value.replace(window.GLOB.externalDatabase, '@db@')
-  //   }
-
   //   value = value.replace(/ mpercent /ig, '%')
     
   //   // 鏇挎崲鍏抽敭瀛�
@@ -230,7 +224,7 @@
   //     value = value.replace(reg, ' ' + item.key + ' ')
   //   })
 
-  //   // value = value.replace(/\n/ig, ' \n ')
+  //   value = value.replace(/ \n /ig, '\n')
 
   //   return value
   // }
@@ -292,12 +286,17 @@
    * @description 鍒濆鍖栨悳绱㈡潯浠跺垵濮嬪��
    * @param {Array}   searches     鎼滅储鏉′欢
    */
-  static initSearchVal (searches) {
-    if (!searches) return []
+  static initSearchVal (config) {
+    if (!config.search) {
+      config.search = []
+      return
+    }
 
     let roleId = sessionStorage.getItem('role_id') || ''
+    let required = false
+    let keys = []
 
-    return searches.map(item => {
+    config.search = config.search.map(item => {
       item.hidden = item.Hide === 'true'
       item.required = !item.hidden && item.required === 'true'
       item.advanced = item.advanced === 'true'
@@ -336,6 +335,8 @@
           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)
@@ -413,8 +414,28 @@
         }
       }
 
+      if (item.required) {
+        required = true
+      }
+
+      if (item.type === 'text' || item.type === 'select') {
+        if (/,/.test(item.field)) {
+          item.field.split(',').forEach(field => {
+            keys.push(field.toLowerCase())
+          })
+        } else {
+          keys.push(item.field.toLowerCase())
+        }
+      } else if (item.type === 'group') {
+        keys.push(item.field.toLowerCase())
+        keys.push(item.datefield.toLowerCase())
+      }
+
       return item
     })
+
+    config.$s_keys = keys
+    config.$s_req = required
   }
 
   /**
@@ -777,8 +798,8 @@
     
     let baseurl = ''
     
-    if (options.cloudServiceApi) {
-      baseurl = options.cloudServiceApi.replace(/webapi(.*)$/, '')
+    if (window.GLOB.cloudServiceApi) {
+      baseurl = window.GLOB.cloudServiceApi.replace(/webapi(.*)$/, '')
     } else {
       baseurl = window.GLOB.baseurl
     }
@@ -800,6 +821,8 @@
         arrfield.push(item.urlField)
       } else if (item.colorField) {
         arrfield.push(item.colorField)
+      } else if (item.parentField) {
+        arrfield.push(item.parentField)
       }
     }
 
@@ -833,10 +856,9 @@
     }
 
     if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-      sql = sql.replace(/\$@/ig, '/*')
-      sql = sql.replace(/@\$/ig, '*/')
+      sql = sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
     } else {
-      sql = sql.replace(/@\$|\$@/ig, '')
+      sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
     }
 
     // 澶栬仈鏁版嵁搴撴浛鎹�
@@ -876,11 +898,6 @@
   let address = sessionStorage.getItem('address') || ''
   let _sheet = item.sheet
 
-  if (sessionStorage.getItem('isEditState') === 'true') {
-    userName = sessionStorage.getItem('CloudUserName') || ''
-    fullName = sessionStorage.getItem('CloudFullName') || ''
-  }
-
   if (window.GLOB.externalDatabase !== null) {
     _sheet = _sheet.replace(/@db@/ig, window.GLOB.externalDatabase)
   }
@@ -905,45 +922,6 @@
   let _topline = btn.range || 0
   let upId = getuuid()
 
-  let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
-  let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
-  let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
-
-  if (btn.scripts) {
-    btn.scripts.forEach(script => {
-      if (script.status === 'false') return
-
-      let _sql = script.sql
-
-      _sql = _sql.replace(/@ID@/ig, `'${primaryId || ''}'`)
-      _sql = _sql.replace(/@BID@/ig, `'${BID}'`)
-      _sql = _sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-      _sql = _sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-      _sql = _sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-      _sql = _sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-      _sql = _sql.replace(/@typename@/ig, `'admin'`)
-
-      if (script.position === 'init') {
-        _initCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${_sql}
-      `
-      } else if (script.position === 'front') {
-        _prevCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${_sql}
-      `
-      } else {
-        _backCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${_sql}
-      `
-      }
-    })
-  }
-
-  // 鎺у埗鍙版墦鍗版暟鎹�
-  let conLtext = []
   let cols = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
   for (let i = 0; i < 26; i++) {
     cols.push('A' + cols[i])
@@ -951,7 +929,6 @@
 
   let _Ltext = data.map((item, lindex) => {
     let vals = []
-    let convals = []
     btn.columns.forEach((col, cindex) => {
       if (col.import === 'false') return
 
@@ -959,14 +936,22 @@
       let _colindex = cols[cindex] || (cindex + 1)
       let _position = (_topline + lindex + 1) + '琛� ' + _colindex + '鍒� '
 
-      if (/^Nvarchar/ig.test(col.type)) {
+      if (col.import === 'init') {
+        if (/^Nvarchar/ig.test(col.type)) {
+          val = ''
+        } else if (/^Decimal/ig.test(col.type) || /^int/ig.test(col.type)) {
+          val = 0
+        } else if (col.type === 'date') {
+          val = '1949-10-01'
+        }
+      } else if (/^Nvarchar/ig.test(col.type)) {
         val = val + ''
 
         if (/'/.test(val)) {
           val = val.replace(/'/ig, '"')
         }
 
-        val = val.replace(/(^\s*$)|\t*|\v*/ig, '')
+        val = val.replace(/(^\s+$)|\t+|\v+/ig, '')
 
         if (!val && col.required === 'true') {            // 蹇呭~鏍¢獙
           errors.push(_position + '鍐呭涓嶅彲涓虹┖')
@@ -1001,7 +986,7 @@
             val = moment('19000101', 'YYYYMMDD').add(Math.floor(val - 2), 'days').format('YYYY-MM-DD')
           }
         } else if (typeof(val) === 'string') {
-          val = val.replace(/(^\s*$)|\t*|\v*/ig, '')
+          val = val.replace(/(^\s+$)|\t+|\v+/ig, '')
           if (!val && col.required === 'true') {           // 鏃堕棿蹇呭~鏍¢獙
             errors.push(_position + '鍐呭涓嶅彲涓虹┖')
           } else if (val && !/^[1-9][0-9]{3}/.test(val)) { // 鏃堕棿姝e垯鏍¢獙
@@ -1013,10 +998,6 @@
       }
 
       vals.push(`'${val}'`)
-
-      if (lindex < 40) {
-        convals.push(`'${val}' as ${col.Column}`)
-      }
     })
 
     let _lineIndex = '0000' + (lindex + 1) + '0'
@@ -1024,26 +1005,61 @@
 
     vals.push(`'${upId + _lineIndex}'`)
     vals.push(`'${BID}'`)
-    
-    if (lindex < 40) {
-      convals.push(`'${upId + _lineIndex}' as jskey`)
-      convals.push(`'${BID}' as BID`)
-      conLtext.push(`Select ${convals.join(',')}`)
-    }
 
     return `Select ${vals.join(',')}`
   })
 
   let result = []
-  for(let i = 0; i < _Ltext.length; i += 20) {
-    result.push(_Ltext.slice(i, i + 20))
-  }
-
-  let _sql = ''
-  let _sqlInsert = ''
-  let _sqlBottom = ''
-
+  let sql = ''
+  
   if (item.intertype === 'system') {
+    let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
+    let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
+    let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
+    let isDM = sessionStorage.getItem('dataM') === 'true'
+    let regs = [
+      {reg: new RegExp('(^|\\s)@' + sheet + '(\\s|$)', 'ig'), value: `#${sheet} `},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\(', 'ig'), value: `#${sheet}(`},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\)', 'ig'), value: `#${sheet})`},
+      {reg: /@ID@/ig, value: `'${primaryId || ''}'`},
+      {reg: /@BID@/ig, value: `'${BID}'`},
+      {reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
+      {reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
+      {reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
+      {reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      {reg: /@typename@/ig, value: `'admin'`},
+      {reg: /\$@/ig, value: isDM ? '/*' : ''},
+      {reg: /@\$/ig, value: isDM ? '*/' : ''},
+      {reg: /@datam@/ig, value: isDM ? `'Y'` : `''`},
+    ]
+
+    btn.scripts && btn.scripts.forEach(script => {
+      if (script.status === 'false') return
+
+      let _sql = script.sql
+
+      regs.forEach(item => {
+        _sql = _sql.replace(item.reg, item.value)
+      })
+
+      if (script.position === 'init') {
+        _initCustomScript += `
+      /* 鑷畾涔夎剼鏈� */
+      ${_sql}
+      `
+      } else if (script.position === 'front') {
+        _prevCustomScript += `
+      /* 鑷畾涔夎剼鏈� */
+      ${_sql}
+      `
+      } else {
+        _backCustomScript += `
+      /* 鑷畾涔夎剼鏈� */
+      ${_sql}
+      `
+      }
+    })
+
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
       btn.uniques.forEach(unique => {
@@ -1061,7 +1077,7 @@
         _uniquesql += `
       /* 閲嶅鎬ч獙璇� */
       Set @tbid=''
-      Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${sheet} ) a group by ${unique.field} having sum(n)>1
+      Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from #${sheet} ) a group by ${unique.field} having sum(n)>1
       
       If @tbid!=''
       Begin
@@ -1070,7 +1086,7 @@
       end
       
       ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
-      Select top 1 @tbid=${_afields.join('+\' \'+')} from  @${sheet} a Inner join ${sheet} b on ${_fields_}
+      Select top 1 @tbid=${_afields.join('+\' \'+')} from  #${sheet} a Inner join ${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
@@ -1102,64 +1118,51 @@
       _insert = `
       /* 榛樿sql */
       Insert into ${database}${sheet} (${fields},createuserid,createuser,createstaff,bid) 
-      Select ${fields},@userid@,@username,@fullname,@BID@ From @${sheet}
+      Select ${fields},'${sessionStorage.getItem('UserID') || ''}',@username,@fullname,'${BID}' From #${sheet}
       `
     }
 
-    _sql = `
+    sql = `
       /* 绯荤粺鐢熸垚 */
-      declare @${sheet} table (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50) )
+      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50) )
       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),@tbid Nvarchar(512)
       
       Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
       ${_initCustomScript}
-      `
-    _sqlInsert = `Insert into @${sheet} (${fields},jskey,BID)`
-    _sqlBottom = `
-      /* 榛樿sql */
-      delete tmp_excel_in where upid=@upid@
       
-      delete tmp_excel_in where datediff(day,createdate,getdate())>15
+      Insert into #${sheet} (${fields},jskey,BID)
+
+      /* excel鏁版嵁*/
+      ${_Ltext.join(' Union all ')}
+
       ${_uniquesql}
       ${_prevCustomScript}
       ${_insert}
       ${_backCustomScript}
-      Delete @${sheet}
+
+      drop table #${sheet}
       
       aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
 
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
-      let fsql = `
-      ${_sql}
-      ${_sqlInsert}
-      
-      /* excel鏁版嵁锛堝墠40鏉★級 */
-      ${conLtext.join(' Union all ')}
-      ${_sqlBottom}
-      `
-      fsql = fsql.replace(/\n\s{8}/ig, '\n')
-      console.info(fsql)
+    sql = sql.replace(/\n\s{6}/ig, '\n')
+
+    if (window.GLOB.debugger === true) {
+      console.info(sql)
     }
-  } else { // s_sDataDictb_excelIn 浜戠瀵嗛挜楠岃瘉鍙傛暟
-    _sql = `
-      /* 绯荤粺鐢熸垚 */
-      declare @${sheet} table (jskey nvarchar(50))
-      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),@tbid Nvarchar(512)
-      
-      Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
-      `
+  } else {
+    for(let i = 0; i < _Ltext.length; i += 20) {
+      result.push(_Ltext.slice(i, i + 20))
+    }
   }
 
   return {
-    sql: _sql,
+    sql: sql,
     lines: result.map((list, index) => {
       return {
         Ltext: window.btoa(window.encodeURIComponent(list.join(' Union all '))),
         Sort: (index + 1) * 10
       }
     }),
-    insert: _sqlInsert,
-    bottom: _sqlBottom,
     errors: errors.join('; ')
   }
 }
@@ -1186,11 +1189,6 @@
   let _sheet = btn.sheet
   let BID = data[0].$$BID || ''
 
-  if (sessionStorage.getItem('isEditState') === 'true') {
-    userName = sessionStorage.getItem('CloudUserName') || ''
-    fullName = sessionStorage.getItem('CloudFullName') || ''
-  }
-
   if (window.GLOB.externalDatabase !== null) {
     _sheet = _sheet.replace(/@db@/ig, window.GLOB.externalDatabase)
   }
@@ -1200,44 +1198,12 @@
   
   database = database ? (database[0] || '') : ''
 
-  let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
-  let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
-  let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
-
-  if (btn.scripts && btn.intertype === 'system') {
-    btn.scripts.forEach(script => {
-      if (script.status === 'false') return
-
-      if (script.position === 'init') {
-        _initCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${script.sql}
-      `
-      } else if (script.position === 'front') {
-        _prevCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${script.sql}
-      `
-      } else {
-        _backCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${script.sql}
-      `
-      }
-    })
-  }
-
-  // 鎺у埗鍙版墦鍗版暟鎹�
-  let conLtext = []
-
   let _Ltext = data.map(item => {
     let vals = []
-    let convals = []
     columns.forEach(col => {
       let val = item[col.field]
 
       vals.push(`'${val}'`)
-      convals.push(`'${val}' as ${col.field}`)
     })
 
     let key = item.$$uuid
@@ -1247,24 +1213,59 @@
     vals.push(`'${type}'`)
     vals.push(`'${BID}'`)
 
-    convals.push(`'${key}' as jskey`)
-    convals.push(`'${type}' as data_type`)
-    convals.push(`'${BID}' as BID`)
-    conLtext.push(`Select ${convals.join(',')}`)
-
     return `Select ${vals.join(',')}`
   })
 
   let result = []
-  for(let i = 0; i < _Ltext.length; i += 20) {
-    result.push(_Ltext.slice(i, i + 20))
-  }
-
-  let _sql = ''
-  let _sqlInsert = ''
-  let _sqlBottom = ''
+  let sql = ''
 
   if (btn.intertype === 'system') {
+    let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
+    let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
+    let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
+    let isDM = sessionStorage.getItem('dataM') === 'true'
+    let regs = [
+      {reg: new RegExp('(^|\\s)@' + sheet + '(\\s|$)', 'ig'), value: `#${sheet} `},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\(', 'ig'), value: `#${sheet}(`},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\)', 'ig'), value: `#${sheet})`},
+      {reg: /@BID@/ig, value: `'${BID}'`},
+      {reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
+      {reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
+      {reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
+      {reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      {reg: /@typename@/ig, value: `'admin'`},
+      {reg: /\$@/ig, value: isDM ? '/*' : ''},
+      {reg: /@\$/ig, value: isDM ? '*/' : ''},
+      {reg: /@datam@/ig, value: isDM ? `'Y'` : `''`},
+    ]
+
+    btn.scripts && btn.scripts.forEach(script => {
+      if (script.status === 'false') return
+
+      let _sql = script.sql
+
+      regs.forEach(item => {
+        _sql = _sql.replace(item.reg, item.value)
+      })
+
+      if (script.position === 'init') {
+        _initCustomScript += `
+      /* 鑷畾涔夎剼鏈� */
+      ${_sql}
+      `
+      } else if (script.position === 'front') {
+        _prevCustomScript += `
+      /* 鑷畾涔夎剼鏈� */
+      ${_sql}
+      `
+      } else {
+        _backCustomScript += `
+      /* 鑷畾涔夎剼鏈� */
+      ${_sql}
+      `
+      }
+    })
+
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
       btn.uniques.forEach(unique => {
@@ -1282,7 +1283,7 @@
         _uniquesql += `
       /* 閲嶅鎬ч獙璇� */
       Set @tbid=''
-      Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${sheet} ) a group by ${unique.field} having sum(n)>1
+      Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from #${sheet} ) a group by ${unique.field} having sum(n)>1
       
       If @tbid!=''
       Begin
@@ -1291,7 +1292,7 @@
       end
       
       ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
-      Select top 1 @tbid=${_afields.join('+\' \'+')} from  @${sheet} a Inner join ${sheet} b on ${_fields_}
+      Select top 1 @tbid=${_afields.join('+\' \'+')} from  #${sheet} a Inner join ${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
@@ -1320,64 +1321,50 @@
       _insert = `
       /* 榛樿sql */
       Insert into ${database}${sheet} (${fields},createuserid,createuser,createstaff,bid) 
-      Select ${fields},@userid@,@username,@fullname,@BID@ From @${sheet}
+      Select ${fields},'${sessionStorage.getItem('UserID') || ''}',@username,@fullname,'${BID}' From #${sheet}
       `
     }
 
-    _sql = `
+    sql = `
       /* 绯荤粺鐢熸垚 */
-      declare @${sheet} table (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50) )
+      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50) )
       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),@tbid Nvarchar(512)
       
       Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
       ${_initCustomScript}
-      `
-    _sqlInsert = `Insert into @${sheet} (${fields},jskey,data_type,BID)`
-    _sqlBottom = `
-      /* 榛樿sql */
-      delete tmp_excel_in where upid=@upid@
-      
-      delete tmp_excel_in where datediff(day,createdate,getdate())>15
+      Insert into #${sheet} (${fields},jskey,data_type,BID)
+
+      /* excel鏁版嵁*/
+      ${_Ltext.join(' Union all ')}
+
       ${_uniquesql}
       ${_prevCustomScript}
       ${_insert}
       ${_backCustomScript}
-      Delete @${sheet}
+
+      drop table #${sheet}
       
       aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
 
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
-      let fsql = `
-      ${_sql}
-      ${_sqlInsert}
-      
-      /* table鏁版嵁 */
-      ${conLtext.join(' Union all \n')}
-      ${_sqlBottom}
-      `
-      fsql = fsql.replace(/\n\s{8}/ig, '\n')
-      console.info(fsql)
+    sql = sql.replace(/\n\s{6}/ig, '\n')
+
+    if (window.GLOB.debugger === true) {
+      console.info(sql)
     }
-  } else { // s_sDataDictb_excelIn 浜戠瀵嗛挜楠岃瘉鍙傛暟
-    _sql = `
-      /* 绯荤粺鐢熸垚 */
-      declare @${sheet} table (jskey nvarchar(50))
-      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),@tbid Nvarchar(512)
-      
-      Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
-      `
+  } else {
+    for(let i = 0; i < _Ltext.length; i += 20) {
+      result.push(_Ltext.slice(i, i + 20))
+    }
   }
 
   return {
-    sql: _sql,
+    sql: sql,
     lines: result.map((list, index) => {
       return {
         Ltext: window.btoa(window.encodeURIComponent(list.join(' Union all '))),
         Sort: (index + 1) * 10
       }
-    }),
-    insert: _sqlInsert,
-    bottom: _sqlBottom
+    })
   }
 }
 
@@ -1577,11 +1564,6 @@
   let city = sessionStorage.getItem('city') || ''
   let district = sessionStorage.getItem('district') || ''
   let address = sessionStorage.getItem('address') || ''
-
-  if (sessionStorage.getItem('isEditState') === 'true') {
-    userName = sessionStorage.getItem('CloudUserName') || ''
-    fullName = sessionStorage.getItem('CloudFullName') || ''
-  }
 
   // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
   _sql += `
@@ -2136,7 +2118,13 @@
   _sql = _sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
   _sql = _sql.replace(/@typename@/ig, `'admin'`)
 
-  if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+  if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+    _sql = _sql.replace(/@datam@/ig, '\'Y\'')
+  } else {
+    _sql = _sql.replace(/@datam@/ig, '\'\'')
+  }
+
+  if (window.GLOB.debugger === true) {
     // _sql = _sql.replace(/\n\s{8}/ig, '\n')
     console.info(_sql)
   }
@@ -2149,6 +2137,12 @@
     _callbacksql = _callbacksql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
     _callbacksql = _callbacksql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
     _callbacksql = _callbacksql.replace(/@typename@/ig, `'admin'`)
+
+    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+      _callbacksql = _callbacksql.replace(/@datam@/ig, '\'Y\'')
+    } else {
+      _callbacksql = _callbacksql.replace(/@datam@/ig, '\'\'')
+    }
     
     return {
       sql: _sql,
@@ -2262,471 +2256,5 @@
       })
       cursor.continue()
     }
-  }
-}
-
-/**
- * @description 鍒涘缓瀛樺偍杩囩▼绫�
- */
-export class FuncUtils {
-  /**
-   * @description 鍒犻櫎瀛樺偍杩囩▼sql
-   * @return {String} name 瀛樺偍杩囩▼鍚嶇О
-   */
-  static dropfunc (name) {
-    return `IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('${name}') AND type in (N'P', N'PC'))  mdrpk PROCEDURE ${name}`
-  }
-
-  /**
-   * @description 鍒涘缓椤甸潰瀛樺偍杩囩▼
-   * @return {String}
-   */
-  static getTableFunc (func = 'func', menu, config) {
-    let form = ''
-    let formParam = ''
-    let _vars = ['bid', 'pageindex', 'pagesize', 'ordercol', 'ordertype', 'exceltype', 'septmenuno', 'lang', 'debug', 'loginuid', 'sessionuid', 'userid', 'errorcode', 'retmsg']
-    let _columns = []
-    let primaryKey = config.setting.primaryKey || 'ID'
-
-    if (!_vars.includes(primaryKey.toLowerCase())) {
-      _vars.push(primaryKey.toLowerCase())
-      formParam = `mchr13k@${primaryKey} nvarchar(50)='',`
-    }
-
-    if (config.search && config.search.length > 0) {
-      let _fields = new Map()
-      config.search.forEach(item => {
-        if (item.field) {
-          let type = ''
-
-          if (item.type.match(/date/ig)) {
-            type = 'datetime=null'
-          } else {
-            type = 'nvarchar(50)=\'\''
-          }
-
-          item.field.split(',').forEach(cell => {
-            let _f = cell
-            if (_fields.has(cell)) {
-              _f = _f + '1'
-            }
-  
-            _fields.set(cell, true)
-
-            if (!_vars.includes(_f.toLowerCase())) {
-              _vars.push(_f.toLowerCase())
-              formParam = formParam + `mchr13k@${_f} ${type},`
-            }
-          })
-        }
-      })
-    }
-
-    if (config.columns && config.columns.length > 0) {
-      config.columns.forEach(item => {
-        if (item.field) {
-          _columns.push(`${item.field} as ${item.label}`)
-        }
-      })
-
-      form = `
-        declare @dc table (${_columns.join(',')})
-        
-        @tableid ='${menu.MenuID}'
-      `
-    }
-
-    let Ltext = `create proc ${func}
-    ( /*${menu.MenuName}*/
-    @appkey nvarchar(50)='',
-    @BID nvarchar(50)='',${formParam}
-    @PageIndex nvarchar(50)='',
-    @PageSize nvarchar(50)='',
-    @OrderCol nvarchar(50)='',
-    @OrderType nvarchar(50)='',
-    @exceltype nvarchar(50)='',
-    @sEPTMenuNo nvarchar(50)='${menu.MenuNo}',
-    @lang nvarchar(50)='',
-    @debug nvarchar(50)='',
-    @LoginUID nvarchar(50)='',
-    @SessionUid nvarchar(50)='',
-    @UserID nvarchar(50),
-    @dataM nvarchar(50),
-    @ErrorCode nvarchar(50) out,
-    @retmsg nvarchar(4000) out
-    )
-    as
-    begin
-    declare  @BegindateTest datetime,@EnddateTest datetime
-    select  @BegindateTest=getdate()
-    set @ErrorCode=''
-    set @retmsg=''
-    BEGIN TRY
-      /*浜嬪姟鎿嶄綔*/
-      BEGIN TRAN
-        /*鍏蜂綋涓氬姟鎿嶄綔*/
-        
-        /* 
-        select top 10 * from sProcExcep order by id desc
-        
-        declare @UserName  nvarchar(50),@FullName nvarchar(50)
-        
-        select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID
-        ${form}
-        if 1=2
-        begin
-          set @ErrorCode='E'
-          set @retmsg='鍦ㄦ鍐欐姤閿�'
-          goto GOTO_RETURN
-        end
-        
-        insert into sNote (remark,createuserid,CreateUser,CreateStaff)
-        select '鍦ㄦ鍐欐棩蹇�',@UserID,@UserName,@FullName
-        */
-        
-      COMMIT TRAN
-      SET NOCOUNT ON
-      RETURN
-    END TRY
-    BEGIN CATCH
-      /*閿欒澶勭悊*/
-      ROLLBACK TRAN
-      DECLARE @ErrorMessage NVARCHAR(4000);
-      DECLARE @ErrorSeverity INT;
-      DECLARE @ErrorState INT;
-      
-      /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/
-      set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
-      SET @retmsg=ERROR_MESSAGE();
-      SELECT @ErrorMessage=ERROR_MESSAGE(),
-        @ErrorSeverity=ERROR_SEVERITY(),
-        @ErrorState=ERROR_STATE();
-        
-      RAISERROR(@ErrorMessage, /*-- Message text.*/
-        @ErrorSeverity, /*-- Severity.*/
-        @ErrorState  /*-- State.*/
-      );
-    END CATCH
-    
-    GOTO_RETURN:
-      ROLLBACK TRAN
-      
-    END`
-
-    Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k')
-
-    return Ltext
-  }
-
-  /**
-   * @description 鍒涘缓瀛樺偍杩囩▼
-   * @return {String}
-   */
-  static getfunc (param, btn, menu, config) {
-    let form = ''
-    let formParam = ''
-    let _vars = ['bid', 'septmenuno', 'lang', 'debug', 'loginuid', 'sessionuid', 'userid', 'errorcode', 'retmsg']
-    let columns = config.columns
-    let primaryKey = config.setting.primaryKey || 'ID'
-
-    if (!_vars.includes(primaryKey.toLowerCase())) {
-      _vars.push(primaryKey.toLowerCase())
-      let _type = '50'
-      if (btn.Ot === 'requiredOnce') { // 澶氳鎷兼帴鏃讹紝涓婚敭璁句负max
-        _type = 'max'
-      }
-      formParam = `mchr13k@${primaryKey} nvarchar(${_type})='',`
-    }
-
-    if (param.fields && param.fields.length > 0) {
-      let _fields = []
-      param.fields.forEach(item => {
-        if (item.field) {
-          let type = ''
-          if (item.type.match(/date/ig)) {
-            type = 'datetime=null'
-          } else if (item.type === 'number') {
-            type = `decimal(18,${item.decimal})=0`
-          } else if (item.type === 'rate') {
-            type = `decimal(18,2)=0`
-          } else {
-            type = 'nvarchar(50)=\'\''
-          }
-
-          if (!_vars.includes(item.field.toLowerCase())) {
-            _vars.push(item.field.toLowerCase())
-            formParam = formParam + `mchr13k@${item.field} ${type},`
-          }
-
-          _fields.push(item.field)
-        }
-      })
-
-      let field1 = _fields.join(',')
-      let field2 = _fields.join(',@')
-      let field3 = _fields.map(cell => {
-        return cell + '=@' + cell
-      })
-
-      field2 = field2 ? '@' + field2 : ''
-      field3 = field3.join(',')
-
-      form = `
-        insert into ${param.name} (${field1},createuserid) select ${field2},@UserID
-        
-        update ${param.name} set ${field3},modifydate=getdate(),modifyuser=@username,modifyuserid=@UserID
-      `
-    } else if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') {
-      form = `
-        update ${param.name} set ModifyDate=getdate(),ModifyUserID=@UserID where ${primaryKey}=@${primaryKey}
-      `
-    }
-
-    if (columns) {
-      let _col = []
-      let _field = []
-      columns.forEach(col => {
-        if (col.field) {
-          if (col.type === 'number') {
-            _col.push(col.field + ' decimal(18,2)')
-          } else {
-            _col.push(col.field + ' nvarchar(50)')
-          }
-          _field.push(col.field)
-        }
-      })
-      _col = _col.join(',')
-      _field = _field.join(',')
-
-      form = form + `
-        declare @dc table (${_col})
-        
-        insert into @dc (${_field})
-
-        @tableid ='${menu.MenuID}'
-      `
-    }
-
-    // 鎵撳嵃鑷畾涔夋ā鏉垮瓧娈垫彁绀�
-    let _printRemark = ''
-    if (btn.funcType === 'print') {
-      _printRemark = '/* 鑷畾涔夋暟鎹墦鍗版ā鏉挎椂锛岃浣跨敤TemplateID瀛楁 */'
-    }
-
-    let Ltext = `create proc ${param.funcName}
-    ( /*${menu.MenuName}  ${btn.label}*/
-    @appkey nvarchar(50)='',
-    @BID nvarchar(50)='',${formParam}
-    @sEPTMenuNo nvarchar(50)='${param.menuNo}',
-    @lang nvarchar(50)='',
-    @debug nvarchar(50)='',
-    @LoginUID nvarchar(50)='',
-    @SessionUid nvarchar(50)='',
-    @UserID nvarchar(50),
-    @ErrorCode nvarchar(50) out,
-    @retmsg nvarchar(4000) out
-    )
-    as
-    begin
-    declare  @BegindateTest datetime,@EnddateTest datetime
-    select  @BegindateTest=getdate()
-    set @ErrorCode=''
-    set @retmsg=''
-    BEGIN TRY
-      /*浜嬪姟鎿嶄綔*/
-      BEGIN TRAN
-        /*鍏蜂綋涓氬姟鎿嶄綔*/
-        ${_printRemark}
-        /* 
-        select top 10 * from sProcExcep order by id desc
-        
-        declare @UserName  nvarchar(50),@FullName nvarchar(50)
-        
-        select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID
-        ${form}
-        if 1=2
-        begin
-          set @ErrorCode='E'
-          set @retmsg='鍦ㄦ鍐欐姤閿�'
-          goto GOTO_RETURN
-        end
-        
-        insert into sNote (remark,createuserid,CreateUser,CreateStaff)
-        select '鍦ㄦ鍐欐棩蹇�',@UserID,@UserName,@FullName
-        */
-        
-      COMMIT TRAN
-      SET NOCOUNT ON
-      RETURN
-    END TRY
-    BEGIN CATCH
-      /*閿欒澶勭悊*/
-      ROLLBACK TRAN
-      DECLARE @ErrorMessage NVARCHAR(4000);
-      DECLARE @ErrorSeverity INT;
-      DECLARE @ErrorState INT;
-      
-      /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/
-      set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
-      SET @retmsg=ERROR_MESSAGE();
-      SELECT @ErrorMessage=ERROR_MESSAGE(),
-        @ErrorSeverity=ERROR_SEVERITY(),
-        @ErrorState=ERROR_STATE();
-        
-      RAISERROR(@ErrorMessage, /* Message text.*/
-        @ErrorSeverity, /* Severity.*/
-        @ErrorState  /* State.*/
-      );
-    END CATCH
-    
-    GOTO_RETURN:
-      ROLLBACK TRAN
-      
-    END`
-
-    Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k')
-
-    return Ltext
-  }
-
-  /**
-   * @description 鍒涘缓瀵煎叆瀛樺偍杩囩▼
-   * @return {String}
-   */
-  static getexcelInfunc (param, btn, menu) {
-    let _verify = btn.verify
-
-    let _uniquesql = ''
-    if (_verify.uniques && _verify.uniques.length > 0) {
-      _verify.uniques.forEach(unique => {
-        if (unique.status === 'false') return
-
-        let _fields = unique.field.split(',')
-        let _fields_ = _fields.map(_field => {
-          return `a.${_field}=b.${_field}`
-        })
-        _fields_ = _fields_.join(' and ')
-
-        if (unique.verifyType !== 'physical') {
-          _fields_ += ' and b.deleted=0'
-        }
-
-        _uniquesql += `
-        Set @tbid=''
-        Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${btn.sheet} ) a group by ${unique.field} having sum(n)>1
-
-        If @tbid!=''
-        Begin
-          select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 閲嶅'
-          goto aaa
-        end
-
-        Set @tbid=''
-        Select top 1 @tbid=${_fields.join('+\' \'+')} from  @${btn.sheet} a
-        Inner join ${btn.sheet} b on ${_fields_}
-
-        If @tbid!=''
-        Begin
-          select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
-          goto aaa
-        end
-        `
-      })
-
-      if (_uniquesql) {
-        _uniquesql = `
-        Declare @tbid Nvarchar(512)
-        ${_uniquesql}`
-      }
-    }
-
-    let declarefields = []
-    let fields = []
-
-    _verify.columns.forEach(col => {
-      declarefields.push(`${col.Column} ${col.type}`)
-      fields.push(col.Column)
-    })
-
-    fields = fields.join(',')
-
-    let _sql = `declare @${btn.sheet} table (${declarefields.join(',')},jskey nvarchar(50))
-      Declare @UserName nvarchar(50),@FullName nvarchar(50)
-      
-      select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID
-      
-      Insert into @${btn.sheet} (${fields},jskey)
-
-      exec s_KeyWords_Replace
-      @LText=@LText, @BID=@BID,@LoginUID=@LoginUID,@SessionUid=@SessionUid,@UserID=@UserID,@ID=@ID
-      ${_uniquesql}
-      Insert into ${btn.sheet} (${fields},createuserid,createuser,createstaff,bid) 
-      Select ${fields},@userid,@username,@fullname,@BID From @${btn.sheet}
-
-      Delete @${btn.sheet}`
-
-    let Ltext = `create proc ${param.funcName}
-    ( /*${menu.MenuName}  ${btn.label}*/
-      @appkey nvarchar(50)='',
-      @ID nvarchar(50)='',
-      @BID nvarchar(50)='',
-      @Ltext nvarchar(max)='',
-      @sEPTMenuNo nvarchar(50)='${param.menuNo}', 
-      @secretkey nvarchar(50)='',
-      @timestamp nvarchar(50)='',
-      @lang nvarchar(50)='',
-      @LoginUID nvarchar(50)='',
-      @SessionUid nvarchar(50)='',
-      @UserID nvarchar(50), 
-      @ErrorCode nvarchar(50) out,
-      @retmsg nvarchar(4000) out
-    )
-    as
-    begin
-    declare @BegindateTest datetime,@EnddateTest datetime 
-    select @BegindateTest=getdate() 
-    set @ErrorCode=''
-    set @retmsg=''
-    BEGIN TRY
-      /*浜嬪姟鎿嶄綔*/
-      BEGIN TRAN
-        /*鍏蜂綋涓氬姟鎿嶄綔*/
-
-        /* 
-        ${_sql}
-        */
-        
-      COMMIT TRAN
-      SET NOCOUNT ON
-      RETURN
-    END TRY
-    BEGIN CATCH
-      /*閿欒澶勭悊*/
-      ROLLBACK TRAN
-      DECLARE @ErrorMessage NVARCHAR(4000);
-      DECLARE @ErrorSeverity INT;
-      DECLARE @ErrorState INT;
-      
-      /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/
-      set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
-      SET @retmsg=ERROR_MESSAGE();
-      SELECT @ErrorMessage=ERROR_MESSAGE(),
-        @ErrorSeverity=ERROR_SEVERITY(),
-        @ErrorState=ERROR_STATE();
-        
-      RAISERROR(@ErrorMessage, /* Message text.*/
-        @ErrorSeverity, /* Severity.*/
-        @ErrorState  /* State.*/
-      );
-    END CATCH
-    
-    GOTO_RETURN:
-      ROLLBACK TRAN
-      
-    END`
-
-    Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k')
-
-    return Ltext
   }
 }
\ No newline at end of file
diff --git a/src/views/appmanage/index.jsx b/src/views/appmanage/index.jsx
index ff500da..75206ec 100644
--- a/src/views/appmanage/index.jsx
+++ b/src/views/appmanage/index.jsx
@@ -23,8 +23,6 @@
 const ScriptForm = asyncComponent(() => import('./scriptform'))
 const SubMutilForm = asyncComponent(() => import('./submutilform'))
 
-sessionStorage.setItem('isEditState', 'true')
-
 const skinStyle = {
   bg_black_style_blue: {name: '钃濊壊', color: '#1890ff'},
   bg_black_style_red: {name: '绾㈣壊', color: '#f5222d'},
@@ -112,6 +110,20 @@
   forbid = false
 
   UNSAFE_componentWillMount() {
+    if (sessionStorage.getItem('devError') === 'true') {
+      sessionStorage.clear()
+      window.history.replaceState(null, null, window.location.href.split('#')[0] + '#/login')
+      window.location.reload()
+      return
+    }
+
+    if (!sessionStorage.getItem('UserID')) {
+      this.props.history.replace('/login')
+      return
+    }
+
+    window.GLOB.developing = true
+
     document.body.className = ''
     this.getAppList()
     this.getSmStemp()
@@ -570,7 +582,7 @@
     param.secretkey = Utils.encrypt(param.LText, param.timestamp)
     param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
     
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       let msgs = []
       if (!res.status) {
         notification.warning({
diff --git a/src/views/basedesign/index.jsx b/src/views/basedesign/index.jsx
index cfb79a4..da66e53 100644
--- a/src/views/basedesign/index.jsx
+++ b/src/views/basedesign/index.jsx
@@ -14,13 +14,11 @@
 const Header = asyncComponent(() => import('@/menu/header'))
 const ComTableConfig = asyncLoadComponent(() => import('@/templates/comtableconfig'))
 const TreePageConfig = asyncLoadComponent(() => import('@/templates/treepageconfig'))
-const CalendarPageConfig = asyncLoadComponent(() => import('@/templates/calendarconfig'))
-const FormTabConfig = asyncLoadComponent(() => import('@/templates/formtabconfig'))
 const ModalConfig = asyncLoadComponent(() => import('@/templates/modalconfig'))
 const SubTable = asyncLoadComponent(() => import('@/templates/subtableconfig'))
+const UpdateFormTab = asyncLoadComponent(() => import('./updateFormTab'))
 
 document.body.className = ''
-sessionStorage.setItem('isEditState', 'true')
 
 class BaseDesign extends Component {
   state = {
@@ -41,6 +39,20 @@
   }
 
   UNSAFE_componentWillMount() {
+    if (sessionStorage.getItem('devError') === 'true') {
+      sessionStorage.clear()
+      window.history.replaceState(null, null, window.location.href.split('#')[0] + '#/login')
+      window.location.reload()
+      return
+    }
+
+    if (!sessionStorage.getItem('UserID')) {
+      this.props.history.replace('/login')
+      return
+    }
+
+    window.GLOB.developing = true
+
     try {
       let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
 
@@ -80,7 +92,7 @@
       loading: true
     })
 
-    Api.getSystemConfig(param).then(res => {
+    Api.getCloudConfig(param).then(res => {
       if (res.status) {
         editMenu.open_edition = res.open_edition || ''
         editMenu.LongParam = ''
@@ -100,7 +112,7 @@
             MenuID: editMenu.PageParam.copyMenuId
           }
       
-          Api.getSystemConfig(_param).then(res => {
+          Api.getCloudConfig(_param).then(res => {
             if (res.status) {
               if (res.LongParam) {
                 let _LongParam = ''
@@ -173,64 +185,57 @@
   }
 
   render () {
-    const { loading } = this.state
+    const { loading, editMenu, subConfig, btnTab } = this.state
 
     return (
       <div className="mk-base-design-wrap">
         <ConfigProvider locale={_locale}>
           <Header/>
-          {this.state.tabview === 'TreePage' ?
-            <TreePageConfig
-              menu={this.state.editMenu}
-              reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
-              handleView={this.handleView}
-            /> : null
-          }
-          {this.state.tabview === 'CalendarPage' ?
-            <CalendarPageConfig
-              menu={this.state.editMenu}
-              reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
-              handleView={this.handleView}
-            /> : null
-          }
           {this.state.tabview === 'CommonTable' ?
             <ComTableConfig
-              menu={this.state.editMenu}
+              menu={editMenu}
               reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
-              handleView={this.handleView}
-            /> : null
-          }
-          {this.state.tabview === 'Modal' ?
-            <ModalConfig
-              menu={this.state.editMenu}
-              editTab={this.state.editTab}
-              tabConfig={this.state.tabConfig}
-              editSubTab={this.state.editSubTab}
-              subTabConfig={this.state.subTabConfig}
-              btnTab={this.state.btnTab}
-              btnTabConfig={this.state.btnTabConfig}
-              editAction={this.state.editAction}
-              subConfig={this.state.subConfig}
               handleView={this.handleView}
             /> : null
           }
           {this.state.tabview === 'SubTable' ?
             <SubTable
-              menu={this.state.editMenu}
+              menu={editMenu}
               editTab={this.state.editTab}
               editSubTab={this.state.editSubTab}
               tabConfig={this.state.tabConfig}
-              btnTab={this.state.btnTab}
+              btnTab={btnTab}
               btnTabConfig={this.state.btnTabConfig}
-              config={this.state.subConfig}
+              config={subConfig}
+              handleView={this.handleView}
+            /> : null
+          }
+          {this.state.tabview === 'Modal' ?
+            <ModalConfig
+              menu={editMenu}
+              editTab={this.state.editTab}
+              tabConfig={this.state.tabConfig}
+              editSubTab={this.state.editSubTab}
+              subTabConfig={this.state.subTabConfig}
+              btnTab={btnTab}
+              btnTabConfig={this.state.btnTabConfig}
+              editAction={this.state.editAction}
+              subConfig={subConfig}
+              handleView={this.handleView}
+            /> : null
+          }
+          {this.state.tabview === 'TreePage' ?
+            <TreePageConfig
+              menu={editMenu}
+              reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
               handleView={this.handleView}
             /> : null
           }
           {this.state.tabview === 'FormTab' ?
-            <FormTabConfig
-              menu={this.state.editMenu}
-              btnTab={this.state.btnTab}
-              config={this.state.subConfig}
+            <UpdateFormTab
+              menu={editMenu}
+              btnTab={btnTab}
+              config={subConfig}
               handleView={this.handleView}
             /> : null
           }
diff --git a/src/views/basedesign/updateFormTab/index.jsx b/src/views/basedesign/updateFormTab/index.jsx
new file mode 100644
index 0000000..bd06654
--- /dev/null
+++ b/src/views/basedesign/updateFormTab/index.jsx
@@ -0,0 +1,1358 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Modal, Button, notification } from 'antd'
+import moment from 'moment'
+import md5 from 'md5'
+
+import { colorTransform } from '@/utils/option.js'
+import { getTables } from '@/utils/utils-custom.js'
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import './index.scss'
+
+const { confirm } = Modal
+
+class UpdateTable extends Component {
+  static propTpyes = {
+    config: PropTypes.object
+  }
+
+  state = {}
+  delButtons = []
+  baseMsg = {}
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  trigger = () => {
+    const { config, menu, btnTab } = this.props
+    const _this = this
+
+    if (!config || !menu || !menu.LongParam) {
+      notification.warning({
+        top: 92,
+        message: '鏈幏鍙栧埌鑿滃崟閰嶇疆锛�',
+        duration: 5
+      })
+      return
+    }
+
+    let _config = fromJS(config).toJS()
+
+    if (menu.LongParam.setting) {
+      _config.setting.primaryKey = menu.LongParam.setting.primaryKey
+    }
+
+    if (!_config.tabgroups) {
+      _config.tabgroups = [{ uuid: 'tabs', sublist: [] }]
+    } else if (typeof(_config.tabgroups[0]) === 'string') {
+      let _tabgroups = []
+      _config.tabgroups.forEach(groupId => {
+        let _group = {
+          uuid: groupId,
+          sublist: fromJS(_config[groupId]).toJS()
+        }
+
+        delete _config[groupId]
+
+        _tabgroups.push(_group)
+      })
+
+      _config.tabgroups = _tabgroups
+    }
+
+    _config.action = _config.action.map(item => {
+      if (item.intertype === 'inner' && !item.innerFunc) {
+        item.intertype = 'system'
+      }
+      return item
+    })
+
+    _config.btnId = btnTab.uuid
+    _config.btnName = btnTab.label
+    
+    confirm({
+      title: '纭畾鍗囩骇褰撳墠鑿滃崟鍚楋紵',
+      content: '',
+      onOk() {
+        return new Promise(resolve => {
+          _this.execUpdate(resolve, _config)
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  execUpdate = (_resolve, config) => {
+    const { menu } = this.props
+    
+    this.delButtons = []
+    this.baseMsg = {
+      fstMenuId: config.fstMenuId,
+      parentId: config.ParentId,
+      MenuName: config.MenuName,
+      MenuNo: config.MenuNo,
+    }
+
+    let MenuID = md5(menu.MenuID + config.btnId)
+
+    let _config = {
+      version: 1.0,
+      uuid: MenuID,
+      MenuID: MenuID,
+      fstMenuId: menu.fstMenuId,
+      parentId: menu.ParentId,
+      Template: 'CustomPage',
+      easyCode: '',
+      enabled: false,
+      MenuName: menu.MenuName + '-' + config.btnName,
+      MenuNo: menu.MenuNo + '_' + MenuID.substr(-4),
+      OpenType: 'newtab',
+      tables: config.tables || [],
+      urlFields: [],
+      hidden: 'true',
+      Remark: '',
+      components: [],
+      viewType: 'menu',
+      style: { backgroundColor: '#ffffff', paddingTop: '16px', paddingBottom: '80px', paddingLeft: '16px', paddingRight: '16px'},
+    }
+
+    let formActions = []
+    let popActions = []
+    let errors = []
+
+    let mainF = {
+      uuid: Utils.getuuid(),
+      type: 'form',
+      format: 'object',   // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+      pageable: false,    // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+      switchable: false,  // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+      width: 24,
+      name: '涓昏〃鍗�',
+      subtype: 'simpleform',
+      setting: { interType: 'system' },
+      wrap: { name: '涓昏〃鍗�', width: 24, datatype: 'static', enable: 'true', closeEnable: 'true' },
+      style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
+      headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
+      columns: [],
+      scripts: [],
+      subcards: []
+    }
+
+    let card = {
+      uuid: Utils.getuuid(),
+      setting: {title: '', align: 'left_right', enable: 'true'},
+      style: {},
+      fields: [],
+      subButton: {label: '纭畾', type: 'submit', reload: 'false', sql: '', Ot: 'notRequired', enable: 'true', style: {backgroundColor: 'rgba(255, 255, 255, 1)', color: 'rgba(24, 144, 255, 1)', paddingLeft: '20px', paddingRight: '20px', paddingTop: '5px', paddingBottom: '5px', borderColor: 'rgba(24, 144, 255, 1)', borderWidth: '1px'}},
+      closeButton: {label: '鍏抽棴', type: 'close', enable: 'true', style: { color: 'rgba(245, 34, 45, 1)', paddingTop: '5px', paddingRight: '20px', marginLeft: '20px', backgroundColor: '#ffffff', borderColor: 'rgba(245, 34, 45, 1)', paddingLeft: '20px', borderWidth: '1px', paddingBottom: '5px'}},
+    }
+
+    let btn = config.action[0]
+
+    card.subButton.intertype = btn.intertype
+    card.subButton.innerFunc = btn.innerFunc || ''
+    card.subButton.execSuccess = btn.execSuccess || 'never'
+    card.subButton.execError = btn.execError || 'never'
+
+    if (btn.intertype === 'outer') {
+      card.subButton.procMode = btn.innerFunc ? 'inner' : 'none'
+      card.subButton.sysInterface = btn.sysInterface || 'false'
+      card.subButton.interface = btn.interface || ''
+      card.subButton.outerFunc = btn.outerFunc || ''
+      card.subButton.callbackFunc = btn.callbackFunc || ''
+      card.subButton.callbackType = btn.callbackFunc ? 'func' : 'none'
+    } else if (btn.intertype === 'system') {
+      card.subButton.sqlType = btn.sqlType || ''
+      card.subButton.sql = btn.sql || ''
+      card.subButton.verify = btn.verify || null
+    }
+
+    if (config.setting.datatype === 'query') {
+      mainF.wrap.datatype = 'dynamic'
+      mainF.setting = {
+        interType: config.setting.interType || 'system',
+        innerFunc: config.setting.innerFunc || '',
+        outerFunc: config.setting.outerFunc || '',
+        interface: config.setting.interface || '',
+        dataresource: config.setting.dataresource || '',
+        sysInterface: config.setting.sysInterface || 'false',
+        order: '',
+        primaryKey: config.setting.primaryKey || 'ID',
+        tableName: menu.LongParam.setting.tableName || '',
+        supModule: ['empty'],
+        sync: 'false',
+        onload: 'true'
+      }
+
+      if (mainF.setting.interType === 'inner' && !mainF.setting.innerFunc) {
+        mainF.setting.interType = 'system'
+      }
+
+      card.subButton.Ot = 'requiredSgl'
+    }
+
+    config.groups.forEach(group => {
+      if (!group.isDefault) {
+        card.fields.push({
+          uuid: Utils.getuuid(),
+          label: group.label,
+          span: 24,
+          type: 'split'
+        })
+      }
+
+      group.sublist.forEach(item => {
+        item.labelwidth = 33.3
+        item.span = 12
+        
+        if (item.type === 'textarea' && config.setting.cols === '2') {
+          item.labelwidth = 16.2
+          item.span = 24
+        }
+
+        card.fields.push(item)
+      })
+    })
+
+    let _ids = []
+
+    card.fields.forEach(item => {
+      if (item.field) {
+        _ids.push(item.field.toLowerCase())
+        if (item.type === 'number') {
+          mainF.columns.push({
+            datatype: `decimal(18,${item.decimal === 0 ? 0 : (item.decimal || 2)})`,
+            field: item.field,
+            decimal: item.decimal || 0,
+            label: item.label,
+            type: 'number',
+            uuid: Utils.getuuid()
+          })
+        } else {
+          mainF.columns.push({
+            datatype: `Nvarchar(${item.fieldlength || 50})`,
+            field: item.field,
+            fieldlength: 50,
+            label: item.label,
+            type: 'text',
+            uuid: Utils.getuuid()
+          })
+        }
+      }
+    })
+
+    mainF.subcards.push(card)
+
+    let oldtabs = {
+      mainTable: mainF.uuid
+    }
+
+    if (mainF.wrap.datatype === 'dynamic') {
+      let primaryKey = mainF.setting.primaryKey.toLowerCase()
+      if (!_ids.includes(primaryKey)) {
+        mainF.columns.push({
+          datatype: `Nvarchar(50)`,
+          field: mainF.setting.primaryKey,
+          fieldlength: 50,
+          label: mainF.setting.primaryKey,
+          type: 'text',
+          uuid: Utils.getuuid()
+        })
+      }
+    } else {
+      oldtabs.mainTable = 'empty'
+    }
+
+    _config.components.push(mainF)
+
+    let _tbs = []
+    if (config.tabgroups && config.tabgroups.length > 0) {
+      config.tabgroups.forEach((m, i) => {
+        if (!m.sublist) return
+
+        m.sublist = m.sublist.filter(c => !!c.linkTab)
+        
+        if (m.sublist.length === 0) return
+
+        let tabs = {
+          uuid: Utils.getuuid(),
+          type: 'tabs',
+          subtype: 'tabs',
+          name: '鏍囩缁�' + (i + 1),
+          width: 24,
+          setting: {name: '鏍囩缁�' + (i + 1), width: 24, position: 'top'},
+          style: {},
+          subtabs: m.sublist.map(n => {
+            let tab = { uuid: Utils.getuuid(), label: n.label, icon: n.icon, permission: 'false', components: [
+              {
+                uuid: Utils.getuuid(),
+                linkTab: n.linkTab,
+                name: n.label,
+                useMSearch: 'false',
+                supModule: n.supMenu || '',
+                equalTab: n.equalTab && n.equalTab.length > 0 ? n.equalTab[0] : ''
+              }
+            ]}
+            this.delButtons.push(n.linkTab)
+            oldtabs[n.uuid] = tab.components[0].uuid
+
+            _tbs.push(tab.components[0])
+
+            return tab
+          })
+        }
+        
+        _config.components.push(tabs)
+      })
+    }
+
+    if (_tbs.length > 0) {
+      let defers = _tbs.map((item, i) => {
+        return new Promise((resolve) => {
+          setTimeout(() => {
+            Api.getCloudConfig({
+              func: 'sPC_Get_LongParam',
+              MenuID: item.linkTab
+            }).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) {
+                  _LongParam.uuid = item.linkTab
+                  resolve(_LongParam)
+                } else {
+                  resolve({uuid: item.linkTab, $empty: true})
+                }
+              } else {
+                notification.warning({
+                  top: 92,
+                  message: res.message,
+                  duration: 5
+                })
+                resolve({uuid: item.linkTab, $empty: true})
+              }
+            })
+          }, i * 50)
+        })
+      })
+      Promise.all(defers).then(res => {
+        let menus = {}
+        res.forEach(item => {
+          if (item && !item.$empty) {
+            menus[item.uuid] = item
+          }
+        })
+
+        let supIds = []
+        _config.components = _config.components.map(item => {
+          if (item.type === 'tabs') {
+            item.subtabs = item.subtabs.map(tab => {
+              tab.components[0] = this.getTable(menus[tab.components[0].linkTab], tab.components[0], errors, formActions, popActions, oldtabs)
+              supIds.push([item.uuid, tab.uuid, tab.components[0].uuid])
+              return tab
+            })
+          }
+          return item
+        })
+
+        _config.components = _config.components.map(item => {
+          if (item.type === 'tabs') {
+            item.subtabs = item.subtabs.map(tab => {
+              if (tab.components[0].setting.supModule && tab.components[0].setting.supModule.length === 1) {
+                supIds.forEach(ids => {
+                  if (ids[2] === tab.components[0].setting.supModule[0]) {
+                    tab.components[0].setting.supModule = ids
+                  }
+                })
+              }
+              return tab
+            })
+          }
+          return item
+        })
+
+        this.setPopView(_resolve, _config, formActions, popActions, errors)
+      })
+    } else {
+      this.setPopView(_resolve, _config, formActions, popActions, errors)
+    }
+  }
+
+  setPopView = (_resolve, _config, formActions, popActions, errors) => {
+    if (popActions.length > 0) {
+      let defers = popActions.map((item, i) => {
+        return new Promise((resolve) => {
+          setTimeout(() => {
+            Api.getCloudConfig({
+              func: 'sPC_Get_LongParam',
+              MenuID: item.linkTab
+            }).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) {
+                  _LongParam.uuid = item.uuid
+                  resolve(_LongParam)
+                } else {
+                  resolve({uuid: item.uuid, $empty: true})
+                }
+              } else {
+                notification.warning({
+                  top: 92,
+                  message: res.message,
+                  duration: 5
+                })
+                resolve({uuid: item.uuid, $empty: true})
+              }
+            })
+          }, i * 50)
+        })
+      })
+      Promise.all(defers).then(res => {
+        let menus = {}
+        res.forEach(item => {
+          if (item && !item.$empty) {
+            menus[item.uuid] = item
+          }
+        })
+
+        _config.components.forEach(item => {
+          if (item.type === 'tabs') {
+            item.subtabs.forEach(tab => {
+              tab.components[0].action.forEach(btn => {
+                if (btn.OpenType === 'popview') {
+                  if (menus[btn.uuid]) {
+                    let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+
+                    btn.config = {
+                      uuid: btn.uuid,
+                      MenuID: btn.uuid,
+                      ParentId: tab.components[0].uuid,
+                      MenuName: btn.label,
+                      tables: _config.tables || [],
+                      Template: 'CustomPage',
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                      viewType: 'popview',
+                      style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                    }
+
+                    btn.config.enabled = this.setEnabled(btn.config)
+                  } else {
+                    errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+              tab.components[0].cols.forEach(col => {
+                if (col.type !== 'custom') return
+                col.elements.forEach(btn => {
+                  if (btn.eleType !== 'button') return
+                  if (btn.OpenType === 'popview') {
+                    if (menus[btn.uuid]) {
+                      let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+  
+                      btn.config = {
+                        uuid: btn.uuid,
+                        MenuID: btn.uuid,
+                        ParentId: tab.components[0].uuid,
+                        MenuName: btn.label,
+                        tables: _config.tables || [],
+                        Template: 'CustomPage',
+                        components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                        viewType: 'popview',
+                        style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                      }
+
+                      btn.config.enabled = this.setEnabled(btn.config)
+                    } else {
+                      errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                    }
+                  }
+                })
+              })
+            })
+          } else if (item.type !== 'form') {
+            item.action.forEach(btn => {
+              if (btn.OpenType === 'popview') {
+                if (menus[btn.uuid]) {
+                  let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+
+                  btn.config = {
+                    uuid: btn.uuid,
+                    MenuID: btn.uuid,
+                    ParentId: item.uuid,
+                    MenuName: btn.label,
+                    tables: _config.tables || [],
+                    Template: 'CustomPage',
+                    components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                    viewType: 'popview',
+                    style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                  }
+
+                  btn.config.enabled = this.setEnabled(btn.config)
+                } else {
+                  errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                }
+              }
+            })
+            item.cols.forEach(col => {
+              if (col.type !== 'custom') return
+              col.elements.forEach(btn => {
+                if (btn.eleType !== 'button') return
+                if (btn.OpenType === 'popview') {
+                  if (menus[btn.uuid]) {
+                    let mainTb = {name: '涓昏〃', uuid: Utils.getuuid(), useMSearch: 'false'}
+  
+                    btn.config = {
+                      uuid: btn.uuid,
+                      MenuID: btn.uuid,
+                      ParentId: item.uuid,
+                      MenuName: btn.label,
+                      tables: _config.tables || [],
+                      Template: 'CustomPage',
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                      viewType: 'popview',
+                      style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
+                    }
+
+                    btn.config.enabled = this.setEnabled(btn.config)
+                  } else {
+                    errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+            })
+          }
+        })
+
+        this.setPopForm(_resolve, _config, formActions, errors)
+      })
+    } else {
+      this.setPopForm(_resolve, _config, formActions, errors)
+    }
+  }
+
+  setEnabled = (config) => {
+    let enabled = true
+    config.components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          if (tab.components[0].errors.length > 0) {
+            enabled = false
+          }
+        })
+      } else {
+        if (item.errors.length > 0) {
+          enabled = false
+        }
+      }
+    })
+
+    return enabled
+  }
+
+  setPopForm = (_resolve, _config, formActions, errors) => {
+    if (formActions.length > 0) {
+      let defers = formActions.map((item, i) => {
+        return new Promise((resolve) => {
+          setTimeout(() => {
+            Api.getCloudConfig({
+              func: 'sPC_Get_LongParam',
+              MenuID: item.origin
+            }).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) {
+                  _LongParam.uuid = item.uuid
+                  resolve(_LongParam)
+                } else {
+                  resolve({uuid: item.uuid, $empty: true})
+                }
+              } else {
+                notification.warning({
+                  top: 92,
+                  message: res.message,
+                  duration: 5
+                })
+                resolve({uuid: item.uuid, $empty: true})
+              }
+            })
+          }, i * 50)
+        })
+      })
+      Promise.all(defers).then(res => {
+        let menus = {}
+        res.forEach(item => {
+          if (item && !item.$empty) {
+            menus[item.uuid] = item
+          }
+        })
+
+        _config.components.forEach(item => {
+          if (item.type === 'tabs') {
+            item.subtabs.forEach(tab => {
+              tab.components[0].action.forEach(btn => {
+                if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                  this.setTbForm(btn.config.components[0], menus, errors, tab.components[0].name + '-' + btn.label)
+                } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                  if (menus[btn.uuid]) {
+                    btn.modal = {
+                      setting: menus[btn.uuid].setting,
+                      tables: [],
+                      groups: [],
+                      fields: menus[btn.uuid].fields || []
+                    }
+                  } else {
+                    errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+              tab.components[0].cols.forEach(col => {
+                if (col.type !== 'custom') return
+                col.elements.forEach(btn => {
+                  if (btn.eleType !== 'button') return
+                  if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                    this.setTbForm(btn.config.components[0], menus, errors, tab.components[0].name + '-' + btn.label)
+                  } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                    if (menus[btn.uuid]) {
+                      btn.modal = {
+                        setting: menus[btn.uuid].setting,
+                        tables: [],
+                        groups: [],
+                        fields: menus[btn.uuid].fields || []
+                      }
+                    } else {
+                      errors.push(tab.label + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                    }
+                  }
+                })
+              })
+            })
+          } else if (item.type !== 'form') {
+            item.action.forEach(btn => {
+              if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                this.setTbForm(btn.config.components[0], menus, errors, item.name + '-' + btn.label)
+              } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                if (menus[btn.uuid]) {
+                  btn.modal = {
+                    setting: menus[btn.uuid].setting,
+                    tables: [],
+                    groups: [],
+                    fields: menus[btn.uuid].fields || []
+                  }
+                } else {
+                  errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                }
+              }
+            })
+
+            item.cols.forEach(col => {
+              if (col.type !== 'custom') return
+              col.elements.forEach(btn => {
+                if (btn.eleType !== 'button') return
+                if (btn.OpenType === 'popview' && btn.config && btn.config.components[0]) {
+                  this.setTbForm(btn.config.components[0], menus, errors, item.name + '-' + btn.label)
+                } else if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+                  if (menus[btn.uuid]) {
+                    btn.modal = {
+                      setting: menus[btn.uuid].setting,
+                      tables: [],
+                      groups: [],
+                      fields: menus[btn.uuid].fields || []
+                    }
+                  } else {
+                    errors.push('涓昏〃涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+                  }
+                }
+              })
+            })
+          }
+        })
+
+        this.saveConfig(_resolve, _config, errors)
+      })
+    } else {
+      this.saveConfig(_resolve, _config, errors)
+    }
+  }
+
+  setTbForm = (item, menus, errors, name) => {
+    item.action.forEach(btn => {
+      if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+        if (menus[btn.uuid]) {
+          btn.modal = {
+            setting: menus[btn.uuid].setting,
+            tables: [],
+            groups: [],
+            fields: menus[btn.uuid].fields || []
+          }
+        } else {
+          errors.push(name + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+        }
+      }
+    })
+    item.cols.forEach(col => {
+      if (col.type !== 'custom') return
+      col.elements.forEach(btn => {
+        if (btn.eleType !== 'button') return
+        if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
+          if (menus[btn.uuid]) {
+            btn.modal = {
+              setting: menus[btn.uuid].setting,
+              tables: [],
+              groups: [],
+              fields: menus[btn.uuid].fields || []
+            }
+          } else {
+            errors.push(name + '涓寜閽��' + btn.label + '銆嬮厤缃俊鎭涪澶�')
+          }
+        }
+      })
+    })
+  }
+
+  saveConfig = (_resolve, _config, errors) => {
+    let err = errors.join('锛�')
+
+    if (err) {
+      notification.warning({
+        top: 92,
+        message: err,
+        duration: 5
+      })
+    }
+
+    this.saveNewMenu(_resolve, _config)
+  }
+
+  saveNewMenu = (_resolve, _config) => {
+    _config.components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components[0].action.forEach(btn => {
+            if (btn.OpenType === 'popview' && btn.config) {
+              btn.config.$tables = getTables(btn.config.components[0])
+            }
+          })
+          tab.components[0].cols.forEach(col => {
+            if (col.type !== 'custom') return
+            col.elements.forEach(btn => {
+              if (btn.eleType !== 'button') return
+              if (btn.OpenType === 'popview' && btn.config) {
+                btn.config.$tables = getTables(btn.config.components[0])
+              }
+            })
+          })
+
+          tab.components[0].$tables = getTables(tab.components[0])
+        })
+      } else {
+        item.$tables = getTables(item)
+      }
+    })
+
+    this.submitConfig(_resolve, _config)
+  }
+
+  checkBtns = (card) => {
+    card.action.forEach(cell => {
+      if (cell.hidden === 'true') return
+      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+        if (!cell.modal || cell.modal.fields.length === 0) {
+          card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
+        }
+      } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
+        card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+      } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+        card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+      }
+    })
+
+    card.cols.forEach(col => {
+      if (col.type !== 'custom') return
+
+      col.elements.forEach(cell => {
+        if (cell.hidden === 'true' || cell.eleType !== 'button') return
+        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+          if (!cell.modal || cell.modal.fields.length === 0) {
+            card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
+          }
+        } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
+          card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+        } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+          card.errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+        }
+      })
+    })
+  }
+
+  submitConfig = (_resolve, config) => {
+    let tbs = []
+    config.components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          if (tab.components[0].$tables) {
+            tbs.push(...tab.components[0].$tables)
+          }
+
+          this.checkBtns(tab.components[0])
+        })
+      } else {
+        if (item.$tables) {
+          tbs.push(...item.$tables)
+        }
+      }
+    })
+
+    let arr = []
+    tbs = tbs.filter(tb => {
+      let _tb = tb.toLowerCase()
+
+      if (arr.includes(_tb)) return false
+      arr.push(_tb)
+
+      return true
+    })
+    tbs.sort()
+    if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
+      let names = sessionStorage.getItem('mk_tb_names')
+      tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
+    }
+    tbs = tbs.map(tb => `'${tb}'`).join(';')
+
+    let key = md5(config.uuid + tbs.toLowerCase())
+
+    let urlparam = {
+      FstId: config.fstMenuId,
+      ParentId: config.parentId,
+      MenuID: config.uuid,
+      MenuName: config.MenuName,
+      MenuNo: config.MenuNo,
+      EasyCode: config.easyCode,
+      type: 'admin',
+      OpenType: config.OpenType,
+      PageParam: {Template: 'CustomPage', OpenType: 'newtab', hidden: config.hidden},
+      MenuType: 'custom'
+    }
+    let url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+    config.tbkey = key
+
+    let param = {
+      func: 'sPC_TrdMenu_AddUpt',
+      FstID: config.fstMenuId || '',
+      SndID: config.parentId,
+      ParentID: config.parentId,
+      MenuID: config.uuid,
+      MenuNo: config.MenuNo || '',
+      EasyCode: config.easyCode || '',
+      Template: 'CustomPage',
+      MenuName: config.MenuName || '',
+      PageParam: JSON.stringify({Template: 'CustomPage', OpenType: config.OpenType, hidden: config.hidden}),
+      open_edition: '',
+      debug_md5: key,
+      debug_url: url,
+      debug_list: window.btoa(tbs),
+      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config)))
+    }
+
+    param.LText = Utils.formatOptions(param.LText)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    Api.getCloudConfig(param).then(res => {
+      _resolve()
+      if (res.status) {
+        // if (this.delButtons.length > 0) {
+        //   Api.getCloudConfig({
+        //     func: 'sPC_MainMenu_Del',
+        //     up_type: 'Y',
+        //     MenuID: this.delButtons.join(',')
+        //   })
+        // }
+
+        delete urlparam.type
+
+        let _param = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+
+        window.open(window.location.href.split('#')[0] + `#/menudesign/${_param}`)
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  getTable = (config, newCon, errors, formActions, popActions, oldtabs) => { 
+    let _card = {
+      uuid: newCon.uuid,
+      type: 'table',
+      name: newCon.name,
+      format: 'array',
+      pageable: true,
+      switchable: true,
+      search: [],
+      action: [],
+      subtype: 'normaltable',
+      setting: { useMSearch: 'false', sync: 'false', onload: 'true' },
+      wrap: {name: newCon.name},
+      style: {},
+      headerStyle: {},
+      columns: [],
+      cols: [],
+      scripts: []
+    }
+
+    if (!config) {
+      errors.push(newCon.name + '閰嶇疆淇℃伅涓㈠け')
+      return _card
+    }
+
+    if (oldtabs && newCon.supModule && oldtabs[newCon.supModule]) {
+      _card.setting.supModule = [oldtabs[newCon.supModule]]
+    } else {
+      _card.setting.supModule = ['empty']
+    }
+
+    _card.search = config.search.map(item => {
+      item.uuid = Utils.getuuid()
+      return item
+    })
+
+    let _cols = {}
+    let _colspan = []
+    let lineMarks = []
+    config.columns.forEach(col => {
+      if (col.type === 'colspan') {
+        if (col.subfield) {
+          _colspan.push(...col.subfield.split(', '))
+        } else if (col.sublist && col.sublist.length > 0) {
+          _colspan.push(...col.sublist)
+        }
+      }
+      if (!col.field) return
+
+      let _col = fromJS(col).toJS()
+
+      if (_col.marks) {
+        _col.marks = []
+        col.marks.forEach(m => {
+          if (m.signType === 'card') return
+
+          let field = []
+          field.push(m.field)
+          field.push(m.contrastType)
+
+          if (m.contrastField) {
+            field.push(m.contrastField)
+          }
+          let color = '#1890ff'
+          if (m.color && m.color[1]) {
+            color = colorTransform[m.color[1]]
+          }
+          let signType = ['font']
+          if (m.signType === 'background') {
+            signType = ['background']
+          } else if (m.signType === 'icon') {
+            if (m.position === 'back') {
+              signType = ['iconback']
+            } else {
+              signType = ['iconfront']
+            }
+            signType.push(m.iconType)
+            signType.push(m.icon)
+          }
+
+          if (m.signType === 'line') {
+            lineMarks.push({
+              $index: lineMarks.length + 1,
+              uuid: Utils.getuuid(),
+              field: field,
+              color: color,
+              contrastValue: m.contrastValue || '',
+              match: m.match,
+              signType: ['background']
+            })
+          } else {
+            _col.marks.push({
+              $index: _col.marks.length + 1,
+              uuid: Utils.getuuid(),
+              field: field,
+              color: color,
+              contrastValue: m.contrastValue || '',
+              match: m.match,
+              signType: signType
+            })
+          }
+        })
+      }
+
+      _cols[col.field] = _col
+    })
+
+    config.columns.forEach(col => {
+      if (col.type === 'index') {
+        col.uuid = Utils.getuuid()
+        _card.cols.push(fromJS(col).toJS())
+      } else if (col.field && _cols[col.field]) {
+        let _col = fromJS(_cols[col.field]).toJS()
+
+        if (_colspan.includes(col.field)) {
+          _col.Hide = 'true'
+        }
+
+        _col.uuid = Utils.getuuid()
+
+        _card.cols.push(_col)
+      }
+
+      if (col.type === 'colspan') {
+        let ucol = {
+          Align: col.Align,
+          Hide: col.Hide,
+          label: col.label,
+          marks: [],
+          isSub: false,
+          uuid: Utils.getuuid(),
+          blacklist: []
+        }
+
+        let _subs = []
+        if (col.subfield) {
+          _subs = col.subfield.split(', ')
+        } else if (col.sublist) {
+          _subs = col.sublist
+        }
+
+        if (col.unfold === 'true') {
+          ucol.type = 'colspan'
+          ucol.subcols = []
+
+          _subs.forEach(sub => {
+            if (_cols[sub]) {
+              let _col = fromJS(_cols[sub]).toJS()
+              _col.Hide = 'false'
+              _col.isSub = true
+              _col.uuid = Utils.getuuid()
+
+              ucol.subcols.push(_col)
+            }
+          })
+
+          if (ucol.subcols.length > 0) {
+            _card.cols.push(ucol)
+          }
+        } else {
+          ucol.Width = 120
+          ucol.type = 'custom'
+          ucol.elements = []
+          ucol.style = {paddingTop: '12px', paddingLeft: '8px', paddingBottom: '12px', paddingRight: '8px'}
+
+          _subs.forEach(sub => {
+            if (_cols[sub]) {
+              let _col = {
+                copyable: 'false',
+                datatype: 'dynamic',
+                eleType: _cols[sub].type !== 'number' ? 'text' : 'number',
+                field: sub,
+                height: '',
+                innerHeight: 'auto',
+                marks: _cols[sub].marks || null,
+                noValue: 'show',
+                prefix: _cols[sub].prefix || '',
+                postfix: _cols[sub].postfix || '',
+                style: {},
+                width: 24,
+                uuid: Utils.getuuid()
+              }
+
+              ucol.elements.push(_col)
+            }
+          })
+
+          if (ucol.elements.length > 0) {
+            _card.cols.push(ucol)
+          }
+        }
+      }
+    })
+
+    _card.lineMarks = lineMarks
+    _card.columns = []
+    _card.absFields = []
+    _card.cols.forEach(col => {
+      if (!col.field) return
+      if (['text', 'picture', 'video', 'textarea'].includes(col.type)) {
+        _card.columns.push({
+          datatype: `Nvarchar(${col.fieldlength || 50})`,
+          field: col.field,
+          fieldlength: col.fieldlength || 50,
+          label: col.label,
+          type: 'text',
+          uuid: Utils.getuuid()
+        })
+      } else if (col.type === 'link') {
+        _card.columns.push({
+          datatype: `Nvarchar(${col.fieldlength || 50})`,
+          field: col.field,
+          fieldlength: col.fieldlength || 50,
+          label: col.label,
+          type: 'text',
+          uuid: Utils.getuuid()
+        })
+        if (col.nameField) {
+          _card.columns.push({
+            datatype: `Nvarchar(${col.fieldlength || 50})`,
+            field: col.nameField,
+            fieldlength: col.fieldlength || 50,
+            label: col.label + '(鍚嶇О)',
+            type: 'text',
+            uuid: Utils.getuuid() + 'name'
+          })
+        }
+      } else if (col.type === 'number') {
+        _card.columns.push({
+          datatype: `Decimal(18,${col.decimal || 0})`,
+          field: col.field,
+          decimal: col.decimal || 0,
+          label: col.label,
+          type: 'number',
+          uuid: Utils.getuuid()
+        })
+
+        if (col.format === 'abs') {
+          _card.absFields.push(col.field)
+        }
+      }
+    })
+
+    if (_card.absFields.length) {
+      _card.absFields = Array.from(new Set(_card.absFields))
+    } else {
+      _card.absFields = null
+    }
+
+    let colbtns = []
+    let colors = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#E7E7EF', default: 'rgba(0, 0, 0, 0.65)' }
+
+    let uuids = {}
+    config.action.forEach(btn => {
+      let _c = btn.class ? btn.class.replace('border-', '') : ''
+      let color = colors[_c] || '#1890ff'
+      let _btn = fromJS(btn).toJS()
+
+      delete _btn.position
+      delete _btn.linkTab
+
+      if (_btn.intertype === 'inner' && !_btn.innerFunc) {
+        _btn.intertype = 'system'
+      }
+      if ((_btn.intertype === 'outer' || _btn.intertype === 'custom') && !_btn.procMode) { // 鍏煎澶栭儴鍑芥暟鐩翠紶绫诲瀷
+        _btn.procMode = !_btn.innerFunc ? 'none' : 'inner'
+      }
+      if (_btn.funcType === 'print' && _btn.execMode) {
+        _btn.OpenType = 'funcbutton'
+      } else if (_btn.OpenType === 'blank') {
+        _btn.OpenType = 'tab'
+      }
+
+      this.delButtons.push(btn.uuid)
+
+      _btn.show = 'button'
+
+      if (_btn.execSuccess === 'equaltab') {
+        _btn.execSuccess = 'grid'
+        _btn.syncComponent = []
+
+        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
+          _btn.syncComponent.push(oldtabs[newCon.equalTab])
+        }
+      } else if (_btn.execSuccess === 'maingrid') {
+        _btn.execSuccess = 'mainline'
+      }
+
+      if (_btn.execError === 'equaltab') {
+        _btn.execError = 'grid'
+      } else if (_btn.execError === 'maingrid') {
+        _btn.execError = 'mainline'
+      }
+
+      if (_btn.popClose === 'equaltab') {
+        _btn.popClose = 'grid'
+        _btn.syncComponent = []
+
+        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
+          _btn.syncComponent.push(oldtabs[newCon.equalTab])
+        }
+      } else if (_btn.popClose === 'maingrid') {
+        _btn.popClose = 'mainline'
+      }
+
+      if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
+
+        formActions.push({origin: btn.uuid, uuid: _btn.uuid, name: newCon.name, label: btn.label})
+      } else if (_btn.OpenType === 'popview') {
+        if (!popActions) return
+
+        popActions.push({origin: btn.uuid, linkTab: btn.linkTab || '', uuid: _btn.uuid, name: newCon.name, label: btn.label})
+      } else if (_btn.OpenType === 'tab') {
+        if (btn.tabTemplate === 'FormTab') {
+          errors.push(newCon.name + '涓寜閽��' + btn.label + '銆嬩笉鍦ㄦ敮鎸�')
+          return
+        } else if (!btn.linkmenu || btn.linkmenu.length !== 3) {
+
+          errors.push(newCon.name + '涓寜閽��' + btn.label + '銆嬩笉鍦ㄦ敮鎸�')
+          return
+        }
+      }
+
+      uuids[btn.uuid] = true
+
+      if (_btn.tabType === 'CommonTable' || _btn.tabType === 'SubTable') {
+        _btn.tabType = 'BaseTable'
+      }
+
+      if (btn.position === 'grid') {
+        _btn.eleType = 'button'
+        _btn.width = 24
+        _btn.style = {color: color, backgroundColor: 'transparent', borderColor: 'transparent'}
+        colbtns.push(_btn)
+      } else {
+        if (btn.class === 'default') {
+          _btn.style = {color: 'rgba(0, 0, 0, 0.65)', backgroundColor: '#fff', borderColor: '#d9d9d9', marginRight: '15px'}
+        } else if (btn.class.indexOf('border') > -1) {
+          _btn.style = {color: color, backgroundColor: '#fff', borderColor: color, marginRight: '15px'}
+        } else {
+          _btn.style = {color: btn.class === 'gray' ? 'rgba(0, 0, 0, 0.65)' : '#fff', backgroundColor: color, borderColor: color, marginRight: '15px'}
+        }
+        _card.action.push(_btn)
+      }
+    })
+
+    if (colbtns.length > 0) {
+      _card.cols.push({
+        Align: 'left',
+        label: '鎿嶄綔',
+        marks: [],
+        isSub: false,
+        uuid: Utils.getuuid(),
+        type: 'custom',
+        Width: 120,
+        elements: colbtns,
+        style: {paddingTop: '12px', paddingLeft: '8px', paddingBottom: '12px', paddingRight: '8px'}
+      })
+    }
+
+    let sets = ['tableName', 'interType', 'sysInterface', 'innerFunc', 'interface', 'proInterface', 'outerFunc', 'dataresource', ['queryType', 'query'], 'primaryKey', 'order', ['laypage', 'true'], ['pageSize', 10], ['onload', 'true']]
+    let wraps = ['tableType', ['bordered', 'true'], 'actionfixed', ['size', 'middle'], ['selected', 'false'], ['tableMode', 'compatible'], ['mask', 'show'], ['borderColor', '#e8e8e8'], 'height', 'controlField', 'controlVal']
+
+    _card.scripts = config.setting.scripts || []
+
+    sets.forEach(n => {
+      if (n === 'interType') {
+        if (!['system', 'inner', 'outer'].includes(config.setting.interType)) {
+          _card.setting.interType = 'system'
+        } else if (config.setting.interType === 'inner' && !config.setting.innerFunc) {
+          _card.setting.interType = 'system'
+        } else {
+          _card.setting.interType = config.setting.interType
+        }
+      } else if (typeof(n) === 'string') {
+        _card.setting[n] = config.setting[n] || ''
+      } else {
+        _card.setting[n[0]] = config.setting[n[0]] || n[1]
+      }
+    })
+    wraps.forEach(w => {
+      if (typeof(w) === 'string') {
+        _card.wrap[w] = config.setting[w] || ''
+      } else {
+        _card.wrap[w[0]] = config.setting[w[0]] || w[1]
+      }
+    })
+
+    _card.wrap.doubleClick = config.setting.doubleClick || ''
+    if (_card.wrap.doubleClick && !uuids[_card.wrap.doubleClick]) {
+      _card.wrap.doubleClick = ''
+    }
+
+    _card.setting.execute = config.setting.default || 'true'
+
+    _card.errors = []
+    let columns = _card.columns.map(c => c.field)
+    if (_card.setting.interType === 'system' && _card.setting.execute !== 'false' && !_card.setting.dataresource) {
+      _card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
+    } else if (_card.setting.interType === 'system' && _card.setting.execute === 'false' && _card.scripts.filter(script => script.status !== 'false').length === 0) {
+      _card.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+    } else if (!_card.setting.primaryKey) {
+      _card.errors.push({ level: 0, detail: '鏈缃富閿紒'})
+    } else if (!columns.includes(_card.setting.primaryKey)) {
+      _card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
+    } else if (!_card.setting.supModule) {
+      _card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+    }
+
+    return _card
+  }
+
+  handleViewBack = () => {
+    const { menu } = this.props
+
+    let param = {
+      editMenu: menu,
+      editTab: null,
+      tabConfig: null,
+      editSubTab: null,
+      subTabConfig: null,
+      btnTab: null,
+      btnTabConfig: null,
+      editAction: null,
+      subConfig: null,
+      tabview: menu.LongParam.Template
+    }
+
+    this.props.handleView(param)
+  }
+ 
+  render() {
+    return (
+      <div className="formtab-update">
+        <div className="tip">琛ㄥ崟鏍囩椤典笉鍦ㄦ敮鎸佹煡鐪嬪強缂栬緫锛岃鐐瑰嚮鍗囩骇鎸夐挳鍒涘缓鏂拌彍鍗曘�傛敞锛氬垱寤烘垚鍔熷悗璇峰湪鍘熻彍鍗曚腑淇敼鍏宠仈鎸夐挳缁戝畾鏂拌彍鍗曘��</div>
+        <div className="buttons">
+          <Button className="mk-border-purple" onClick={this.trigger}>鍗囩骇</Button>
+          <Button onClick={this.handleViewBack}>杩斿洖</Button>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default UpdateTable
\ No newline at end of file
diff --git a/src/views/basedesign/updateFormTab/index.scss b/src/views/basedesign/updateFormTab/index.scss
new file mode 100644
index 0000000..af33966
--- /dev/null
+++ b/src/views/basedesign/updateFormTab/index.scss
@@ -0,0 +1,18 @@
+.formtab-update {
+  position: absolute;
+  top: 40%;
+  left: 50%;
+  transform: translate(-50%, 0px);
+
+  .tip {
+    width: 400px;
+    line-height: 25px;
+    margin-bottom: 20px;
+  }
+  .buttons {
+    text-align: center;
+    .mk-border-purple {
+      margin-right: 15px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/views/billprint/index.jsx b/src/views/billprint/index.jsx
index de28f47..a245790 100644
--- a/src/views/billprint/index.jsx
+++ b/src/views/billprint/index.jsx
@@ -5,9 +5,7 @@
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-import options, { styles } from '@/store/options.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
+import { styles } from '@/store/options.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
 import NotFount from '@/components/404'
 import asyncComponent from '@/utils/asyncComponent'
@@ -29,20 +27,23 @@
 const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor'))
 const Balcony = asyncComponent(() => import('@/tabviews/custom/components/card/balcony'))
 const AntvG6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-G6'))
+const AntvX6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-X6'))
 const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
 
 class BillPrint extends Component {
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     loadingview: true,
     printing: false,
     pages: null,
     BID: '',
     data: '',
     tempId: '',
+    pageId: '',
     config: null,
     urlParam: null,
     visible: false,
+    rePos: false,
+    loading: false,
     auto: true
   }
 
@@ -64,7 +65,8 @@
         this.setState({
           BID: param.id || '',
           tempId: param.tempId,
-          urlParam: param
+          urlParam: param,
+          pageId: param.pageId || ''
         }, () => {
           setTimeout(() => {
             this.getMenuParam()
@@ -87,22 +89,36 @@
   componentDidMount() {
     const _this = this
 
-    Object.defineProperty(window, 'debug', {
-      configurable: true,
-      enumerable: true,
-      set(value) {
-        if (value + '' === 'false') {
-          window.debugger = false
-          window.GLOB.breakpoint = false
-          sessionStorage.removeItem('breakpoint')
-        } else {
-          window.debugger = true
-          window.GLOB.breakpoint = value + ''
-          sessionStorage.setItem('breakpoint', value)
+    if (window.GLOB.sysType !== 'cloud') {
+      Object.defineProperty(window, 'debugger', {
+        configurable: true,
+        enumerable: true,
+        set(value) {
+          if (value + '' === 'false') {
+            window.GLOB.debugger = false
+          } else {
+            window.GLOB.debugger = true
+          }
         }
-        _this.debugChange()
-      }
-    })
+      })
+
+      Object.defineProperty(window, 'debug', {
+        configurable: true,
+        enumerable: true,
+        set(value) {
+          if (value + '' === 'false') {
+            window.GLOB.debugger = false
+            window.GLOB.breakpoint = false
+            sessionStorage.removeItem('breakpoint')
+          } else {
+            window.GLOB.debugger = true
+            window.GLOB.breakpoint = value + ''
+            sessionStorage.setItem('breakpoint', value)
+          }
+          _this.debugChange()
+        }
+      })
+    }
 
     document.onkeydown = (event) => {
       let e = event || window.event
@@ -122,7 +138,6 @@
       let _shortcut = `${preKey}+${keyCode}`
 
       if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
-        window.debugger = false
         window.GLOB.breakpoint = false
         sessionStorage.removeItem('breakpoint')
         
@@ -230,7 +245,7 @@
           this.setState({
             viewlost: true,
             loadingview: false,
-            lostmsg: this.state.dict['main.view.unenabled']
+            lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
           })
           return
         }
@@ -283,11 +298,6 @@
         let userName = sessionStorage.getItem('User_Name') || ''
         let fullName = sessionStorage.getItem('Full_Name') || ''
 
-        if (sessionStorage.getItem('isEditState') === 'true') {
-          userName = sessionStorage.getItem('CloudUserName') || ''
-          fullName = sessionStorage.getItem('CloudFullName') || ''
-        }
-
         let regs = [
           { reg: /@userName@/ig, value: `'${userName}'` },
           { reg: /@fullName@/ig, value: `'${fullName}'` }
@@ -312,9 +322,23 @@
 
         window.GLOB.CacheData.set(tempId, {$BID: BID})
 
+        let initInters = []
+
+        this.formatInterSetting(config.interfaces, regs, initInters, params, BID)
+
         config.components = config.components.map(component => {
-          if (component.action) component.action = []
-          if (component.search) component.search = []
+          if (component.action) {
+            component.action = component.action.filter(cell => {
+              cell = this.resetButton(component, cell)
+              cell.$toolbtn = true
+    
+              return !cell.hidden
+            })
+          }
+          if (component.search) {
+            component.search = []
+            component.$searches = []
+          }
           component.data = [] // 鍒濆鍖栨暟鎹负绌�
 
           if (component.subtype === 'tablecard') { // 鍏煎
@@ -341,10 +365,15 @@
                   }
                 } else if (item.type === 'custom') {
                   item.elements = item.elements.filter(cell => {
-                    if (cell.eleType === 'button') return false
+                    if (cell.eleType === 'button') {
+                      cell = this.resetButton(component, cell)
+
+                      return !cell.hidden
+                    }
 
                     cell = this.resetElement(cell)
-                    return cell
+
+                    return true
                   })
                   if (item.elements.length === 0) {
                     return false
@@ -368,18 +397,26 @@
               }
     
               card.elements = card.elements.filter(cell => {
-                if (cell.eleType === 'button') return false
-   
+                if (cell.eleType === 'button') {
+                  cell = this.resetButton(component, cell)
+
+                  return !cell.hidden
+                }
+
                 cell = this.resetElement(cell)
-    
+   
                 return true
               })
     
               if (!card.backElements || card.backElements.length === 0) return
     
               card.backElements = card.backElements.filter(cell => {
-                if (cell.eleType === 'button') return false
-   
+                if (cell.eleType === 'button') {
+                  cell = this.resetButton(component, cell)
+
+                  return !cell.hidden
+                }
+
                 cell = this.resetElement(cell)
     
                 return true
@@ -387,8 +424,12 @@
             })
           } else if (component.type === 'balcony') {
             component.elements = component.elements.filter(cell => {
-              if (cell.eleType === 'button') return false
-                
+              if (cell.eleType === 'button') {
+                cell = this.resetButton(component, cell)
+
+                return !cell.hidden
+              }
+              
               cell = this.resetElement(cell)
     
               return true
@@ -397,19 +438,31 @@
 
           if (component.wrap && component.wrap.datatype === 'static') {
             component.format = ''
+          } else if (component.wrap && component.wrap.datatype === 'public') {
+            component.componentId = component.wrap.publicId
+            component.format = ''
           }
     
           if (!component.setting) return component // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
           if (!component.format) return component  // 娌℃湁鍔ㄦ�佹暟鎹�  鏁版嵁鏍煎紡 array 鎴� object
+
+          component.setting.arr_field = component.columns ? component.columns.map(col => col.field).join(',') : ''
+
           if (component.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
             component.setting.sync = 'false'
             return component
           }
     
           let _customScript = ''
+          let _tailScript = ''
           component.scripts && component.scripts.forEach(script => {
-            if (script.status !== 'false') {
+            if (script.status === 'false') return
+            if (script.position !== 'back') {
               _customScript += `
+              ${script.sql}
+              `
+            } else {
+              _tailScript += `
               ${script.sql}
               `
             }
@@ -428,21 +481,23 @@
           }
       
           if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-            component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*')
-            component.setting.dataresource = component.setting.dataresource.replace(/@\$/ig, '*/')
-            _customScript = _customScript.replace(/\$@/ig, '/*')
-            _customScript = _customScript.replace(/@\$/ig, '*/')
+            component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+            _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+            _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
           } else {
-            component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '')
-            _customScript = _customScript.replace(/@\$|\$@/ig, '')
+            component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+            _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+            _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
           }
 
           regs.forEach(cell => {
             component.setting.dataresource = component.setting.dataresource.replace(cell.reg, cell.value)
             _customScript = _customScript.replace(cell.reg, cell.value)
+            _tailScript = _tailScript.replace(cell.reg, cell.value)
           })
     
           component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+          component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
     
           // floor    缁勪欢鐨勫眰绾�
           // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
@@ -450,9 +505,8 @@
             component.dataName = 'mk' + component.uuid.slice(-18)
             let param = this.getDefaultParam(component)
             _pars.push(param)
-          } else {
-            let arr_field = component.columns.map(col => col.field).join(',')
-            let param = UtilsDM.getQueryDataParams(component.setting, arr_field, [], component.setting.order || '', 1, 1000, BID)
+          } else if (component.subtype !== 'dualdatacard') {
+            let param = UtilsDM.getQueryDataParams(component.setting, [], component.setting.order || '', 1, 1000, BID)
             
             param.componentId = component.uuid
 
@@ -486,8 +540,10 @@
           auto: config.printPage === 'auto',
           config
         }, () => {
-          if (params.length === 0) {
+          if (params.length === 0 && initInters.length === 0) {
             this.setState({loadingview: false, pages: [config.components]})
+          } else if (initInters.length > 0) {
+            this.loadinit(initInters, params)
           } else {
             this.loadmaindata(params)
           }
@@ -502,8 +558,35 @@
     })
   }
 
+  resetButton = (item, cell) => {
+    cell.logLabel = item.$menuname + '-' + cell.label
+    cell.Ot = cell.Ot || 'requiredSgl'
+    cell.syncComponentId = ''
+    cell.$menuId = item.uuid
+
+    cell.hidden = cell.hidden === 'true'
+    if (!['pop', 'prompt', 'exec', 'innerpage', 'form'].includes(cell.OpenType)) {
+      cell.hidden = true
+    }
+
+    if (cell.controlField) {
+      if (/,/ig.test(cell.controlVal)) {
+        cell.controlVals = cell.controlVal.split(',')
+      } else {
+        cell.controlVals = [(cell.controlVal || '')]
+      }
+    }
+
+    return cell
+  }
+
   resetElement = (cell) => {
     cell.style = cell.style || {}
+
+    if (cell.style.display === 'inline-block') {
+      cell.style.verticalAlign = 'top'
+    }
+    
     if (['text', 'number', 'formula'].includes(cell.eleType)) {
       cell.innerHeight = cell.innerHeight || 'auto'
       cell.alignItems = cell.height > 1 ? cell.alignItems : ''
@@ -519,6 +602,92 @@
     return cell
   }
 
+  formatInterSetting = (inters, regs, initInters, params, BID) => {
+    if (!inters) return []
+
+    let delay = 15
+    inters.forEach(inter => {
+      if (inter.status !== 'true') return
+
+      inter.setting.delay = delay
+      delay += 15
+
+      inter.setting.supModule = ''
+      inter.setting.arr_field = inter.columns.map(col => col.field).join(',')
+
+      if (inter.setting.interType !== 'system') {
+        let param = UtilsDM.getQueryDataParams(inter.setting, [], inter.setting.order || '', 1, 1000, BID)
+              
+        param.componentId = inter.uuid
+
+        if (inter.setting.loadlevel === 'init') {
+          initInters.push(param)
+        } else {
+          param.public = true
+          params.push(param)
+        }
+        return
+      }
+
+      let _customScript = ''
+      let _tailScript = ''
+      inter.scripts.forEach(script => {
+        if (script.status === 'false') return
+        if (script.position !== 'back') {
+          _customScript += `
+          ${script.sql}
+          `
+        } else {
+          _tailScript += `
+          ${script.sql}
+          `
+        }
+      })
+      delete inter.scripts
+
+      inter.setting.$name = '鍏叡鏁版嵁婧�-' + inter.setting.name
+      inter.setting.execute = inter.setting.execute !== 'false'
+      inter.setting.laypage = true
+
+      if (!inter.setting.execute) {
+        inter.setting.dataresource = ''
+      }
+      if (/\s/.test(inter.setting.dataresource)) {
+        inter.setting.dataresource = '(' + inter.setting.dataresource + ') tb'
+      }
+  
+      if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+        inter.setting.dataresource = inter.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+      } else {
+        inter.setting.dataresource = inter.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+      }
+
+      regs.forEach(cell => {
+        inter.setting.dataresource = inter.setting.dataresource.replace(cell.reg, cell.value)
+        _customScript = _customScript.replace(cell.reg, cell.value)
+        _tailScript = _tailScript.replace(cell.reg, cell.value)
+      })
+
+      inter.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+      inter.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
+
+      let param = UtilsDM.getQueryDataParams(inter.setting, [], inter.setting.order || '', 1, 1000, BID)
+            
+      param.componentId = inter.uuid
+
+      if (inter.setting.loadlevel === 'init') {
+        initInters.push(param)
+      } else {
+        param.public = true
+        params.push(param)
+      }
+    })
+  }
+
   reload = () => {
     const { tempId } = this.state
     
@@ -532,11 +701,6 @@
       setTimeout(() => {
         this.getMenuParam()
       }, 50)
-      // Api.getAppVersion(tempId).then(() => {
-      //   this.getMenuParam()
-      // }, () => {
-      //   this.getMenuParam()
-      // })
     })
   }
 
@@ -546,18 +710,17 @@
   getDefaultParam = (component) => {
     const { columns, setting, dataName, format } = component
     
-    let arr_field = columns.map(col => col.field)
     let _dataresource = setting.dataresource
     let _customScript = setting.customScript
 
     if (setting.order && _dataresource) {
-      _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows `
+      _dataresource = `select top 1000 ${setting.arr_field} from (select ${setting.arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows `
     } else if (_dataresource) {
-      _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} `
+      _dataresource = `select top 1000 ${setting.arr_field} from ${_dataresource} `
     }
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
+    if (window.GLOB.debugger === true) {
       _customScript &&  console.info(`${_dataresource ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
       _dataresource &&  console.info(_dataresource)
     }
@@ -591,11 +754,6 @@
     let city = sessionStorage.getItem('city') || ''
     let district = sessionStorage.getItem('district') || ''
     let address = sessionStorage.getItem('address') || ''
-  
-    if (sessionStorage.getItem('isEditState') === 'true') {
-      userName = sessionStorage.getItem('CloudUserName') || ''
-      fullName = sessionStorage.getItem('CloudFullName') || ''
-    }
 
     let LText = params.map((item, index) => {
       let _sql = item.sql
@@ -618,7 +776,9 @@
       func: 'sPC_Get_structured_data',
       LText: LText.join(' union all '),
       LText_field: LText_field.join(' union all '),
-      BID: BID || ''
+      BID: BID || '',
+      username: userName,
+      fullName: fullName
     }
 
     param.LText = Utils.formatOptions(param.LText)
@@ -629,6 +789,40 @@
     return param
   }
 
+  loadinit = (initInters, params) => {
+    let deffers = initInters.map(item => {
+      let componentId = item.componentId
+      delete item.componentId
+      return new Promise(resolve => {
+        Api.genericInterface(item).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+            resolve()
+          } else {
+            let _data = { $$empty: true }
+            if (res.data && res.data[0]) {
+              _data = res.data[0]
+            }
+            window.GLOB.CacheData.set(componentId, _data)
+          }
+          resolve()
+        })
+      })
+    })
+
+    Promise.all(deffers).then(() => {
+      if (params.length === 0) {
+        this.setState({loadingview: false, pages: [this.state.config.components]})
+      } else {
+        this.loadmaindata(params)
+      }
+    })
+  }
+
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
    */ 
@@ -637,7 +831,9 @@
 
     let deffers = params.map(item => {
       let componentId = item.componentId
+      let ispublic = item.public
       delete item.componentId
+      delete item.public
       return new Promise(resolve => {
         Api.genericInterface(item).then(res => {
           if (!res.status) {
@@ -649,6 +845,14 @@
             resolve(false)
           } else {
             res.componentId = componentId
+
+            if (ispublic) {
+              let _data = { $$empty: true }
+              if (res.data && res.data[0]) {
+                _data = res.data[0]
+              }
+              window.GLOB.CacheData.set(componentId, _data)
+            }
             resolve(res)
           }
         })
@@ -659,17 +863,30 @@
       let _results = results.filter(Boolean)
 
       let comps = components.map(item => {
+        item.wrap = item.wrap || {}
+        item.data = null
+
         if (!item.format) return item
 
+        if ((item.subtype === 'datacard' && item.wrap.layout !== 'flex') || item.type === 'table') {
+          item.$page = true
+        }
+
         _results.forEach(res => {
-          if (res.componentId === item.uuid && res.data) {
-            item.data = res.data
+          if ((res.componentId === item.uuid || res.componentId === item.componentId) && res.data) {
             item.dataArray = fromJS(res.data).toJS()
           } else if (res.componentId === 'union' && res[item.dataName]) {
-            item.data = res[item.dataName]
-            item.dataArray = fromJS(res[item.dataName]).toJS()
+            let data = res[item.dataName]
+            if (!Array.isArray(data)) {
+              data = [data]
+            }
+            item.dataArray = fromJS(data).toJS()
           }
         })
+
+        if (item.$page && !item.dataArray) {
+          item.$page = false
+        }
 
         return item
       })
@@ -683,94 +900,104 @@
         this.setState({loadingview: false, pages})
       }
 
+      let setData = (item) => {
+        if (item.setting && item.setting.sync === 'true' && item.data) {
+          item.dataName = Utils.getuuid()
+          window.GLOB.SyncData.set(item.dataName, item.data)
+        }
+      }
+
       while (!over) {
         let page = []
         let count = 0
         let _pageover = false
-        let pagesover = false
 
-        comps.forEach((_item, index) => {
-          let item = fromJS(_item).toJS()
+        comps.forEach(comp => {
+          let item = fromJS(comp).toJS()
 
-          if (index + 1 >= length && !_pageover) {
-            pagesover = true
+          if (item.wrap.printType === 'headerOrfooter') { // 椤电湁椤佃剼
+            item.data = item.dataArray || null
+            setData(item)
+            page.push(item)
+            comp.added = true
           }
 
-          if (item.wrap && item.wrap.printType === 'headerOrfooter') { // 椤电湁椤佃剼
-            page.push(item)
-          } else if (_pageover) {
-            return
-          } else if (item.subtype === 'datacard' || item.type === 'table') {
-            if (_item.dataArray && _item.dataArray.length > 0) {
-              if (item.subtype === 'datacard' && item.wrap.layout === 'flex') {
-                if (!item.added && item.wrap.printHeight) {
-                  count += item.wrap.printHeight
-                  if (count >= limit) {
-                    _pageover = true
-                  }
-                  if (count <= limit) {
-                    _item.added = true
-                    page.push(item)
-                  }
-                } else if (!item.added) {
-                  _item.added = true
-                  page.push(item)
-                }
-              } else {
-                item.data = []
-  
-                while (count + 1 <= limit && _item.dataArray.length > 0) {
-                  item.data.push(_item.dataArray.shift())
-                  count++
-                }
-    
-                if (count >= limit) {
-                  _pageover = true
-                } else if (_item.dataArray.length > 0) {
-                  _pageover = true
+          if (_pageover) return
 
-                }
+          if (item.$page && comp.dataArray.length > 0) {
+            item.data = []
 
-                page.push(item)
-              }
-              _item.added = true
-            } else if (!item.added) {
-              _item.added = true
-              page.push(item)
-            }
-          } else if (!item.added && item.wrap && item.wrap.printHeight) {
-            if (item.wrap.empty === 'hidden' && (!item.data || item.data.length === 0)) {
-              _item.added = true
-              return
+            while (count + 1 <= limit && comp.dataArray.length > 0) {
+              item.data.push(comp.dataArray.shift())
+              count++
             }
 
-            count += item.wrap.printHeight
-            if (count >= limit) {
+            if (count >= limit || comp.dataArray.length > 0) {
               _pageover = true
             }
-            if (count <= limit) {
-              _item.added = true
-              page.push(item)
+
+            if (comp.dataArray.length === 0) {
+              comp.added = true
             }
-          } else if (!item.added) {
-            _item.added = true
+
+            setData(item)
             page.push(item)
-          }
-          
-          if (index + 1 >= length && !_pageover) {
-            pagesover = true
+          } else if (!comp.added) {
+            if (item.wrap.printHeight) {
+              count += item.wrap.printHeight
+              if (count >= limit) {
+                _pageover = true
+                return
+              }
+            }
+
+            item.data = item.dataArray || null
+
+            setData(item)
+            page.push(item)
+            comp.added = true
           }
         })
 
         pages.push(page)
         pageIndex++
 
-        if (pageIndex >= 2000 || pagesover) {
+        if (pageIndex >= 2000 || comps.findIndex(comp => !comp.added) === -1) {
           over = true
         }
       }
 
-      this.setState({loadingview: false, pages})
+      let total = pages.length
+      let date = moment().format('YYYY-MM-DD')
+      let datetime = moment().format('YYYY-MM-DD HH:mm:ss')
+      let rePos = false
+
+      pages.forEach((page, index) => {
+        page.forEach(item => {
+          if (item.wrap.printType === 'headerOrfooter') { // 椤电湁椤佃剼
+            if (item.type === 'balcony') {
+              if (item.style.position === 'absolute') {
+                rePos = true
+              }
+              item.elements.forEach(cell => {
+                if (cell.eleType === 'text' && cell.datatype === 'static') {
+                  cell.value = cell.value.replace(/@total@/ig, total).replace(/@pageIndex@/ig, index + 1).replace(/@date@/ig, date).replace(/@datetime@/ig, datetime)
+                }
+              })
+            } else if (item.subtype === 'propcard') {
+              item.subcards.forEach(card => {
+                card.elements.forEach(cell => {
+                  if (cell.eleType === 'text' && cell.datatype === 'static') {
+                    cell.value = cell.value.replace(/@total@/ig, total).replace(/@pageIndex@/ig, index + 1).replace(/@date@/ig, date).replace(/@datetime@/ig, datetime)
+                  }
+                })
+              })
+            }
+          }
+        })
+      })
+
+      this.setState({loadingview: false, pages, rePos})
     })
   }
 
@@ -789,9 +1016,54 @@
   }
 
   print = () => {
-    const { config, printing } = this.state
+    const { config, printing, BID, tempId, pageId } = this.state
     
     if (printing) return
+
+    this.setState({printing: true})
+    
+    if (config.callback === 'true') {
+      this.setState({loading: true})
+
+      Api.genericInterface({
+        func: 's_print_proc',
+        username: sessionStorage.getItem('User_Name') || '',
+        fullname: sessionStorage.getItem('Full_Name') || '',
+        BID: BID || '',
+        print_type: config.callNo || '',
+        MenuNo: config.MenuNo || '',
+        Menuid: tempId || ''
+      }).then(res => {
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message || '鎵ц澶辫触锛�',
+            duration: 5
+          })
+
+          this.setState({printing: false, loading: false})
+          return
+        }
+
+        let refresh = !/@no_target_menu@/i.test(res.message)
+
+        this.setState({loading: false})
+
+        if (pageId && refresh) {
+          localStorage.setItem('menuUpdate', new Date().getTime() + ',' + pageId + ',menu')
+        }
+
+        setTimeout(() => {
+          this.execPrint()
+        }, 300)
+      })
+    } else {
+      this.execPrint()
+    }
+  }
+
+  execPrint = () => {
+    const { config } = this.state
 
     let qrcodes = document.getElementsByClassName('qrcode-box')
 
@@ -822,8 +1094,6 @@
     }
 
     let jubuData = document.getElementById('bill-print').innerHTML
-
-    this.setState({printing: true})
     
     try {
       let iframe = document.createElement('IFRAME')
@@ -875,90 +1145,104 @@
 
       if (item.style && item.style.clear === 'left') {
         style = {clear: 'left'}
+      } else if (item.style && item.style.clear === 'right') {
+        style = {float: 'right'}
       }
 
       if (item.type === 'bar' || item.type === 'line') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvBarAndLine config={item} initdata={item.data} mainSearch={[]} />
+            <AntvBarAndLine config={item}/>
           </Col>
         )
       } else if (item.type === 'pie') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvPie config={item} initdata={item.data} mainSearch={[]} />
+            <AntvPie config={item} />
           </Col>
         )
       } else if (item.type === 'scatter') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvScatter config={item} initdata={item.data} mainSearch={[]}/>
+            <AntvScatter config={item}/>
           </Col>
         )
       } else if (item.type === 'dashboard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvDashboard config={item} initdata={item.data} mainSearch={[]}/>
+            <AntvDashboard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DataCard config={item} initdata={item.data} mainSearch={[]} />
+            <DataCard config={item} />
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'propcard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <PropCard config={item} initdata={item.data} mainSearch={[]} />
+            <PropCard config={item} />
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'dualdatacard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <DoubleDataCard config={item} mainSearch={[]}/>
+            <DoubleDataCard config={item}/>
           </Col>
         )
       } else if (item.type === 'card' && item.subtype === 'tablecard') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TableCard config={item} initdata={item.data} mainSearch={[]}/>
+            <TableCard config={item}/>
           </Col>
         )
       } else if (item.type === 'table' && item.subtype === 'normaltable') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <NormalTable config={item} initdata={item.data} mainSearch={[]}/>
+            <NormalTable config={item}/>
           </Col>
         )
       } else if (item.type === 'code') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <SandBox config={item} initdata={item.data} mainSearch={[]}/>
+            <SandBox config={item}/>
           </Col>
         )
       } else if (item.type === 'balcony') {
-        return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <Balcony config={item} initdata={item.data}/>
-          </Col>
-        )
+        if (item.wrap.printType === 'headerOrfooter' && item.style.position === 'absolute') {
+          return (
+            <Balcony key={item.uuid} config={item}/>
+          )
+        } else {
+          return (
+            <Col span={item.width} style={style} key={item.uuid}>
+              <Balcony config={item}/>
+            </Col>
+          )
+        }
       } else if (item.type === 'timeline') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <TimeLine config={item} initdata={item.data} mainSearch={[]}/>
+            <TimeLine config={item}/>
           </Col>
         )
       } else if (item.type === 'editor') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <BraftEditor config={item} initdata={item.data} mainSearch={[]}/>
+            <BraftEditor config={item}/>
           </Col>
         )
       } else if (item.type === 'antvG6') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
-            <AntvG6 config={item} initdata={item.data} mainSearch={[]}/>
+            <AntvG6 config={item}/>
+          </Col>
+        )
+      } else if (item.type === 'antvX6') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <AntvX6 config={item}/>
           </Col>
         )
       } else {
@@ -968,13 +1252,13 @@
   }
 
   render() {
-    const { loadingview, viewlost, config, pages, auto } = this.state
+    const { loadingview, viewlost, config, pages, auto, rePos, loading } = this.state
 
     return (
       <div className="bill-print-wrap" >
-        {loadingview && <Spin size="large" />}
+        {loadingview || loading ? <Spin size="large" /> : null}
         {pages ? <div id="bill-print">
-          {pages.map((components, index) => (<div className={'print-page' + (auto ? ' auto' : '')} key={index} style={{...config.style, overflow: 'hidden', boxSizing: 'border-box'}}><Row className="component-wrap">{this.getComponents(components)}</Row></div>))}
+          {pages.map((components, index) => (<div className={'print-page' + (auto ? ' auto' : '') + (rePos ? ' reset-position' : '')} key={index} style={{...config.style, overflow: 'hidden', boxSizing: 'border-box'}}><Row className="component-wrap">{this.getComponents(components)}</Row></div>))}
         </div> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
         {config && window.GLOB.breakpoint ? <DebugTable /> : null}
diff --git a/src/views/billprint/index.scss b/src/views/billprint/index.scss
index fa8b84a..3ad6384 100644
--- a/src/views/billprint/index.scss
+++ b/src/views/billprint/index.scss
@@ -82,6 +82,12 @@
 .print-page.auto:last-child {
   height: auto!important;
 }
+.reset-position.print-page {
+  position: relative;
+  .component-wrap {
+    position: unset;
+  }
+}
 
 .normal-custom-table .main-pickup {
   display: none!important;
diff --git a/src/views/design/header/editfirstmenu/index.jsx b/src/views/design/header/editfirstmenu/index.jsx
index 45a5b8d..06dc1e7 100644
--- a/src/views/design/header/editfirstmenu/index.jsx
+++ b/src/views/design/header/editfirstmenu/index.jsx
@@ -60,7 +60,7 @@
       this.setState({
         loading: true
       })
-      Api.getSystemConfig(param).then(res => {
+      Api.getCloudConfig(param).then(res => {
         if (res.status) {
           this.setState({
             loading: false,
@@ -101,7 +101,7 @@
           func: 'sPC_MainMenu_Del',
           MenuID: item.MenuID
         }
-        return Api.getSystemConfig(param).then(res => {
+        return Api.getCloudConfig(param).then(res => {
           if (res.status) {
             _this.props.reload()
           } else {
@@ -139,7 +139,7 @@
         title: '纭璋冩暣鑿滃崟椤哄簭鍚楋紵',
         content: '',
         onOk() {
-          return Api.getSystemConfig(param).then(res => {
+          return Api.getCloudConfig(param).then(res => {
             if (res.status) {
               that.setState({ change: false })
               that.props.reload()
diff --git a/src/views/design/header/index.jsx b/src/views/design/header/index.jsx
index 2155478..3fe5ad4 100644
--- a/src/views/design/header/index.jsx
+++ b/src/views/design/header/index.jsx
@@ -1,22 +1,14 @@
 import React, {Component} from 'react'
 import { withRouter } from 'react-router-dom'
-import {connect} from 'react-redux'
 import { Dropdown, Menu, Modal, notification, Switch, Button, Popover } from 'antd'
 import { MenuFoldOutlined, SettingOutlined, AppstoreOutlined, DownOutlined, HomeOutlined, ApiOutlined, PlusOutlined, EditOutlined, MenuOutlined, DatabaseOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
-import asyncComponent from '@/utils/asyncComponent'
-import {
-  modifyMenuTree,
-  modifyMainMenu,
-  resetEditLevel,
-  logout
-} from '@/store/action'
 import Api from '@/api'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import avatar from '@/assets/img/avatar.jpg'
 import MainLogo from '@/assets/img/main-logo.png'
+import asyncComponent from '@/utils/asyncComponent'
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
@@ -44,7 +36,6 @@
       content: '',
       onOk() {
         sessionStorage.clear()
-        _this.props.logout()
         _this.props.history.replace('/login')
       },
       onCancel() {}
@@ -64,12 +55,12 @@
     // 鑾峰彇涓昏彍鍗�
     let _param = {
       func: 's_get_pc_menus',
-      systemType: options.sysType,
+      systemType: window.GLOB.sysType,
       pro_sys: window.GLOB.systemType === 'production' ? 'Y' : '',
       debug: 'Y'
     }
 
-    let result = await Api.getSystemConfig(_param)
+    let result = await Api.getCloudConfig(_param)
 
     // 鐧诲綍瓒呮椂
     if (!result) return
@@ -189,6 +180,7 @@
   }
 
   changeEditState = () => {
+    sessionStorage.removeItem('isEditState')
     this.props.history.replace('/main')
     window.location.reload()
   }
@@ -214,7 +206,7 @@
       this.setState({
         loading: true
       })
-      Api.getSystemConfig(param).then(res => {
+      Api.getCloudConfig(param).then(res => {
         if (res.status) {
           this.setState({
             loading: false,
@@ -319,7 +311,7 @@
       param.secretkey = Utils.encrypt(param.LText, param.timestamp)
       param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
       
-      Api.getSystemConfig(param).then(res => {
+      Api.getCloudConfig(param).then(res => {
         let msgs = []
         if (!res.status) {
           notification.warning({
@@ -336,7 +328,6 @@
   }
   
   UNSAFE_componentWillMount () {
-    sessionStorage.setItem('isEditState', 'true')
     document.body.className = ''
     
     // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
@@ -357,7 +348,7 @@
 
     if (window.GLOB.systemType !== 'production') {
       setTimeout(() => {
-        Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
+        Api.getCloudConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
           if (res.status) {
             let _permFuncField = []
             let _sysRoles = []
@@ -388,7 +379,8 @@
       }, 100)
 
       setTimeout(() => {
-        this.setSystemFuncs()
+        // positecgroup
+        // this.setSystemFuncs()
         this.getSmStemp()
       }, 500)
     }
@@ -405,11 +397,11 @@
   }
 
   gotoDoc = () => {
-    if (options.sysType === 'local' && window.GLOB.mainSystemApi) {
+    if (window.GLOB.sysType === 'local' && window.GLOB.mainSystemApi) {
       let ssodomain = window.GLOB.mainSystemApi.replace('/webapi/dostars', '')
       let url = `${ssodomain}/doc/index.html#?appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
       window.open(url)
-    } else if (options.sysType === 'SSO' || options.sysType === 'cloud') {
+    } else if (window.GLOB.sysType === 'SSO' || window.GLOB.sysType === 'cloud') {
       window.open(`${window.location.href.replace(/\/index.html(.*)|\/#(.*)/ig, '')}/doc/index.html#?appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`)
     }
   }
@@ -511,7 +503,7 @@
               <Switch size="small" style={{marginLeft: '7px'}} disabled={!!editLevel} checked={true} onChange={this.changeEditState} />
             </Menu.Item>
             <Menu.Item key="doc" onClick={this.gotoDoc}>鏂囨。涓績</Menu.Item>
-            {options.sysType !== 'cloud' ? <Menu.Item style={{padding: 0}} key="verup">
+            {window.GLOB.sysType !== 'cloud' ? <Menu.Item style={{padding: 0}} key="verup">
               <VersionsUp />
             </Menu.Item> : null}
             <Menu.Item key="logout" onClick={this.logout}>閫�鍑�</Menu.Item>
@@ -543,21 +535,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    menuTree: state.menuTree,
-    mainMenu: state.mainMenu,
-    editLevel: state.editLevel
-  }
-}
-
-const mapDispatchToProps = (dispatch) => {
-  return {
-    modifyMenuTree: (menuTree) => dispatch(modifyMenuTree(menuTree)),
-    modifyMainMenu: (mainMenu) => dispatch(modifyMainMenu(mainMenu)),
-    resetEditLevel: (level) => dispatch(resetEditLevel(level)),
-    logout: () => dispatch(logout())
-  }
-}
-
-export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header))
\ No newline at end of file
+export default withRouter(Header)
\ No newline at end of file
diff --git a/src/views/design/header/versions/index.jsx b/src/views/design/header/versions/index.jsx
index 806b3ac..100b669 100644
--- a/src/views/design/header/versions/index.jsx
+++ b/src/views/design/header/versions/index.jsx
@@ -5,7 +5,6 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import './index.scss'
 
@@ -28,7 +27,7 @@
       func: 's_get_sversions_sys',
     }
 
-    Api.getSystemConfig(_param).then(result => {
+    Api.getCloudConfig(_param).then(result => {
       if (!result.status) {
         notification.warning({
           top: 92,
@@ -39,9 +38,9 @@
       }
 
       let edition_int = ''
-      if (options.sysType === 'SSO') {
+      if (window.GLOB.sysType === 'SSO') {
         edition_int = result.edition_int_sso
-      } else if (options.sysType === 'local' && window.GLOB.systemType !== 'production') {
+      } else if (window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
         edition_int = result.edition_int_local
       } else {
         if (result.edition_int_sso < result.edition_int_local) {
@@ -59,7 +58,7 @@
         return
       }
 
-      let sysType = options.sysType.toLowerCase()
+      let sysType = window.GLOB.sysType.toLowerCase()
 
       if (window.GLOB.systemType === 'production' || sysType !== 'local') {
         sysType = ''
diff --git a/src/views/design/index.jsx b/src/views/design/index.jsx
index 5cd309f..f965c69 100644
--- a/src/views/design/index.jsx
+++ b/src/views/design/index.jsx
@@ -1,36 +1,69 @@
 import React, {Component} from 'react'
+import { withRouter } from 'react-router-dom'
 import { ConfigProvider } from 'antd'
-import enUS from 'antd/es/locale/en_US'
+// import enUS from 'antd/es/locale/en_US'
 import zhCN from 'antd/es/locale/zh_CN'
 
 import Header from './header'
-import { setGLOBFuncs } from '@/utils/utils.js'
 import Sidemenu from './sidemenu'
+import { setGLOBFuncs } from '@/utils/utils.js'
 
 import '@/assets/css/design.scss'
 import './index.scss'
 
-const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
-
 class Design extends Component {
+  state = {
+    editLevel: false,
+    mainMenu: null,
+    unvalid: !sessionStorage.getItem('UserID'),
+    menuTree: []
+  }
+
   componentDidMount() {
-    window.debugger = false
-    window.GLOB.breakpoint = false
-    window.GLOB.designView = true
-    sessionStorage.removeItem('breakpoint')
-    setGLOBFuncs()
+    if (!sessionStorage.getItem('UserID')) {
+      this.props.history.replace('/login')
+      return
+    }
+
+    if (sessionStorage.getItem('isEditState') === 'true') {
+      sessionStorage.removeItem('isEditState')
+      this.props.history.replace('/main')
+      window.location.reload()
+    } else {
+      sessionStorage.setItem('isEditState', 'true')
+      window.GLOB.breakpoint = false
+      window.GLOB.designView = true
+      sessionStorage.removeItem('breakpoint')
+      setGLOBFuncs()
+    }
+  }
+
+  resetEditLevel = (level) => {
+    this.setState({editLevel: level})
+  }
+  
+  modifyMenuTree = (menulist) => {
+    this.setState({menuTree: menulist})
+  }
+
+  modifyMainMenu = (menu) => {
+    this.setState({mainMenu: menu})
   }
   
   render () {
+    const { editLevel, menuTree, mainMenu, unvalid } = this.state
+
+    if (unvalid) return null
+
     return (
       <div className={'mk-main-view ' + (window.GLOB.systemType || '')}>
-        <ConfigProvider locale={_locale}>
-          <Sidemenu key="sidemenu"/>
-          <Header key="header"/>
+        <ConfigProvider locale={zhCN}>
+          <Sidemenu key="sidemenu" editLevel={editLevel} menuTree={menuTree} mainMenu={mainMenu} resetEditLevel={this.resetEditLevel}/>
+          <Header key="header" editLevel={editLevel} mainMenu={mainMenu} resetEditLevel={this.resetEditLevel} modifyMenuTree={this.modifyMenuTree} modifyMainMenu={this.modifyMainMenu}/>
         </ConfigProvider>
       </div>
     )
   }
 }
 
-export default Design
\ No newline at end of file
+export default withRouter(Design)
\ No newline at end of file
diff --git a/src/views/design/sidemenu/editsecmenu/index.jsx b/src/views/design/sidemenu/editsecmenu/index.jsx
index 57e0cff..c630d72 100644
--- a/src/views/design/sidemenu/editsecmenu/index.jsx
+++ b/src/views/design/sidemenu/editsecmenu/index.jsx
@@ -58,7 +58,7 @@
             func: 'sPC_MainMenu_Del',
             MenuID: menu.card.MenuID
           }
-          return Api.getSystemConfig(param).then(res => {
+          return Api.getCloudConfig(param).then(res => {
             if (res.status) {
               MKEmitter.emit('mkUpdateMenuList')
             } else {
@@ -124,7 +124,7 @@
         title: '纭璋冩暣鑿滃崟椤哄簭鍚楋紵',
         content: '',
         onOk() {
-          return Api.getSystemConfig(param).then(res => {
+          return Api.getCloudConfig(param).then(res => {
             if (res.status) {
               that.setState({ change: false })
               MKEmitter.emit('mkUpdateMenuList')
@@ -169,7 +169,7 @@
       this.setState({
         loading: true
       })
-      Api.getSystemConfig(param).then(res => {
+      Api.getCloudConfig(param).then(res => {
         if (res.status) {
           this.setState({
             loading: false,
diff --git a/src/views/design/sidemenu/editthdmenu/index.jsx b/src/views/design/sidemenu/editthdmenu/index.jsx
index 7b575a2..2402f75 100644
--- a/src/views/design/sidemenu/editthdmenu/index.jsx
+++ b/src/views/design/sidemenu/editthdmenu/index.jsx
@@ -1,7 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { connect } from 'react-redux'
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
 import { notification, Modal, Button } from 'antd'
@@ -21,6 +20,7 @@
 
 class EditMenu extends Component {
   static propTpyes = {
+    menuTree: PropTypes.array,   // 鑿滃崟鏍�
     menulist: PropTypes.any,     // 涓夌骇鑿滃崟鍒楄〃
     exitEdit: PropTypes.func,    // 閫�鍑虹紪杈戠姸鎬�
     supMenu: PropTypes.object,   // 瀵瑰簲鐨勪笂绾ц彍鍗�
@@ -80,7 +80,7 @@
             func: 'sPC_MainMenu_Del',
             MenuID: menu.card.MenuID
           }
-          return Api.getSystemConfig(param).then(res => {
+          return Api.getCloudConfig(param).then(res => {
             if (res.status) {
               MKEmitter.emit('mkUpdateMenuList')
             } else {
@@ -109,7 +109,7 @@
           handleMVisible: true,
           sysMenu: _menu
         })
-      } else if (['CommonTable', 'TreePage', 'CalendarPage'].includes(_menu.PageParam.Template)) {
+      } else if (['CommonTable', 'TreePage'].includes(_menu.PageParam.Template)) {
         sessionStorage.setItem('menuTree', JSON.stringify(this.props.menuTree))
         let _param = window.btoa(window.encodeURIComponent(JSON.stringify(_menu)))
 
@@ -117,7 +117,7 @@
       } else if (_menu.PageParam.Template === 'BaseTable') {
         sessionStorage.setItem('menuTree', JSON.stringify(this.props.menuTree))
         let _param = window.btoa(window.encodeURIComponent(JSON.stringify(_menu)))
-  
+
         window.open(`#/tabledesign/${_param}`)
       } else if (_menu.PageParam.Template === 'CustomPage') {
         let _param = {
@@ -155,7 +155,7 @@
         title: '纭璋冩暣鑿滃崟椤哄簭鍚楋紵',
         content: '',
         onOk() {
-          return Api.getSystemConfig(param).then(res => {
+          return Api.getCloudConfig(param).then(res => {
             if (res.status) {
               that.setState({ change: false })
               MKEmitter.emit('mkUpdateMenuList')
@@ -224,7 +224,7 @@
         confirmLoading: true
       })
 
-      Api.getSystemConfig(param).then(response => {
+      Api.getCloudConfig(param).then(response => {
         if (response.status) {
           this.setState({
             confirmLoading: false,
@@ -304,14 +304,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    menuTree: state.menuTree
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(EditMenu)
\ No newline at end of file
+export default EditMenu
\ No newline at end of file
diff --git a/src/views/design/sidemenu/index.jsx b/src/views/design/sidemenu/index.jsx
index 8729535..3e07e00 100644
--- a/src/views/design/sidemenu/index.jsx
+++ b/src/views/design/sidemenu/index.jsx
@@ -1,12 +1,10 @@
 import React, {Component} from 'react'
-import { connect } from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { Menu, Popover, Modal, notification } from 'antd'
 import { EditOutlined, PlusOutlined, SettingOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
 import asyncComponent from '@/utils/asyncComponent'
-import { resetEditLevel } from '@/store/action'
 import Utils from '@/utils/utils.js'
 import Api from '@/api'
 import MKEmitter from '@/utils/events.js'
@@ -121,7 +119,7 @@
       }
       _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
       window.open(`#/menudesign/${_param}`)
-    } else if (['CommonTable', 'TreePage', 'CalendarPage'].includes(cell.type)) {
+    } else if (['CommonTable', 'TreePage'].includes(cell.type)) {
       sessionStorage.setItem('menuTree', JSON.stringify(this.props.menuTree))
       let _param = window.btoa(window.encodeURIComponent(JSON.stringify(cell)))
 
@@ -202,7 +200,7 @@
       this.setState({
         loading: true
       })
-      Api.getSystemConfig(param).then(res => {
+      Api.getCloudConfig(param).then(res => {
         if (res.status) {
           this.setState({
             loading: false,
@@ -262,7 +260,7 @@
         loading: true
       })
 
-      Api.getSystemConfig(param).then(response => {
+      Api.getCloudConfig(param).then(response => {
         if (response.status) {
           this.setState({
             loading: false,
@@ -349,6 +347,7 @@
             menulist={this.state.editMenu.children}
             supMenuList={mainMenu.children}
             supMenu={this.state.editMenu}
+            menuTree={this.props.menuTree}
             exitEdit={this.exitEdit}
           /> : null
         }
@@ -386,18 +385,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    mainMenu: state.mainMenu,
-    menuTree: state.menuTree,
-    editLevel: state.editLevel
-  }
-}
-
-const mapDispatchToProps = (dispatch) => {
-  return {
-    resetEditLevel: (level) => dispatch(resetEditLevel(level))
-  }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(Sidemenu)
\ No newline at end of file
+export default Sidemenu
\ No newline at end of file
diff --git a/src/views/design/sidemenu/thdmenuform/index.jsx b/src/views/design/sidemenu/thdmenuform/index.jsx
index e393aa9..cb8f0da 100644
--- a/src/views/design/sidemenu/thdmenuform/index.jsx
+++ b/src/views/design/sidemenu/thdmenuform/index.jsx
@@ -1,7 +1,8 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select } from 'antd'
+import { Form, Row, Col, Input, Select, Tooltip } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
 // import './index.scss'
 
 const { TextArea } = Input
@@ -74,7 +75,7 @@
       <Form {...formItemLayout} style={{paddingRight: '20px'}}>
         <Row gutter={24}>
           <Col span={22}>
-            <Form.Item label={'涓�绾ц彍鍗�'}>
+            <Form.Item label="涓�绾ц彍鍗�">
               {getFieldDecorator('fstMenuId', {
                 initialValue: menu.fstMenuId,
                 rules: [
@@ -97,7 +98,7 @@
             </Form.Item>
           </Col>
           <Col span={22}>
-            <Form.Item label={'浜岀骇鑿滃崟'}>
+            <Form.Item label="浜岀骇鑿滃崟">
               {getFieldDecorator('ParentID', {
                 initialValue: menu.ParentId,
                 rules: [
@@ -119,7 +120,7 @@
             </Form.Item>
           </Col>
           <Col span={22}>
-            <Form.Item label={'鑿滃崟鍚嶇О'}>
+            <Form.Item label="鑿滃崟鍚嶇О">
               {getFieldDecorator('MenuName', {
                 initialValue: menu.MenuName || '',
                 rules: [
@@ -132,7 +133,7 @@
             </Form.Item>
           </Col>
           <Col span={22}>
-            <Form.Item label={'鑿滃崟鍙傛暟'}>
+            <Form.Item label="鑿滃崟鍙傛暟">
               {getFieldDecorator('MenuNo', {
                 initialValue: menu.MenuNo || '',
                 rules: [
@@ -145,7 +146,9 @@
             </Form.Item>
           </Col>
           {menu.Template === 'NewPage' ? <Col span={22}>
-            <Form.Item label={'閾炬帴鍦板潃'}>
+            <Form.Item label={
+              <Tooltip overlayStyle={{minWidth: 500}} placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>浣跨敤鍚屼竴鍗曠偣绯荤粺涓嬬殑鍏朵粬涓氬姟绯荤粺锛岄摼鎺ユ牸寮忎负锛歨ttp://<span style={{color: 'orange'}}>******</span>/admin/index.html#/iframe/<span style={{color: 'orange'}}>menuId</span>/<span style={{color: 'orange'}}>loginuid</span>/<span style={{color: 'orange'}}>BID</span>銆傛敞锛�******涓哄煙鍚�+铏氭嫙鐩綍锛沵enuId涓鸿彍鍗旾D锛沴oginuid涓虹櫥褰曚俊鎭紙浣跨敤@loginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛夛紱BID鏄悜鑿滃崟涓殑浼犲弬锛屽彲涓虹┖銆�</div>}><QuestionCircleOutlined className="mk-form-tip" />閾炬帴鍦板潃</Tooltip>
+            }>
               {getFieldDecorator('url', {
                 initialValue: menu.url || '',
                 rules: [
diff --git a/src/views/design/sidemenu/thdmenuplus/index.jsx b/src/views/design/sidemenu/thdmenuplus/index.jsx
index ad47ac4..7131595 100644
--- a/src/views/design/sidemenu/thdmenuplus/index.jsx
+++ b/src/views/design/sidemenu/thdmenuplus/index.jsx
@@ -57,7 +57,7 @@
       CustomPage: customImg
     }
 
-    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'menu'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'menu'}).then(res => {
       let _templates = []
 
       res.UserTemp.forEach(temp => {
@@ -189,7 +189,7 @@
       if ((sysMenu.Template === 'CustomPage' || sysMenu.Template === 'BaseTable') && sysMenu.copyId) {
         this.copyMenu(param, sysMenu.copyId)
       } else {
-        Api.getSystemConfig(param).then(response => {
+        Api.getCloudConfig(param).then(response => {
           if (response.status) {
             this.setState({
               loading: false,
@@ -214,7 +214,7 @@
   }
 
   copyMenu = (param, MenuId) => {
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 'sPC_Get_LongParam',
       MenuID: MenuId
     }).then(result => {
@@ -250,7 +250,7 @@
           param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
         }
 
-        Api.getSystemConfig(param).then(response => {
+        Api.getCloudConfig(param).then(response => {
           if (response.status) {
             this.setState({
               loading: false,
diff --git a/src/views/imdesign/index.jsx b/src/views/imdesign/index.jsx
index 47ab0c1..6bd3c0c 100644
--- a/src/views/imdesign/index.jsx
+++ b/src/views/imdesign/index.jsx
@@ -26,7 +26,6 @@
 const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
 const NormalForm = asyncComponent(() => import('@/components/normalform'))
 
-sessionStorage.setItem('isEditState', 'true')
 sessionStorage.setItem('appType', 'mob')       // 搴旂敤绫诲瀷
 document.body.className = ''
 window.GLOB.CacheIndependent = new Map()
@@ -98,10 +97,6 @@
   }
 
   componentDidMount () {
-    setTimeout(() => {
-      this.getAppPictures()
-    }, 1000)
-
     document.onkeydown = (event) => {
       let e = event || window.event
       let keyCode = e.keyCode || e.which || e.charCode
@@ -163,7 +158,7 @@
   }
 
   getAppMessage = (MenuID) => {
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 's_get_keyids',
       bid: sessionStorage.getItem('appId')
     }).then(res => {
@@ -184,43 +179,6 @@
       sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
       this.props.history.replace('/imdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID, type: 'view'}))))
       window.location.reload()
-    })
-  }
-
-  getAppPictures = () => {
-    if (sessionStorage.getItem('app_pictures')) return
-    
-    let deffers = []
-    let param = {
-      func: 's_url_db_adduptdel',
-      PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
-      PageSize: 0,   // 0 浠h〃鍏ㄩ儴
-      type: 'search'
-    }
-    deffers = [new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'image'}).then(res => {
-          resolve(res.data)
-        })
-      }, 500)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'video'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1000)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'color'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1500)
-    })]
-
-    Promise.all(deffers).then(response => {
-      sessionStorage.setItem('app_pictures', JSON.stringify(response[0] || []))
-      sessionStorage.setItem('app_videos', JSON.stringify(response[1] || []))
-      sessionStorage.setItem('app_colors', JSON.stringify(response[2] || []))
     })
   }
 
@@ -272,7 +230,7 @@
       MenuID: MenuId
     }
 
-    Api.getSystemConfig(param).then(result => {
+    Api.getCloudConfig(param).then(result => {
       if (!result.status) {
         notification.warning({
           top: 92,
@@ -337,7 +295,7 @@
 
     _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
 
-    Api.getSystemConfig(_param).then(res => {
+    Api.getCloudConfig(_param).then(res => {
       if (!res.status) {
         notification.warning({
           top: 92,
@@ -411,7 +369,7 @@
       param.secretkey = Utils.encrypt('', param.timestamp)
       param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
 
-      Api.getSystemConfig(param).then(res => {
+      Api.getCloudConfig(param).then(res => {
         if (!res.status) {
           notification.warning({
             top: 92,
diff --git a/src/views/interface/history/index.jsx b/src/views/interface/history/index.jsx
index c9c9143..8b92672 100644
--- a/src/views/interface/history/index.jsx
+++ b/src/views/interface/history/index.jsx
@@ -211,7 +211,7 @@
       interface: window.GLOB.baseurl + 'webapi/dostars',
       method: 'POST',
       params: [],
-      raw: "{\n \"func\":\"******\",\n \"LoginUID\":\"" + (sessionStorage.getItem('LoginUID') || "******") + "\",\n \"UserID\":\"" + (sessionStorage.getItem('UserID') || "******") + "\",\n \"nonc\":\"" + Utils.getguid() + "\",\n \"t\":" + parseInt(new Date().getTime() / 1000) + "\n}",
+      raw: "{\n \"func\":\"******\",\n \"LoginUID\":\"@loginuid@\",\n \"UserID\":\"@userid@\",\n \"nonc\":\"" + Utils.getguid() + "\",\n \"t\":" + parseInt(new Date().getTime() / 1000) + "\n}",
       id: 'dologon'
     }
     MKEmitter.emit('useInterface', m)
diff --git a/src/views/interface/workspace/request/index.jsx b/src/views/interface/workspace/request/index.jsx
index ae73278..33f2c1e 100644
--- a/src/views/interface/workspace/request/index.jsx
+++ b/src/views/interface/workspace/request/index.jsx
@@ -95,7 +95,8 @@
     } else if (config.active === 'raw') {
       if (config.raw) {
         try {
-          raws = JSON.parse(config.raw)
+          raws = config.raw.replace(/@userid@/ig, sessionStorage.getItem('UserID') || '').replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID') || '')
+          raws = JSON.parse(raws)
         } catch (e) {
           Modal.error({
             title: '鍙傛暟鏍煎紡閿欒锛屽繀椤讳负JSON鏍煎紡锛�'
@@ -281,6 +282,7 @@
                 <Radio value={'formData'}>formData</Radio>
                 <Radio value={'raw'}>raw</Radio>
               </Radio.Group>
+              {active === 'raw' ? <span style={{float: 'right', color: '#a5a5a5', fontSize: '13px'}}>娉細浣跨敤@userid@銆丂loginuid@鏃跺皢鑷姩鏇挎崲銆�</span> : null}
             </div>
             <div className={'body-content ' + (active === 'none' ? 'show' : '')}>
               <div className="no-body">This request does not have a body</div>
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index 44b5c39..bbc3c2a 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -6,7 +6,7 @@
 import Api from '@/api'
 import Utils from '@/utils/utils.js' 
 import MKEmitter from '@/utils/events.js'
-import options, { styles } from '@/store/options.js'
+import { styles } from '@/store/options.js'
 import zhCN from '@/locales/zh-CN/login.js'
 import enUS from '@/locales/en-US/login.js'
 import asyncComponent from '@/utils/asyncComponent'
@@ -99,6 +99,7 @@
           return
         }
       }
+
       localStorage.setItem('UserID', res.UserID)
       localStorage.setItem('LoginUID', res.LoginUID)
       localStorage.setItem('User_Name', res.UserName)
@@ -112,17 +113,40 @@
       localStorage.setItem('organization', res.organization || '')
       localStorage.setItem('mk_user_type', res.mk_user_type || '')
 
-      localStorage.setItem('lang', 'zh-CN')
+      sessionStorage.setItem('UserID', res.UserID)
+      sessionStorage.setItem('LoginUID', res.LoginUID)
+      sessionStorage.setItem('User_Name', res.UserName)
+      sessionStorage.setItem('Full_Name', res.FullName)
+      sessionStorage.setItem('avatar', res.icon || '')
+      sessionStorage.setItem('dataM', res.dataM ? 'true' : '')
+      sessionStorage.setItem('debug', res.debug || '')
+      sessionStorage.setItem('role_id', res.role_id || '')
+      sessionStorage.setItem('departmentcode', res.departmentcode || '')
+      sessionStorage.setItem('organization', res.organization || '')
+      sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
 
-      let _url = window.location.href.split('#')[0]
+      if (res.paas_externalDatabase) {
+        sessionStorage.setItem('externalDatabase', res.paas_externalDatabase)
+        window.GLOB.externalDatabase = `[${res.paas_externalDatabase}]..`
+      }
 
-      // 璁颁綇瀵嗙爜鏃惰处鍙峰瘑鐮佸瓨鍏ocalStorage
-      localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify({username: param.username, password: param.password}))))
+      localStorage.setItem(_href + 'lang', param.lang || 'zh-CN')
+      sessionStorage.setItem('lang', param.lang || 'zh-CN')
 
-      let _param = {
-        UserName: param.username,
-        Password: param.password,
-        BasePath: '/'
+      sessionStorage.removeItem('visitorUserID')
+      sessionStorage.removeItem('visitorLoginUID')
+      
+      let users = localStorage.getItem(_href + 'users')
+      
+      if (users) {
+        try {
+          users = JSON.parse(window.decodeURIComponent(window.atob(users)))
+        } catch (e) {
+          console.warn('Parse Failure')
+          users = []
+        }
+      } else {
+        users = []
       }
       
       // positecgroup
@@ -134,7 +158,17 @@
         })
         return
       }
-      
+
+      users = users.filter(item => item.username !== param.username)
+
+      if (users.length > 4) {
+        users.length = 4
+      }
+
+      users.unshift({username: param.username, password: param.remember ? param.password : ''})
+
+      localStorage.setItem(_href + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(users))))
+
       let level = localStorage.getItem(_href + 'pwdlevel')
 
       if (level && process.env.NODE_ENV === 'production') {
@@ -170,7 +204,12 @@
         }
       }
 
-      if (process.env.NODE_ENV === 'production') {
+      if (process.env.NODE_ENV === 'production' && param.username !== 'IF_DMS_APP') {
+        let _param = {
+          UserName: param.username,
+          Password: param.password,
+          BasePath: '/'
+        }
         Api.loginAndRedirect(_param).then(result => {
           if (result.IsError) {
             this.setState({
@@ -182,20 +221,15 @@
           }
         })
       } else {
-        sessionStorage.setItem('UserID', res.UserID)
-        sessionStorage.setItem('LoginUID', res.LoginUID)
-        sessionStorage.setItem('User_Name', res.UserName)
-        sessionStorage.setItem('Full_Name', res.FullName)
-        sessionStorage.setItem('avatar', res.icon || '')
-        sessionStorage.setItem('dataM', res.dataM ? 'true' : '')
-        sessionStorage.setItem('localDataM', res.dataM ? 'true' : '')
-        sessionStorage.setItem('debug', res.debug || '')
-        sessionStorage.setItem('role_id', res.role_id || '')
-        sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
-
-        this.props.history.replace('/main')
+        let iframe = sessionStorage.getItem('iframe')
+        if (iframe) {
+          sessionStorage.removeItem('iframe')
+          this.props.history.replace(iframe.replace(/@loginuid@/, res.LoginUID))
+        } else {
+          this.props.history.replace('/main')
+        }
       }
-    } else if (res.ErrCode === 'Need_Get_Appkey' && options.sysType === 'SSO') {
+    } else if (res.ErrCode === 'Need_Get_Appkey' && window.GLOB.sysType === 'SSO') {
       message.warning('搴旂敤灏氭湭鍒涘缓锛岃鍚戜簯绔悓姝ュ簲鐢紒')
 
       this.setState({
@@ -210,7 +244,8 @@
           input.select()
         }
       } else if (res.message.indexOf('鐧诲綍鏉冮檺') > -1) {
-        const input = document.getElementById('username')
+        const wrap = document.getElementById('username')
+        const input = wrap ? wrap.getElementsByTagName('input')[0] : null
         if (input) {
           input.select()
         }
@@ -248,8 +283,14 @@
       sessionStorage.removeItem('visitorUserID')
       sessionStorage.removeItem('visitorLoginUID')
 
-      this.props.history.replace('/main')
-    } else if (res.ErrCode === 'Need_Get_Appkey' && options.sysType === 'SSO') {
+      let iframe = sessionStorage.getItem('iframe')
+      if (iframe) {
+        sessionStorage.removeItem('iframe')
+        this.props.history.replace(iframe.replace(/@loginuid@/, res.LoginUID))
+      } else {
+        this.props.history.replace('/main')
+      }
+    } else if (res.ErrCode === 'Need_Get_Appkey' && window.GLOB.sysType === 'SSO') {
       message.warning('搴旂敤灏氭湭鍒涘缓锛岃鍚戜簯绔悓姝ュ簲鐢紒')
 
       this.setState({
@@ -287,8 +328,14 @@
         sessionStorage.removeItem('visitorUserID')
         sessionStorage.removeItem('visitorLoginUID')
   
-        this.props.history.replace('/main')
-      } else if (res.ErrCode === 'Need_Get_Appkey' && options.sysType === 'SSO') {
+        let iframe = sessionStorage.getItem('iframe')
+        if (iframe) {
+          sessionStorage.removeItem('iframe')
+          this.props.history.replace(iframe.replace(/@loginuid@/, res.LoginUID))
+        } else {
+          this.props.history.replace('/main')
+        }
+      } else if (res.ErrCode === 'Need_Get_Appkey' && window.GLOB.sysType === 'SSO') {
         message.warning('搴旂敤灏氭湭鍒涘缓锛岃鍚戜簯绔悓姝ュ簲鐢紒')
   
         this.setState({
@@ -320,7 +367,7 @@
         document.getElementsByTagName('head')[0].removeChild(JSONP)
       },500)
     })
-}
+  }
 
   componentDidMount () {
     // md5("/ws/location/v1/ip?callback=callbackFunction&key=key&output=jsonp secret key")
@@ -336,27 +383,6 @@
       if (view) {
         view.style.filter = 'grayscale(100%)'
       }
-    }
-
-    if (sessionStorage.getItem('loginError')) {
-      try {
-        let res = JSON.parse(sessionStorage.getItem('loginError'))
-        console.info(res.url)
-        console.info(res.request)
-        console.info(res.response)
-
-        let result = JSON.parse(res.response)
-
-        notification.warning({
-          top: 92,
-          message: result.message,
-          duration: 5
-        })
-      } catch (e) {}
-      
-      setTimeout(() => {
-        sessionStorage.removeItem('loginError')
-      }, 2000)
     }
 
     const _addressUrl = _href + 'queryAddress'
@@ -453,22 +479,17 @@
     }
 
     if (!window.GLOB.licenseKey && (index === -1 || index > 5)) {
-      let _appId = window.GLOB.appId
-  
-      if (options.sysType === 'cloud') { // 浜戠浣跨敤绯荤粺閰嶇疆appid
-        _appId = options.caId
-      }
-  
-      let str = md5('MK19' + _appId + timeStamp)
+      let str = md5('MK19' + window.GLOB.appId + timeStamp)
       let _rduri = window.atob('aHR0cHM6Ly9lcGMubWs5aC5$mkjbi93ZWJhcGkvZG9zdGFycw=='.replace(/\$mk/ig, ''))
       let _func = window.atob('c0VtcG93ZXJDbG91$mkZF9HZXRfTGlua1VybA=='.replace(/\$mk/ig, ''))
       let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
   
       let param = {
         func: _func,
-        AppID: _appId,
+        AppID: window.GLOB.appId,
         TimeStamp: timeStamp,
         appkey: window.GLOB.appkey,
+        SessionUid: localStorage.getItem('SessionUid') || '',
         userid: _id,
         LoginUID: _id,
         nonc: Utils.getuuid()
@@ -536,7 +557,30 @@
             authError: res.message
           })
         }
-      }, () => {
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') {
+          let param = {
+            func: 's_visitor_login',
+            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), 
+            SessionUid: _id,
+            TypeCharOne: 'pc',
+            appkey: '202004041613277377A6A2456D34A4948AE84'
+          }
+
+          param.LText = md5(window.btoa(_id + param.timestamp))
+          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
+
+          let params = {
+            url: _rduri.replace('dostars', 'dologon'),
+            method: 'post',
+            data: JSON.stringify(param)
+          }
+
+          Api.directRequest(params)
+
+          return
+        }
+
         if (index === -1 || index > 10) {
           this.setState({
             auth: false,
@@ -583,12 +627,29 @@
         _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
 
         Api.getSystemConfig(_param).then(res => {
+          if (!res) return
+          
           if (res.status) {
             // positecgroup
-            res.Banner = res.Banner ? res.Banner.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
-            res.doclogo = res.doclogo ? res.doclogo.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
-            res.indexlogo = res.indexlogo ? res.indexlogo.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
-            res.loginlogo = res.loginlogo ? res.loginlogo.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
+            // if (window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
+            //   if (md5(('mk' + window.GLOB.appkey + res.sys_datetime + res.member_type + res.registry_date).toLowerCase()) !== res.secret_key) {
+            //     Modal.warning({
+            //       title: '瀵嗛挜閿欒锛岃鑱旂郴绠$悊鍛橈紒',
+            //       okText: '鐭ラ亾浜�'
+            //     })
+            //     this.setState({
+            //       auth: false,
+            //       authError: '瀵嗛挜閿欒锛岃鑱旂郴绠$悊鍛橈紒'
+            //     })
+            //     return
+            //   } else if (res.member_type === 'personal' && res.registry_date) {
+            //     let saveDelay = 0
+            //     try {
+            //       saveDelay = parseInt((new Date().getTime() - new Date(res.registry_date).getTime()) / 4320000)
+            //       sessionStorage.setItem('mkDelay', saveDelay)
+            //     } catch(e) {}
+            //   }
+            // }
 
             if (!['shutter', 'linkage_navigation', 'linkage', 'menu_board', 'menu_board_navigation'].includes(res.menu_type)) {
               res.menu_type = 'shutter'
@@ -701,7 +762,7 @@
 
             let memberLevel = res.member_level
 
-            if (typeof(memberLevel) === 'number' && memberLevel > 10 && parseInt(memberLevel / 10) * 10 === memberLevel) {
+            if (typeof(memberLevel) === 'number' && memberLevel > 0 && parseInt(memberLevel / 10) * 10 === memberLevel) {
               sessionStorage.setItem('Member_Level', md5('mksoft' + window.GLOB.appkey + new Date().getFullYear() + new Date().getMonth() + memberLevel))
               window.GLOB.memberLevel = memberLevel
             }
@@ -787,15 +848,15 @@
       func: 's_get_app_from_cloud',
       UserName: '',
       Password: '',
-      systemType: options.sysType,
+      systemType: window.GLOB.sysType,
       Type: 'X',
       debug: 'Y'
     }
 
     param.appkey = window.GLOB.appkey || ''
 
-    if (options.cloudServiceApi) {
-      param.rduri = options.cloudServiceApi.replace('dostars', 'dostar')
+    if (window.GLOB.cloudServiceApi) {
+      param.rduri = window.GLOB.cloudServiceApi.replace('dostars', 'dostar')
     }
 
     this.logincloudRef.handleConfirm().then(result => {
@@ -914,7 +975,6 @@
         </div>
         <div className="login-middle" style={bgImage ? {backgroundImage: 'url(' + bgImage + ')'} : null}>
           {loginWays ? <LoginForm
-            platName={this.state.platName}
             dict={this.state.dict}
             auth={this.state.auth}
             authError={this.state.authError}
diff --git a/src/views/login/index.scss b/src/views/login/index.scss
index 10f9671..60e1213 100644
--- a/src/views/login/index.scss
+++ b/src/views/login/index.scss
@@ -298,6 +298,19 @@
     }
   }
 }
+.mk-user-option {
+  .anticon-close-circle {
+    float: right;
+    opacity: 0;
+    transition: opacity 0.3s;
+    padding: 3px;
+  }
+}
+.mk-user-option:hover {
+  .anticon-close-circle {
+    opacity: 1;
+  }
+}
 .sync-cloud-application {
   .ant-modal-body {
     min-height: 176px;
diff --git a/src/views/login/logincloudform.jsx b/src/views/login/logincloudform.jsx
index c87cf3f..374ef07 100644
--- a/src/views/login/logincloudform.jsx
+++ b/src/views/login/logincloudform.jsx
@@ -20,8 +20,8 @@
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
-          values.cloudusername = values.cloudusername.replace(/\t*|\v*|\s*/g, '')
-          values.cloudpassword = values.cloudpassword.replace(/\t*|\v*|\s*/g, '')
+          values.cloudusername = values.cloudusername.replace(/\t+|\v+|\s+/g, '')
+          values.cloudpassword = values.cloudpassword.replace(/\t+|\v+|\s+/g, '')
           resolve(values)
         } else {
           reject(err)
diff --git a/src/views/login/loginform.jsx b/src/views/login/loginform.jsx
index cb74ecf..dbbcaa3 100644
--- a/src/views/login/loginform.jsx
+++ b/src/views/login/loginform.jsx
@@ -1,13 +1,11 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Form, Icon, Input, Button, Modal, message } from 'antd'
-import { UserOutlined } from '@ant-design/icons'
+import { Form, Input, Button, Checkbox, Select, Modal, message, AutoComplete } from 'antd'
+import { UserOutlined, LockOutlined, CloseCircleOutlined } from '@ant-design/icons'
 import md5 from 'md5'
 import moment from 'moment'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import './index.scss'
 
 const { warning } = Modal
@@ -23,23 +21,23 @@
     touristLogin: PropTypes.bool,
     lang: PropTypes.string,
     langList: PropTypes.array,
-    loginWays: PropTypes.array,
-    platName: PropTypes.string
+    loginWays: PropTypes.array
   }
 
   state = {
-    activeKey: 'uname_pwd',
     username: '',
     password: '',
     remember: true,
     delay: null,
     loginWays: [],
     smsId: '',
-    verdisabled: false
+    verdisabled: false,
+    hasScan: false,
+    timeout: false,
+    users: []
   }
 
   UNSAFE_componentWillMount () {
-    const { loginWays } = this.props
     let remember = true
     let _url = window.location.href.split('#')[0]
     
@@ -52,58 +50,43 @@
 
     let smsId = ''
     let _loginWays = []
-    loginWays.forEach(item => {
-      if (item.type === 'sms_vcode') {
-        smsId = item.smsId
-        _loginWays.push(item)
-      } else if (item.type === 'uname_pwd') {
-        _loginWays.push(item)
+
+    let users = localStorage.getItem(_url + 'users')
+    let _user = null
+    
+    if (users) {
+      try {
+        users = JSON.parse(window.decodeURIComponent(window.atob(users)))
+      } catch (e) {
+        users = []
       }
-    })
+    } else {
+      users = []
+    }
+
+    if (users[0]) {
+      _user = users[0]
+    }
 
     this.setState({
+      users: users,
+      username: _user ? _user.username : '',
+      password: _user ? _user.password : '',
       smsId: smsId,
       loginWays: _loginWays,
-      activeKey: _loginWays[0].type,
       remember
     })
   }
 
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (!is(fromJS(this.props.loginWays), fromJS(nextProps.loginWays))) {
-      let smsId = ''
-      let _loginWays = []
-      nextProps.loginWays.forEach(item => {
-        if (item.type === 'sms_vcode') {
-          smsId = item.smsId
-          _loginWays.push(item)
-        } else if (item.type === 'uname_pwd') {
-          _loginWays.push(item)
-        }
-      })
-
-      this.setState({
-        smsId: smsId,
-        loginWays: _loginWays,
-        activeKey: _loginWays[0].type
-      })
-    }
-  }
-
   handleConfirm = () => {
-    const { activeKey } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
-          if (activeKey === 'uname_pwd') {
-            values.username = values.username.replace(/\t*|\v*|\s*/g, '')
-            values.password = values.password.replace(/\t*|\v*|\s*/g, '')
-          } else if (activeKey === 'sms_vcode') {
-            values.phone = values.phone.replace(/\t*|\v*|\s*/g, '')
-            values.vercode = values.vercode.replace(/\t*|\v*|\s*/g, '')
-          }
-          resolve({type: activeKey, ...values})
+          values.username = values.username.replace(/\t+|\v+|\s+/g, '')
+          values.password = values.password.replace(/\t+|\v+|\s+/g, '')
+
+          resolve({type: 'uname_pwd', ...values})
         } else {
           reject(err)
         }
@@ -116,9 +99,8 @@
   }
 
   handleSubmit = e => {
-    const { activeKey } = this.state
     // 鐧诲綍鍙傛暟妫�楠�
-    e.preventDefault()
+    e && e.preventDefault()
     if (!this.props.auth) {
       warning({
         title: this.props.dict['login.auth.tip'],
@@ -130,70 +112,28 @@
       return
     }
 
-    if (activeKey === 'uname_pwd') {
-      if (!this.props.form.getFieldValue('username')) {
-        const input = document.getElementById('username')
-        if (input) {
-          input.focus()
-        }
-      } else if (!this.props.form.getFieldValue('password')) {
-        const input = document.getElementById('password')
-        if (input) {
-          input.focus()
-        }
-      } else {
-        this.props.handleSubmit()
+    if (!this.props.form.getFieldValue('username')) {
+      const wrap = document.getElementById('username')
+      const input = wrap ? wrap.getElementsByTagName('input')[0] : null
+      if (input) {
+        input.focus()
       }
-    } else if (activeKey === 'sms_vcode') {
-      if (!this.props.form.getFieldValue('phone')) {
-        const input = document.getElementById('phone')
-        if (input) {
-          input.focus()
-        }
-      } else if (!this.props.form.getFieldValue('vercode')) {
-        const input = document.getElementById('vercode')
-        if (input) {
-          input.focus()
-        }
-      } else {
-        this.props.handleSubmit()
+    } else if (!this.props.form.getFieldValue('password')) {
+      const input = document.getElementById('password')
+      if (input) {
+        input.focus()
       }
+    } else {
+      this.props.handleSubmit()
     }
   }
 
   componentDidMount () {
-    let _url = window.location.href.split('#')[0]
-    let _user = localStorage.getItem(_url)
-    
-    if (_user) {
-      try {
-        _user = JSON.parse(window.decodeURIComponent(window.atob(_user)))
-      } catch {
-        console.warn('Parse Failure')
-        _user = ''
-      }
+    const wrap = document.getElementById('username')
+    const input = wrap ? wrap.getElementsByTagName('input')[0] : null
+    if (input) {
+      input.focus()
     }
-
-    if (_user) {
-      this.setState({
-        username: _user.username,
-        password: _user.password
-      }, () => {
-        const input = document.getElementById('username')
-        if (input) {
-          input.focus()
-        }
-      })
-    } else {
-      const input = document.getElementById('username')
-      if (input) {
-        input.focus()
-      }
-    }
-  }
-
-  onChangeTab = (activeKey) => {
-    this.setState({activeKey})
   }
 
   getvercode = () => {
@@ -264,7 +204,30 @@
           })
           message.warning(res.message)
         }
-      }, () => {
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') {
+          let param = {
+            func: 's_visitor_login',
+            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), 
+            SessionUid: 'bh0bapabtd45epsgra79segbch6c1ibk',
+            TypeCharOne: 'pc',
+            appkey: '202004041613277377A6A2456D34A4948AE84'
+          }
+          
+          param.LText = md5(window.btoa('bh0bapabtd45epsgra79segbch6c1ibk' + param.timestamp))
+          param.secretkey = md5(param.LText + 'mingke' + param.timestamp)
+  
+          let params = {
+            url: 'https://sso.mk9h.cn/webapi/dologon',
+            method: 'post',
+            data: JSON.stringify(param)
+          }
+
+          Api.directRequest(params)
+
+          return
+        }
+
         if (LoginVerCodeTimer) {
           clearTimeout(LoginVerCodeTimer)
         }
@@ -296,6 +259,36 @@
     localStorage.setItem(_url + 'remember', val)
   }
 
+  complete = (val) => {
+    const { users } = this.state
+
+    let user = users.filter(m => m.username === val)[0]
+    let password = user && user.password ? user.password : ''
+
+    this.props.form.setFieldsValue({password: password})
+
+    if (!password) {
+      const input = document.getElementById('password')
+      if (input) {
+        input.focus()
+      }
+    }
+  }
+
+  deleteUser = (e, val) => {
+    const { users } = this.state
+
+    e.stopPropagation()
+
+    let _users = users.filter(m => m.username !== val)
+    
+    this.setState({users: _users})
+
+    let _url = window.location.href.split('#')[0]
+
+    localStorage.setItem(_url + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(_users))))
+  }
+
   /**
    * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
    */
@@ -306,26 +299,40 @@
   }
 
   render() {
+    const { langList } = this.props
     const { getFieldDecorator } = this.props.form
-    const { activeKey, verdisabled, delay, loginWays } = this.state
+    const { remember, users } = this.state
 
     return (
-      <Form className={`login-form login-form-${loginWays.length}`} id="login-form" onSubmit={this.handleSubmit}>
+      <Form className={`login-form login-form-1`} id="login-form" onSubmit={this.handleSubmit}>
         <p className="title">{this.props.platName}</p>
         <div className="form-item-wrap">
-          {activeKey === 'uname_pwd' ? <Form.Item>
+          <Form.Item>
             {getFieldDecorator('username', {
               rules: [{ required: true, message: this.props.dict['login.username.empty'] }],
               initialValue: this.state.username || '',
             })(
-              <Input
-                prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
-                placeholder={this.props.dict['login.username']}
-                autoComplete="off"
-              />,
+              <AutoComplete
+                className
+                dataSource={users.map((cell, i) => <AutoComplete.Option className="mk-user-option" value={cell.username} key={i}>
+                  {cell.username}
+                  <CloseCircleOutlined onClick={(e) => this.deleteUser(e, cell.username)}/>
+                </AutoComplete.Option>)}
+                filterOption={false}
+                onSelect={this.complete}
+                defaultActiveFirstOption={false}
+                defaultOpen={false}
+                optionLabelProp="value"
+              >
+                <Input
+                  prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
+                  placeholder={this.props.dict['login.username']}
+                  autoComplete="off"
+                />
+              </AutoComplete>
             )}
-          </Form.Item> : null}
-          {activeKey === 'uname_pwd' ? <Form.Item>
+          </Form.Item>
+          <Form.Item>
             {getFieldDecorator('password', {
               initialValue: this.state.password || '',
               rules: [
@@ -334,55 +341,33 @@
                   message: this.props.dict['login.password.empty'],
                 }
               ]
-            })(<Input.Password placeholder={this.props.dict['login.password']} prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
-          </Form.Item> : null}
-          {activeKey === 'sms_vcode' ? <Form.Item>
-            {getFieldDecorator('phone', {
-              rules: [{ required: true, message: this.props.dict['login.phone.empty'] }],
-              initialValue: '',
-            })(
-              <Input
-                placeholder={this.props.dict['login.phone']}
-                autoComplete="off"
-              />
-            )}
-          </Form.Item> : null}
-          {activeKey === 'sms_vcode' ? <Form.Item className="vercode">
-            {getFieldDecorator('vercode', {
-              initialValue: '',
-              rules: [
-                {
-                  required: true,
-                  message: this.props.dict['login.vercode.empty'],
-                }
-              ]
-            })(
-              <Input
-                addonAfter={
-                  <Button type="link" className="vercode" size="small" disabled={verdisabled} onClick={this.getvercode}>
-                    {delay ? `${delay}s鍚庨噸鏂拌幏鍙朻 : '鑾峰彇楠岃瘉鐮�'}
-                  </Button>
-                }
-                placeholder={this.props.dict['login.vercode']}
-                autoComplete="off"
-              />
-            )}
-          </Form.Item> : null}
-          {/* {activeKey === 'uname_pwd' ? <Form.Item className="minline">
+            })(<Input.Password placeholder={this.props.dict['login.password']} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
+          </Form.Item>
+          {window.GLOB.keepKey ? <Form.Item className="minline">
             {getFieldDecorator('remember', {
               valuePropName: 'checked',
               initialValue: remember,
             })(<Checkbox onChange={this.rememberChange}>{this.props.dict['login.remember']}</Checkbox>)}
-          </Form.Item> : null} */}
-          {['uname_pwd', 'sms_vcode'].includes(activeKey) ? <Form.Item className="btn-login">
+          </Form.Item> : <div style={{height: '30px', float: 'left'}}></div>}
+          {langList && langList.length > 0 ? <Form.Item className="minline right">
+            {getFieldDecorator('lang', {
+              initialValue: this.props.lang,
+            })(
+              <Select
+                onChange={(value) => {this.changelang(value)}}
+                getPopupContainer={() => document.getElementById('login-form')}
+              >
+                {langList.map((item, index) => {
+                  return <Select.Option key={index} value={item.Lang}>{item.LangName}</Select.Option>
+                })}
+              </Select>
+            )}
+          </Form.Item> : null}
+          <Form.Item className="btn-login">
             <Button type="primary" htmlType="submit" className="login-form-button" disabled={this.props.isDisabled} loading={this.props.isDisabled}>
               {this.props.dict['login.submit']}
             </Button>
-          </Form.Item> : null}
-          {options.sysType === 'cloud' && options.cdomain.indexOf('mk9h') > -1 ? <Form.Item className="register-line">
-            <a href="http://minkesoft.com/#/signup" target="_blank" rel="noopener noreferrer" className="register">娉ㄥ唽</a>
-            <a href="http://minkesoft.com/#/forgotPwd" target="_blank" rel="noopener noreferrer" className="forgot">蹇樿瀵嗙爜锛�</a>
-          </Form.Item> : null}
+          </Form.Item>
         </div>
       </Form>
     )
diff --git a/src/views/main/index.jsx b/src/views/main/index.jsx
index 3fa342e..8f64b52 100644
--- a/src/views/main/index.jsx
+++ b/src/views/main/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import { ConfigProvider } from 'antd'
-import enUS from 'antd/es/locale/en_US'
+// import enUS from 'antd/es/locale/en_US'
 import zhCN from 'antd/es/locale/zh_CN'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -14,7 +14,6 @@
 
 const Tabview = asyncComponent(() => import('@/components/tabview'))
 const Breadview = asyncComponent(() => import('@/components/breadview'))
-const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 
 class Main extends Component {
   state = {
@@ -30,22 +29,36 @@
   componentDidMount () {
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
 
-    Object.defineProperty(window, 'debug', {
-      configurable: true,
-      enumerable: true,
-      set(value) {
-        if (value + '' === 'false') {
-          window.debugger = false
-          window.GLOB.breakpoint = false
-          sessionStorage.removeItem('breakpoint')
-        } else {
-          window.debugger = true
-          window.GLOB.breakpoint = value + ''
-          sessionStorage.setItem('breakpoint', value)
+    if (window.GLOB.sysType !== 'cloud') {
+      Object.defineProperty(window, 'debugger', {
+        configurable: true,
+        enumerable: true,
+        set(value) {
+          if (value + '' === 'false') {
+            window.GLOB.debugger = false
+          } else {
+            window.GLOB.debugger = true
+          }
         }
-        MKEmitter.emit('debugChange')
-      }
-    })
+      })
+
+      Object.defineProperty(window, 'debug', {
+        configurable: true,
+        enumerable: true,
+        set(value) {
+          if (value + '' === 'false') {
+            window.GLOB.debugger = false
+            window.GLOB.breakpoint = false
+            sessionStorage.removeItem('breakpoint')
+          } else {
+            window.GLOB.debugger = true
+            window.GLOB.breakpoint = value + ''
+            sessionStorage.setItem('breakpoint', value)
+          }
+          MKEmitter.emit('debugChange')
+        }
+      })
+    }
   }
 
   componentWillUnmount () {
@@ -63,7 +76,7 @@
 
     return (
       <div className="mk-main-view">
-        <ConfigProvider locale={_locale}>
+        <ConfigProvider locale={zhCN}>
           <Header key="header"/>
           {navBar === 'shutter' ? <Sidemenu key="sidemenu"/> : null}
           {navBar === 'shutter' || navBar === 'menu_board_navigation' ?
diff --git a/src/views/menudesign/homeform/index.jsx b/src/views/menudesign/homeform/index.jsx
index 4454c32..427ff91 100644
--- a/src/views/menudesign/homeform/index.jsx
+++ b/src/views/menudesign/homeform/index.jsx
@@ -4,7 +4,6 @@
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 // import './index.scss'
 
 class CustomMenuForm extends Component {
@@ -24,7 +23,7 @@
   }
 
   getMenus = () => {
-    Api.getSystemConfig({func: 's_get_pc_menus', systemType: options.sysType, debug: 'Y'}).then(result => {
+    Api.getCloudConfig({func: 's_get_pc_menus', systemType: window.GLOB.sysType, debug: 'Y'}).then(result => {
       if (result.status) {
         let thdMenuList = []
         let menulist = result.fst_menu.map(fst => {
@@ -99,20 +98,13 @@
   selectChange = (key, value) => {
     const { config } = this.props
 
-    if (key === 'cacheUseful') {
-      this.props.updateConfig({...config, cacheUseful: value})
-    } else if (key === 'timeUnit') {
-      this.props.updateConfig({...config, timeUnit: value})
-    } else if (key === 'cacheLocal') {
-      this.props.updateConfig({...config, cacheLocal: value})
+    if (key === 'cacheTime' || key === 'localCacheTime') {
+      if (typeof(value) !== 'number') {
+        value = ''
+      }
     }
-  }
-
-  changeCacheDay = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
-    }
-    this.props.updateConfig({...this.props.config, cacheTime: val})
+    
+    this.props.updateConfig({...config, [key]: value})
   }
 
   render() {
@@ -149,6 +141,20 @@
               )}
             </Form.Item>
           </Col>
+          {config.cacheLocal === 'true' ? <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="璁剧疆鏈湴缂撳瓨鏃堕暱鍚庯紝鍦ㄧ紦瀛樻湡闄愬唴涓嶅悜鍚庡彴璇锋眰鏁版嵁锛屾椂闀挎渶澶т负5澶╋紙鍗�7200鍒嗛挓锛夈�傛敞锛氭椂闀夸负绌烘椂缂撳瓨鏁版嵁鍙敤浜庨〉闈㈠揩閫熷憟鐜帮紝涓嶅奖鍝嶆帴鍙h姹傘��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏃堕暱(鍒�)
+              </Tooltip>
+            }>
+              {getFieldDecorator('localCacheTime', {
+                initialValue: config.localCacheTime
+              })(
+                <InputNumber min={1} max={7200} precision={0} onChange={(val) => {this.selectChange('localCacheTime', val)}}/>
+              )}
+            </Form.Item>
+          </Col> : null}
           <Col span={24}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="瀵逛簬涓嶇粡甯告�у彉鍔ㄧ殑淇℃伅锛岀紦瀛樻暟鎹湁鍔╀簬鎻愰珮鏌ヨ鏁堢巼銆�">
@@ -190,10 +196,27 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={(val) => {this.selectChange('cacheTime', val)}}/>
               )}
             </Form.Item>
           </Col> : null}
+          <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鏁版嵁鍔犺浇鏃剁殑閬僵鏄惁鏄剧ず銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍔犺浇閬僵
+              </Tooltip>
+            }>
+              {getFieldDecorator('mask', {
+                initialValue: config.mask || 'true'
+              })(
+                <Radio.Group onChange={(e) => {this.selectChange('mask', e.target.value)}}>
+                  <Radio value="true">鏄剧ず</Radio>
+                  <Radio value="false">闅愯棌</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
         </Row>
       </Form>
     )
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index fdf22ba..0a95623 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -10,7 +10,6 @@
 import md5 from 'md5'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import Utils, { setGLOBFuncs } from '@/utils/utils.js'
 import antdZhCN from 'antd/es/locale/zh_CN'
 import MKEmitter from '@/utils/events.js'
@@ -48,7 +47,6 @@
 const StyleCombControlButton = asyncComponent(() => import('@/menu/stylecombcontrolbutton'))
 const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
 
-sessionStorage.setItem('isEditState', 'true')
 sessionStorage.setItem('appType', '')          // 搴旂敤绫诲瀷
 document.body.className = ''
 
@@ -63,7 +61,6 @@
     menuloading: false,
     oriConfig: null,
     config: null,
-    customComponents: [],
     comloading: false,
     settingshow: sessionStorage.getItem('settingshow') !== 'false',
     eyeopen: false,
@@ -81,7 +78,6 @@
     }
     
     if (!sessionStorage.getItem('UserID')) {
-      sessionStorage.removeItem('isEditState')
       sessionStorage.removeItem('appType')
       this.props.history.replace('/login')
       return
@@ -126,18 +122,7 @@
     
     MKEmitter.addListener('changePopview', this.initPopview)
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
-    MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent)
     setTimeout(() => {
-      if (sessionStorage.getItem('app_custom_components')) {
-        let list = sessionStorage.getItem('app_custom_components')
-        list = JSON.parse(list)
-
-        this.setCustomComponent(list)
-      } else {
-        this.updateCustomComponent()
-      }
-      this.getAppPictures()
-      this.getPrintTemp()
       this.getRoleFields()
       setGLOBFuncs()
     }, 1000)
@@ -208,7 +193,6 @@
     }
     MKEmitter.removeListener('changePopview', this.initPopview)
     MKEmitter.removeListener('triggerMenuSave', this.triggerMenuSave)
-    MKEmitter.removeListener('updateCustomComponent', this.updateCustomComponent)
   }
 
   triggerMenuSave = () => {
@@ -238,135 +222,6 @@
     window.GLOB.customMenu = config
 
     this.setState({view: '', popConfig: null})
-  }
-
-  getPrintTemp = () => {
-    if (!sessionStorage.getItem('printTemps')) {
-      let _sql = `select ID,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate 
-      where appkey= @appkey@ and Deleted=0 and typechartwo='web_print'
-      union select ID,Images,a.PrintTempNO+PrintTempName as PN 
-      from (select * from sPrintTemplate where appkey= '' and Deleted=0 and typechartwo='web_print') a 
-      left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@ and Deleted=0 ) b 
-      on a.PrintTempNO=b.PrintTempNO 
-      left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c 
-      on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null`
-  
-      let param = {
-        func: 'sPC_Get_SelectedList',
-        LText: Utils.formatOptions(_sql),
-        obj_name: 'data',
-        arr_field: 'PN,ID,Images'
-      }
-  
-      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-  
-      param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
-  
-      Api.getSystemConfig(param).then(res => {
-        if (res.status) {
-          let temps = res.data.map(temp => {
-            return {
-              value: temp.ID,
-              text: temp.PN
-            }
-          })
-  
-          sessionStorage.setItem('printTemps', JSON.stringify(temps))
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-        }
-      })
-    }
-  }
-
-  getAppPictures = () => {
-    if (sessionStorage.getItem('app_pictures')) return
-    
-    let deffers = []
-    let param = {
-      func: 's_url_db_adduptdel',
-      PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
-      PageSize: 0,   // 0 浠h〃鍏ㄩ儴
-      type: 'search'
-    }
-    deffers = [new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'image'}).then(res => {
-          resolve(res.data)
-        })
-      }, 500)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'video'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1000)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'color'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1500)
-    })]
-
-    Promise.all(deffers).then(response => {
-      sessionStorage.setItem('app_pictures', JSON.stringify(response[0] || []))
-      sessionStorage.setItem('app_videos', JSON.stringify(response[1] || []))
-      sessionStorage.setItem('app_colors', JSON.stringify(response[2] || []))
-    })
-  }
-
-  updateCustomComponent = () => {
-    Api.getSystemConfig({
-      func: 's_get_custom_components',
-      typename: '',
-      typecharone: ''
-    }).then(res => {
-      if (!res.status) {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      } else if (res.cus_list) {
-        sessionStorage.setItem('app_custom_components', JSON.stringify(res.cus_list))
-        this.setCustomComponent(res.cus_list)
-      }
-    })
-  }
-
-  setCustomComponent = (cus_list) => {
-    let coms = []
-
-    cus_list.forEach(item => {
-      let config = ''
-
-      try {
-        config = JSON.parse(window.decodeURIComponent(window.atob(item.long_param)))
-      } catch (e) {
-        console.warn('Parse Failure')
-        config = ''
-      }
-
-      if (!config || !item.c_name) return
-
-      window.GLOB.UserComponentMap.set(item.c_id, item.c_name)
-      coms.push({
-        uuid: item.c_id,
-        type: 'menu',
-        title: item.c_name,
-        url: item.images,
-        component: config.type,
-        subtype: config.subtype,
-        config
-      })
-    })
-    this.setState({customComponents: coms})
   }
 
   initPopview = (card, btn) => {
@@ -438,7 +293,7 @@
       MenuID: MenuId
     }
 
-    Api.getSystemConfig(param).then(result => {
+    Api.getCloudConfig(param).then(result => {
       if (result.status) {
         let config = null
 
@@ -651,6 +506,8 @@
         comloading: false,
         needUpdate: true
       })
+
+      window.GLOB.customMenu = config
       return
     }
 
@@ -662,7 +519,7 @@
         }
     
         setTimeout(() => {
-          Api.getSystemConfig(param).then(res => {
+          Api.getCloudConfig(param).then(res => {
             let _config = null
             try {
               _config = res.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(res.LongParam))) : null
@@ -729,6 +586,8 @@
       config.components = this.setPopView(config.components, parents, popbtns)
 
       this.setState({ delButtons: bts, config, comloading: false })
+
+      window.GLOB.customMenu = config
     })
   }
 
@@ -816,7 +675,7 @@
   checkBase = () => {
     const { MenuType, config } = this.state
 
-    if (MenuType === 'billPrint' && config.printPage === 'page' && !config.everyPCount) {
+    if (MenuType === 'billPrint' && ((config.printPage === 'page' && !config.everyPCount) || (config.callback === 'true' && !config.callNo))) {
       return false
     } else if (MenuType === 'home' && (config.cacheUseful === 'true' && !config.cacheTime)) {
       return false
@@ -963,15 +822,15 @@
               Base64Img: canvas.toDataURL('image/png') // 鑾峰彇鐢熸垚鐨勫浘鐗�
             }
   
-            if (options.cloudServiceApi) {
-              param.rduri = options.cloudServiceApi
+            if (window.GLOB.cloudServiceApi) {
+              param.rduri = window.GLOB.cloudServiceApi
               param.userid = sessionStorage.getItem('CloudUserID') || ''
               param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
             }
   
             Api.fileuploadbase64(param).then(result => {
               if (result.status) {
-                Api.getSystemConfig({
+                Api.getCloudConfig({
                   func: 's_PrintTemplateMSub',
                   ID: config.uuid,
                   Images: Utils.getcloudurl(result.Images),
@@ -991,7 +850,7 @@
       }).then(res => { // 椤甸潰淇濆瓨
         if (!res || !res.status) return res
 
-        return Api.getSystemConfig(param)
+        return Api.getCloudConfig(param)
       }).then(res => { // 鎸夐挳鍒犻櫎
         if (!res || !res.status) return res
 
@@ -1014,7 +873,7 @@
             func: 'sPC_MainMenu_Del',
             MenuID: this.state.delButtons.join(',')
           }
-          return Api.getSystemConfig(_param)
+          return Api.getCloudConfig(_param)
         }
       }, this.netError).then(res => { // 椤甸潰鎸夐挳鍏崇郴淇濆瓨
         if (!res || !res.status) return res
@@ -1024,7 +883,7 @@
         })
 
         if (MenuType !== 'billPrint') {
-          return Api.getSystemConfig(btnParam)
+          return Api.getCloudConfig(btnParam)
         } else {
           return {
             status: true
@@ -1043,7 +902,6 @@
             message: '淇濆瓨鎴愬姛',
             duration: 2
           })
-          MKEmitter.emit('completeSave')
         } else {
           notification.warning({
             top: 92,
@@ -1051,6 +909,7 @@
             duration: 5
           })
         }
+        MKEmitter.emit('completeSave')
       }, this.netError)
     }, 300 + (+sessionStorage.getItem('mkDelay')))
   }
@@ -1067,12 +926,13 @@
         duration: 5
       })
     }
+    MKEmitter.emit('completeSave')
   }
 
   getRoleFields = () => {
     if (sessionStorage.getItem('sysRoles')) return
 
-    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
       if (res.status) {
         let _permFuncField = []
         let _sysRoles = []
@@ -1240,7 +1100,7 @@
   }
 
   render () {
-    const { view, comloading, MenuType, MenuId, config, settingshow, ParentId, menuloading, customComponents, eyeopen, needUpdate } = this.state
+    const { view, comloading, MenuType, MenuId, config, settingshow, ParentId, menuloading, eyeopen, needUpdate } = this.state
 
     return (
       <ConfigProvider locale={_locale}>
@@ -1288,9 +1148,6 @@
                   <Panel header="鍏冪礌" key="element">
                     <Modulecell />
                   </Panel>
-                  {customComponents && customComponents.length ? <Panel header="鑷畾涔夌粍浠�" key="cuscomponent">
-                    <SourceWrap components={customComponents} MenuType={MenuType} />
-                  </Panel> : null}
                   <Panel header="椤甸潰鏍峰紡" key="background">
                     {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
                   </Panel>
diff --git a/src/views/menudesign/menuform/index.jsx b/src/views/menudesign/menuform/index.jsx
index f746df1..0a0e3ba 100644
--- a/src/views/menudesign/menuform/index.jsx
+++ b/src/views/menudesign/menuform/index.jsx
@@ -4,7 +4,6 @@
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import './index.scss'
 
 const { TextArea } = Input
@@ -77,7 +76,7 @@
   getMenus = () => {
     const { MenuId, config } = this.props
 
-    Api.getSystemConfig({func: 's_get_pc_menus', systemType: options.sysType, debug: 'Y'}).then(result => {
+    Api.getCloudConfig({func: 's_get_pc_menus', systemType: window.GLOB.sysType, debug: 'Y'}).then(result => {
       if (result.status) {
         let thdMenu = null
         let thdMenuList = []
@@ -173,7 +172,6 @@
     })
   }
 
-  // 涓�浜岀骇鑿滃崟鍒囨崲
   selectChange = (key, value) => {
     const { config } = this.props
     const { menulist } = this.state
@@ -194,7 +192,7 @@
         this.props.updateConfig({...config, fstMenuId: value, parentId: _id})
       })
     } else {
-      if (key === 'cacheTime' || key === 'minWidth') {
+      if (key === 'cacheTime' || key === 'minWidth' || key === 'localCacheTime') {
         if (typeof(value) !== 'number') {
           value = ''
         }
@@ -293,17 +291,13 @@
             <Form.Item label="鎵撳紑鏂瑰紡">
               {getFieldDecorator('OpenType', {
                 initialValue: config.OpenType || 'newtab',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鎵撳紑鏂瑰紡!'
-                  }
-                ]
+                rules: [{ required: true, message: '璇烽�夋嫨鎵撳紑鏂瑰紡!' }]
               })(
-                <Radio.Group onChange={(e) => {this.selectChange('OpenType', e.target.value)}}>
-                  <Radio value="newtab">鏍囩椤�</Radio>
-                  <Radio value="newpage">鏂伴〉闈�</Radio>
-                </Radio.Group>
+                <Select onChange={(value) => {this.selectChange('OpenType', value)}}>
+                  <Select.Option value="newtab">鏍囩椤�</Select.Option>
+                  <Select.Option value="newpage">鏂伴〉闈紙鏍囩椤碉級</Select.Option>
+                  <Select.Option value="view">鏂伴〉闈紙鍏ㄥ睆锛�</Select.Option>
+                </Select>
               )}
             </Form.Item>
           </Col>
@@ -341,6 +335,20 @@
               )}
             </Form.Item>
           </Col>
+          {config.cacheLocal === 'true' ? <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="璁剧疆鏈湴缂撳瓨鏃堕暱鍚庯紝鍦ㄧ紦瀛樻湡闄愬唴涓嶅悜鍚庡彴璇锋眰鏁版嵁锛屾椂闀挎渶澶т负5澶╋紙鍗�7200鍒嗛挓锛夈�傛敞锛氭椂闀夸负绌烘椂缂撳瓨鏁版嵁鍙敤浜庨〉闈㈠揩閫熷憟鐜帮紝涓嶅奖鍝嶆帴鍙h姹傘��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏃堕暱(鍒�)
+              </Tooltip>
+            }>
+              {getFieldDecorator('localCacheTime', {
+                initialValue: config.localCacheTime
+              })(
+                <InputNumber min={1} max={7200} precision={0} onChange={(val) => {this.selectChange('localCacheTime', val)}}/>
+              )}
+            </Form.Item>
+          </Col> : null}
           <Col span={24}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="瀵逛簬涓嶇粡甯告�у彉鍔ㄧ殑淇℃伅锛岀紦瀛樻暟鎹湁鍔╀簬鎻愰珮鏌ヨ鏁堢巼銆�">
@@ -388,6 +396,23 @@
           </Col> : null}
           <Col span={24}>
             <Form.Item label={
+              <Tooltip placement="topLeft" title="鏁版嵁鍔犺浇鏃剁殑閬僵鏄惁鏄剧ず銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍔犺浇閬僵
+              </Tooltip>
+            }>
+              {getFieldDecorator('mask', {
+                initialValue: config.mask || 'true'
+              })(
+                <Radio.Group onChange={(e) => {this.selectChange('mask', e.target.value)}}>
+                  <Radio value="true">鏄剧ず</Radio>
+                  <Radio value="false">闅愯棌</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label={
               <Tooltip placement="topLeft" title="濡傛灉椤甸潰鍐呭鍦ㄧ獥鍙d腑鏃犳硶瀹屽叏灞曠ず锛屽彲璁剧疆鏈�灏忓搴︼紝瀹炵幇椤甸潰鐨勬í鍚戞粴鍔ㄣ��">
                 <QuestionCircleOutlined className="mk-form-tip" />
                 鏈�灏忓搴�
diff --git a/src/views/menudesign/popview/index.jsx b/src/views/menudesign/popview/index.jsx
index 8a783ea..d5eccea 100644
--- a/src/views/menudesign/popview/index.jsx
+++ b/src/views/menudesign/popview/index.jsx
@@ -12,7 +12,6 @@
 const { Panel } = Collapse
 const { confirm } = Modal
 
-const MenuForm = asyncComponent(() => import('./menuform'))
 const SourceWrap = asyncComponent(() => import('@/menu/modulesource'))
 const Modulecell = asyncComponent(() => import('@/menu/modulecell'))
 const MenuShell = asyncComponent(() => import('@/menu/menushell'))
@@ -265,8 +264,6 @@
             <Collapse accordion defaultActiveKey="basedata" bordered={false}>
               {/* 鍩烘湰淇℃伅 */}
               <Panel header="鍩烘湰淇℃伅" key="basedata">
-                {/* 鑿滃崟淇℃伅 */}
-                <MenuForm config={config} updateConfig={this.updateConfig}/>
                 {/* 琛ㄥ悕娣诲姞 */}
                 <TableComponent config={config} updatetable={this.updatetable}/>
               </Panel>
diff --git a/src/views/menudesign/popview/menuform/index.jsx b/src/views/menudesign/popview/menuform/index.jsx
deleted file mode 100644
index e84a5af..0000000
--- a/src/views/menudesign/popview/menuform/index.jsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Radio, Tooltip, InputNumber } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-
-// import './index.scss'
-
-class CustomMenuForm extends Component {
-  static propTpyes = {
-    config: PropTypes.object,
-    updateConfig: PropTypes.func
-  }
-  
-  changeCacheDay = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
-    }
-    this.props.updateConfig({...this.props.config, cacheTime: val})
-  }
-
-  selectChange = (key, value) => {
-    const { config } = this.props
-
-    if (key === 'cacheUseful') {
-      this.props.updateConfig({...config, cacheUseful: value})
-    } else if (key === 'timeUnit') {
-      this.props.updateConfig({...config, timeUnit: value})
-    } else if (key === 'cacheLocal') {
-      this.props.updateConfig({...config, cacheLocal: value})
-    }
-  }
-
-  render() {
-    const { config } = this.props
-    const { getFieldDecorator } = this.props.form
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <Form {...formItemLayout}>
-        <Row>
-          <Col span={24}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鏁版嵁浼氱紦瀛樺埌鐢ㄦ埛鏈湴锛屾柟渚块〉闈㈠揩閫熷憟鐜般��">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鏈湴缂撳瓨
-              </Tooltip>
-            }>
-              {getFieldDecorator('cacheLocal', {
-                initialValue: config.cacheLocal || 'false'
-              })(
-                <Radio.Group onChange={(e) => {this.selectChange('cacheLocal', e.target.value)}}>
-                  <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" />
-                鍚庣缂撳瓨
-              </Tooltip>
-            }>
-              {getFieldDecorator('cacheUseful', {
-                initialValue: config.cacheUseful || 'false'
-              })(
-                <Radio.Group onChange={(e) => {this.selectChange('cacheUseful', e.target.value)}}>
-                  <Radio value="true">浣跨敤</Radio>
-                  <Radio value="false">涓嶄娇鐢�</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          {config.cacheUseful === 'true' ? <Col span={24}>
-            <Form.Item label="鍗曚綅">
-              {getFieldDecorator('timeUnit', {
-                initialValue: config.timeUnit || 'day'
-              })(
-                <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
-                  <Radio value="day">澶�</Radio>
-                  <Radio value="hour">灏忔椂</Radio>
-                  <Radio value="minute">鍒嗛挓</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          {config.cacheUseful === 'true' ? <Col span={24}>
-            <Form.Item label="鏃堕暱">
-              {getFieldDecorator('cacheTime', {
-                initialValue: config.cacheTime,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ユ椂闀�!'
-                  }
-                ]
-              })(
-                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
-              )}
-            </Form.Item>
-          </Col> : null}
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(CustomMenuForm)
\ No newline at end of file
diff --git a/src/views/menudesign/popview/menuform/index.scss b/src/views/menudesign/popview/menuform/index.scss
deleted file mode 100644
index e69de29..0000000
--- a/src/views/menudesign/popview/menuform/index.scss
+++ /dev/null
diff --git a/src/views/menudesign/printmenuform/index.jsx b/src/views/menudesign/printmenuform/index.jsx
index be3c97d..315cbe0 100644
--- a/src/views/menudesign/printmenuform/index.jsx
+++ b/src/views/menudesign/printmenuform/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, InputNumber, Select, Radio, Tooltip } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
+import { Form, Row, Col, InputNumber, Select, Radio, Tooltip, Input } from 'antd'
+import { QuestionCircleOutlined, EditOutlined } from '@ant-design/icons'
 
 // import './index.scss'
 
@@ -11,49 +11,24 @@
     updateConfig: PropTypes.func
   }
 
-  changeCount = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
+  selectChange = (key, value) => {
+    const { config } = this.props
+
+    if (['everyPCount', 'printWidth', 'printHeight'].includes(key)) {
+      if (typeof(value) !== 'number') {
+        value = ''
+      }
+    } else if (key === 'callNo') {
+      if (!/^[a-zA-Z0-9_]+$/.test(value)) {
+        value = ''
+      }
     }
-    this.props.updateConfig({...this.props.config, everyPCount: val})
-  }
 
-  changePrintWidth = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
+    this.props.updateConfig({...config, [key]: value})
+
+    if (['pageSize', 'pageLayout', 'pagePadding', 'printCustom'].includes(key)) {
+      this.resetPage()
     }
-    this.props.updateConfig({...this.props.config, printWidth: val})
-  }
-
-  changePrintHeight = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
-    }
-    this.props.updateConfig({...this.props.config, printHeight: val})
-  }
-
-  onPrintPageChange = (val) => {
-    this.props.updateConfig({...this.props.config, printPage: val})
-  }
-
-  pageSizeChange = (val) => {
-    this.props.updateConfig({...this.props.config, pageSize: val})
-    this.resetPage()
-  }
-
-  onLayoutChange = (val) => {
-    this.props.updateConfig({...this.props.config, pageLayout: val})
-    this.resetPage()
-  }
-  
-  onPaddingChange = (val) => {
-    this.props.updateConfig({...this.props.config, pagePadding: val})
-    this.resetPage()
-  }
-
-  onPrintCustomChange = (val) => {
-    this.props.updateConfig({...this.props.config, printCustom: val})
-    this.resetPage()
   }
 
   resetPage = () => {
@@ -143,7 +118,7 @@
                   }
                 ]
               })(
-                <Select onChange={this.pageSizeChange}>
+                <Select onChange={(val) => this.selectChange('pageSize', val)}>
                   <Select.Option value="A3">A3</Select.Option>
                   <Select.Option value="A4">A4</Select.Option>
                   <Select.Option value="A5">A5</Select.Option>
@@ -162,7 +137,7 @@
                   }
                 ]
               })(
-                <Radio.Group onChange={(e) => {this.onLayoutChange(e.target.value)}}>
+                <Radio.Group onChange={(e) => this.selectChange('pageLayout', e.target.value)}>
                   <Radio value="vertical">绾靛悜</Radio>
                   <Radio value="horizontal">妯悜</Radio>
                 </Radio.Group>
@@ -180,7 +155,7 @@
                   }
                 ]
               })(
-                <Radio.Group onChange={(e) => {this.onPaddingChange(e.target.value)}}>
+                <Radio.Group onChange={(e) => this.selectChange('pagePadding', e.target.value)}>
                   <Radio value="default">榛樿</Radio>
                   <Radio value="without">鏃�</Radio>
                 </Radio.Group>
@@ -192,26 +167,13 @@
               {getFieldDecorator('printPage', {
                 initialValue: config.printPage || 'auto'
               })(
-                <Radio.Group onChange={(e) => {this.onPrintPageChange(e.target.value)}}>
+                <Radio.Group onChange={(e) => this.selectChange('printPage', e.target.value)}>
                   <Radio value="auto">鑷�傚簲</Radio>
                   <Radio value="page">鍒嗛〉</Radio>
                 </Radio.Group>
               )}
             </Form.Item>
           </Col>
-          {/* <Col span={24}>
-            <Form.Item label="棣栭〉鏁�(鏉�)">
-              {getFieldDecorator('firstCount', {
-                initialValue: config.firstCount,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ラ椤垫暟!'
-                  }
-                ]
-              })(<InputNumber min={1} max={1000} precision={1} onChange={this.changeFirstCount}/>)}
-            </Form.Item>
-          </Col> */}
           {config.printPage === 'page' ? <Col span={24}>
             <Form.Item label="姣忛〉鏁�(鏉�)">
               {getFieldDecorator('everyPCount', {
@@ -222,16 +184,9 @@
                     message: '璇疯緭鍏ユ瘡椤垫暟!'
                   }
                 ]
-              })(<InputNumber min={1} max={1000} precision={1} onChange={this.changeCount}/>)}
+              })(<InputNumber min={1} max={1000} precision={1} onChange={(val) => this.selectChange('everyPCount', val)}/>)}
             </Form.Item>
           </Col> : null}
-          {/* <Col span={24}>
-            <Form.Item label="灏鹃〉鏁�(鏉�)">
-              {getFieldDecorator('lastCount', {
-                initialValue: config.lastCount
-              })(<InputNumber min={1} max={1000} precision={1} onChange={this.changeLastCount}/>)}
-            </Form.Item>
-          </Col> */}
           <Col span={24}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="閽堝涓嶈鍒欑焊寮狅紝鍙嚜瀹氫箟璁剧疆鎵撳嵃楂樺害鍜屽搴︼紝娉細鍚屾椂璁剧疆鎵撳嵃瀹藉害鍜岄珮搴﹀悗鏂瑰彲鐢熸晥銆�">
@@ -242,7 +197,7 @@
               {getFieldDecorator('printCustom', {
                 initialValue: config.printCustom || 'false'
               })(
-                <Radio.Group onChange={(e) => {this.onPrintCustomChange(e.target.value)}}>
+                <Radio.Group onChange={(e) => this.selectChange('printCustom', e.target.value)}>
                   <Radio value="false">涓嶅惎鐢�</Radio>
                   <Radio value="true">鍚敤</Radio>
                 </Radio.Group>
@@ -253,14 +208,53 @@
             <Form.Item label="鎵撳嵃瀹藉害">
               {getFieldDecorator('printWidth', {
                 initialValue: config.printWidth || ''
-              })(<InputNumber min={10} max={9999} precision={0} onChange={this.changePrintWidth}/>)}
+              })(<InputNumber min={10} max={9999} precision={0} onChange={(val) => this.selectChange('printWidth', val)}/>)}
             </Form.Item>
           </Col> : null}
           {config.printCustom === 'true' ? <Col span={24}>
             <Form.Item label="鎵撳嵃楂樺害">
               {getFieldDecorator('printHeight', {
                 initialValue: config.printHeight || ''
-              })(<InputNumber min={10} max={9999} precision={0} onChange={this.changePrintHeight}/>)}
+              })(<InputNumber min={10} max={9999} precision={0} onChange={(val) => this.selectChange('printHeight', val)}/>)}
+            </Form.Item>
+          </Col> : null}
+          <Col span={24}>
+            <Form.Item label="鍥炶皟">
+              {getFieldDecorator('callback', {
+                initialValue: config.callback || 'false'
+              })(
+                <Radio.Group onChange={(e) => this.selectChange('callback', e.target.value)}>
+                  <Radio value="false">涓嶅惎鐢�</Radio>
+                  <Radio value="true">鍚敤</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          {config.callback === 'true' ? <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鍥炶皟鍑芥暟鎵ц鎴愬姛鍚庨粯璁や細鍒锋柊婧愯彍鍗曢〉锛岃繑鍥炰俊鎭紙@retmsg锛変腑鍚湁锛園no_target_menu@锛夊彲闃绘姝ら」鍒锋柊銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍥炶皟鍑芥暟
+              </Tooltip>
+            }>
+              s_print_proc <EditOutlined style={{cursor: 'pointer'}} onClick={() => {window.open('#/proc/s_print_proc')}}/>
+            </Form.Item>
+          </Col> : null}
+          {config.callback === 'true' ? <Col span={24}>
+            <Form.Item label="鍥炶皟鍙傛暟">
+              {getFieldDecorator('callNo', {
+                initialValue: config.callNo || '',
+                rules: [
+                  {
+                    required: true,
+                    message: '璇峰~鍐欏洖璋冨弬鏁�!'
+                  },
+                  {
+                    pattern: /^[a-zA-Z0-9_]+$/,
+                    message: '鍥炶皟鍙傛暟鍙彲浣跨敤瀛楁瘝銆佹暟瀛椾互鍙奯'
+                  }
+                ]
+              })(<Input onChange={(e) => this.selectChange('callNo', e.target.value)}/>)}
             </Form.Item>
           </Col> : null}
         </Row>
diff --git a/src/views/mkiframe/index.jsx b/src/views/mkiframe/index.jsx
new file mode 100644
index 0000000..3f11727
--- /dev/null
+++ b/src/views/mkiframe/index.jsx
@@ -0,0 +1,233 @@
+import React, {Component} from 'react'
+import { Spin, notification, ConfigProvider } from 'antd'
+import zhCN from 'antd/es/locale/zh_CN'
+
+import Api from '@/api'
+import asyncComponent from '@/utils/asyncLoadComponent'
+import MKEmitter from '@/utils/events.js'
+import ImgScale from '@/components/imgScale'
+import './index.scss'
+
+const CustomPage = asyncComponent(() => import('@/tabviews/custom'))
+const BaseTable = asyncComponent(() => import('@/tabviews/basetable'))
+
+class MkIframe extends Component {
+  state = {
+    loading: true,
+    BID: '',
+    MenuId: '',
+    type: 'CustomPage'
+  }
+
+  UNSAFE_componentWillMount() {
+    const { params, path } = this.props.match
+    const { menuId, loginUid, bid } = params
+
+    if (/^\/view\//.test(path)) {
+      localStorage.setItem('getSysPermission', window.GLOB.appkey)
+      const that = this
+    
+      window.addEventListener('storage', function(event) {
+        if (event.key === 'sysPermissions' && event.newValue) {
+          let values = event.newValue
+          values = JSON.parse(values)
+
+          window.GLOB.mkThdMenus = values.mkThdMenus
+          window.GLOB.mkActions = values.mkActions
+        } else if (event.key === 'menuUpdate') {
+          let vals = event.newValue.split(',')
+          let MenuId = vals[1]
+          let position = vals[2] || ''
+          if (position === 'menu' && menuId === MenuId) {
+            that.setState({loading: true}, () => {
+              that.setState({loading: false})
+            })
+          }
+        }
+      })
+
+      setTimeout(() => {
+        localStorage.removeItem('getSysPermission')
+        localStorage.removeItem('sysPermissions')
+
+        if (window.GLOB.mkActions && window.GLOB.mkActions.loaded) {
+          this.setState({loading: false})
+        } else {
+          this.getPermRole()
+        }
+      }, 20)
+    } else if (sessionStorage.getItem('UserID')) {
+      this.getPermRole()
+    } else {
+      sessionStorage.setItem('LoginUID', loginUid)
+  
+      Api.getTouristMsg('login_check').then(res => {
+        if (res.status) {
+          sessionStorage.setItem('UserID', res.UserID)
+          sessionStorage.setItem('LoginUID', res.LoginUID)
+          sessionStorage.setItem('User_Name', res.UserName)
+          sessionStorage.setItem('Full_Name', res.FullName)
+          sessionStorage.setItem('avatar', res.icon || '')
+          sessionStorage.setItem('dataM', res.dataM ? 'true' : '')
+          sessionStorage.setItem('debug', res.debug || '')
+          sessionStorage.setItem('role_id', res.role_id || '')
+          sessionStorage.setItem('departmentcode', res.departmentcode || '')
+          sessionStorage.setItem('organization', res.organization || '')
+          sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
+          this.getPermRole()
+        } else {
+          sessionStorage.clear()
+          sessionStorage.setItem('iframe', `/iframe/${menuId}/@loginuid@/${bid || ''}`)
+          this.props.history.replace('/login')
+        }
+      })
+    }
+
+    this.setState({BID: bid || '', MenuId: menuId})
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('modifyTabs', this.modifyTabs)
+    MKEmitter.addListener('closeTabView', this.closeTabView)
+
+    if (window.GLOB.sysType !== 'cloud') {
+      Object.defineProperty(window, 'debugger', {
+        configurable: true,
+        enumerable: true,
+        set(value) {
+          if (value + '' === 'false') {
+            window.GLOB.debugger = false
+          } else {
+            window.GLOB.debugger = true
+          }
+        }
+      })
+
+      Object.defineProperty(window, 'debug', {
+        configurable: true,
+        enumerable: true,
+        set(value) {
+          if (value + '' === 'false') {
+            window.GLOB.debugger = false
+            window.GLOB.breakpoint = false
+            sessionStorage.removeItem('breakpoint')
+          } else {
+            window.GLOB.debugger = true
+            window.GLOB.breakpoint = value + ''
+            sessionStorage.setItem('breakpoint', value)
+          }
+          MKEmitter.emit('debugChange')
+        }
+      })
+    }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('modifyTabs', this.modifyTabs)
+    MKEmitter.removeListener('closeTabView', this.closeTabView)
+  }
+
+  modifyTabs = (tab) => {
+    const { MenuId, BID } = this.state
+
+    let _menuId = tab.MenuID
+    let _BID = tab.param && tab.param.$BID ? tab.param.$BID : ''
+
+    let historys = sessionStorage.getItem('page_historys')
+    historys = historys ? JSON.parse(historys) : []
+
+    historys.push({MenuId: MenuId, BID: BID})
+
+    sessionStorage.setItem('page_historys', JSON.stringify(historys))
+
+    this.setState({
+      MenuId: _menuId,
+      BID: _BID,
+      loading: true
+    }, () => {
+      this.setState({
+        loading: false
+      })
+    })
+  }
+
+  closeTabView = () => {
+    let historys = sessionStorage.getItem('page_historys')
+    historys = historys ? JSON.parse(historys) : []
+
+    if (historys.length === 0) return
+
+    let tab = historys.shift()
+
+    sessionStorage.setItem('page_historys', JSON.stringify(historys))
+    
+    this.setState({
+      MenuId: tab.MenuId,
+      BID: tab.BID,
+      loading: true
+    }, () => {
+      this.setState({
+        loading: false
+      })
+    })
+  }
+
+  getPermRole = () => {
+    Api.getSystemConfig({
+      func: 's_Get_TrdMenu_Role',
+      edition_type: 'A',
+      pro_sys: window.GLOB.systemType === 'production' ? 'Y' : ''
+    }).then(result => {
+      if (!result.status) {
+        notification.error({
+          top: 92,
+          message: result.message,
+          duration: 10
+        })
+        return
+      }
+
+      let _permAction = {loaded: true} // 鎸夐挳鏉冮檺
+  
+      if (result.UserRoles_Menu) {
+        result.UserRoles_Menu.forEach(menu => {
+          if (!menu.MenuID) return
+          _permAction[menu.MenuID] = true
+        })
+      }
+  
+      window.GLOB.mkActions = _permAction
+
+      this.setState({loading: false})
+    })
+  }
+
+  changeTemp = (MenuID, Template) => {
+    this.setState({
+      type: Template
+    })
+  }
+
+  render () {
+    const { loading, BID, MenuId, type } = this.state
+
+    return (
+      <div className="main-iframe">
+        <ConfigProvider locale={zhCN}>
+          {loading ? <Spin size="large" /> : null}
+          {!loading && type === 'CustomPage' ? <CustomPage MenuID={MenuId} param={{$BID: BID}} changeTemp={this.changeTemp}/> : null}
+          {!loading && type === 'BaseTable' ? <BaseTable MenuID={MenuId} param={{$BID: BID}} changeTemp={this.changeTemp}/> : null}
+        </ConfigProvider>
+        <ImgScale />
+      </div>
+    )
+  }
+}
+
+export default MkIframe
\ No newline at end of file
diff --git a/src/views/mkiframe/index.scss b/src/views/mkiframe/index.scss
new file mode 100644
index 0000000..9390276
--- /dev/null
+++ b/src/views/mkiframe/index.scss
@@ -0,0 +1,10 @@
+.main-iframe {
+  .ant-spin {
+    position: absolute;
+    left: calc(50vw - 22px);
+    top: 45vh;
+  }
+  .custom-table-wrap, .custom-page-wrap {
+    min-height: 100vh;
+  }
+}
\ No newline at end of file
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index 7c8d241..9b01279 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -4,7 +4,7 @@
 import { is, fromJS } from 'immutable'
 import HTML5Backend from 'react-dnd-html5-backend'
 import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
-import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, RedoOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
+import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import md5 from 'md5'
 
@@ -48,7 +48,6 @@
 const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
 const PopView = asyncComponent(() => import('./popview'))
 
-sessionStorage.setItem('isEditState', 'true')
 sessionStorage.setItem('editMenuType', 'menu') // 缂栬緫鑿滃崟绫诲瀷
 sessionStorage.setItem('appType', 'mob')       // 搴旂敤绫诲瀷
 document.body.className = ''
@@ -89,7 +88,6 @@
     }
     
     if (!sessionStorage.getItem('UserID')) {
-      sessionStorage.removeItem('isEditState')
       sessionStorage.removeItem('editMenuType')
       sessionStorage.removeItem('appType')
       this.props.history.replace('/login')
@@ -167,7 +165,6 @@
     MKEmitter.addListener('triggerMenuSave', this.submitConfig)
     MKEmitter.addListener('changeEditMenu', this.changeEditMenu)
     setTimeout(() => {
-      this.getAppPictures()
       this.getRoleFields()
       setGLOBFuncs()
     }, 1000)
@@ -408,7 +405,7 @@
   }
 
   getAppMessage = (MenuID) => {
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 's_get_keyids',
       bid: sessionStorage.getItem('appId')
     }).then(res => {
@@ -458,7 +455,7 @@
         param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
         param.secretkey = Utils.encrypt('', param.timestamp)
 
-        Api.getSystemConfig(param).then(result => {
+        Api.getCloudConfig(param).then(result => {
           if (!result.status) {
             notification.warning({
               top: 92,
@@ -474,43 +471,6 @@
         sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
         this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID || homeId, type: 'view'}))))
       }
-    })
-  }
-
-  getAppPictures = () => {
-    if (sessionStorage.getItem('app_pictures')) return
-    
-    let deffers = []
-    let param = {
-      func: 's_url_db_adduptdel',
-      PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
-      PageSize: 0,   // 0 浠h〃鍏ㄩ儴
-      type: 'search'
-    }
-    deffers = [new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'image'}).then(res => {
-          resolve(res.data)
-        })
-      }, 500)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'video'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1000)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'color'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1500)
-    })]
-
-    Promise.all(deffers).then(response => {
-      sessionStorage.setItem('app_pictures', JSON.stringify(response[0] || []))
-      sessionStorage.setItem('app_videos', JSON.stringify(response[1] || []))
-      sessionStorage.setItem('app_colors', JSON.stringify(response[2] || []))
     })
   }
 
@@ -562,7 +522,7 @@
       MenuID: MenuId
     }
 
-    Api.getSystemConfig(param).then(result => {
+    Api.getCloudConfig(param).then(result => {
       if (!result.status) {
         notification.warning({
           top: 92,
@@ -748,7 +708,7 @@
 
     _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
 
-    Api.getSystemConfig(_param).then(res => {
+    Api.getCloudConfig(_param).then(res => {
       if (!res.status) {
         notification.warning({
           top: 92,
@@ -794,7 +754,7 @@
       MenuID: urlParam.copyMenuId
     }
 
-    Api.getSystemConfig(param).then(result => {
+    Api.getCloudConfig(param).then(result => {
       if (!result.status) {
         notification.warning({
           top: 92,
@@ -907,7 +867,7 @@
   }
 
   jointComponents = (config, navItem) => {
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 'sPC_Get_LongParam',
       TypeCharOne: sessionStorage.getItem('kei_no'),
       typename: sessionStorage.getItem('typename'),
@@ -1637,7 +1597,7 @@
             _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
             _param.secretkey = Utils.encrypt('', _param.timestamp)
             
-            Api.getSystemConfig(_param).then(res => {
+            Api.getCloudConfig(_param).then(res => {
               if (res.status) {
                 NavBar.open_edition = res.open_edition || ''
                 window.GLOB.CacheIndependent.set(NavBar.uuid, fromJS(NavBar).toJS())
@@ -1682,7 +1642,7 @@
                   kparam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
                   kparam.secretkey = Utils.encrypt('', kparam.timestamp)
         
-                  Api.getSystemConfig(kparam).then(result => {
+                  Api.getCloudConfig(kparam).then(result => {
                     if (result.status) {
                       sessionStorage.setItem('appViewList', viewList)
                     }
@@ -1701,7 +1661,7 @@
       }).then(res => { // 椤甸潰淇濆瓨
         if (!res || !res.status) return res
 
-        return Api.getSystemConfig(param)
+        return Api.getCloudConfig(param)
       }).then(res => {
         this.setState({
           menuloading: false
@@ -1725,7 +1685,6 @@
             message: '淇濆瓨鎴愬姛',
             duration: 2
           })
-          MKEmitter.emit('completeSave')
         } else {
           notification.warning({
             top: 92,
@@ -1733,6 +1692,7 @@
             duration: 5
           })
         }
+        MKEmitter.emit('completeSave')
       }, this.netError)
     }, 300 + (+sessionStorage.getItem('mkDelay')))
   }
@@ -1749,12 +1709,13 @@
         duration: 5
       })
     }
+    MKEmitter.emit('completeSave')
   }
 
   getRoleFields = () => {
     if (sessionStorage.getItem('sysRoles')) return
 
-    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
       if (res.status) {
         let _permFuncField = []
         let _sysRoles = []
@@ -1937,26 +1898,6 @@
     })
   }
 
-  refreshView = () => {
-    const { oriConfig, config } = this.state
-
-    if (!is(fromJS(oriConfig || {}), fromJS(config || {}))) {
-      notification.warning({
-        top: 92,
-        message: '閰嶇疆淇℃伅鏈繚瀛橈紒',
-        duration: 5
-      })
-      return
-    }
-
-    sessionStorage.removeItem('sysRoles')
-    sessionStorage.removeItem('permFuncField')
-    sessionStorage.removeItem('app_videos')
-    sessionStorage.removeItem('app_pictures')
-    
-    window.location.reload()
-  }
-
   setHomeView = () => {
     const { oriConfig, config } = this.state
 
@@ -2000,7 +1941,7 @@
       title: '纭畾璁剧疆鏈〉闈负棣栭〉鍚楋紵',
       content: '',
       onOk() {
-        Api.getSystemConfig(param).then(result => {
+        Api.getCloudConfig(param).then(result => {
           if (!result.status) {
             notification.warning({
               top: 92,
@@ -2061,7 +2002,7 @@
       title: '纭畾璁剧疆鏈〉闈负鐧诲綍椤靛悧锛�',
       content: hasLogin ? '' : '褰撳墠椤甸潰灏氭湭娣诲姞鐧诲綍缁勪欢銆�',
       onOk() {
-        Api.getSystemConfig(param).then(result => {
+        Api.getCloudConfig(param).then(result => {
           if (!result.status) {
             notification.warning({
               top: 92,
@@ -2186,7 +2127,6 @@
                 <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                 <Transfer MenuID={MenuId} />
                 <Versions MenuId={MenuId} open_edition={config ? config.open_edition : ''}/>
-                <Button className="mk-border-danger" onClick={this.refreshView}><RedoOutlined /> 寮哄埗鍒锋柊</Button>
                 <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
               </div>
             </div>
diff --git a/src/views/mobdesign/menuform/index.jsx b/src/views/mobdesign/menuform/index.jsx
index b6371cf..49d4013 100644
--- a/src/views/mobdesign/menuform/index.jsx
+++ b/src/views/mobdesign/menuform/index.jsx
@@ -22,34 +22,23 @@
 
   // 涓�浜岀骇鑿滃崟鍒囨崲
   selectChange = (key, value, hex) => {
+    if (key === 'cacheTime' || key === 'localCacheTime') {
+      if (typeof(value) !== 'number') {
+        value = ''
+      }
+    }
+
     let _config = {...this.props.config, [key]: value}
 
-    if (key === 'statusBarbgColor' && hex) {
-      _config.statusBarHexColor = hex
+    if (key === 'statusBarbgColor') { // 灏忕▼搴忕姸鎬佹爮
+      if (hex) {
+        _config.statusBarHexColor = hex
+      } else {
+        delete _config.statusBarHexColor
+      }
     }
 
     this.props.updateConfig(_config)
-  }
-
-  // 鑿滃崟鍚嶇О
-  changeName = (e) => {
-    this.props.updateConfig({...this.props.config, MenuName: e.target.value})
-  }
-
-  // 鑿滃崟鍙傛暟
-  changeNo = (e) => {
-    this.props.updateConfig({...this.props.config, MenuNo: e.target.value})
-  }
-
-  changeRemark = (e) => {
-    this.props.updateConfig({...this.props.config, Remark: e.target.value})
-  }
-
-  changeCacheDay = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
-    }
-    this.props.updateConfig({...this.props.config, cacheTime: val})
   }
 
   render() {
@@ -79,7 +68,7 @@
                     message: '璇疯緭鍏ヨ彍鍗曞悕绉�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" onChange={this.changeName}/>)}
+              })(<Input placeholder="" autoComplete="off" onChange={(e) => {this.selectChange('MenuName', e.target.value)}}/>)}
             </Form.Item>
           </Col>
           <Col span={24}>
@@ -92,7 +81,7 @@
                     message: '璇疯緭鍏ヨ彍鍗曞弬鏁�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" onChange={this.changeNo}/>)}
+              })(<Input placeholder="" autoComplete="off" onChange={(e) => {this.selectChange('MenuNo', e.target.value)}}/>)}
             </Form.Item>
           </Col>
           <Col span={24}>
@@ -112,6 +101,20 @@
               )}
             </Form.Item>
           </Col>
+          {config.cacheLocal === 'true' ? <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="璁剧疆鏈湴缂撳瓨鏃堕暱鍚庯紝鍦ㄧ紦瀛樻湡闄愬唴涓嶅悜鍚庡彴璇锋眰鏁版嵁锛屾椂闀挎渶澶т负5澶╋紙鍗�7200鍒嗛挓锛夈�傛敞锛氭椂闀夸负绌烘椂缂撳瓨鏁版嵁鍙敤浜庨〉闈㈠揩閫熷憟鐜帮紝涓嶅奖鍝嶆帴鍙h姹傘��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏃堕暱(鍒�)
+              </Tooltip>
+            }>
+              {getFieldDecorator('localCacheTime', {
+                initialValue: config.localCacheTime
+              })(
+                <InputNumber min={1} max={7200} precision={0} onChange={(val) => {this.selectChange('localCacheTime', val)}}/>
+              )}
+            </Form.Item>
+          </Col> : null}
           <Col span={24}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="瀵逛簬涓嶇粡甯告�у彉鍔ㄧ殑淇℃伅锛岀紦瀛樻暟鎹湁鍔╀簬鎻愰珮鏌ヨ鏁堢巼銆�">
@@ -187,7 +190,7 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={(val) => {this.selectChange('cacheTime', val)}}/>
               )}
             </Form.Item>
           </Col> : null}
@@ -342,7 +345,7 @@
                     message: '澶囨敞鏈�澶�512涓瓧绗︼紒'
                   }
                 ]
-              })(<TextArea rows={2} placeholder={''} onChange={this.changeRemark} />)}
+              })(<TextArea rows={2} placeholder={''} onChange={(e) => {this.selectChange('Remark', e.target.value)}}/>)}
             </Form.Item>
           </Col>
         </Row>
diff --git a/src/views/mobdesign/popview/index.jsx b/src/views/mobdesign/popview/index.jsx
index 03cfee3..eeaa4c7 100644
--- a/src/views/mobdesign/popview/index.jsx
+++ b/src/views/mobdesign/popview/index.jsx
@@ -12,7 +12,6 @@
 const { Panel } = Collapse
 const { confirm } = Modal
 
-const MenuForm = asyncComponent(() => import('./menuform'))
 const MobShell = asyncComponent(() => import('@/mob/mobshell'))
 const SourceWrap = asyncComponent(() => import('@/mob/modulesource'))
 const Modulecell = asyncComponent(() => import('@/menu/modulecell'))
@@ -271,8 +270,6 @@
             <Collapse accordion defaultActiveKey="component" bordered={false}>
               {/* 鍩烘湰淇℃伅 */}
               <Panel header="鍩烘湰淇℃伅" forceRender className="basedata" key="basedata">
-                {/* 鑿滃崟淇℃伅 */}
-                <MenuForm config={config} updateConfig={this.updateConfig}/>
                 {/* 琛ㄥ悕娣诲姞 */}
                 <TableComponent config={config} updatetable={this.updateConfig}/>
               </Panel>
diff --git a/src/views/mobdesign/popview/menuform/index.jsx b/src/views/mobdesign/popview/menuform/index.jsx
deleted file mode 100644
index e84a5af..0000000
--- a/src/views/mobdesign/popview/menuform/index.jsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Radio, Tooltip, InputNumber } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-
-// import './index.scss'
-
-class CustomMenuForm extends Component {
-  static propTpyes = {
-    config: PropTypes.object,
-    updateConfig: PropTypes.func
-  }
-  
-  changeCacheDay = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
-    }
-    this.props.updateConfig({...this.props.config, cacheTime: val})
-  }
-
-  selectChange = (key, value) => {
-    const { config } = this.props
-
-    if (key === 'cacheUseful') {
-      this.props.updateConfig({...config, cacheUseful: value})
-    } else if (key === 'timeUnit') {
-      this.props.updateConfig({...config, timeUnit: value})
-    } else if (key === 'cacheLocal') {
-      this.props.updateConfig({...config, cacheLocal: value})
-    }
-  }
-
-  render() {
-    const { config } = this.props
-    const { getFieldDecorator } = this.props.form
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <Form {...formItemLayout}>
-        <Row>
-          <Col span={24}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鏁版嵁浼氱紦瀛樺埌鐢ㄦ埛鏈湴锛屾柟渚块〉闈㈠揩閫熷憟鐜般��">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鏈湴缂撳瓨
-              </Tooltip>
-            }>
-              {getFieldDecorator('cacheLocal', {
-                initialValue: config.cacheLocal || 'false'
-              })(
-                <Radio.Group onChange={(e) => {this.selectChange('cacheLocal', e.target.value)}}>
-                  <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" />
-                鍚庣缂撳瓨
-              </Tooltip>
-            }>
-              {getFieldDecorator('cacheUseful', {
-                initialValue: config.cacheUseful || 'false'
-              })(
-                <Radio.Group onChange={(e) => {this.selectChange('cacheUseful', e.target.value)}}>
-                  <Radio value="true">浣跨敤</Radio>
-                  <Radio value="false">涓嶄娇鐢�</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          {config.cacheUseful === 'true' ? <Col span={24}>
-            <Form.Item label="鍗曚綅">
-              {getFieldDecorator('timeUnit', {
-                initialValue: config.timeUnit || 'day'
-              })(
-                <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
-                  <Radio value="day">澶�</Radio>
-                  <Radio value="hour">灏忔椂</Radio>
-                  <Radio value="minute">鍒嗛挓</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          {config.cacheUseful === 'true' ? <Col span={24}>
-            <Form.Item label="鏃堕暱">
-              {getFieldDecorator('cacheTime', {
-                initialValue: config.cacheTime,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ユ椂闀�!'
-                  }
-                ]
-              })(
-                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
-              )}
-            </Form.Item>
-          </Col> : null}
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(CustomMenuForm)
\ No newline at end of file
diff --git a/src/views/mobdesign/popview/menuform/index.scss b/src/views/mobdesign/popview/menuform/index.scss
deleted file mode 100644
index e69de29..0000000
--- a/src/views/mobdesign/popview/menuform/index.scss
+++ /dev/null
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index a8dcca3..79bb8c8 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -4,7 +4,7 @@
 import { is, fromJS } from 'immutable'
 import HTML5Backend from 'react-dnd-html5-backend'
 import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
-import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, RedoOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
+import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import md5 from 'md5'
 
@@ -48,8 +48,6 @@
 const StyleCombControlButton = asyncComponent(() => import('@/menu/stylecombcontrolbutton'))
 const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
 
-sessionStorage.setItem('isEditState', 'true')
-
 sessionStorage.setItem('appType', 'pc')        // 搴旂敤绫诲瀷
 sessionStorage.setItem('typename', 'pc')
 document.body.className = ''
@@ -84,7 +82,6 @@
     }
     
     if (!sessionStorage.getItem('UserID')) {
-      sessionStorage.removeItem('isEditState')
       sessionStorage.removeItem('appType')
       this.props.history.replace('/login')
       return
@@ -149,7 +146,6 @@
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
 
     setTimeout(() => {
-      this.getAppPictures()
       this.getRoleFields()
       setGLOBFuncs()
     }, 1000)
@@ -262,7 +258,7 @@
   }
 
   getAppMessage = (MenuID) => {
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 's_get_keyids',
       bid: sessionStorage.getItem('appId')
     }).then(res => {
@@ -312,7 +308,7 @@
         param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
         param.secretkey = Utils.encrypt('', param.timestamp)
 
-        Api.getSystemConfig(param).then(result => {
+        Api.getCloudConfig(param).then(result => {
           if (!result.status) {
             notification.warning({
               top: 92,
@@ -328,43 +324,6 @@
         sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
         this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID || homeId, type: 'view'}))))
       }
-    })
-  }
-
-  getAppPictures = () => {
-    if (sessionStorage.getItem('app_pictures')) return
-    
-    let deffers = []
-    let param = {
-      func: 's_url_db_adduptdel',
-      PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
-      PageSize: 0,   // 0 浠h〃鍏ㄩ儴
-      type: 'search'
-    }
-    deffers = [new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'image'}).then(res => {
-          resolve(res.data)
-        })
-      }, 500)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'video'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1000)
-    }), new Promise(resolve => {
-      setTimeout(() => {
-        Api.getSystemConfig({...param, typecharone: 'color'}).then(res => {
-          resolve(res.data)
-        })
-      }, 1500)
-    })]
-
-    Promise.all(deffers).then(response => {
-      sessionStorage.setItem('app_pictures', JSON.stringify(response[0] || []))
-      sessionStorage.setItem('app_videos', JSON.stringify(response[1] || []))
-      sessionStorage.setItem('app_colors', JSON.stringify(response[2] || []))
     })
   }
 
@@ -532,7 +491,7 @@
       MenuID: MenuId
     }
 
-    Api.getSystemConfig(param).then(result => {
+    Api.getCloudConfig(param).then(result => {
       if (!result.status) {
         notification.warning({
           top: 92,
@@ -679,7 +638,7 @@
 
     _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
 
-    Api.getSystemConfig(_param).then(res => {
+    Api.getCloudConfig(_param).then(res => {
       if (!res.status) {
         notification.warning({
           top: 92,
@@ -718,7 +677,7 @@
       MenuID: urlParam.copyMenuId
     }
 
-    Api.getSystemConfig(param).then(result => {
+    Api.getCloudConfig(param).then(result => {
       if (!result.status) {
         notification.warning({
           top: 92,
@@ -804,7 +763,7 @@
   }
 
   jointComponents = (config, navItem) => {
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 'sPC_Get_LongParam',
       TypeCharOne: sessionStorage.getItem('kei_no'),
       typename: 'pc',
@@ -1355,7 +1314,7 @@
             _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
             _param.secretkey = Utils.encrypt('', _param.timestamp)
 
-            Api.getSystemConfig(_param).then(res => {
+            Api.getCloudConfig(_param).then(res => {
               if (res.status) {
                 NavBar.open_edition = res.open_edition || ''
                 window.GLOB.CacheIndependent.set(NavBar.uuid, fromJS(NavBar).toJS())
@@ -1400,7 +1359,7 @@
                   kparam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
                   kparam.secretkey = Utils.encrypt('', kparam.timestamp)
         
-                  Api.getSystemConfig(kparam).then(result => {
+                  Api.getCloudConfig(kparam).then(result => {
                     if (result.status) {
                       sessionStorage.setItem('appViewList', viewList)
                     }
@@ -1419,7 +1378,7 @@
       }).then(res => { // 椤甸潰淇濆瓨
         if (!res || !res.status) return res
 
-        return Api.getSystemConfig(param)
+        return Api.getCloudConfig(param)
       }).then(res => {
         this.setState({
           menuloading: false
@@ -1443,7 +1402,6 @@
             message: '淇濆瓨鎴愬姛',
             duration: 2
           })
-          MKEmitter.emit('completeSave')
         } else {
           notification.warning({
             top: 92,
@@ -1451,6 +1409,7 @@
             duration: 5
           })
         }
+        MKEmitter.emit('completeSave')
       }, this.netError)
     }, 300 + (+sessionStorage.getItem('mkDelay')))
   }
@@ -1467,11 +1426,12 @@
         duration: 5
       })
     }
+    MKEmitter.emit('completeSave')
   }
 
   getRoleFields = () => {
     if (sessionStorage.getItem('sysRoles') || sessionStorage.getItem('permFuncField')) return
-    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
       if (res.status) {
         let _permFuncField = []
         let _sysRoles = []
@@ -1594,24 +1554,6 @@
     })
   }
 
-  refreshView = () => {
-    if (!is(fromJS(this.state.oriConfig || {}), fromJS(this.state.config || {}))) {
-      notification.warning({
-        top: 92,
-        message: '閰嶇疆淇℃伅鏈繚瀛橈紒',
-        duration: 5
-      })
-      return
-    }
-
-    sessionStorage.removeItem('sysRoles')
-    sessionStorage.removeItem('permFuncField')
-    sessionStorage.removeItem('app_videos')
-    sessionStorage.removeItem('app_pictures')
-    
-    window.location.reload()
-  }
-
   setHomeView = () => {
     const { config } = this.state
 
@@ -1655,7 +1597,7 @@
       title: '纭畾璁剧疆鏈〉闈负棣栭〉鍚楋紵',
       content: '',
       onOk() {
-        Api.getSystemConfig(param).then(result => {
+        Api.getCloudConfig(param).then(result => {
           if (!result.status) {
             notification.warning({
               top: 92,
@@ -1716,7 +1658,7 @@
       title: '纭畾璁剧疆鏈〉闈负鐧诲綍椤靛悧锛�',
       content: hasLogin ? '' : '褰撳墠椤甸潰灏氭湭娣诲姞鐧诲綍缁勪欢銆�',
       onOk() {
-        Api.getSystemConfig(param).then(result => {
+        Api.getCloudConfig(param).then(result => {
           if (!result.status) {
             notification.warning({
               top: 92,
@@ -1797,7 +1739,6 @@
                 <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                 <Transfer MenuID={MenuId} />
                 <Versions MenuId={MenuId} open_edition={config ? config.open_edition : ''}/>
-                <Button className="mk-border-danger" onClick={this.refreshView}><RedoOutlined /> 寮哄埗鍒锋柊</Button>
                 <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
               </div>
             </div>
diff --git a/src/views/pcdesign/menuform/index.jsx b/src/views/pcdesign/menuform/index.jsx
index 8c6262b..54bfde8 100644
--- a/src/views/pcdesign/menuform/index.jsx
+++ b/src/views/pcdesign/menuform/index.jsx
@@ -16,42 +16,16 @@
 
   state = {}
 
-  // 涓�浜岀骇鑿滃崟鍒囨崲
   selectChange = (key, value) => {
     const { config } = this.props
 
-    if (key === 'cacheUseful') {
-      this.props.updateConfig({...config, cacheUseful: value})
-    } else if (key === 'timeUnit') {
-      this.props.updateConfig({...config, timeUnit: value})
-    } else if (key === 'mask') {
-      this.props.updateConfig({...config, mask: value})
-    } else if (key === 'cacheLocal') {
-      this.props.updateConfig({...config, cacheLocal: value})
-    // } else if (key === 'permission') {
-    //   this.props.updateConfig({...config, permission: value})
+    if (key === 'cacheTime' || key === 'localCacheTime') {
+      if (typeof(value) !== 'number') {
+        value = ''
+      }
     }
-  }
 
-  // 鑿滃崟鍚嶇О
-  changeName = (e) => {
-    this.props.updateConfig({...this.props.config, MenuName: e.target.value})
-  }
-
-  // 鑿滃崟鍙傛暟
-  changeNo = (e) => {
-    this.props.updateConfig({...this.props.config, MenuNo: e.target.value})
-  }
-
-  changeRemark = (e) => {
-    this.props.updateConfig({...this.props.config, Remark: e.target.value})
-  }
-
-  changeCacheDay = (val) => {
-    if (typeof(val) !== 'number') {
-      val = ''
-    }
-    this.props.updateConfig({...this.props.config, cacheTime: val})
+    this.props.updateConfig({...config, [key]: value})
   }
 
   render() {
@@ -81,7 +55,7 @@
                     message: '璇疯緭鍏ヨ彍鍗曞悕绉�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" onChange={this.changeName}/>)}
+              })(<Input placeholder="" autoComplete="off" onChange={(e) => {this.selectChange('MenuName', e.target.value)}}/>)}
             </Form.Item>
           </Col>
           <Col span={24}>
@@ -94,7 +68,7 @@
                     message: '璇疯緭鍏ヨ彍鍗曞弬鏁�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" onChange={this.changeNo}/>)}
+              })(<Input placeholder="" autoComplete="off" onChange={(e) => {this.selectChange('MenuNo', e.target.value)}}/>)}
             </Form.Item>
           </Col>
           <Col span={24}>
@@ -114,6 +88,20 @@
               )}
             </Form.Item>
           </Col>
+          {config.cacheLocal === 'true' ? <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="璁剧疆鏈湴缂撳瓨鏃堕暱鍚庯紝鍦ㄧ紦瀛樻湡闄愬唴涓嶅悜鍚庡彴璇锋眰鏁版嵁锛屾椂闀挎渶澶т负5澶╋紙鍗�7200鍒嗛挓锛夈�傛敞锛氭椂闀夸负绌烘椂缂撳瓨鏁版嵁鍙敤浜庨〉闈㈠揩閫熷憟鐜帮紝涓嶅奖鍝嶆帴鍙h姹傘��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏃堕暱(鍒�)
+              </Tooltip>
+            }>
+              {getFieldDecorator('localCacheTime', {
+                initialValue: config.localCacheTime
+              })(
+                <InputNumber min={1} max={7200} precision={0} onChange={(val) => {this.selectChange('localCacheTime', val)}}/>
+              )}
+            </Form.Item>
+          </Col> : null}
           <Col span={24}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="瀵逛簬涓嶇粡甯告�у彉鍔ㄧ殑淇℃伅锛岀紦瀛樻暟鎹湁鍔╀簬鎻愰珮鏌ヨ鏁堢巼銆�">
@@ -167,9 +155,9 @@
           </Col>
           <Col span={24}>
             <Form.Item label={
-              <Tooltip placement="topLeft" title="鏁版嵁鍔犺浇鏃剁殑閬僵鍜岀┖鏁版嵁鍥炬爣鏄惁鏄剧ず銆�">
+              <Tooltip placement="topLeft" title="鏁版嵁鍔犺浇鏃剁殑閬僵鏄惁鏄剧ず銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
-                鏁版嵁鎻愮ず
+                鍔犺浇閬僵
               </Tooltip>
             }>
               {getFieldDecorator('mask', {
@@ -206,7 +194,7 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={(val) => {this.selectChange('cacheTime', val)}}/>
               )}
             </Form.Item>
           </Col> : null}
@@ -220,7 +208,7 @@
                     message: '澶囨敞鏈�澶�512涓瓧绗︼紒'
                   }
                 ]
-              })(<TextArea rows={2} placeholder={''} onChange={this.changeRemark} />)}
+              })(<TextArea rows={2} placeholder={''} onChange={(e) => {this.selectChange('Remark', e.target.value)}}/>)}
             </Form.Item>
           </Col>
         </Row>
diff --git a/src/views/printTemplate/index.jsx b/src/views/printTemplate/index.jsx
index a477433..3375efd 100644
--- a/src/views/printTemplate/index.jsx
+++ b/src/views/printTemplate/index.jsx
@@ -20,7 +20,6 @@
   qrurl,
   imgurl
 } from './option.js'
-import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
 import printCtrl from './print.js'
 import Api from '@/api'
@@ -455,7 +454,7 @@
 
     let deffers = tables.map(name => {
       return new Promise(resolve => {
-        Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: name}).then(res => {
+        Api.getCloudConfig({func: 'sPC_Get_FieldName', TBName: name}).then(res => {
           resolve(res)
         })
       })
@@ -776,8 +775,8 @@
           Base64Img: res
         }
 
-        if (options.cloudServiceApi) {
-          param.rduri = options.cloudServiceApi
+        if (window.GLOB.cloudServiceApi) {
+          param.rduri = window.GLOB.cloudServiceApi
           param.userid = sessionStorage.getItem('CloudUserID') || ''
           param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         }
diff --git a/src/views/rolemanage/index.jsx b/src/views/rolemanage/index.jsx
index 5c5a369..ce7203b 100644
--- a/src/views/rolemanage/index.jsx
+++ b/src/views/rolemanage/index.jsx
@@ -19,8 +19,6 @@
 const Header = asyncComponent(() => import('./header'))
 const TransferForm = asyncComponent(() => import('@/templates/zshare/basetransferform'))
 
-sessionStorage.setItem('isEditState', 'true')
-
 class RoleManage extends Component {
   state = {
     app: null,
@@ -95,7 +93,7 @@
   getAppViewList = () => {
     const { app } = this.state
 
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 's_get_keyids',
       bid: app.ID
     }).then(result => {
@@ -482,7 +480,7 @@
       confirmLoading: true
     })
 
-    Api.getSystemConfig({
+    Api.getCloudConfig({
       func: 'sPC_MainMenu_ReDel',
       MenuID: targetKeys.join(','),
       TypeCharOne: app.kei_no,
@@ -549,7 +547,7 @@
             })
 
             if (app.typename === 'pc' && list.length > 0) {
-              Api.getSystemConfig({
+              Api.getCloudConfig({
                 func: 'sPC_MainMenu_ReDel',
                 MenuID: list.join(','),
                 TypeCharOne: app.kei_no,
diff --git a/src/views/sso/index.jsx b/src/views/sso/index.jsx
index a26036a..053eaf1 100644
--- a/src/views/sso/index.jsx
+++ b/src/views/sso/index.jsx
@@ -62,12 +62,6 @@
 
     Api.getSystemConfig(_param).then(res => {
       if (res.status) {
-        // positecgroup
-        res.Banner = res.Banner ? res.Banner.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
-        res.doclogo = res.doclogo ? res.doclogo.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
-        res.indexlogo = res.indexlogo ? res.indexlogo.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
-        res.loginlogo = res.loginlogo ? res.loginlogo.replace(/:8080/ig, '').replace(/http:/ig, 'https:') : ''
-
         if (!['shutter', 'linkage_navigation', 'linkage', 'menu_board', 'menu_board_navigation'].includes(res.menu_type)) {
           res.menu_type = 'shutter'
         }
@@ -141,7 +135,7 @@
 
         let memberLevel = res.member_level
 
-        if (typeof(memberLevel) === 'number' && memberLevel > 10 && parseInt(memberLevel / 10) * 10 === memberLevel) {
+        if (typeof(memberLevel) === 'number' && memberLevel > 0 && parseInt(memberLevel / 10) * 10 === memberLevel) {
           sessionStorage.setItem('Member_Level', md5('mksoft' + window.GLOB.appkey + new Date().getFullYear() + new Date().getMonth() + memberLevel))
           window.GLOB.memberLevel = memberLevel
         }
diff --git a/src/views/systemfunc/index.jsx b/src/views/systemfunc/index.jsx
index 6910e9b..270c6ea 100644
--- a/src/views/systemfunc/index.jsx
+++ b/src/views/systemfunc/index.jsx
@@ -1,5 +1,6 @@
 import React, {Component} from 'react'
 import { ConfigProvider } from 'antd'
+import { withRouter } from 'react-router-dom'
 import zhCN from 'antd/es/locale/zh_CN'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -11,22 +12,29 @@
 
 const Tabview = asyncComponent(() => import('@/components/tabview'))
 
-class Design extends Component {
+class MkHS extends Component {
   UNSAFE_componentWillMount() {
-    sessionStorage.setItem('role_id', sessionStorage.getItem('cloudRole_id'))
-    sessionStorage.setItem('dataM', sessionStorage.getItem('cloudDataM'))
-    document.body.className = 'mk-blue-black'
-    sessionStorage.setItem('isEditState', 'true')
-    window.GLOB.mkHS = true
-
-    // HS涓嬩笉鍙紑鍚柇鐐硅皟璇�
-    window.GLOB.breakpoint = false
-    sessionStorage.removeItem('breakpoint')
-
-    Object.defineProperty(window, 'debugger', {
-      writable: false,
-      value: false
-    })
+    if (!sessionStorage.getItem('UserID')) {
+      this.props.history.replace('/login')
+    } else {
+      sessionStorage.setItem('role_id', sessionStorage.getItem('cloudRole_id'))
+      sessionStorage.setItem('dataM', sessionStorage.getItem('cloudDataM'))
+      sessionStorage.setItem('User_Name', sessionStorage.getItem('CloudUserName'))
+      sessionStorage.setItem('Full_Name', sessionStorage.getItem('CloudFullName'))
+  
+      document.body.className = 'mk-blue-black'
+      window.GLOB.dataFormat = false // 鍘婚櫎姘村嵃
+      window.GLOB.mkHS = true
+  
+      // HS涓嬩笉鍙紑鍚柇鐐硅皟璇�
+      window.GLOB.breakpoint = false
+      sessionStorage.removeItem('breakpoint')
+  
+      Object.defineProperty(window, 'debugger', {
+        writable: false,
+        value: false
+      })
+    }
   }
 
   componentDidMount () {
@@ -54,4 +62,4 @@
   }
 }
 
-export default Design
\ No newline at end of file
+export default withRouter(MkHS)
\ No newline at end of file
diff --git a/src/views/systemfunc/sidemenu/config.jsx b/src/views/systemfunc/sidemenu/config.jsx
index e62128f..ce7475b 100644
--- a/src/views/systemfunc/sidemenu/config.jsx
+++ b/src/views/systemfunc/sidemenu/config.jsx
@@ -98,36 +98,36 @@
     MenuName: '鎺ュ彛涓绘暟鎹�',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1582777675954ifu05upurs465omoth7',
     MenuNo: 'KUNMainM',
     MenuName: '鏌ヨ鎺ュ彛',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '158294809668898cklbv6c5bou8e1fpu',
     MenuNo: 'KUNMainMOut_advanced',
     MenuName: '楂橀樁鏌ヨ',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1584676379094iktph45fb8imhg96bql',
     MenuNo: 'KUNMainM_Out_usual',
     MenuName: '閫氱敤鏌ヨ鎺ュ彛',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1584695125339vo5g7iqgfn01qmrd6s2',
     MenuNo: 'KUNMainM_In_usual',
     MenuName: '閫氱敤鍐欏叆鎺ュ彛',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1584699661372vhmpp9dn9foo0eob722',
     MenuNo: 'KUNMainM_In',
     MenuName: '鍐欏叆鎺ュ彛',
diff --git a/src/views/systemfunc/sidemenu/index.jsx b/src/views/systemfunc/sidemenu/index.jsx
index 21bd103..b6c4b15 100644
--- a/src/views/systemfunc/sidemenu/index.jsx
+++ b/src/views/systemfunc/sidemenu/index.jsx
@@ -4,7 +4,6 @@
 import { FolderOutlined } from '@ant-design/icons'
 
 import { SySMenuList } from './config'
-import options from '@/store/options.js'
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
@@ -34,7 +33,7 @@
       menulist = menulist.filter(menu => menu.children.length > 0)
     } else {
       menulist.forEach(menu => {
-        menu.children = menu.children.filter(item => !item.systems || item.systems.includes(options.sysType))
+        menu.children = menu.children.filter(item => !item.systems || item.systems.includes(window.GLOB.sysType))
       })
 
       menulist = menulist.filter(menu => menu.children.length > 0)
diff --git a/src/views/systemproc/index.jsx b/src/views/systemproc/index.jsx
index 7aab3b5..9f1f68a 100644
--- a/src/views/systemproc/index.jsx
+++ b/src/views/systemproc/index.jsx
@@ -1,24 +1,32 @@
 import React, {Component} from 'react'
 import { ConfigProvider } from 'antd'
+import { withRouter } from 'react-router-dom'
 import zhCN from 'antd/es/locale/zh_CN'
 
-// import Api from '@/api'
-// import Utils from '@/utils/utils.js' 
 import Header from '../systemfunc/header'
 import Proc from './proc'
 import './index.scss'
 
 class SysProc extends Component {
+  componentDidMount() {
+    if (!sessionStorage.getItem('UserID')) {
+      this.props.history.replace('/login')
+    }
+  }
+
   render () {
+    const { params } = this.props.match
+    let func = params && params.func ? params.func : ''
+
     return (
       <div className="mk-proc-view">
         <ConfigProvider locale={zhCN}>
           <Header key="header"/>
-          <Proc />
+          <Proc func={func} />
         </ConfigProvider>
       </div>
     )
   }
 }
 
-export default SysProc
\ No newline at end of file
+export default withRouter(SysProc)
\ No newline at end of file
diff --git a/src/views/systemproc/proc/index.jsx b/src/views/systemproc/proc/index.jsx
index f5156bb..62ce63a 100644
--- a/src/views/systemproc/proc/index.jsx
+++ b/src/views/systemproc/proc/index.jsx
@@ -13,7 +13,7 @@
 
 class ProcControl extends Component {
   state = {
-    procName: '',
+    procName: this.props.func || '',
     content: '',
     loading: false,
     visible: false,
@@ -24,9 +24,12 @@
   }
 
   componentDidMount () {
+    sessionStorage.setItem('User_Name', sessionStorage.getItem('CloudUserName'))
+    sessionStorage.setItem('Full_Name', sessionStorage.getItem('CloudFullName'))
+    
     if (sessionStorage.getItem('permFuncField')) {
       this.setState({permFuncs: JSON.parse(sessionStorage.getItem('permFuncField'))})
-    } else {
+    } else if (sessionStorage.getItem('UserID')) {
       Api.getCloudConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
         if (res.status) {
           let _permFuncs = []
@@ -53,6 +56,12 @@
           })
         }
       })
+    }
+
+    if (this.props.func && sessionStorage.getItem('UserID')) {
+      setTimeout(() => {
+        this.search(this.props.func)
+      }, 500)
     }
   }
 
@@ -159,7 +168,6 @@
     dropParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     dropParam.secretkey = Utils.encrypt(dropParam.LText, dropParam.timestamp)
     dropParam.open_key = Utils.encryptOpenKey(dropParam.secretkey, dropParam.timestamp)
-
 
     let createParam = {
       func: 'sPC_TableData_InUpDe',
diff --git a/src/views/systemproc/proc/index.scss b/src/views/systemproc/proc/index.scss
index e0a327c..ac98dcd 100644
--- a/src/views/systemproc/proc/index.scss
+++ b/src/views/systemproc/proc/index.scss
@@ -113,6 +113,15 @@
   .code-mirror-wrap .anticon-font-size {
     position: absolute;
   }
+
+  .anticon-swap {
+    position: absolute;
+    z-index: 11;
+    left: auto;
+    right: 10px;
+    top: auto;
+    bottom: 20px;
+  }
 }
 
 .mk-create-func {
diff --git a/src/views/tabledesign/index.jsx b/src/views/tabledesign/index.jsx
index 759be21..4696876 100644
--- a/src/views/tabledesign/index.jsx
+++ b/src/views/tabledesign/index.jsx
@@ -42,7 +42,6 @@
 const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
 const PasteBaseTable = asyncComponent(() => import('@/menu/components/share/pastebasetable'))
 
-sessionStorage.setItem('isEditState', 'true')
 sessionStorage.setItem('appType', '')          // 搴旂敤绫诲瀷
 document.body.className = ''
 
@@ -71,7 +70,6 @@
     }
     
     if (!sessionStorage.getItem('UserID')) {
-      sessionStorage.removeItem('isEditState')
       sessionStorage.removeItem('appType')
       this.props.history.replace('/login')
       return
@@ -116,7 +114,6 @@
     MKEmitter.addListener('changePopview', this.initPopview)
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
     setTimeout(() => {
-      this.getPrintTemp()
       this.getRoleFields()
       setGLOBFuncs()
     }, 1000)
@@ -193,50 +190,6 @@
     if (this.state.view === 'popview') return
     
     this.submitConfig()
-  }
-
-  getPrintTemp = () => {
-    if (!sessionStorage.getItem('printTemps')) {
-      let _sql = `select ID,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate 
-      where appkey= @appkey@ and Deleted=0 and typechartwo='web_print'
-      union select ID,Images,a.PrintTempNO+PrintTempName as PN 
-      from (select * from sPrintTemplate where appkey= '' and Deleted=0 and typechartwo='web_print') a 
-      left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@ and Deleted=0 ) b 
-      on a.PrintTempNO=b.PrintTempNO 
-      left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c 
-      on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null`
-  
-      let param = {
-        func: 'sPC_Get_SelectedList',
-        LText: Utils.formatOptions(_sql),
-        obj_name: 'data',
-        arr_field: 'PN,ID,Images'
-      }
-  
-      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-  
-      param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
-  
-      Api.getSystemConfig(param).then(res => {
-        if (res.status) {
-          let temps = res.data.map(temp => {
-            return {
-              value: temp.ID,
-              text: temp.PN
-            }
-          })
-  
-          sessionStorage.setItem('printTemps', JSON.stringify(temps))
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-        }
-      })
-    }
   }
 
   initPopview = (card, btn) => {
@@ -390,7 +343,7 @@
       MenuID: MenuId
     }
 
-    Api.getSystemConfig(param).then(result => {
+    Api.getCloudConfig(param).then(result => {
       if (result.status) {
         let config = null
 
@@ -666,7 +619,7 @@
       btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
 
       new Promise(resolve => {
-        Api.getSystemConfig(param).then(res => {
+        Api.getCloudConfig(param).then(res => {
           resolve(res)
         }, this.netError)
       }).then(res => {
@@ -680,7 +633,7 @@
           oriConfig: fromJS(config).toJS(),
         })
 
-        return Api.getSystemConfig(btnParam)
+        return Api.getCloudConfig(btnParam)
       }).then(res => {
         this.setState({
           menuloading: false
@@ -694,7 +647,6 @@
             message: '淇濆瓨鎴愬姛',
             duration: 2
           })
-          MKEmitter.emit('completeSave')
         } else {
           notification.warning({
             top: 92,
@@ -702,6 +654,7 @@
             duration: 5
           })
         }
+        MKEmitter.emit('completeSave')
       }, this.netError)
     }, 300 + (+sessionStorage.getItem('mkDelay')))
   }
@@ -718,11 +671,12 @@
         duration: 5
       })
     }
+    MKEmitter.emit('completeSave')
   }
 
   getRoleFields = () => {
     if (sessionStorage.getItem('sysRoles')) return
-    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
+    Api.getCloudConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
       if (res.status) {
         let _permFuncField = []
         let _sysRoles = []
diff --git a/src/views/tabledesign/menuform/index.jsx b/src/views/tabledesign/menuform/index.jsx
index fe0a8e6..9c128c1 100644
--- a/src/views/tabledesign/menuform/index.jsx
+++ b/src/views/tabledesign/menuform/index.jsx
@@ -1,9 +1,8 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, notification, Radio, Switch } from 'antd'
+import { Form, Row, Col, Input, Select, notification, Switch } from 'antd'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import './index.scss'
 
 const { TextArea } = Input
@@ -76,7 +75,7 @@
   getMenus = () => {
     const { MenuId, config } = this.props
 
-    Api.getSystemConfig({func: 's_get_pc_menus', systemType: options.sysType, debug: 'Y'}).then(result => {
+    Api.getCloudConfig({func: 's_get_pc_menus', systemType: window.GLOB.sysType, debug: 'Y'}).then(result => {
       if (result.status) {
         let thdMenu = null
         let thdMenuList = []
@@ -324,10 +323,11 @@
                   }
                 ]
               })(
-                <Radio.Group onChange={(e) => {this.selectChange('OpenType', e.target.value)}}>
-                  <Radio value="newtab">鏍囩椤�</Radio>
-                  <Radio value="newpage">鏂伴〉闈�</Radio>
-                </Radio.Group>
+                <Select onChange={(value) => {this.selectChange('OpenType', value)}}>
+                  <Select.Option value="newtab">鏍囩椤�</Select.Option>
+                  <Select.Option value="newpage">鏂伴〉闈紙鏍囩椤碉級</Select.Option>
+                  <Select.Option value="view">鏂伴〉闈紙鍏ㄥ睆锛�</Select.Option>
+                </Select>
               )}
             </Form.Item>
           </Col>

--
Gitblit v1.8.0