From 08cce3334a2dc81d690b518136b0aaea64e48b0b Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 14 六月 2023 09:55:50 +0800
Subject: [PATCH] 2023-06-14

---
 src/templates/zshare/modalform/index.jsx                                           |   81 
 src/tabviews/formtab/index.jsx                                                     |    2 
 src/menu/components/timeline/normal-timeline/index.jsx                             |   37 
 src/tabviews/custom/components/editor/braft-editor/index.jsx                       |    2 
 src/menu/components/form/dragtitle/options.jsx                                     |   67 
 src/menu/components/card/balcony/options.jsx                                       |   26 
 src/menu/components/chart/antv-X6/index.scss                                       |  233 
 src/tabviews/zshare/settingcomponent/index.jsx                                     |   52 
 src/templates/zshare/verifycard/customscript/index.jsx                             |    9 
 src/tabviews/custom/popview/index.jsx                                              |  375 
 src/menu/components/chart/antv-scatter/index.jsx                                   |   34 
 src/menu/components/table/edit-table/columns/editColumn/index.scss                 |   29 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx  |   73 
 src/views/interface/workspace/index.jsx                                            |   18 
 src/menu/components/table/edit-table/columns/editColumn/index.jsx                  |  198 
 src/templates/zshare/editTable/index.scss                                          |    3 
 src/tabviews/zshare/actionList/changeuserbutton/index.jsx                          |    2 
 src/menu/components/table/edit-table/columns/tableIn/index.scss                    |    8 
 src/menu/datasource/verifycard/index.jsx                                           |   54 
 src/views/menudesign/popview/menuform/index.jsx                                    |    5 
 src/views/menudesign/menuform/index.scss                                           |    8 
 src/components/header/index.scss                                                   |   15 
 src/menu/components/chart/antv-G6/index.scss                                       |   23 
 src/menu/components/card/cardcellcomponent/index.jsx                               |   51 
 src/menu/components/form/tab-form/index.jsx                                        |  137 
 src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx     |   10 
 src/menu/components/carousel/prop-card/index.jsx                                   |   61 
 src/templates/zshare/verifycard/uniqueform/index.jsx                               |    2 
 src/menu/components/search/main-search/dragsearch/card.jsx                         |    6 
 src/menu/components/card/cardcomponent/index.jsx                                   |   57 
 src/templates/modalconfig/dragelement/index.scss                                   |   34 
 src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx                |   32 
 src/menu/components/chart/antv-pie/index.jsx                                       |   34 
 src/menu/components/table/edit-table/columns/index.scss                            |   18 
 src/menu/components/table/edit-table/columns/tableIn/uniqueform/index.jsx          |    6 
 src/menu/components/card/prop-card/index.jsx                                       |  123 
 src/templates/zshare/customscript/index.jsx                                        |    7 
 src/templates/zshare/modalform/modaleditable/index.jsx                             |   84 
 src/menu/components/tabs/paste/index.jsx                                           |   12 
 src/menu/components/table/edit-table/columns/index.jsx                             |  235 
 src/menu/modalconfig/controller.jsx                                                |    2 
 src/menu/components/module/voucher/voucherTable/index.scss                         |  110 
 src/menu/components/card/cardsimplecomponent/node-wrap/index.jsx                   |    6 
 src/tabviews/custom/components/chart/antv-bar-line/index.jsx                       |    7 
 package-lock.json                                                                  |  108 
 src/assets/css/viewstyle.scss                                                      |   16 
 src/tabviews/custom/components/chart/antv-dashboard/index.jsx                      |    7 
 src/views/login/loginform.jsx                                                      |    7 
 src/views/menudesign/popview/index.jsx                                             |   33 
 src/views/pcdesign/menuform/index.scss                                             |    8 
 src/menu/datasource/verifycard/index.scss                                          |   28 
 src/templates/zshare/codemirror/index.scss                                         |   41 
 src/menu/components/share/actioncomponent/dragaction/card.jsx                      |    6 
 src/tabviews/zshare/topSearch/index.jsx                                            |   12 
 src/templates/comtableconfig/index.jsx                                             |    8 
 src/menu/components/chart/chart-custom/index.jsx                                   |   18 
 src/menu/components/form/simple-form/options.jsx                                   |   57 
 src/menu/components/card/cardsimplecomponent/options.jsx                           |   11 
 src/menu/components/form/simple-form/index.jsx                                     |  133 
 src/tabviews/zshare/mutilform/mkCheck/index.jsx                                    |   41 
 src/menu/modalconfig/tablecomponent/index.scss                                     |   36 
 src/tabviews/custom/components/table/edit-table/index.jsx                          |  326 
 src/api/index.js                                                                   |  415 
 src/mob/components/formdragelement/index.scss                                      |   65 
 src/tabviews/zshare/topSearch/index.scss                                           |    4 
 src/views/mobdesign/menuform/index.scss                                            |    8 
 src/templates/formtabconfig/index.scss                                             |    2 
 src/templates/zshare/codemirror/index.jsx                                          |   97 
 src/menu/sysinterface/index.jsx                                                    |    7 
 src/mob/components/search/single-search/index.jsx                                  |    4 
 src/menu/components/table/base-table/columns/index.scss                            |   13 
 src/menu/components/table/base-table/columns/editColumn/index.jsx                  |  223 
 src/tabviews/custom/components/table/base-table/index.scss                         |   24 
 src/views/pcdesign/index.jsx                                                       |  193 
 src/menu/datasource/verifycard/settingform/index.jsx                               |   35 
 src/mob/components/formdragelement/index.jsx                                       |    2 
 src/menu/components/share/actioncomponent/index.jsx                                |  188 
 src/menu/components/card/cardsimplecomponent/index.jsx                             |    1 
 src/tabviews/custom/components/form/step-form/index.jsx                            |   12 
 src/components/pasteboard/index.jsx                                                |  134 
 src/views/systemfunc/sidemenu/config.jsx                                           |  115 
 src/menu/components/form/dragtitle/card.jsx                                        |   14 
 src/templates/zshare/editTable/index.jsx                                           |  210 
 src/tabviews/formtab/actionList/index.jsx                                          |    2 
 src/menu/components/editor/braft-editor/options.jsx                                |   35 
 src/menu/components/group/paste/index.jsx                                          |    4 
 src/tabviews/custom/components/tree/antd-tree/index.jsx                            |    7 
 src/tabviews/zshare/actionList/popupbutton/index.jsx                               |   14 
 src/templates/zshare/codemirror/replaceform/index.jsx                              |  102 
 src/tabviews/custom/components/tabs/antv-tabs/index.jsx                            |    2 
 src/tabviews/zshare/normalTable/index.jsx                                          |    3 
 src/templates/comtableconfig/updatetable/index.jsx                                 |  292 
 src/templates/zshare/codemirror/replaceform/index.scss                             |    0 
 src/views/menudesign/homeform/index.jsx                                            |    5 
 src/views/menudesign/menuform/index.jsx                                            |  110 
 src/menu/datasource/index.jsx                                                      |   10 
 src/menu/components/module/voucher/index.jsx                                       |    4 
 src/templates/zshare/menuform/index.jsx                                            |    2 
 src/menu/components/table/base-table/index.scss                                    |    3 
 src/templates/zshare/verifycard/contrastform/index.jsx                             |    2 
 src/menu/components/tree/antd-tree/index.jsx                                       |   31 
 src/tabviews/custom/index.scss                                                     |   11 
 src/views/billprint/index.jsx                                                      |   89 
 src/locales/en-US/main.js                                                          |   26 
 src/menu/components/editor/braft-editor/index.scss                                 |    9 
 src/tabviews/subtabtable/index.jsx                                                 |    2 
 src/tabviews/zshare/actionList/normalbutton/index.jsx                              |  317 
 src/tabviews/custom/components/table/normal-table/index.scss                       |   36 
 src/views/menudesign/index.jsx                                                     |  166 
 src/menu/modulesource/option.jsx                                                   |    6 
 src/tabviews/custom/components/card/data-card/index.jsx                            |  123 
 src/templates/zshare/verifycard/fullScripts/index.scss                             |  130 
 src/components/mkPicture/index.jsx                                                 |   13 
 src/tabviews/subtable/index.scss                                                   |   15 
 src/tabviews/custom/components/module/voucher/index.jsx                            |   61 
 src/menu/components/code/sandbox/codecontent/index.jsx                             |   12 
 src/templates/sharecomponent/actioncomponent/actionform/index.jsx                  |    8 
 src/menu/modalconfig/tablecomponent/index.jsx                                      |  163 
 src/templates/calendarconfig/index.jsx                                             |    5 
 src/templates/zshare/pasteform/index.jsx                                           |   31 
 src/menu/components/card/double-data-card/index.jsx                                |   84 
 src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx              |    5 
 src/views/login/logincloudform.jsx                                                 |    2 
 src/menu/components/card/doublecardcomponent/index.jsx                             |    4 
 src/router/index.js                                                                |   71 
 src/menu/pastecontroller/index.jsx                                                 |   20 
 src/menu/components/card/data-card/index.jsx                                       |   85 
 src/menu/components/chart/antv-dashboard/index.jsx                                 |   26 
 src/menu/components/share/clockcomponent/settingform/index.jsx                     |    4 
 src/views/appmanage/index.jsx                                                      |   33 
 src/menu/components/card/cardcellcomponent/elementform/index.scss                  |   20 
 src/tabviews/custom/components/card/tableHeader/index.jsx                          |  160 
 src/tabviews/zshare/actionList/index.scss                                          |    7 
 src/templates/sharecomponent/settingcomponent/index.jsx                            |    1 
 src/menu/components/card/doublecardcomponent/options.jsx                           |   11 
 src/menu/components/chart/antv-G6/index.jsx                                        |   39 
 src/templates/subtableconfig/source.jsx                                            |  124 
 src/menu/components/table/normal-table/options.jsx                                 |   95 
 src/components/header/index.jsx                                                    |   36 
 src/views/pcdesign/menuform/index.jsx                                              |    7 
 src/tabviews/custom/components/card/double-data-card/index.jsx                     |  360 
 src/templates/formtabconfig/index.jsx                                              |   32 
 src/templates/zshare/verifycard/callbackcustomscript/index.jsx                     |    9 
 src/views/interface/api/index.js                                                   |  116 
 src/tabviews/custom/components/card/cardItem/index.jsx                             |   19 
 src/menu/components/chart/antv-X6/index.jsx                                        |  788 ++
 src/menu/transfer/index.jsx                                                        |    6 
 src/menu/components/iframe/index.jsx                                               |   19 
 src/tabviews/custom/components/carousel/data-card/index.jsx                        |   25 
 src/templates/sharecomponent/fieldscomponent/index.jsx                             |   28 
 src/menu/components/code/sandbox/index.jsx                                         |   17 
 src/views/tabledesign/menuform/index.jsx                                           |    4 
 src/templates/zshare/verifycard/customform/index.jsx                               |   11 
 src/menu/components/chart/antv-X6/nodeupdate/index.jsx                             |  288 
 src/menu/components/table/normal-table/columns/index.scss                          |   15 
 src/tabviews/custom/components/tree/antd-tree/index.scss                           |   24 
 src/components/paste/index.jsx                                                     |    4 
 src/tabviews/custom/components/chart/custom-chart/index.jsx                        |    7 
 src/menu/components/card/balcony/index.jsx                                         |   72 
 src/tabviews/zshare/actionList/tabbutton/index.jsx                                 |    2 
 src/components/normalform/modalform/index.jsx                                      |   43 
 src/menu/stylecontroller/index.jsx                                                 |   98 
 src/menu/components/table/base-table/options.jsx                                   |   27 
 src/tabviews/custom/components/module/voucher/voucherTable/index.scss              |   11 
 src/templates/zshare/verifycard/index.jsx                                          |  192 
 src/menu/modulecell/index.jsx                                                      |    3 
 src/tabviews/zshare/actionList/printbutton/index.jsx                               |  151 
 src/menu/components/chart/antv-X6/nodeupdate/index.scss                            |   67 
 src/tabviews/custom/components/table/edit-table/normalTable/index.scss             |  172 
 src/menu/components/card/cardcellcomponent/formconfig.jsx                          |  175 
 src/templates/sharecomponent/actioncomponent/index.jsx                             |   14 
 src/tabviews/custom/components/module/voucher/index.scss                           |   11 
 src/menu/components/editor/braft-editor/index.jsx                                  |   21 
 src/menu/components/module/voucher/index.scss                                      |   10 
 package.json                                                                       |   11 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx   |   40 
 src/menu/components/share/markcomponent/markform/index.jsx                         |    9 
 src/views/systemproc/proc/index.jsx                                                |    3 
 src/menu/components/card/cardsimplecomponent/node-wrap/menus/index.jsx             |   19 
 src/templates/sharecomponent/columncomponent/columnform/index.scss                 |    5 
 src/menu/components/share/markcomponent/index.jsx                                  |    9 
 src/mob/components/tabs/antv-tabs/options.jsx                                      |   12 
 src/menu/components/card/cardcellcomponent/index.scss                              |  227 
 src/menu/components/card/cardcellcomponent/dragaction/action.jsx                   |    7 
 src/menu/components/card/cardcellcomponent/elementform/index.jsx                   |  329 
 src/menu/components/share/actioncomponent/dragaction/index.jsx                     |   14 
 src/menu/components/table/edit-table/options.jsx                                   |  162 
 src/templates/modalconfig/index.jsx                                                |    5 
 src/views/systemfunc/index.jsx                                                     |   15 
 src/templates/sharecomponent/tablecomponent/index.jsx                              |   29 
 src/tabviews/zshare/actionList/newpagebutton/index.jsx                             |    2 
 src/mob/modalconfig/index.jsx                                                      |   66 
 src/tabviews/commontable/index.jsx                                                 |   15 
 src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx  |    8 
 src/components/header/loginform.jsx                                                |   22 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx               |   82 
 src/views/tabledesign/menuform/index.scss                                          |    8 
 src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx             |  155 
 src/tabviews/custom/components/table/edit-table/index.scss                         |   62 
 src/tabviews/custom/components/card/cardcellList/index.jsx                         |  255 
 src/tabviews/custom/components/card/prop-card/index.jsx                            |   43 
 src/views/design/sidemenu/editsecmenu/index.jsx                                    |    1 
 src/menu/components/carousel/data-card/options.jsx                                 |    4 
 src/menu/components/card/data-card/options.jsx                                     |   66 
 src/tabviews/custom/components/table/normal-table/index.jsx                        |  161 
 src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx |    8 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx   |    6 
 src/menu/components/chart/antv-X6/chartcompile/index.scss                          |    6 
 src/tabviews/custom/components/chart/antv-pie/index.jsx                            |    7 
 src/tabviews/custom/components/timeline/normal-timeline/index.jsx                  |   42 
 src/templates/subtableconfig/index.jsx                                             |    7 
 src/tabviews/custom/components/table/edit-table/normalTable/index.jsx              | 1119 +-
 src/components/breadview/index.jsx                                                 |   14 
 src/tabviews/custom/components/editor/braft-editor/index.scss                      |   10 
 src/tabviews/zshare/mutilform/index.jsx                                            |   87 
 src/tabviews/commontable/index.scss                                                |    2 
 src/templates/zshare/modalform/index.scss                                          |    6 
 src/menu/components/share/actioncomponent/actionform/index.jsx                     |   95 
 src/tabviews/custom/index.jsx                                                      |  492 
 src/menu/components/card/cardcomponent/index.scss                                  |    5 
 src/menu/components/table/normal-table/columns/index.jsx                           |  204 
 src/menu/components/timeline/normal-timeline/options.jsx                           |   48 
 src/pc/components/navbar/normal-navbar/index.jsx                                   |    4 
 src/tabviews/custom/components/chart/antv-scatter/index.jsx                        |    7 
 src/menu/components/card/cardcellcomponent/dragaction/index.scss                   |   17 
 src/views/design/header/index.jsx                                                  |   96 
 src/tabviews/custom/components/module/account/index.jsx                            |   23 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx    |    4 
 src/menu/components/chart/antv-X6/chartcompile/index.jsx                           |  179 
 src/tabviews/custom/components/chart/antv-G6/index.jsx                             |    6 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx    |    6 
 src/menu/components/card/cardcellcomponent/dragaction/index.jsx                    |   18 
 src/menu/components/table/base-table/columns/editColumn/formconfig.jsx             |   67 
 src/tabviews/custom/popview/index.scss                                             |    6 
 src/templates/zshare/verifycard/fullScripts/index.jsx                              |  130 
 src/templates/zshare/verifycard/billcodeform/index.jsx                             |    2 
 src/tabviews/zshare/actionList/exceloutbutton/index.jsx                            |   38 
 src/menu/components/card/cardcellcomponent/dragaction/card.jsx                     |   12 
 src/menu/components/card/balcony/index.scss                                        |    1 
 src/menu/components/chart/antv-bar/index.jsx                                       |   43 
 src/views/tabledesign/index.jsx                                                    |  161 
 src/tabviews/zshare/actionList/index.jsx                                           |   42 
 src/tabviews/subtable/index.jsx                                                    |    2 
 src/menu/components/table/normal-table/columns/editColumn/index.scss               |   23 
 src/menu/components/table/edit-table/index.jsx                                     |   76 
 src/menu/components/carousel/data-card/index.jsx                                   |   38 
 src/templates/zshare/verifycard/index.scss                                         |  130 
 src/tabviews/custom/components/card/table-card/index.jsx                           |   16 
 src/menu/components/module/voucher/options.jsx                                     |   21 
 src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx                 |   47 
 src/menu/components/form/step-form/index.jsx                                       |  145 
 src/menu/components/share/actioncomponent/index.scss                               |    3 
 src/templates/comtableconfig/source.jsx                                            |  230 
 src/views/mobdesign/popview/index.jsx                                              |   33 
 src/menu/components/search/main-search/index.jsx                                   |    2 
 src/tabviews/custom/components/module/voucher/voucherTable/index.jsx               |    8 
 src/tabviews/zshare/mutilform/mkCheck/index.scss                                   |    0 
 src/tabviews/zshare/pageMessage/index.jsx                                          |    5 
 src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx        |   64 
 src/components/sidemenu/index.jsx                                                  |    3 
 src/views/login/index.jsx                                                          |   49 
 src/menu/components/card/cardsimplecomponent/node-wrap/menus/columnform/index.jsx  |   19 
 src/tabviews/custom/components/code/sand-box/index.jsx                             |   56 
 src/menu/components/table/edit-table/columns/tableIn/index.jsx                     |  188 
 src/tabviews/zshare/actionList/editLine/index.jsx                                  |  149 
 src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx   |    7 
 src/menu/components/card/table-card/index.jsx                                      |   57 
 src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx                      |  232 
 src/templates/zshare/verifycard/baseform/index.scss                                |   26 
 src/menu/components/share/pastebasetable/index.jsx                                 |   41 
 src/menu/components/share/pasteforms/index.jsx                                     |  178 
 src/tabviews/subtabtable/index.scss                                                |   15 
 src/utils/utils-custom.js                                                          |  398 
 src/views/main/index.jsx                                                           |   14 
 src/tabviews/custom/components/share/normalTable/index.scss                        |   74 
 src/templates/sharecomponent/fieldscomponent/editcard/index.jsx                    |    5 
 src/views/design/header/editfirstmenu/index.jsx                                    |    1 
 src/tabviews/zshare/actionList/excelInbutton/index.jsx                             |   24 
 public/options.json                                                                |    3 
 src/menu/components/share/searchcomponent/dragsearch/card.jsx                      |    6 
 src/views/tabledesign/source.jsx                                                   |    6 
 src/menu/components/table/normal-table/columns/editColumn/index.jsx                |  204 
 src/tabviews/basetable/index.jsx                                                   |  126 
 src/menu/components/card/data-card/index.scss                                      |    9 
 src/menu/menushell/card.jsx                                                        |   12 
 src/tabviews/zshare/mutilform/mkVercode/index.jsx                                  |    2 
 src/menu/components/code/sandbox/options.jsx                                       |   28 
 src/templates/calendarconfig/source.jsx                                            |   37 
 src/templates/modalconfig/dragelement/card.jsx                                     |   10 
 src/views/design/sidemenu/editthdmenu/index.jsx                                    |    1 
 src/views/mobdesign/index.jsx                                                      |  224 
 src/views/interface/history/index.jsx                                              |  251 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss              |    8 
 src/components/normalform/modalform/mkSelect/index.jsx                             |   11 
 src/templates/zshare/verifycard/voucherform/index.jsx                              |    2 
 src/api/cacheutils.js                                                              |  340 
 src/menu/components/card/double-data-card/options.jsx                              |   35 
 src/mob/colorsketch/index.jsx                                                      |   66 
 src/tabviews/calendar/index.scss                                                   |    2 
 src/templates/zshare/modalform/datatable/index.jsx                                 |    6 
 src/menu/components/share/actioncomponent/formconfig.jsx                           |  127 
 src/tabviews/basetable/index.scss                                                  |    6 
 src/tabviews/custom/components/group/normal-group/index.jsx                        |   98 
 src/menu/components/group/normal-group/options.jsx                                 |  112 
 src/tabviews/custom/components/carousel/prop-card/index.jsx                        |    7 
 src/menu/components/table/base-table/columns/index.jsx                             |  205 
 src/mob/colorsketch/index.scss                                                     |   17 
 src/menu/components/table/normal-table/index.jsx                                   |   85 
 src/menu/components/card/cardcomponent/options.jsx                                 |   29 
 src/menu/components/group/normal-group/index.jsx                                   |    6 
 src/tabviews/zshare/normalTable/index.scss                                         |    5 
 src/templates/sharecomponent/searchcomponent/searchform/index.jsx                  |   24 
 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx           |   31 
 src/tabviews/custom/components/table/base-table/index.jsx                          |   29 
 src/tabviews/custom/components/card/double-data-card/index.scss                    |   63 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx |   45 
 src/tabviews/custom/components/card/balcony/index.scss                             |    1 
 src/views/mobdesign/menuform/index.jsx                                             |    7 
 src/menu/datasource/verifycard/customscript/index.jsx                              |    7 
 src/templates/sharecomponent/searchcomponent/index.jsx                             |   10 
 src/views/mobdesign/popview/menuform/index.jsx                                     |    5 
 src/templates/sharecomponent/columncomponent/index.jsx                             |   14 
 src/menu/components/share/pasteforms/index.scss                                    |    0 
 src/tabviews/custom/components/share/normalheader/index.scss                       |    2 
 src/tabviews/custom/components/share/normalTable/index.jsx                         |   50 
 src/templates/modalconfig/dragelement/index.jsx                                    |    2 
 src/components/breadview/index.scss                                                |    2 
 src/tabviews/custom/components/card/data-card/index.scss                           |   11 
 src/utils/utils.js                                                                 |  185 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx              |  110 
 src/components/pasteboard/index.scss                                               |    0 
 src/index.js                                                                       |    9 
 src/views/sso/index.jsx                                                            |    8 
 src/menu/components/share/usercomponent/index.jsx                                  |   50 
 src/menu/components/share/pastecomponent/index.jsx                                 |   51 
 src/tabviews/custom/components/timeline/normal-timeline/index.scss                 |  118 
 src/locales/zh-CN/main.js                                                          |   26 
 src/tabviews/zshare/actionList/editLine/index.scss                                 |    0 
 src/tabviews/custom/components/share/tabtransfer/index.jsx                         |   13 
 src/templates/zshare/formconfig.jsx                                                |  119 
 src/tabviews/custom/components/interfaces/interItem/index.jsx                      |   31 
 src/menu/replaceField/index.jsx                                                    |  202 
 src/tabviews/custom/components/card/tableHeader/index.scss                         |   45 
 src/mob/components/formdragelement/card.jsx                                        |   29 
 src/pc/components/login/normal-login/index.jsx                                     |    2 
 src/menu/modalconfig/index.scss                                                    |   28 
 src/assets/mobimg/xflow.png                                                        |    0 
 src/menu/modalconfig/index.jsx                                                     |   67 
 src/tabviews/custom/components/card/balcony/index.jsx                              |    8 
 src/menu/components/table/base-table/columns/editColumn/index.scss                 |   23 
 src/tabviews/custom/components/card/cardcellList/index.scss                        |  224 
 src/menu/components/table/base-table/index.jsx                                     |  110 
 src/templates/zshare/verifycard/baseform/index.jsx                                 |  164 
 src/menu/menushell/index.jsx                                                       |    1 
 src/utils/option.js                                                                |   64 
 355 files changed, 13,643 insertions(+), 8,254 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 40ebbc0..6f465c9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -624,24 +624,76 @@
       }
     },
     "@antv/x6": {
-      "version": "1.33.0",
-      "resolved": "https://registry.npmjs.org/@antv/x6/-/x6-1.33.0.tgz",
-      "integrity": "sha512-B9KkOZJrhgjwDfwUBl58YAGcnD3lpebVaGPGxFMtLcBWmM7K6aDu+TK0CbcdoTS99OyqUQkzNI4O4RFwrw+SRA==",
+      "version": "2.11.1",
+      "resolved": "https://registry.npmjs.org/@antv/x6/-/x6-2.11.1.tgz",
+      "integrity": "sha512-DwyuT/zuTEhwsnKwCj67cadwLeEbB5jfdCxrkTnEm6pg0+vT3FinbF71IK7SHoY8d4HOHl+sJt7ikJfr61JqLw==",
       "requires": {
-        "csstype": "^3.0.3",
-        "jquery": "^3.5.1",
-        "jquery-mousewheel": "^3.1.13",
-        "lodash-es": "^4.17.15",
-        "mousetrap": "^1.6.5",
+        "@antv/x6-common": "^2.0.12",
+        "@antv/x6-geometry": "^2.0.5",
         "utility-types": "^3.10.0"
-      },
-      "dependencies": {
-        "csstype": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-          "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        }
       }
+    },
+    "@antv/x6-common": {
+      "version": "2.0.12",
+      "resolved": "https://registry.npmjs.org/@antv/x6-common/-/x6-common-2.0.12.tgz",
+      "integrity": "sha512-7PcvHGJ2UhrBEtsLI6MaHw6BCMhy22leCH8vCaMvmF32EEQ/491v6DKVPhcpp0dYZNERpfqvAB1w407Aw+bwLA==",
+      "requires": {
+        "lodash-es": "^4.17.15",
+        "utility-types": "^3.10.0"
+      }
+    },
+    "@antv/x6-geometry": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@antv/x6-geometry/-/x6-geometry-2.0.5.tgz",
+      "integrity": "sha512-MId6riEQkxphBpVeTcL4ZNXL4lScyvDEPLyIafvWMcWNTGK0jgkK7N20XSzqt8ltJb0mGUso5s56mrk8ysHu2A=="
+    },
+    "@antv/x6-plugin-clipboard": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-clipboard/-/x6-plugin-clipboard-2.1.6.tgz",
+      "integrity": "sha512-roZPLnZx6PK8MBvee0QMo90fz/TXeF0WNe4EGin2NBq5M1I5XTWrYvA6N2XVIiWAAI67gjQeEE8TpkL7f8QdqA=="
+    },
+    "@antv/x6-plugin-dnd": {
+      "version": "2.0.5",
+      "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-history": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-history/-/x6-plugin-history-2.2.3.tgz",
+      "integrity": "sha512-yiv5e7CQKm1HrJe7je4iWjkzDzU+I0WsyL8En2j0UwXJrUNaKYyv4BkRg2tvyi52hydxidMgi3tNnNQHEZwoMg=="
+    },
+    "@antv/x6-plugin-keyboard": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-keyboard/-/x6-plugin-keyboard-2.2.1.tgz",
+      "integrity": "sha512-sqfN0h4txVO211uIeKBd3zQ/IN2zPzDThWNTEhRx7Lecg1fO7uRXWBbOA48j3EgpRFXVexdSzIEVJEx+IWUdYw==",
+      "requires": {
+        "mousetrap": "^1.6.5"
+      }
+    },
+    "@antv/x6-plugin-scroller": {
+      "version": "2.0.9",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-scroller/-/x6-plugin-scroller-2.0.9.tgz",
+      "integrity": "sha512-f3fluvSIbZBp+c5iKyidAoz19i0beWOnPA0CPfu/K4C+Jf1eWNgaFXbN3hcHPQRvFRJiPtvPApK30aCaik9Omg=="
+    },
+    "@antv/x6-plugin-selection": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-selection/-/x6-plugin-selection-2.1.7.tgz",
+      "integrity": "sha512-ODfYLNwKSaLgIYMYfMW4dYQ9KKFOVBEdH0BzvyG8mfRol+JtZuyrm4BRbAvMryQKHrSxs4JCYXTFd2F7ZTuxLQ=="
+    },
+    "@antv/x6-plugin-snapline": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-snapline/-/x6-plugin-snapline-2.1.7.tgz",
+      "integrity": "sha512-AsysoCb9vES0U2USNhEpYuO/W8I0aYfkhlbee5Kt4NYiMfQfZKQyqW/YjDVaS2pm38C1NKu1LdPVk/BBr4CasA=="
+    },
+    "@antv/x6-plugin-stencil": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-stencil/-/x6-plugin-stencil-2.0.3.tgz",
+      "integrity": "sha512-pQkTIbMCezTqo38fofuFGnI30Rk0j5gHc/+Ndml1RHVEV0p8i1HGRAR5we7SVTcT56AHlP46H+oRFReQmVgvKA=="
+    },
+    "@antv/x6-plugin-transform": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/@antv/x6-plugin-transform/-/x6-plugin-transform-2.1.7.tgz",
+      "integrity": "sha512-idzBr8/Bcw8zHQUSNS0Y8VSNMigCWiUuiwqO572Ac/P2tMfP6Ot2SahEYHGUOD2NEMPr95q4JMZc+Evvt4JFTw=="
     },
     "@antv/x6-react-components": {
       "version": "1.1.15",
@@ -795,6 +847,24 @@
             "d3-force": "^2.0.1",
             "ml-matrix": "^6.5.0"
           }
+        },
+        "@antv/x6": {
+          "version": "1.34.13",
+          "resolved": "https://registry.npmjs.org/@antv/x6/-/x6-1.34.13.tgz",
+          "integrity": "sha512-gYFxh9Sd1UXPO0aO9LHclASacT6HKkG7AP9XQqRuuCcJYWQiZVRmTN1mYQf3lTZDdybdI6IisZp6zFoGjmFxig==",
+          "requires": {
+            "csstype": "^3.0.3",
+            "jquery": "^3.5.1",
+            "jquery-mousewheel": "^3.1.13",
+            "lodash-es": "^4.17.15",
+            "mousetrap": "^1.6.5",
+            "utility-types": "^3.10.0"
+          }
+        },
+        "csstype": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+          "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
         }
       }
     },
@@ -11268,7 +11338,7 @@
     "insert-css": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz",
-      "integrity": "sha1-610Ql7dUL0x56jBg067gfQU4gPQ="
+      "integrity": "sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA=="
     },
     "internal-ip": {
       "version": "4.3.0",
@@ -12591,9 +12661,9 @@
       "integrity": "sha512-JNAkmPeB/GS2tCRqUzRPsTOHpGDah7xP18vGJfIjZC+W2sxEHbxgJxetIjIqhjQ3yYbYNEELkM/spKLtwoOSUQ=="
     },
     "jquery": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
-      "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz",
+      "integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ=="
     },
     "jquery-mousewheel": {
       "version": "3.1.13",
diff --git a/package.json b/package.json
index 2f95956..ab2d13a 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,16 @@
     "@antv/g2": "^4.1.34",
     "@antv/g6": "^4.6.4",
     "@antv/util": "^2.0.17",
+    "@antv/x6": "^2.11.1",
+    "@antv/x6-plugin-clipboard": "^2.1.6",
+    "@antv/x6-plugin-dnd": "^2.0.5",
+    "@antv/x6-plugin-history": "^2.2.3",
+    "@antv/x6-plugin-keyboard": "^2.2.1",
+    "@antv/x6-plugin-scroller": "^2.0.9",
+    "@antv/x6-plugin-selection": "^2.1.7",
+    "@antv/x6-plugin-snapline": "^2.1.7",
+    "@antv/x6-plugin-stencil": "^2.0.3",
+    "@antv/x6-plugin-transform": "^2.1.7",
     "@antv/xflow": "^1.0.50",
     "@babel/core": "7.5.5",
     "@svgr/webpack": "4.3.2",
@@ -54,6 +64,7 @@
     "identity-obj-proxy": "3.0.0",
     "immutability-helper": "^3.0.1",
     "immutable": "^4.0.0-rc.12",
+    "insert-css": "^2.0.0",
     "is-wsl": "^1.1.0",
     "jest": "24.8.0",
     "jest-environment-jsdom-fourteen": "0.1.0",
diff --git a/public/options.json b/public/options.json
index 58add2d..2f15ea6 100644
--- a/public/options.json
+++ b/public/options.json
@@ -8,8 +8,9 @@
   "filter": "false",
   "defaultApp": "",
   "defaultLang": "zh-CN",
-  "WXAppID": "wx4d8a34c8d4494872",
+  "WXAppID": "",
   "WXminiAppID": "",
+  "WXNotice": "false",
   "nginx": "true",
   "debugger": true,
   "licenseKey": "",
diff --git a/src/api/cacheutils.js b/src/api/cacheutils.js
index 1c174d9..265071c 100644
--- a/src/api/cacheutils.js
+++ b/src/api/cacheutils.js
@@ -3,280 +3,11 @@
  */
 export default class CacheUtils {
   /**
-   * @description 鎵撳紑websql
-   */
-  static openWebSql (db) {
-    try {
-      window.GLOB.WebSql = openDatabase(db, '1', 'mk-pc-database', 50 * 1024 * 1024)
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql('CREATE TABLE IF NOT EXISTS VERSIONS (version varchar(50), createDate varchar(50), CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50))', [], () => {
-        
-        }, () => {
-          // eslint-disable-next-line
-          throw 'CREATE TABLE ERROR'
-        })
-        tx.executeSql('CREATE TABLE IF NOT EXISTS CONFIGS (menuid varchar(50), userid varchar(50), openEdition varchar(50), webEdition varchar(50), LongParam text, LongParamUser text, CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50), CDefine4 varchar(50), CDefine5 varchar(50))', [], () => {
-
-        }, () => {
-          // eslint-disable-next-line
-          throw 'CREATE TABLE ERROR'
-        })
-
-        tx.executeSql('CREATE TABLE IF NOT EXISTS CACHES (menuid varchar(50), CreateDate varchar(50), LongParam text, CDefine1 varchar(50), CDefine2 varchar(50))', [], () => {
-
-        }, () => {
-          // eslint-disable-next-line
-          throw 'CREATE TABLE ERROR'
-        })
-
-        if (window.GLOB.systemType === '') {
-          tx.executeSql('CREATE TABLE IF NOT EXISTS FUNCS (func_code varchar(50), key_sql text, CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50))', [], () => {
-
-          }, () => {
-            // eslint-disable-next-line
-            throw 'CREATE TABLE ERROR'
-          })
-        }
-      })
-      // window.GLOB.WebSql.transaction(tx => {
-      //   tx.executeSql('DROP TABLE VERSIONS')
-      //   tx.executeSql('DROP TABLE CONFIGS')
-      // })
-    } catch (e) {
-      console.warn('WebSql 鍒濆鍖栧け璐ワ紒')
-      window.GLOB.WebSql = null
-
-      if (window.indexedDB) {
-        this.openIndexDB(db)
-      }
-    }
-  }
-
-  /**
-   * @description 娓呯┖鍑芥暟
-   */
-  static clearFuncs () {
-    if (window.GLOB.systemType !== '') return
-
-    if (window.GLOB.WebSql) {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql('DELETE FROM FUNCS')
-
-        tx.executeSql(`UPDATE VERSIONS SET createDate='1970-01-01 14:59:09.000' where CDefine1='funcs'`)
-      })
-    } else if (window.GLOB.IndexDB) {
-      let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs')
-      objectStore.clear()
-
-      window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version').delete('funcs')
-    }
-  }
-
-  /**
-   * @description 鑾峰彇websql涓繚瀛樹俊鎭増鏈�
-   */
-  static getWebSqlVersion () {
-    if (!window.GLOB.WebSql) {
-      return Promise.reject()
-    }
-
-    let deffers = []
-
-    deffers.push(
-      new Promise((resolve) => {
-        window.GLOB.WebSql.transaction(tx => {
-          tx.executeSql("SELECT * FROM VERSIONS where CDefine1='LongParam'", [], (tx, results) => {
-            if (results.rows[0]) {
-              resolve(results.rows[0])
-            } else {
-              resolve({version: '', createDate: ''})
-            }
-          }, (tx, results) => {
-            console.warn(results)
-            resolve({version: '', createDate: ''})
-          })
-        })
-      })
-    )
-
-    deffers.push(
-      new Promise((resolve) => {
-        window.GLOB.WebSql.transaction(tx => {
-          tx.executeSql(`SELECT * FROM CONFIGS`, [], (tx, results) => {
-            let menus = []
-            for (let i = 0; i < results.rows.length; i++) {
-              menus.push(`'${results.rows[i].menuid}','${results.rows[i].openEdition || 'mk'}'`)
-            }
-            resolve(menus)
-          }, (tx, results) => {
-            console.warn(results)
-            resolve([])
-          })
-        })
-      })
-    )
-
-    return new Promise((resolve) => {
-      Promise.all(deffers).then(res => {
-        let result = res[0]
-
-        if (result.createDate && !/^\d{4}-\d{2}-\d{2}/.test(result.createDate)) {
-          result.createDate = ''
-        }
-
-        result.menuids = res[1].join(';')
-
-        resolve(result)
-      })
-    })
-  }
-
-  /**
-   * @description 鍒犻櫎websql涓繚瀛樼殑閰嶇疆淇℃伅
-   */
-  static delWebSqlConfig (keys) {
-    if (!window.GLOB.WebSql) return
-
-    if (!keys) {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`DELETE FROM CONFIGS`, [], () => {}, (tx, results) => {
-          console.warn(results)
-        })
-      })
-    } else {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`DELETE FROM CONFIGS where menuid in (${keys})`, [], () => {}, (tx, results) => {
-          console.warn(results)
-        })
-      })
-    }
-  }
-
-  /**
-   * @description 鍒犻櫎websql涓繚瀛樼殑閰嶇疆淇℃伅
-   */
-  static delMenuWebSqlConfig (menuId) {
-    if (!window.GLOB.WebSql || !menuId) return Promise.resolve()
-    return new Promise(resolve => {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`DELETE FROM CONFIGS where menuid='${menuId}'`, [], () => {
-          resolve()
-        }, (tx, results) => {
-          console.warn(results)
-          resolve()
-        })
-      })
-    })
-  }
-
-  /**
-   * @description 鏇存柊websql涓厤缃俊鎭殑鐗堟湰
-   */
-  static updateWebSqlversion (version, curTime) {
-    if (!window.GLOB.WebSql) return
-
-    window.GLOB.WebSql.transaction(tx => {
-      tx.executeSql(`DELETE FROM VERSIONS where CDefine1='LongParam'`)
-
-      if (version) {
-        tx.executeSql('INSERT INTO VERSIONS (version, createDate, CDefine1) VALUES (?, ?, ?)', [version, curTime, 'LongParam'], () => {}, (tx, results) => {
-          console.warn(results)
-        })
-      }
-    })
-  }
-
-  /**
-   * @description 鑾峰彇websql涓殑閰嶇疆淇℃伅
-   */
-  static getWebSqlMenuConfig (MenuID, userid) {
-    if (!window.GLOB.WebSql || !MenuID || !userid) return Promise.reject()
-    return new Promise((resolve, reject) => {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`SELECT * FROM CONFIGS WHERE menuid='${MenuID}' and userid='${userid}'`, [], (tx, results) => {
-          let paramItem = results.rows[0]
-          if (paramItem) {
-            resolve({
-              ErrCode: 'S',
-              ErrMesg: '',
-              LongParam: paramItem.LongParam,
-              LongParamUser: paramItem.LongParamUser,
-              message: '',
-              open_edition: paramItem.openEdition,
-              status: true,
-              web_edition: paramItem.webEdition
-            })
-          } else {
-            reject()
-          }
-        }, (tx, results) => {
-          console.warn(results)
-          reject()
-        })
-      })
-    })
-  }
-
-  /**
-   * @description 灏嗘暟鎹啓鍏ebsql
-   */
-  static writeInWebSql (data) {
-    if (!window.GLOB.WebSql || !data) return
-    window.GLOB.WebSql.transaction(tx => {
-      tx.executeSql('INSERT INTO CONFIGS (menuid, userid, openEdition, webEdition, LongParam, LongParamUser) VALUES (?, ?, ?, ?, ?, ?)', data)
-    })
-  }
-
-  /**
-   * @description 灏嗙紦瀛樻暟鎹啓鍏ebsql
-   */
-  static writeCacheInWebSql (data) {
-    if (!window.GLOB.WebSql) return
-    window.GLOB.WebSql.transaction(tx => {
-      tx.executeSql(`DELETE FROM CACHES where menuid='${data[0]}'`)
-      if (data[2]) {
-        tx.executeSql('INSERT INTO CACHES (menuid, CreateDate, LongParam) VALUES (?, ?, ?)', data)
-      }
-    })
-  }
-
-  /**
-   * @description 鑾峰彇websql涓殑閰嶇疆淇℃伅
-   */
-  static getWebSqlCacheConfig (MenuID) {
-    if (!window.GLOB.WebSql) return Promise.resolve()
-    return new Promise((resolve, reject) => {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`SELECT * FROM CACHES WHERE menuid='${MenuID}'`, [], (tx, results) => {
-          resolve(results.rows[0])
-        }, (tx, results) => {
-          console.warn(results)
-          resolve()
-        })
-      })
-    })
-  }
-
-  /**
-   * @description 鍒犻櫎websql涓秴杩�7澶╃殑缂撳瓨淇℃伅
-   */
-  static delWebSqlCacheConfig (date, type) {
-    if (!window.GLOB.WebSql) return
-    window.GLOB.WebSql.transaction(tx => {
-      if (type === 'all') {
-        tx.executeSql('DELETE FROM CACHES')
-      } else {
-        tx.executeSql(`DELETE FROM CACHES where CreateDate<'${date}'`)
-      }
-    })
-  }
-
-  /**
    * @description 鎵撳紑IndexedDB
    */
   static openIndexDB (db) {
     try {
-      let request = window.indexedDB.open(db, 2)
+      let request = window.indexedDB.open(db, 3)
       request.onerror = () => {
         console.warn('IndexedDB 鍒濆鍖栧け璐ワ紒')
       }
@@ -296,7 +27,7 @@
         if (!window.GLOB.IndexDB.objectStoreNames.contains('caches')) {
           window.GLOB.IndexDB.createObjectStore('caches', { keyPath: 'menuid' })
         }
-        if (window.GLOB.systemType === '' && !window.GLOB.IndexDB.objectStoreNames.contains('funcs')) {
+        if (!window.GLOB.IndexDB.objectStoreNames.contains('funcs')) {
           window.GLOB.IndexDB.createObjectStore('funcs', { keyPath: 'id' })
         }
       }
@@ -323,7 +54,6 @@
           .get('mksoft')
 
         request.onerror = (event) => {
-          window.GLOB.IndexDB = null
           console.warn(event)
           resolve({version: '', createDate: ''})
         }
@@ -342,16 +72,19 @@
       new Promise((resolve) => {
         let request = window.GLOB.IndexDB.transaction(['configs']).objectStore('configs').openCursor()
         let menus = []
+        let ids = []
 
         request.onerror = () => {
-          window.GLOB.IndexDB = null
           resolve(menus)
         }
 
         request.onsuccess = (e) => {
           let cursor = e.target.result
           if (cursor) {
-            menus.push(`'${cursor.value.menuid}','${cursor.value.open_edition || 'mk'}'`)
+            if (cursor.value.menuid && !ids.includes(cursor.value.menuid)) {
+              menus.push(`'${cursor.value.menuid}','${cursor.value.open_edition || 'mk'}'`)
+              ids.push(cursor.value.menuid)
+            }
             cursor.continue()
           } else {
             resolve(menus)
@@ -382,58 +115,21 @@
     if (!window.GLOB.IndexDB || !version) return
 
     if (!version) {
-      let request = window.GLOB.IndexDB.transaction(['configs'], 'readwrite').objectStore('configs').delete('mksoft')
-  
-      request.onerror = () => {
-        window.GLOB.IndexDB = null
-      }
+      window.GLOB.IndexDB.transaction(['configs'], 'readwrite').objectStore('configs').delete('mksoft')
     } else {
       version.id = 'mksoft'
 
       let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version')
       let request = objectStore.get('mksoft')
   
-      request.onerror = () => {
-        window.GLOB.IndexDB = null
-      }
-  
       request.onsuccess = () => {
         if (request.result) {
-          let put = objectStore.put(version)
-  
-          put.onerror = () => {
-            window.GLOB.IndexDB = null
-          }
+          objectStore.put(version)
         } else {
-          let add = objectStore.add(version)
-  
-          add.onerror = () => {
-            window.GLOB.IndexDB = null
-          }
+          objectStore.add(version)
         }
       }
     }
-  }
-
-  /**
-   * @description 鍒犻櫎IndexedDB涓繚瀛樼殑閰嶇疆淇℃伅
-   */
-  static delMenuIndexDBConfig (key) {
-    if (!window.GLOB.IndexDB || !key) return Promise.resolve()
-
-    return new Promise(resolve => {
-      let request = window.GLOB.IndexDB.transaction(['configs'], 'readwrite')
-        .objectStore('configs')
-        .delete(key)
-
-      request.onsuccess = () => {
-        resolve()
-      }
-      request.onerror = () => {
-        window.GLOB.IndexDB = null
-        resolve()
-      }
-    })
   }
 
   /**
@@ -443,17 +139,9 @@
     if (!window.GLOB.IndexDB) return
 
     if (!menuids) {
-      let request = window.GLOB.IndexDB.transaction(['configs'], 'readwrite').objectStore('configs').clear()
-  
-      request.onerror = () => {
-        window.GLOB.IndexDB = null
-      }
+      window.GLOB.IndexDB.transaction(['configs'], 'readwrite').objectStore('configs').clear()
     } else {
       let request = window.GLOB.IndexDB.transaction(['configs'], 'readwrite').objectStore('configs').openCursor()
-  
-      request.onerror = () => {
-        window.GLOB.IndexDB = null
-      }
 
       request.onsuccess = (e) => {
         let cursor = e.target.result
@@ -470,15 +158,13 @@
   /**
    * @description 鑾峰彇IndexedDB涓殑閰嶇疆淇℃伅
    */
-  static getIndexDBMenuConfig (MenuID, userid) {
-    if (!window.GLOB.IndexDB || !MenuID || !userid) return Promise.reject()
-    let key = MenuID + userid
+  static getIndexDBMenuConfig (key) {
+    if (!window.GLOB.IndexDB || !key) return Promise.reject()
     
     return new Promise((resolve, reject) => {
       let request = window.GLOB.IndexDB.transaction(['configs']).objectStore('configs').get(key)
 
       request.onerror = () => {
-        window.GLOB.IndexDB = null
         reject()
       }
 
diff --git a/src/api/index.js b/src/api/index.js
index 3e3ae10..46f97a8 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -9,21 +9,13 @@
 import CacheUtils from './cacheutils'
 import options from '@/store/options.js'
 
-window.GLOB.WebSql = null
 window.GLOB.IndexDB = null
 window.GLOB.OuterToken = {}
-const systemMenuKeys = `1581067625930haged11ieaivpavv77k,1581734956310scks442ul2d955g9tu5,1583991994144ndddg0bhh0is6shi0v1,1583979633842550imkchl4qt4qppsiv,
-  1585192949946f3et2ts8tn82krmumdf,15855615451212m12ip23vpcm79kloro,1587005717541lov40vg61q7l1rbveon,1590458676585agbbr63t6ihighg2i1g,1602315375262ikd33ii0nii34pt861o,1582771068837vsv54a089lgp45migbg,
-  1582777675954ifu05upurs465omoth7,158294809668898cklbv6c5bou8e1fpu,1584676379094iktph45fb8imhg96bql,1584695125339vo5g7iqgfn01qmrd6s2,1584699661372vhmpp9dn9foo0eob722,15848421131551gg04ie8sitsd3f7467,
-  1589782279158ngr675kk3oksin35sul,1589788042787ffdt9hle4s45k9r1nvs,1594095599055qicg2eb642v5qglhnuo,1577972969199lei1g0qkvlh4tkc908m,16044812935562g807p3p12huk8kokmb,
-  1578479100252lfbp29v1kafk4s4q4ig,1577971621421tg4v0i1ur8873k7e0ob,1577929944419lgc5h3hepum765e2k7u,1588493493409k9guqp067d31lu7blsv,15827879285193g85m3i2uprektpgmpf`
 
 let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : ''
 let db = `mkdb${service}`
 
-if (window.openDatabase) {
-  CacheUtils.openWebSql(db)
-} else if (window.indexedDB) {
+if (window.indexedDB) {
   CacheUtils.openIndexDB(db)
 }
 
@@ -61,7 +53,6 @@
     localStorage.removeItem('debug')
     localStorage.removeItem('role_id')
     localStorage.removeItem('mk_user_type')
-    localStorage.removeItem('localRole_id')
 
     sessionStorage.clear()
     sessionStorage.setItem('loginError', JSON.stringify({url: res.config ? res.config.url : '', request: res.config ? res.config.data : '', response: JSON.stringify(res.data)}))
@@ -72,7 +63,7 @@
 
 axios.interceptors.response.use((response) => {
   if (response.data.ErrCode === 'LoginError') {
-    if (window.debugger === true) {
+    if (window.debugger === true || window.GLOB.saving) {
       response.data.ErrCode = 'E'
       return Promise.resolve(response.data)
     } else if (!sessionStorage.getItem('loginError')) {
@@ -141,17 +132,18 @@
   /* @description 鐩存帴璇锋眰
    * @description 寰俊涓氬姟璇锋眰
    */
-  wxAccessToken () {
+  wxAccessToken (domain = '') {
     let _url = window.GLOB.baseurl + 'wxpay/getaccesstoken'
-    if (process.env.NODE_ENV !== 'production') {
-      _url = document.location.origin + '/wxpay/getaccesstoken'
+
+    if (domain) {
+      _url = domain + 'wxpay/getaccesstoken'
     }
 
     return new Promise(resolve => {
-      if (window.GLOB.accessToken.accessTime && (parseInt(new Date().getTime() / 1000) - window.GLOB.accessToken.accessTime < 30)) {
+      if (window.GLOB.accessToken.domain === domain && window.GLOB.accessToken.accessTime && (parseInt(new Date().getTime() / 1000) - window.GLOB.accessToken.accessTime < 30)) {
         resolve(window.GLOB.accessToken)
       } else {
-        window.GLOB.accessToken = {}
+        window.GLOB.accessToken = {domain}
         axios({
           url: _url,
           method: 'get'
@@ -171,19 +163,23 @@
    * @description 寰俊涓氬姟璇锋眰
    */
   wxNginxRequest (url, method, param) {
-    let _url = window.GLOB.location + '/' + url
-    if (process.env.NODE_ENV === 'production') {
-      _url = document.location.origin + '/' + url
-    }
-    if (/^http:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
-      _url = window.GLOB.location + ':8080/' + url
+    let _url = url
+
+    if (!/^http/.test(url)) {
+      _url = window.GLOB.location + '/' + url
       if (process.env.NODE_ENV === 'production') {
-        _url = document.location.origin + ':8080/' + url
+        _url = document.location.origin + '/' + url
       }
-    } else if (/^https:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
-      _url = window.GLOB.location + ':8443/' + url
-      if (process.env.NODE_ENV === 'production') {
-        _url = document.location.origin + ':8443/' + url
+      if (/^http:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
+        _url = window.GLOB.location + ':8080/' + url
+        if (process.env.NODE_ENV === 'production') {
+          _url = document.location.origin + ':8080/' + url
+        }
+      } else if (/^https:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
+        _url = window.GLOB.location + ':8443/' + url
+        if (process.env.NODE_ENV === 'production') {
+          _url = document.location.origin + ':8443/' + url
+        }
       }
     }
     
@@ -338,6 +334,7 @@
    * @description 鐧诲綍绯荤粺, 鑾峰彇鐢ㄦ埛淇℃伅
    */
   getusermsg (username, password, isCloud = false) {
+    let shim = +sessionStorage.getItem('sys_time_shim')
     let param = {
       // func: 'webapi_login',
       UserName: username,
@@ -347,15 +344,8 @@
       login_id_address: sessionStorage.getItem('ipAddress') || '',
       kei_id: window.btoa(window.encodeURIComponent(window.GLOB.host)),
       device_id: localStorage.getItem('SessionUid'),
-      timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
+      timestamp: moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss'),
       appkey: window.GLOB.appkey || ''
-    }
-
-    let sys_datetime = sessionStorage.getItem('sys_datetime')
-    let app_datetime = sessionStorage.getItem('app_datetime')
-    if (sys_datetime && app_datetime) {
-      let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000)
-      param.timestamp = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss')
     }
     
     // Type: 'S' 鏃�
@@ -402,7 +392,6 @@
 
   delCacheConfig (type = '') {
     let date = moment().subtract(7, 'days').format('YYYY-MM-DD')
-    CacheUtils.delWebSqlCacheConfig(date, type)
     CacheUtils.delIndexDBCacheConfig(date, type)
   }
 
@@ -411,26 +400,12 @@
     let date = moment().format('YYYY-MM-DD')
     let _data = data ? JSON.stringify(data) : ''
 
-    CacheUtils.writeCacheInWebSql([menuid, date, _data])
     CacheUtils.writeCacheInIndexDB({menuid, CreateDate: date, LongParam: _data})
   }
 
   getLCacheConfig (menuid) {
     return new Promise((resolve, reject) => {
-      if (window.GLOB.WebSql) {
-        CacheUtils.getWebSqlCacheConfig(menuid).then(res => {
-          if (res && res.LongParam) {
-            let _data = JSON.parse(res.LongParam)
-            if (_data.length === 0) {
-              resolve()
-            } else {
-              resolve(_data)
-            }
-          } else {
-            resolve()
-          }
-        })
-      } else if (window.GLOB.IndexDB) {
+      if (window.GLOB.IndexDB) {
         CacheUtils.getIndexDBCacheConfig(menuid).then(res => {
           if (res && res.LongParam) {
             let _data = JSON.parse(res.LongParam)
@@ -483,181 +458,98 @@
    * @description 鑾峰彇绯荤粺鐗堟湰淇℃伅锛屽惎鐢ㄦ垨鏇存柊websql
    */
   getAppVersion (reload) {
-    if (!window.GLOB.WebSql && !window.GLOB.IndexDB) {
+    if (!window.GLOB.IndexDB) {
       return Promise.reject()
     }
 
-    let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
-    let sys_datetime = sessionStorage.getItem('sys_datetime')
-    let app_datetime = sessionStorage.getItem('app_datetime')
-    if (sys_datetime && app_datetime) {
-      let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000)
-      let _curTime = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss') + '.000'
-      if (/^\d{4}-\d{2}-\d{2}/.test(_curTime)) {
-        curTime = _curTime
-      }
-    }
+    let shim = +sessionStorage.getItem('sys_time_shim')
+    let curTime = moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss') + '.000'
 
-    if (window.GLOB.WebSql) {
-      return new Promise((resolve, reject) => {
-        CacheUtils.getWebSqlVersion().then(msg => {
-          let param = {
-            func: 's_get_app_version',
-            modifydate: msg.createDate
-          }
+    return new Promise((resolve, reject) => {
+      CacheUtils.getIndexDBVersion().then(msg => {
+        let param = {
+          func: 's_get_app_version',
+          modifydate: msg.createDate
+        }
 
-          param.TypeCharOne = ''
-          param.typename = ''
+        param.TypeCharOne = ''
+        param.typename = ''
 
-          if (!msg.createDate && !msg.menuids) {
-            CacheUtils.updateWebSqlversion('1.00', curTime)
-            resolve()
-            return
-          } else if (!msg.createDate || reload === true) {
-            param.modifydate = curTime
+        if (!msg.createDate && !msg.menuids) {
+          CacheUtils.updateIndexDBversion({version: '1.00', createDate: curTime})
+          resolve()
+          return
+        } else if (!msg.createDate || reload === true) {
+          param.modifydate = curTime
+          param.menuids = window.btoa(msg.menuids)
+        } else if (msg.menuids) {
+          let d = localStorage.getItem(db)
+
+          if (!d || curTime.indexOf(d) === -1) {
             param.menuids = window.btoa(msg.menuids)
-          } else if (msg.menuids) {
-            let d = localStorage.getItem(db)
-
-            if (!d || curTime.indexOf(d) === -1) {
-              param.menuids = window.btoa(msg.menuids)
-            }
-
-            localStorage.setItem(db, curTime.substr(0, 10))
-          }
-  
-          this.getSystemConfig(param).then(res => {
-            if (!res.status) {
-              reject()
-              return
-            }
-            
-            let list = res.menu_data || []
-
-            if (res.menu_del) {
-              list.push(...res.menu_del)
-            }
-
-            list = list.map(mid => mid.menuid)
-
-            if (typeof(reload) === 'string' && !list.includes(reload)) {
-              list.push(reload)
-            }
-
-            if (list.length > 0) {
-              let clear = false
-              list.forEach(mid => {
-                if (systemMenuKeys.indexOf(mid) > -1) {
-                  clear = true
-                }
-              })
-              if (clear) {
-                list = ''
-              } else {
-                list = list.map(mid => `'${mid}'`).join(',')
-              }
-              CacheUtils.delWebSqlConfig(list)
-            }
-
-            CacheUtils.updateWebSqlversion(res.app_version || '1.00', curTime)
-  
-            resolve()
-          })
-        }, () => {
-          reject()
-        })
-      })
-    } else {
-      return new Promise((resolve, reject) => {
-        CacheUtils.getIndexDBVersion().then(msg => {
-          let param = {
-            func: 's_get_app_version',
-            modifydate: msg.createDate
           }
 
-          param.TypeCharOne = ''
-          param.typename = ''
+          localStorage.setItem(db, curTime.substr(0, 10))
+        }
 
-          if (!msg.createDate && !msg.menuids) {
-            CacheUtils.updateIndexDBversion({version: '1.00', createDate: curTime})
-            resolve()
+        this.getSystemConfig(param).then(res => {
+          if (!res.status) {
+            reject()
             return
-          } else if (!msg.createDate || reload === true) {
-            param.modifydate = curTime
-            param.menuids = window.btoa(msg.menuids)
-          } else if (msg.menuids) {
-            let d = localStorage.getItem(db)
-
-            if (!d || curTime.indexOf(d) === -1) {
-              param.menuids = window.btoa(msg.menuids)
-            }
-
-            localStorage.setItem(db, curTime.substr(0, 10))
           }
 
-          this.getSystemConfig(param).then(res => {
-            if (!res.status) {
-              reject()
-              return
-            }
-  
-            let list = res.menu_data || []
+          let list = res.menu_data || []
 
-            if (res.menu_del) {
-              list.push(...res.menu_del)
-            }
+          if (res.menu_del) {
+            list.push(...res.menu_del)
+          }
 
-            list = list.map(mid => mid.menuid)
+          list = list.map(mid => mid.menuid)
 
-            if (typeof(reload) === 'string' && !list.includes(reload)) {
-              list.push(reload)
-            }
+          if (typeof(reload) === 'string' && !list.includes(reload)) {
+            list.push(reload)
+          }
 
-            if (list.length > 0) {
-              let clear = false
-              list.forEach(mid => {
-                if (systemMenuKeys.indexOf(mid) > -1) {
-                  clear = true
-                }
-              })
-              if (clear) {
-                list = ''
+          if (list.length > 0) {
+            let clear = false
+            let _appkey = window.GLOB.appkey.substr(-10)
+            let reg = new RegExp(_appkey + '$', 'ig')
+
+            list.forEach(mid => {
+              if (reg.test(mid)) {
+                clear = true
               }
-              CacheUtils.delIndexDBConfig(list)
+            })
+            if (clear) {
+              list = ''
             }
+            CacheUtils.delIndexDBConfig(list)
+          }
 
-            CacheUtils.updateIndexDBversion({version: res.app_version || '1.00', createDate: curTime})
-  
-            resolve()
-          })
-        }, () => {
-          reject()
+          CacheUtils.updateIndexDBversion({version: res.app_version || '1.00', createDate: curTime})
+
+          resolve()
         })
+      }, () => {
+        reject()
       })
-    }
+    })
   }
 
   /**
    * @description 鏇存柊绯荤粺鐗堟湰淇℃伅锛屾竻绌洪厤缃俊鎭�
    */
   updateAppVersion () {
-    CacheUtils.delWebSqlConfig()
-    CacheUtils.updateWebSqlversion()
     CacheUtils.delIndexDBConfig()
     CacheUtils.updateIndexDBversion()
-    CacheUtils.clearFuncs()
+    // CacheUtils.clearFuncs()
   }
 
   /**
    * @description 鍒犻櫎鏌愪釜鑿滃崟閰嶇疆淇℃伅
    */
   deleteMenuStorage (menuId) {
-    if (window.GLOB.IndexDB) {
-      let key = menuId + (sessionStorage.getItem('UserID') || '')
-      return CacheUtils.delMenuIndexDBConfig(key)
-    } else {
-      return CacheUtils.delMenuWebSqlConfig(menuId)
-    }
+    CacheUtils.delIndexDBConfig(menuId)
   }
 
   /**
@@ -741,7 +633,7 @@
   }
 
   /**
-   * @description 鑾峰彇绯荤粺閰嶇疆锛屽彇鍊间紭鍏堢瓑绾ebsql銆佺紦瀛樸�佹湇鍔″櫒
+   * @description 鑾峰彇绯荤粺閰嶇疆锛屽彇鍊间紭鍏堢瓑绾ndexDB銆佺紦瀛樸�佹湇鍔″櫒
    */
   getCacheConfig (param) {
     param.userid = sessionStorage.getItem('UserID') || ''
@@ -765,53 +657,11 @@
       }
     }
 
-    let _param = JSON.parse(JSON.stringify(param)) // 缂撳瓨鏍¢獙锛屽幓闄ゆ椂闂村拰鍔犲瘑瀛楃
-    delete _param.timestamp
-    delete _param.secretkey
-    delete _param.open_key
-    _param = JSON.stringify(_param)
-    _param  = md5(_param)
-
-    if (param.MenuID === 'home_page_id' && localStorage.getItem('homeLoaded') !== 'true') {
-      param = this.encryptParam(param)
-
-      localStorage.setItem('homeLoaded', 'true')
-
+    let key = md5(param.MenuID + param.userid)
+    
+    if (window.GLOB.IndexDB) {
       return new Promise(resolve => {
-        axios({
-          url: `${url}${param.func ? '/' + param.func : ''}`,
-          method: 'post',
-          data: param
-        }).then(res => {
-          if (res.status) {
-            window.GLOB.CacheMap.set(_param, res)
-          }
-          resolve(res)
-        })
-      })
-    } else if (window.GLOB.WebSql) {
-      return new Promise(resolve => {
-        CacheUtils.getWebSqlMenuConfig(param.MenuID, param.userid).then(res => {
-          resolve(res)
-        }, () => {
-          param = this.encryptParam(param)
-          axios({
-            url: `${url}${param.func ? '/' + param.func : ''}`,
-            method: 'post',
-            data: param
-          }).then(res => {
-            if (res.status && window.GLOB.WebSql) {
-              CacheUtils.writeInWebSql([param.MenuID, param.userid, res.open_edition, res.web_edition, res.LongParam, res.LongParamUser])
-            } else if (res.status) {
-              window.GLOB.CacheMap.set(_param, res)
-            }
-            resolve(res)
-          })
-        })
-      })
-    } else if (window.GLOB.IndexDB) {
-      return new Promise(resolve => {
-        CacheUtils.getIndexDBMenuConfig(param.MenuID, param.userid).then(res => {
+        CacheUtils.getIndexDBMenuConfig(key).then(res => {
           resolve(res)
         }, () => {
           param = this.encryptParam(param)
@@ -825,18 +675,18 @@
                 ...res,
                 userid: param.userid,
                 menuid: param.MenuID,
-                id: param.MenuID + param.userid
+                id: key
               }
               CacheUtils.writeInIndexDB(msg)
             } else if (res.status) {
-              window.GLOB.CacheMap.set(_param, res)
+              window.GLOB.CacheMap.set(key, res)
             }
             resolve(res)
           })
         })
       })
-    } else if (window.GLOB.CacheMap.has(_param)) {
-      return Promise.resolve(window.GLOB.CacheMap.get(_param))
+    } else if (window.GLOB.CacheMap.has(key)) {
+      return Promise.resolve(window.GLOB.CacheMap.get(key))
     } else {
       param = this.encryptParam(param)
 
@@ -847,7 +697,7 @@
           data: param
         }).then(res => {
           if (res.status) {
-            window.GLOB.CacheMap.set(_param, res)
+            window.GLOB.CacheMap.set(key, res)
           }
           resolve(res)
         })
@@ -866,16 +716,8 @@
     param.appkey = window.GLOB.appkey || ''
 
     let _param  = md5(JSON.stringify(param))
-    
-    if (window.GLOB.WebSql) {
-      return new Promise(resolve => {
-        CacheUtils.getWebSqlMenuConfig(param.MenuID, param.userid).then(res => {
-          resolve(res)
-        }, () => {
-          resolve({ ErrCode: 'S', ErrMesg: '', LongParam: '', message: '', status: false })
-        })
-      })
-    } else if (window.GLOB.CacheMap.has(_param)) {
+
+    if (window.GLOB.CacheMap.has(_param)) {
       return Promise.resolve(window.GLOB.CacheMap.get(_param))
     } else {
       return Promise.resolve({ErrCode: 'S', ErrMesg: '', LongParam: '', message: '', status: false})
@@ -982,7 +824,7 @@
       token = JSON.parse(window.decodeURIComponent(window.atob(token)))
     } catch (e) {
       token = null
-      _resolve({status: false, ErrCode: 'E', message: '鎺ュ彛淇℃伅瑙f瀽澶辫触锛�'})
+      _resolve({status: false, ErrCode: 'E', message: '鎺ュ彛淇℃伅瑙f瀽澶辫触锛�', ErrMesg: 'token_error'})
     }
 
     if (!token) return
@@ -1085,7 +927,7 @@
     param.appkey = window.GLOB.appkey || ''
 
     if (param.$token === '') {
-      return Promise.resolve({status: false, ErrCode: 'E', message: '鎺ュ彛鍦板潃灏氭湭璁剧疆锛�'})
+      return Promise.resolve({status: false, ErrCode: 'E', message: '鎺ュ彛鍦板潃灏氭湭璁剧疆锛�', ErrMesg: 'token_error'})
     } else if (param.$token) {
       return new Promise(resolve => this.visitOuterSystem(param, resolve))
     }
@@ -1162,57 +1004,6 @@
       })
     }
   }
-
-  /**
-   * @description 瀵煎嚭Excel锛屽悗鍙扮敓鎴愭枃浠�
-   */
-  // getExcelOut (param, name) {
-  //   param.userid = sessionStorage.getItem('UserID')
-  //   param.lang = sessionStorage.getItem('lang') || ''
-  //   param.SessionUid = localStorage.getItem('SessionUid') || ''
-  //   param.LoginUID = sessionStorage.getItem('LoginUID') || ''
-  //   param.appkey = window.GLOB.appkey || ''
-    
-  //   return new Promise(resolve => {
-  //     axios({
-  //       url: '/webapi/doexcel',
-  //       responseType: 'blob',
-  //       method: 'post',
-  //       data: param
-  //     }).then(res => {
-  //       try {
-  //         const blob = new Blob([res])
-          
-  //         if (res.type === 'application/json') {
-  //           const reader = new FileReader()
-  //           reader.onload = e => resolve(JSON.parse(e.target.result))
-  //           reader.readAsText(blob)
-  //         } else {
-  //           if ('download' in document.createElement('a')) { // 闈濱E涓嬭浇
-  //             const elink = document.createElement('a')
-  //             elink.download = name
-  //             elink.style.display = 'none'
-  //             elink.href = URL.createObjectURL(blob)
-  //             document.body.appendChild(elink)
-  //             elink.click()
-  //             URL.revokeObjectURL(elink.href) // 閲婃斁URL 瀵硅薄
-  //             document.body.removeChild(elink)
-  //           } else { // IE10+涓嬭浇
-  //             navigator.msSaveBlob(blob, name)
-  //           }
-  //           resolve()
-  //         }
-  //       } catch (e) {
-  //         resolve({
-  //           ErrCode: 'E',
-  //           ErrMesg: '鏂囦欢瑙f瀽閿欒',
-  //           message: '',
-  //           status: false
-  //         })
-  //       }
-  //     })
-  //   })
-  // }
 
   /**
    * @description 涓婁紶base64
@@ -1308,9 +1099,6 @@
    */
   getWxNativePay (param) {
     let _url = window.GLOB.baseurl + 'wxpay/wxNativePay'
-    if (process.env.NODE_ENV !== 'production') {
-      _url = document.location.origin + '/wxpay/wxNativePay'
-    }
 
     return axios({
       url: _url,
@@ -1326,17 +1114,6 @@
       data: data
     })
   }
-
-  // /**
-  //  * @description 鏂囦欢涓婁紶
-  //  */
-  // getFileUpload (param) {
-  //   return axios({
-  //     url: '/zh-CN/Home/Upload',
-  //     method: 'post',
-  //     data: param
-  //   })
-  // }
 }
 
 export default new Api()
\ No newline at end of file
diff --git a/src/assets/css/viewstyle.scss b/src/assets/css/viewstyle.scss
index 198cd72..29384da 100644
--- a/src/assets/css/viewstyle.scss
+++ b/src/assets/css/viewstyle.scss
@@ -112,7 +112,7 @@
     }
   }
   // 鎼滅储鏍�
-  .top-search {
+  .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 {
@@ -135,7 +135,7 @@
     }
   }
   // 琛ㄦ牸
-  .normal-data-table, .normal-custom-table {
+  .normal-data-table, .normal-custom-table, .edit-custom-table {
     table {
       .ant-table-tbody {
         > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td {
@@ -299,17 +299,7 @@
   .system-color {
     color: $color6;
   }
-  
-  .ant-timeline.system {
-    .ant-timeline-item-tail {
-      border-color: $color2;
-    }
-  }
-  .mk-time-line-wrap.system {
-    .mk-timeline-item-tail {
-      border-color: $color2;
-    }
-  }
+
   .custom-tab-form-box .mk-normal-form-title.mkbtn {
     .form-title {
       color: $color6;
diff --git a/src/assets/mobimg/xflow.png b/src/assets/mobimg/xflow.png
new file mode 100644
index 0000000..3fa7da2
--- /dev/null
+++ b/src/assets/mobimg/xflow.png
Binary files differ
diff --git a/src/components/breadview/index.jsx b/src/components/breadview/index.jsx
index 7158fbb..b1f59ca 100644
--- a/src/components/breadview/index.jsx
+++ b/src/components/breadview/index.jsx
@@ -87,20 +87,20 @@
 
   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}/>)
-    } else if (view.type === 'BaseTable') {
+    if (view.type === 'BaseTable') {
       return (<BaseTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} 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}/>)
+    } else if (view.type === 'Home') {
+      return (<Home MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>)
+    } else if (view.type === 'RolePermission') {
+      return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>)
+    } else if (view.type === 'CommonTable') {
+      return (<CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} 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 === '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}/>)
     } else if (view.type === 'iframe') {
diff --git a/src/components/breadview/index.scss b/src/components/breadview/index.scss
index 52d908d..810603f 100644
--- a/src/components/breadview/index.scss
+++ b/src/components/breadview/index.scss
@@ -22,7 +22,7 @@
     padding-right: 15px;
   }
   >.commontable, >.calendar-page {
-    > .top-search {
+    > .mk-search-wrap {
       padding-left: 0;
       padding-right: 0;
       margin: 0 24px;
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index cfbbe05..def0339 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -11,7 +11,8 @@
   modifyMainMenu,
   logout
 } from '@/store/action'
-import asyncComponent from '@/utils/asyncSpinComponent'
+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'
@@ -22,7 +23,8 @@
 const { confirm } = Modal
 const { Search } = Input
 const Resetpwd = asyncComponent(() => import('@/components/resetPassword'))
-const LoginForm = asyncComponent(() => import('./loginform'))
+const QrCode = asyncComponent(() => import('@/components/qrcode'))
+const LoginForm = asyncSpinComponent(() => import('./loginform'))
 
 class Header extends Component {
   static propTpyes = {
@@ -33,7 +35,6 @@
     userName: '',
     fullName: '',
     logourl: window.GLOB.mainlogo,
-    appVersion: window.GLOB.appVersion,
     loginVisible: false,
     loginLoading: false,
     avatar: Utils.getrealurl(sessionStorage.getItem('avatar')),
@@ -288,8 +289,6 @@
         loginVisible: true
       })
     } else {
-      sessionStorage.setItem('role_id', sessionStorage.getItem('cloudRole_id'))
-      sessionStorage.setItem('dataM', sessionStorage.getItem('cloudDataM'))
       sessionStorage.setItem('isEditState', 'true')
 
       this.props.modifyMainMenu(null)
@@ -332,8 +331,6 @@
           sessionStorage.setItem('cloudDataM', res.dataM ? 'true' : '')
           sessionStorage.setItem('cloudRole_id', res.role_id || '')
 
-          sessionStorage.setItem('role_id', res.role_id || '')
-          sessionStorage.setItem('dataM', res.dataM ? 'true' : '')
           sessionStorage.setItem('isEditState', 'true')
 
           if (param.remember) {
@@ -444,12 +441,6 @@
     setTimeout(() => {
       Api.getAppVersion()
     }, 1000)
-    // Api.genericInterface({
-    //   func: 's_get_fcc_account_data',
-    //   fcc_date: '2022-03-01',
-    //   search_type: ''
-    // }).then(res => {
-    // })
 
     // sessionStorage 璺ㄩ〉闈㈠叡浜�
     window.addEventListener('storage', (e) => {
@@ -513,7 +504,7 @@
       content: '閲嶆柊鍔犺浇搴旂敤淇℃伅',
       onOk() {
         return new Promise(resolve => {
-          if (!window.GLOB.WebSql && !window.GLOB.IndexDB) {
+          if (!window.GLOB.IndexDB) {
             notification.warning({
               top: 92,
               message: '鏇存柊澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯锛�',
@@ -540,7 +531,15 @@
 
   about = () => {
     Modal.success({
-      title: '绯荤粺鐗堟湰v' + this.state.appVersion
+      title: '绯荤粺鐗堟湰v' + window.GLOB.appVersion
+    })
+  }
+
+  wxnotice = () => {
+    Modal.success({
+      className: 'mk-wx-notice',
+      title: <QrCode card={{qrWidth: 320, color: '#000000'}} value={window.GLOB.baseurl + 'mob/wxnotice.html?userid=' + sessionStorage.getItem('UserID') + '&loginuid=' + sessionStorage.getItem('LoginUID')}/>,
+      okText: '鍏抽棴'
     })
   }
 
@@ -552,7 +551,7 @@
 
   render () {
     const { mainMenu, collapse } = this.props
-    const { thdMenuList, searchkey, debug, menulist, appVersion } = this.state
+    const { thdMenuList, searchkey, debug, menulist } = this.state
     const navBar = window.GLOB.navBar
 
     const menu = (
@@ -571,7 +570,10 @@
         <Menu.Item key="verup" onClick={this.verup}>
           椤甸潰鏇存柊
         </Menu.Item>
-        {appVersion ? <Menu.Item key="version" onClick={this.about}>
+        {window.GLOB.WXNotice ? <Menu.Item key="wxnotice" onClick={this.wxnotice}>
+          寰俊娑堟伅
+        </Menu.Item> : null}
+        {window.GLOB.appVersion ? <Menu.Item key="version" onClick={this.about}>
           鍏充簬
         </Menu.Item> : null}
         <Menu.Item key="logout" onClick={this.logout}>閫�鍑�</Menu.Item>
diff --git a/src/components/header/index.scss b/src/components/header/index.scss
index 913208f..d38a22d 100644
--- a/src/components/header/index.scss
+++ b/src/components/header/index.scss
@@ -274,4 +274,19 @@
       }
     }
   }
+}
+
+.mk-wx-notice {
+  top: 100px!important;
+  .anticon-check-circle {
+    display: none;
+  }
+  .ant-modal-confirm-title {
+    text-align: center;
+    min-height: 320px;
+  }
+  .ant-modal-confirm-btns {
+    float: none!important;
+    text-align: center;
+  }
 }
\ No newline at end of file
diff --git a/src/components/header/loginform.jsx b/src/components/header/loginform.jsx
index 899741a..b20fc13 100644
--- a/src/components/header/loginform.jsx
+++ b/src/components/header/loginform.jsx
@@ -17,6 +17,7 @@
     remember: false,
     username: '',
     password: '',
+    oripassword: '',
     delay: +sessionStorage.getItem('mkDelay')
   }
 
@@ -38,18 +39,29 @@
       localStorage.removeItem(_url)
     }
 
-    this.setState({
-      remember: _user ? true : false,
-      username: _user ? _user.username : '',
-      password: _user ? _user.password : ''
-    })
+    if (_user) {
+      this.setState({
+        remember: true,
+        username: _user.username,
+        password: '*********',
+        oripassword: _user.password
+      })
+    }
   }
 
   handleConfirm = () => {
+    const { oripassword } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
+          if (oripassword && values.password === '*********') {
+            values.password = oripassword
+          }
+          
+          values.username = values.username.replace(/\t*|\v*|\s*/g, '')
+          values.password = values.password.replace(/\t*|\v*|\s*/g, '')
+
           resolve(values)
         } else {
           reject(err)
diff --git a/src/components/mkPicture/index.jsx b/src/components/mkPicture/index.jsx
index 6414970..e4b8f39 100644
--- a/src/components/mkPicture/index.jsx
+++ b/src/components/mkPicture/index.jsx
@@ -44,7 +44,18 @@
   checkUrl = (url) => {
     let img = new Image()
     img.addEventListener('error', this.loadHandler)
-    img.src = url
+
+    if (/^https/.test(window.location.protocol)) { // https杞崲
+      if (/^http:/.test(url)) {
+        img.src = url.replace(/^http:/, 'https:')
+      } else if (/^\/\//.test(url)) {
+        img.src = 'https:' + url
+      } else {
+        img.src = url
+      }
+    } else {
+      img.src = url
+    }
   }
 
   loadHandler = (e) => {
diff --git a/src/components/normalform/modalform/index.jsx b/src/components/normalform/modalform/index.jsx
index eb177a9..7ce6bc5 100644
--- a/src/components/normalform/modalform/index.jsx
+++ b/src/components/normalform/modalform/index.jsx
@@ -45,6 +45,8 @@
       
       item.hidden = false
 
+      if (item.forbid && item.del) return false
+
       if (item.forbid) {
         item.hidden = true
       }
@@ -104,6 +106,12 @@
       if (!fieldMap.has(key)) return
 
       let supItem = fieldMap.get(key)
+      let supval = supItem.initval
+
+      if (supItem.initval && supItem.type !== 'checkbox' && JSON.stringify(supItem.initval) === '[]') {
+        supval = ''
+      }
+
       let fields = []
       controlFields[key].forEach(item => {
         if (!fieldMap.has(item.field)) return
@@ -117,15 +125,16 @@
         } else if (supItem.hidden) {
           cell.hidden = true
         } else if (supItem.type === 'checkbox') {
-          let vals = [...supItem.initval, ...item.values]
+          let vals = [...supval, ...item.values]
           if (vals.length === new Set(vals).size) {
             cell.hidden = true
           }
         } else if (item.notNull) {
-          cell.hidden = !supItem.initval || JSON.stringify(supItem.initval) === '[]'
-        } else if (!item.values.includes(supItem.initval)) {
+          cell.hidden = !supval
+        } else if (!item.values.includes(supval)) {
           cell.hidden = true
         }
+
         fieldMap.set(item.field, cell)
 
         fields.push(item)
@@ -169,7 +178,9 @@
   recordChange = (values, item) => {
     this.record = {...this.record, ...values}
 
-    if (item && item.controlFields) {
+    if (!item) return
+    
+    if (item.controlFields) {
       let map = new Map()
       this.state.formlist.forEach(cell => {
         if (!cell.field) return
@@ -178,6 +189,10 @@
 
       let reset = (current) => {
         let val = this.record[current.field]
+
+        if (val && current.type !== 'checkbox' && JSON.stringify(val) === '[]') {
+          val = ''
+        }
 
         current.controlFields.forEach(cell => {
           let m = map.get(cell.field)
@@ -192,7 +207,7 @@
               m.hidden = true
             }
           } else if (cell.notNull) {
-            m.hidden = !val || JSON.stringify(val) === '[]'
+            m.hidden = !val
           } else {
             m.hidden = !cell.values.includes(val)
           }
@@ -226,6 +241,24 @@
           return item || cell
         })
       })
+    } else if (item.reset_source) {
+      let map = new Map()
+      this.state.formlist.forEach(cell => {
+        if (!cell.field) return
+        map.set(cell.field, cell)
+      })
+
+      item.callback(map, this.record)
+
+      this.setState({
+        formlist: this.state.formlist.map(cell => {
+          if (!cell.field) return cell
+
+          let item = map.get(cell.field)
+
+          return item || cell
+        })
+      })
     }
   }
 
diff --git a/src/components/normalform/modalform/mkSelect/index.jsx b/src/components/normalform/modalform/mkSelect/index.jsx
index 92784fe..840dd4a 100644
--- a/src/components/normalform/modalform/mkSelect/index.jsx
+++ b/src/components/normalform/modalform/mkSelect/index.jsx
@@ -31,6 +31,17 @@
     MKEmitter.addListener('mkFC', this.mkFormControl)
   }
 
+  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()
+      })
+    }
+  }
+
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
   }
diff --git a/src/components/paste/index.jsx b/src/components/paste/index.jsx
index bf998d5..ce96162 100644
--- a/src/components/paste/index.jsx
+++ b/src/components/paste/index.jsx
@@ -33,10 +33,10 @@
           })
           this.setState({visible: false})
         } else {
-          notification.success({
+          notification.warning({
             top: 92,
             message: result.message,
-            duration: 2
+            duration: 5
           })
         }
       })
diff --git a/src/components/pasteboard/index.jsx b/src/components/pasteboard/index.jsx
new file mode 100644
index 0000000..aae3fa1
--- /dev/null
+++ b/src/components/pasteboard/index.jsx
@@ -0,0 +1,134 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Input, notification, Modal } from 'antd'
+import { SnippetsOutlined } from '@ant-design/icons'
+
+// import './index.scss'
+
+const { TextArea } = Input
+
+class PaseComponent extends Component {
+  static propTpyes = {
+    inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢
+  }
+
+  state = {
+    visible: false,
+    value: ''
+  }
+
+  trigger = () => {
+    // navigator.clipboard
+    //   .readText()
+    //   .then((val) => {
+    //     this.evalContent(val)
+    //   })
+    //   .catch((v) => {
+    //     this.setState({visible: true, value: ''})
+    //   })
+
+    this.setState({visible: true, value: ''})
+  }
+
+  evalContent = (config) => {
+    let _config = config.replace(/(\n|\s)+/g, '')
+
+    if (!_config) {
+      notification.warning({
+        top: 92,
+        message: '鏈幏鍙栧埌閰嶇疆淇℃伅',
+        duration: 5
+      })
+      return
+    }
+
+    try {
+      _config = JSON.parse(window.decodeURIComponent(window.atob(_config)))
+
+      if (typeof(_config) === 'object' && _config.$srcId) {
+        let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+        if (srcid && _config.$srcId !== srcid) {
+          notification.warning({
+            top: 92,
+            message: '褰撳墠绯荤粺鏃犳潈闄愪娇鐢ㄦ椤归厤缃紒',
+            duration: 5
+          })
+
+          _config = ''
+        } else {
+          delete _config.$srcId
+        }
+      }
+    } catch (e) {
+      // 閫氳繃sql璇彞娣诲姞瀛楁闆�
+      if (/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int)/ig.test(config)) {
+        _config = {
+          key: 'datasourcefield',
+          type: 'array',
+          data: []
+        }
+
+        let list = config.match(/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int)/ig)
+
+        list.forEach(item => {
+          _config.data.unshift({
+            datatype: item.split(/\s+/)[1],
+            field: item.split(/\s+/)[0],
+            label: item.split(/\s+/)[0],
+          })
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: '瑙f瀽閿欒',
+          duration: 5
+        })
+        _config = ''
+      }
+    }
+
+    if (!_config) return
+
+    this.props.getPasteValue(_config, () => {
+      this.setState({visible: false, value: ''})
+    })
+  }
+
+  changeVal = (e) => {
+    this.setState({value: e.target.value})
+  }
+
+  pasteSubmit = () => {
+    this.evalContent(this.state.value)
+  }
+
+  enterPress = (e) => {
+    e.stopPropagation()
+
+    this.evalContent(this.state.value)
+  }
+
+  render() {
+    const { children } = this.props
+    const { visible, value } = this.state
+
+    return (
+      <>
+        {children ? <span onClick={this.trigger}>{children}</span> : <SnippetsOutlined title="绮樿创" onClick={this.trigger} />}
+        <Modal
+          title="绮樿创"
+          visible={visible}
+          width={600}
+          maskClosable={false}
+          onOk={this.pasteSubmit}
+          onCancel={() => {this.setState({visible: false})}}
+          destroyOnClose
+        >
+          <TextArea placeholder="璇疯緭鍏ラ厤缃俊鎭�" autoFocus autoSize={{ minRows: 8, maxRows: 8 }} value={value} onChange={this.changeVal} onPressEnter={this.enterPress}/>
+        </Modal>
+      </>
+    )
+  }
+}
+
+export default PaseComponent
\ No newline at end of file
diff --git a/src/components/pasteboard/index.scss b/src/components/pasteboard/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/components/pasteboard/index.scss
diff --git a/src/components/sidemenu/index.jsx b/src/components/sidemenu/index.jsx
index 452c916..94686bd 100644
--- a/src/components/sidemenu/index.jsx
+++ b/src/components/sidemenu/index.jsx
@@ -18,8 +18,7 @@
   state = {
     subMenulist: [],         // 浜岀骇鑿滃崟
     rootSubmenuKeys: null,
-    openKeys: null,
-    preview: null
+    openKeys: null
   }
 
   async loadsubmenu (menu) {
diff --git a/src/index.js b/src/index.js
index f7ee9b8..761e47e 100644
--- a/src/index.js
+++ b/src/index.js
@@ -57,7 +57,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('localRole_id', localStorage.getItem('localRole_id') || '')
 sessionStorage.setItem('lang', 'zh-CN')
 
 if (sessionStorage.getItem('loginError')) {
@@ -68,8 +67,6 @@
   } catch (e) {}
 }
 sessionStorage.removeItem('isEditState')
-sessionStorage.setItem('role_id', sessionStorage.getItem('localRole_id') || '')
-sessionStorage.setItem('dataM', sessionStorage.getItem('localDataM') || '')
 
 // 鏂扮郴缁熸枃浠剁疆浜巃dmin涓� ../options.json , { cache: 'no-cache'}
 
@@ -99,6 +96,7 @@
     GLOB.nginx = config.nginx + '' === 'true'
     GLOB.WXAppID = config.WXAppID || ''
     GLOB.WXminiAppID = config.WXminiAppID || ''
+    GLOB.WXNotice = config.WXNotice + '' === 'true'
     GLOB.accessToken = {}
     GLOB.mkHS = false
 
@@ -161,6 +159,7 @@
 
     if (options.sysType === 'cloud') { // cloud涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�,浜戠appkey涓虹郴缁熻缃�
       GLOB.appkey = options.cakey
+      GLOB.WXNotice = false
     } else if (options.sysType === 'SSO') { // sso涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�
       GLOB.appkey = config.appkey
     } else if (options.sysType === 'local') { // 涓氬姟绯荤粺
@@ -172,6 +171,10 @@
         } else if (!/webapi\/dostars$/ig.test(systemApi)) {
           systemApi = systemApi.replace(/\/?$/, '/webapi/dostars')
         }
+
+        if (/^https/.test(window.location.protocol) && /^http:/.test(systemApi) && !GLOB.transfer) {
+          systemApi = systemApi.replace(/^http:/, 'https:')
+        }
       
         GLOB.mainSystemApi = systemApi
       }
diff --git a/src/locales/en-US/main.js b/src/locales/en-US/main.js
index 1b18f24..c979dee 100644
--- a/src/locales/en-US/main.js
+++ b/src/locales/en-US/main.js
@@ -6,37 +6,11 @@
   'main.return': 'Return',
   'main.close': 'Close',
   'main.cancel': 'Cancel',
-  'main.revert.default': 'Restore default Settings',
-  'main.copy.success': 'Copy success',
-  'main.pagination.of': 'of',
-  'main.pagination.items': 'items',
-  'main.page.settingerror': '椤甸潰閰嶇疆閿欒锛�',
-  'main.datasource.settingerror': '鏁版嵁婧愰厤缃敊璇紒',
-  'main.action.settingerror': 'Button setting error!',
   '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.action.primarykey.required': 'Primary key not set!',
-  'main.action.primarykey.repetition': 'There are multiple primary keys!',
-  'main.action.primarykey.repetitionbid': 'There are multiple BID!',
   'main.view.unenabled': '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��',
-  'main.excel.line': 'line',
-  'main.excel.column': 'column',
-  'main.excel.includekey': ' Contain keywords ',
-  'main.excel.content.emptyerror': '鍐呭涓嶅彲涓虹┖',
-  'main.excel.content.typeerror': '鍐呭搴斾负鏁板��',
-  'main.excel.content.interror': '鍐呭搴斾负鏁存暟',
-  'main.excel.content.floaterror': '鍐呭搴斾负娴偣鏁�',
-  'main.excel.content.floatIntover': '鏁存暟浣嶈秴鍑鸿寖鍥�',
-  'main.excel.content.floatPointover': '灏忔暟浣嶈秴鍑鸿寖鍥�',
-  'main.excel.content.date.over': '鏃堕棿涓鸿礋鍊兼垨澶ぇ',
-  'main.excel.content.date.formatError': '鏃堕棿鏍煎紡閿欒',
-  'main.excel.content.maxlimit': '鍐呭瓒呴暱',
-  'main.excel.content.limitmin': '灏忎簬鏈�灏忓��',
-  'main.excel.content.limitmax': '澶т簬鏈�澶у��',
-  'main.form.link.error': '鑱斿姩鑿滃崟璁剧疆閿欒锛�',
-  'main.form.picture.check': '鏌ョ湅鍥剧墖',
   'main.role.title': 'The role list',
   'form.required.input': 'Please enter the ',
   'form.required.select': 'Please select a '
diff --git a/src/locales/zh-CN/main.js b/src/locales/zh-CN/main.js
index cf33d24..5fc8412 100644
--- a/src/locales/zh-CN/main.js
+++ b/src/locales/zh-CN/main.js
@@ -6,37 +6,11 @@
   'main.return': '杩斿洖',
   'main.close': '鍏抽棴',
   'main.cancel': '鍙栨秷',
-  'main.revert.default': '鎭㈠榛樿璁剧疆',
-  'main.copy.success': '澶嶅埗鎴愬姛',
-  'main.pagination.of': '鍏�',
-  'main.pagination.items': '鏉�',
-  'main.page.settingerror': '椤甸潰閰嶇疆閿欒锛�',
-  'main.datasource.settingerror': '鏁版嵁婧愰厤缃敊璇紒',
-  'main.action.settingerror': '鎸夐挳璁剧疆閿欒锛�',
   'main.action.confirm.tip': '纭畾瑕佹墽琛屽悧?',
   'main.action.confirm.success': '鎵ц鎴愬姛锛�',
   'main.action.confirm.selectline': '璇烽�夋嫨琛岋紒',
   'main.action.confirm.selectSingleLine': '璇烽�夋嫨鍗曡鏁版嵁锛�',
-  'main.action.primarykey.required': '鏈缃富閿紒',
-  'main.action.primarykey.repetition': '瀛樺湪澶氫釜涓婚敭锛�',
-  'main.action.primarykey.repetitionbid': '瀛樺湪澶氫釜BID锛�',
   'main.view.unenabled': '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��',
-  'main.excel.line': '琛�',
-  'main.excel.column': '鍒�',
-  'main.excel.includekey': '鍚湁鍏抽敭瀛�',
-  'main.excel.content.emptyerror': '鍐呭涓嶅彲涓虹┖',
-  'main.excel.content.typeerror': '鍐呭搴斾负鏁板��',
-  'main.excel.content.interror': '鍐呭搴斾负鏁存暟',
-  'main.excel.content.floaterror': '鍐呭搴斾负娴偣鏁�',
-  'main.excel.content.floatIntover': '鏁存暟浣嶈秴鍑鸿寖鍥�',
-  'main.excel.content.floatPointover': '灏忔暟浣嶈秴鍑鸿寖鍥�',
-  'main.excel.content.date.over': '鏃堕棿涓鸿礋鍊兼垨澶ぇ',
-  'main.excel.content.date.formatError': '鏃堕棿鏍煎紡閿欒',
-  'main.excel.content.maxlimit': '鍐呭瓒呴暱',
-  'main.excel.content.limitmin': '灏忎簬鏈�灏忓��',
-  'main.excel.content.limitmax': '澶т簬鏈�澶у��',
-  'main.form.link.error': '鑱斿姩鑿滃崟璁剧疆閿欒锛�',
-  'main.form.picture.check': '鏌ョ湅鍥剧墖',
   'main.role.title': '瑙掕壊鍒楄〃',
   'form.required.input': '璇疯緭鍏�',
   'form.required.select': '璇烽�夋嫨'
diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx
index d495918..691e7f3 100644
--- a/src/menu/components/card/balcony/index.jsx
+++ b/src/menu/components/card/balcony/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -126,51 +126,15 @@
       return
     }
 
-    card.errors = []
+    card.$c_ds = card.wrap.datatype === 'dynamic'
+    card.$c_ac = false
+    card.$c_sc = false
+    card.$c_el = true
+    
+    card.errors = checkComponent(card)
 
-    if (card.wrap.datatype === 'static') {
-      card.elements.forEach(cell => {
-        if (cell.eleType === 'button') {
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          }
-        } else if (cell.datatype === 'dynamic' && cell.field) {
-          card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-        }
-      })
+    if (card.errors.length === 0) {
       card.$tables = getTables(card)
-    } else {
-      let columns = card.columns.map(c => c.field)
-
-      if (card.wrap.datatype === 'dynamic') {
-        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: '涓婚敭宸插け鏁堬紒'})
-        }
-      }
-
-      if (card.errors.length === 0) {
-        card.$tables = getTables(card)
-      }
-
-      card.elements.forEach(cell => {
-        if (cell.eleType === 'button') {
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          }
-        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-          card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-        }
-      })
     }
 
     this.setState({
@@ -211,6 +175,10 @@
     newcard.datatype = 'dynamic'
     newcard.height = 1
 
+    if (card.wrap.datatype === 'static') {
+      newcard.datatype = 'static'
+    }
+
     // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
     MKEmitter.emit('cardAddElement', card.uuid, newcard)
   }
@@ -239,6 +207,7 @@
       MKEmitter.emit('cardAddElement', card.uuid, res)
     } else {
       res.eleType = 'button'
+      res.width = res.width || 12
       MKEmitter.emit('cardAddElement', card.uuid, res)
     }
     resolve({status: true})
@@ -272,6 +241,19 @@
 
       if (d) {
         _card.columns = fromJS(d.columns).toJS()
+      }
+    }
+
+    if (_card.wrap.position === 'fixed') {
+      if (_card.wrap.top && _card.wrap.bottom && _card.wrap.top.indexOf('vh') > -1 && _card.wrap.bottom.indexOf('vh') > -1) {
+        if (parseFloat(_card.wrap.top) + parseFloat(_card.wrap.bottom) >= 100) {
+          message.warning('鍏冪礌璺濅笂璺濅笅涔嬪拰瓒呭嚭100%锛屽彲鑳藉鑷村厓绱犳棤娉曟樉绀恒��')
+        }
+      }
+      if (_card.wrap.left && _card.wrap.right && _card.wrap.left.indexOf('vw') > -1 && _card.wrap.right.indexOf('vw') > -1) {
+        if (parseFloat(_card.wrap.left) + parseFloat(_card.wrap.right) >= 100) {
+          message.warning('鍏冪礌璺濆乏璺濆彸涔嬪拰瓒呭嚭100%锛屽彲鑳藉鑷村厓绱犳棤娉曟樉绀恒��')
+        }
       }
     }
 
@@ -310,7 +292,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/card/balcony/index.scss b/src/menu/components/card/balcony/index.scss
index 3aaefbb..1108b2c 100644
--- a/src/menu/components/card/balcony/index.scss
+++ b/src/menu/components/card/balcony/index.scss
@@ -7,6 +7,7 @@
   background-size: cover;
   min-height: 30px;
   display: flex;
+  overflow: hidden;
   
   .check-all {
     width: 70px;
diff --git a/src/menu/components/card/balcony/options.jsx b/src/menu/components/card/balcony/options.jsx
index 4cce86c..b7dd426 100644
--- a/src/menu/components/card/balcony/options.jsx
+++ b/src/menu/components/card/balcony/options.jsx
@@ -78,7 +78,27 @@
       label: '鏁版嵁婧�',
       initval: wrap.publicId || '',
       required: true,
-      options: interfaces
+      options: interfaces,
+      reset_source: true,
+      callback: (map, record) => {
+        if (!record.publicId) return
+
+        let interfaces = window.GLOB.customMenu.interfaces || []
+
+        let d = interfaces.filter(m => m.uuid === record.publicId && m.status === 'true')[0]
+
+        if (!d || !d.columns) return
+
+        let columns = JSON.parse(JSON.stringify(d.columns))
+
+        let _bgField = map.get('bgField')
+
+        if (_bgField && !_bgField.forbid) {
+          _bgField.options = columns
+          _bgField.oriOptions = columns
+          map.set('bgField', _bgField)
+        }
+      }
     },
     {
       type: 'radio',
@@ -261,13 +281,13 @@
       type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
-      initval: wrap.permission || 'false',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
       type: 'select',
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
index 5b2b78c..0fb5013 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
@@ -82,6 +82,12 @@
     className += ' ' + card.checkType
   }
 
+  let updateTime = null
+
+  if (card.updateTime && card.updateTime.indexOf(window.GLOB.curDate) > -1) {
+    updateTime = card.updateTime.substr(11)
+  }
+
   return (
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
       <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
@@ -90,6 +96,7 @@
         <CloseOutlined className="close" title="鍒犻櫎" onClick={() => delCard(id)} />
         <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)} />
         {hasProfile ? <ProfileOutlined className="profile" title="setting" onClick={() => profileCard(id)} /> : null}
+        {updateTime}
       </div>
     } trigger="hover">
       <div ref={node => drag(drop(node))} style={_style_} className={'ant-col card-button-cell ant-col-' + className} onDoubleClick={(e) => {e.stopPropagation(); doubleClickCard(id)}}>
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
index 8069bcf..6494683 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -1,7 +1,7 @@
 import React from 'react'
 import { useDrag, useDrop } from 'react-dnd'
 import { Popover } from 'antd'
-import { EditOutlined, CopyOutlined, CloseOutlined, FontColorsOutlined } from '@ant-design/icons'
+import { EditOutlined, CopyOutlined, CloseOutlined, FontColorsOutlined, CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons'
 
 import MkIcon from '@/components/mk-icon'
 import moment from 'moment'
@@ -84,6 +84,9 @@
       if (card.fixStyle === 'alone') {
         let _s = {fontSize: card.fixSize, color: card.fixColor, marginLeft: card.fixLeft, marginRight: card.fixRight}
         val = <><span style={_s}>{card.prefix || ''}</span>{`${card.datatype === 'static' ? (card.value || '') : (card.field || '')}`}<span style={_s}>{card.postfix || ''}</span></>
+      }
+      if (card.sortField) {
+        val = <><span>{val}</span><span className="sort-wrap"><CaretUpOutlined /><CaretDownOutlined /></span></>
       }
       return (
         <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight || 'auto'}}>{val}</div>
@@ -211,6 +214,11 @@
     _style_ = {clear: 'left'}
   }
 
+  let tableHCell = false
+  if (parent.setting && parent.setting.cardRole === 'header') {
+    tableHCell = true
+  }
+
   return (
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
       <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
@@ -218,7 +226,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) ? <MarkColumn field={card.field || ''} columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null }
+        {['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 }
       </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.jsx b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
index d2d89ac..41c2326 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -1,6 +1,7 @@
 import React, { useState } from 'react'
 import { useDrop } from 'react-dnd'
 import { is, fromJS } from 'immutable'
+import { message } from 'antd'
 import update from 'immutability-helper'
 
 import Card from './card'
@@ -53,7 +54,6 @@
     }
 
     copycard.uuid = Utils.getuuid()
-    copycard.originCard = card
 
     try {
       delete _val.$srcId
@@ -76,12 +76,18 @@
       oInput.select()
       document.execCommand('Copy')
       document.body.removeChild(oInput)
+      
+      message.success('澶嶅埗鎴愬姛銆�')
+    } else {
+      message.warning('澶嶅埗澶辫触銆�')
     }
 
-    _cards.push(copycard)
-
-    handleList(_cards)
-    handleMenu(copycard)
+    if (card.eleType !== 'button') {
+      _cards.push(copycard)
+  
+      handleList(_cards)
+      handleMenu(copycard)
+    }
   }
 
   const changeStyle = id => {
@@ -149,7 +155,7 @@
 
           if (newcard.OpenType === 'excelIn') {
             newcard.label = item.text
-            newcard.class = 'dgreen'
+            newcard.class = 'border-dgreen'
             newcard.Ot = 'notRequired'
           } else if (item.subType === 'excelOut') {
             newcard.label = item.text
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.scss b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
index 3d44552..51310de 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.scss
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -214,4 +214,21 @@
     background-repeat: no-repeat;
     background-size: cover;
   }
+  .sort-wrap {
+    position: relative;
+    margin-left: 5px;
+    font-size: 12px;
+    color: #bfbfbf;
+    display: none;
+
+    .anticon-caret-up {
+      position: relative;
+      top: -4px;
+    }
+    .anticon-caret-down {
+      position: absolute;
+      top: 5px;
+      left: 0px;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/menu/components/card/cardcellcomponent/elementform/index.jsx b/src/menu/components/card/cardcellcomponent/elementform/index.jsx
index 009826c..10007af 100644
--- a/src/menu/components/card/cardcellcomponent/elementform/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/elementform/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 } from 'antd'
+import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Popover } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import { formRule } from '@/utils/option.js'
@@ -15,8 +15,8 @@
 
 const cardTypeOptions = {
   sequence: ['eleType', 'width'],
-  text: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix', 'link', 'anchors', 'noValue', 'bgImage', 'fixStyle', 'copyable'],
-  number: ['eleType', 'datatype', 'width', 'height', 'prefix', 'postfix', 'noValue', 'fixStyle'],
+  text: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix', 'link', 'anchors', 'noValue', 'bgImage', 'fixStyle', 'copyable', 'alignItems', 'sortField'],
+  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'],
@@ -25,11 +25,11 @@
   barcode: ['eleType', 'datatype', 'width', 'barHeight', 'displayValue', 'interval', 'noValue'],
   qrcode: ['eleType', 'datatype', 'width', 'qrWidth', 'color', 'url', 'noValue'],
   currentDate: ['eleType', 'width', 'dateFormat', 'prefix', 'postfix', 'fixStyle'],
-  formula: ['eleType', 'width', 'height', 'prefix', 'postfix', 'eval', 'formula', 'noValue', 'fixStyle'],
+  formula: ['eleType', 'width', 'height', 'prefix', 'postfix', 'eval', 'formula', 'noValue', 'fixStyle', 'alignItems'],
   color: ['eleType', 'datatype', 'width', 'lenWidRadio', 'noValue', 'copyable'],
 }
 
-class MainSearch extends Component {
+class ElementEditForm extends Component {
   static propTpyes = {
     config: PropTypes.object,    // 缁勪欢淇℃伅
     formlist: PropTypes.any,     // 琛ㄥ崟淇℃伅
@@ -38,28 +38,24 @@
   }
 
   state = {
-    formlist: null,  // 琛ㄥ崟淇℃伅
-    eleType: '',
-    datatype: '',
-    showType: '',
-    showInfo: 'false',
-    fixStyle: '',
-    link: ''
+    formlist: null  // 琛ㄥ崟淇℃伅
   }
 
+  record = null
+
   UNSAFE_componentWillMount () {
-    const { card, config, side } = this.props
-    let _options = this.getOptions(card.eleType, card.datatype, card.link, (card.showType || 'line'), card.showInfo, card.fixStyle || '', card.posterType || '')
+    const { card, config, side, formlist } = this.props
     
+    this.record = {}
+
+    formlist.forEach(item => {
+      this.record[item.key] = item.initVal
+    })
+    
+    let _options = this.getOptions()
+
     this.setState({
-      link: card.link,
-      eleType: card.eleType,
-      datatype: card.datatype,
-      showType: card.showType || 'line',
-      showInfo: card.showInfo || 'false',
-      fixStyle: card.fixStyle || '',
-      posterType: card.posterType || '',
-      formlist: this.props.formlist.map(item => {
+      formlist: formlist.map(item => {
         item.hidden = !_options.includes(item.key)
 
         if (item.key === 'field' || item.key === 'linkurl' || item.key === 'bgImage' || item.key === 'posterField') {
@@ -96,9 +92,43 @@
               }
             })
           }
+        } else if (item.key === 'sortField' && !item.forbid) {
+          item.options = []
+
+          config.columns.forEach(col => {
+            let label = `${col.field}锛�${col.label}锛塦
+            item.options.push({
+              value: col.field,
+              text: label
+            })
+          })
+          
+          if (config.subColumns) {
+            config.subColumns.forEach(col => {
+              let label = `${col.field}锛�${col.label}锛塦
+              item.options.push({
+                value: col.field,
+                text: label
+              })
+            })
+          }
         } else if (item.key === 'value' && card.eleType === 'slider') {
           item.type = 'number'
           item.label = '鍊�'
+        } else if (item.key === 'formula') {
+          item.fields = []
+
+          config.columns.forEach(col => {
+            item.fields.push(col.field)
+          })
+          
+          if (config.subColumns) {
+            config.subColumns.forEach(col => {
+              item.fields.push(col.field)
+            })
+          }
+
+          item.fields = item.fields.join(', ')
         } else if (item.key === 'value' && card.eleType === 'text') {
           item.type = 'textarea'
           item.label = '鍐呭'
@@ -120,50 +150,62 @@
     })
   }
 
-  getOptions = (eleType, datatype, link, showType, showInfo, fixStyle, posterType) => {
-    let _options = fromJS(cardTypeOptions[eleType]).toJS() // 閫夐」鍒楄〃
+  getOptions = () => {
+    let _options = fromJS(cardTypeOptions[this.record.eleType]).toJS() // 閫夐」鍒楄〃
     
-    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video', 'color'].includes(eleType)) {
-      if (datatype === 'dynamic') {
+    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video', 'color'].includes(this.record.eleType)) {
+      if (this.record.datatype === 'dynamic') {
         _options.push('field')
-        if (eleType === 'number') {
+        if (this.record.eleType === 'number') {
           _options.push('decimal', 'format')
         }
-      } else if (eleType === 'picture' || eleType === 'video') {
+      } else if (this.record.eleType === 'picture' || this.record.eleType === 'video') {
         _options.push('url')
       } else {
         _options.push('value')
       }
-      if (eleType === 'video' && posterType) {
-        if (posterType === 'dynamic') {
+      if (this.record.eleType === 'video' && this.record.posterType) {
+        if (this.record.posterType === 'dynamic') {
           _options.push('posterField')
         } else {
           _options.push('posterUrl')
         }
       }
 
-      if (['text', 'picture'].includes(eleType) && link) {
-        // if (link === 'dynamic' || link === 'static') {
-          _options.push('linkurl', 'joint', 'linkType')
-        // }
-      } else if (eleType === 'picture' && !link) {
+      if (['text', 'picture'].includes(this.record.eleType) && this.record.link) {
+        _options.push('linkType')
+        if (this.record.linkType === 'linkmenu') {
+          _options.push('open', 'joint')
+          if (this.record.link === 'static') {
+            _options.push('linkmenu')
+          } else {
+            _options.push('linkurl')
+          }
+        } else if (this.record.linkType === 'other') {
+          _options.push('linkurl', 'joint', 'open')
+        } else {
+          _options.push('linkurl')
+        }
+      } else if (this.record.eleType === 'picture' && !this.record.link) {
         _options.push('scale')
-      } else if (eleType === 'slider') {
-        if (showInfo === 'true') {
+      } else if (this.record.eleType === 'slider') {
+        if (this.record.showInfo === 'true') {
           _options.push('infoColor')
         }
-        if (showType !== 'line') {
+        if (this.record.showType !== 'line') {
           _options.push('outlineWidth', 'textAlign')
         }
       }
-    } else if (eleType === 'icon') {
-      if (datatype === 'dynamic') {
+    } else if (this.record.eleType === 'icon') {
+      if (this.record.datatype === 'dynamic') {
         _options.push('field', 'noValue')
       } else {
         _options.push('icon')
       }
+    } else if (this.record.eleType === 'formula' && this.record.eval === 'true') {
+      _options.push('decimal')
     }
-    if (_options.includes('fixStyle') && fixStyle === 'alone') {
+    if (_options.includes('fixStyle') && this.record.fixStyle === 'alone') {
       _options.push('fixSize', 'fixColor', 'fixLeft', 'fixRight')
     }
 
@@ -177,13 +219,22 @@
    * 3銆佸垏鎹㈡爣绛剧被鍨嬶紝閲嶇疆鍙�夋爣绛�
    */
   selectChange = (key, value, option) => {
-    const { card, config, side } = this.props
-    const { datatype, eleType, showType, showInfo, fixStyle, posterType } = this.state
+    const { config, side } = this.props
+
+    this.record[key] = value
 
     if (key === 'eleType') {
-      let _options = this.getOptions(value, datatype, '', showType, showInfo, fixStyle, posterType)
+      this.record.link = ''
+      let _options = this.getOptions()
+
+      if (value === 'splitline') {
+        this.record.color = '#EBE9E9'
+      } else if (value === 'formula') {
+        this.record.decimal = ''
+      }
       
       let _formlist = this.state.formlist.map(item => {
+        item.initVal = this.record[item.key]
         item.hidden = !_options.includes(item.key)
 
         if (item.key === 'field') {
@@ -240,25 +291,17 @@
           }
         } else if (item.key === 'url') {
           item.required = value !== 'qrcode'
-        } else if (item.key === 'showInfo') {
-          item.initVal = showInfo
-        } else if (item.key === 'posterType') {
-          item.initVal = posterType
-        } else if (item.key === 'fixStyle') {
-          item.initVal = fixStyle
-        } else if (item.key === 'color') {
-          if (value === 'splitline') {
-            item.initVal = '#EBE9E9'
-          }
         }
 
         return item
       })
 
+      let _field = ''
+      if (value === 'formula') {
+        _field = this.props.form.getFieldValue('field') || ''
+      }
+
       this.setState({
-        link: '',
-        eleType: value,
-        showType: card.showType || 'line',
         formlist: _formlist
       }, () => {
         if (value === 'splitline') {
@@ -269,6 +312,8 @@
           this.props.form.setFieldsValue({color: '#000000'})
         } else if (value === 'text' || value === 'number') {
           this.props.form.setFieldsValue({format: ''})
+        } else if (value === 'formula' && _field) {
+          this.props.form.setFieldsValue({formula: '@' + _field + '@'})
         }
         if (value === 'text' || value === 'picture') {
           this.props.form.setFieldsValue({link: ''})
@@ -279,90 +324,27 @@
         this.props.form.setFieldsValue({value: option.props.title})
       }
     } else if (key === 'link') {
-      let _options = this.getOptions(eleType, datatype, value, showType, showInfo, fixStyle, posterType)
+      let _options = this.getOptions()
       this.setState({
-        link: value,
         formlist: this.state.formlist.map(item => {
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
+
           if (item.key === 'linkurl') {
             item.type = value === 'dynamic' ? 'select' : 'textarea'
           }
           return item
         })
       })
-    }
-  }
-
-  onChange = (e, key) => {
-    const { eleType, datatype, link, showType, showInfo, fixStyle, posterType } = this.state
-    let value = e.target.value
-
-    if (key === 'datatype') {
-      let _options = this.getOptions(eleType, value, link, showType, showInfo, fixStyle, posterType)
+    } else if (['datatype', 'showInfo', 'showType', 'fixStyle', 'posterType', 'eval', 'linkType'].includes(key)) {
+      let _options = this.getOptions()
 
       this.setState({
-        datatype: value,
         formlist: this.state.formlist.map(item => {
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
 
           return item
-        })
-      })
-    } else if (key === 'link') {
-      let _options = this.getOptions(eleType, datatype, value, showType, showInfo, fixStyle, posterType)
-      this.setState({
-        link: value,
-        formlist: this.state.formlist.map(item => {
-          item.hidden = !_options.includes(item.key)
-          if (item.key === 'linkurl') {
-            item.type = value === 'dynamic' ? 'select' : 'textarea'
-          }
-          return item
-        })
-      })
-    } else if (key === 'showInfo') {
-      let _options = this.getOptions(eleType, datatype, link, showType, value, fixStyle, posterType)
-      this.setState({
-        showInfo: value,
-        formlist: this.state.formlist.map(item => {
-          item.hidden = !_options.includes(item.key)
-          return item
-        })
-      })
-    } else if (key === 'showType') {
-      this.setState({
-        showType: value
-      }, () => {
-        let _options = this.getOptions(eleType, datatype, link, value, showInfo, fixStyle, posterType)
-        this.setState({
-          formlist: this.state.formlist.map(item => {
-            item.hidden = !_options.includes(item.key)
-            return item
-          })
-        })
-      })
-    } else if (key === 'fixStyle') {
-      this.setState({
-        fixStyle: value
-      }, () => {
-        let _options = this.getOptions(eleType, datatype, link, showType, showInfo, value, posterType)
-        this.setState({
-          formlist: this.state.formlist.map(item => {
-            item.hidden = !_options.includes(item.key)
-            return item
-          })
-        })
-      })
-    } else if (key === 'posterType') {
-      this.setState({
-        posterType: value
-      }, () => {
-        let _options = this.getOptions(eleType, datatype, link, showType, showInfo, fixStyle, value)
-        this.setState({
-          formlist: this.state.formlist.map(item => {
-            item.hidden = !_options.includes(item.key)
-            return item
-          })
         })
       })
     }
@@ -409,26 +391,52 @@
           </Col>
         )
       } else if (item.type === 'textarea') {
-        fields.push(
-          <Col span={24} className="textarea" 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.readonly ? false : !!item.required,
-                    message: '璇疯緭鍏�' + item.label + '!'
-                  }
-                ]
-              })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
-            </Form.Item>
-          </Col>
-        )
+        if (item.key === 'formula') {
+          fields.push(
+            <Col span={24} className="textarea" 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.readonly ? false : !!item.required,
+                      message: '璇疯緭鍏�' + item.label + '!'
+                    }
+                  ]
+                })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
+              </Form.Item>
+              <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click">
+                <span className="formula-icon">瀛楁闆�</span>
+              </Popover>
+            </Col>
+          )
+        } else {
+          fields.push(
+            <Col span={24} className="textarea" 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.readonly ? false : !!item.required,
+                      message: '璇疯緭鍏�' + item.label + '!'
+                    }
+                  ]
+                })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
+              </Form.Item>
+            </Col>
+          )
+        }
       } else if (item.type === 'number') {
         fields.push(
           <Col span={12} key={index}>
@@ -472,8 +480,8 @@
                   getPopupContainer={() => document.getElementById('card-winter')}
                 >
                   {item.options.map((option, index) =>
-                    <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}>
-                      {option.text}
+                    <Select.Option id={`${index}`} title={option.text || option.label} key={`${index}`} value={option.value}>
+                      {option.text || option.label}
                     </Select.Option>
                   )}
                 </Select>
@@ -518,7 +526,7 @@
                   message: '璇烽�夋嫨' + item.label + '!'
                 }]
               })(
-                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}} disabled={item.readonly}>
+                <Radio.Group onChange={(e) => {this.selectChange(item.key, e.target.value)}} disabled={item.readonly}>
                   {item.options.map(option => {
                     return (
                       <Radio key={option.value} value={option.value}>{option.text}</Radio>
@@ -603,12 +611,33 @@
   }
 
   handleConfirm = () => {
+    const { config } = this.props
+
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
           values.uuid = this.props.card.uuid
           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)) {
+            let cols = []
+            config.subColumns && config.subColumns.forEach(col => {
+              if (/^(Int|Decimal)/ig.test(col.datatype)) {
+                cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
+              }
+            })
+            config.columns.forEach(col => {
+              if (/^(Int|Decimal)/ig.test(col.datatype)) {
+                cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
+              }
+            })
+
+            cols.forEach(col => {
+              values.formula = values.formula.replace(col.reg, col.value)
+            })
+          }
 
           resolve(values)
         } else {
@@ -637,4 +666,4 @@
   }
 }
 
-export default Form.create()(MainSearch)
\ No newline at end of file
+export default Form.create()(ElementEditForm)
\ No newline at end of file
diff --git a/src/menu/components/card/cardcellcomponent/elementform/index.scss b/src/menu/components/card/cardcellcomponent/elementform/index.scss
index 090ce2d..45788e3 100644
--- a/src/menu/components/card/cardcellcomponent/elementform/index.scss
+++ b/src/menu/components/card/cardcellcomponent/elementform/index.scss
@@ -6,12 +6,22 @@
       height: 65px;
     }
     .ant-col.textarea {
+      position: relative;
       min-height: 80px;
       .ant-form-item-label {
         width: 14.2%;
       }
       .ant-form-item-control-wrapper {
         width: 85.8%;
+      }
+
+      .formula-icon {
+        position: absolute;
+        bottom: 5px;
+        right: 15px;
+        cursor: pointer;
+        font-size: 12px;
+        color: #1890ff;
       }
     }
   }
@@ -26,4 +36,14 @@
   .ant-form-explain, .ant-form-extra {
     font-size: 13px;
   }
+}
+.formula-fields {
+  z-index: 1200!important;
+
+  .ant-popover-inner-content {
+    div {
+      max-width: 750px;
+      word-break: break-all;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/menu/components/card/cardcellcomponent/formconfig.jsx b/src/menu/components/card/cardcellcomponent/formconfig.jsx
index 859dc58..76dc518 100644
--- a/src/menu/components/card/cardcellcomponent/formconfig.jsx
+++ b/src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -43,6 +43,71 @@
     tooltip = '鍦ㄦ墿灞曞崱鐗囦腑锛屽姩鎬佹暟鎹樉绀哄�间负鑾峰彇鍒扮殑绗竴琛屾暟鎹��'
   }
 
+  let isHeader = false
+  if (cardCell.$cardType === 'extendCard' && cardCell.setting.cardRole === 'header') {
+    isHeader = true
+    anchors = null
+    card.link = ''
+    _options = [{ value: 'text', text: '鏂囨湰'}]
+  }
+
+  let width = card.width || 12
+  if (/x/.test(card.width)) {
+    width = +width.replace(/x/, '.5')
+  }
+
+  let linkTypes = [
+    { value: 'tel', text: '鐢佃瘽' },
+    { value: 'email', text: '閭' },
+    { value: 'other', text: '鍏朵粬' }
+  ]
+
+  if (appType === 'mob') {
+    linkTypes = [
+      { value: 'tel', text: '鐢佃瘽' },
+      { value: 'email', text: '閭' },
+      { value: 'qywx', text: '浼佷笟寰俊' },
+      { value: 'linkmenu', text: '鍏宠仈鑿滃崟' },
+      { value: 'other', text: '鍏朵粬' }
+    ]
+  } else if (appType === 'pc') {
+    linkTypes = [
+      { value: 'tel', text: '鐢佃瘽' },
+      { value: 'email', text: '閭' },
+      { value: 'linkmenu', text: '鍏宠仈鑿滃崟' },
+      { value: 'other', text: '鍏朵粬' }
+    ]
+  }
+
+  if (card.linkType === 'qywx') {
+    if (appType !== 'mob') {
+      card.link = ''
+      card.linkType = ''
+      card.linkurl = ''
+    }
+  } else if (card.linkType === 'linkmenu') {
+    if (appType !== 'mob' && appType !== 'pc') {
+      card.link = ''
+      card.linkType = ''
+      card.linkurl = ''
+      card.linkmenu = ''
+    }
+  }
+
+  let appMenus = sessionStorage.getItem('appMenus')
+  if (['pc', 'mob'].includes(appType)) {
+    if (appMenus) {
+      try {
+        appMenus = JSON.parse(appMenus)
+      } catch (e) {
+        appMenus = []
+      }
+    } else {
+      appMenus = []
+    }
+    appMenus.push({value: 'goback', text: '杩斿洖锛堜笂涓�椤碉級'})
+  }
+
   let forms = [
     {
       type: 'select',
@@ -85,7 +150,7 @@
       min: 0,
       label: '鍐呭',
       initVal: card.value || '',
-      tooltip: '鏂囨湰绫诲瀷锛屼細鏇挎崲鍐呭涓殑@username@銆丂fullName@銆丂mk_city@銆丂appname@銆丂bid@銆�',
+      tooltip: '鏂囨湰绫诲瀷锛屼細鏇挎崲鍐呭涓殑@username@銆丂fullName@銆丂mk_city@銆丂appname@銆丂bid@銆丂month@銆丂week@銆丂day@',
       required: true
     },
     {
@@ -156,6 +221,21 @@
       required: true
     },
     {
+      type: 'radio',
+      key: 'eval',
+      label: '瑙f瀽',
+      initVal: card.eval || 'false',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      required: false,
+      options: [{
+        value: 'true',
+        text: '鏄�'
+      }, {
+        value: 'false',
+        text: '鍚�'
+      }]
+    },
+    {
       type: 'number',
       key: 'decimal',
       min: 0,
@@ -188,7 +268,8 @@
         { value: 'MM鏈圖D鏃� ahh:mm', text: '鑷畾涔�2锛堜緥锛�12鏈�17鏃� 涓婂崍10:57锛�' },
         { value: 'calendar1', text: '鑷畾涔�3锛堜緥锛氫粖澶� 涓婂崍10:57锛�' },
         { value: 'calendar2', text: '鑷畾涔�4锛堜緥锛氬垰鍒氥�佹槰澶┿��5澶╁墠锛�' },
-      ]
+      ],
+      forbid: isHeader
     },
     {
       type: 'select',
@@ -328,12 +409,12 @@
     {
       type: 'number',
       key: 'width',
-      min: 1,
+      min: 0.5,
       max: 24,
-      precision: 0,
+      precision: 1,
       label: '鍏冪礌瀹藉害',
-      initVal: card.width || 12,
-      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+      initVal: width,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒楋紝鍙缃崐鍒楀嵆.5銆�',
       required: true
     },
     {
@@ -354,7 +435,8 @@
       tooltip: '缁戝畾鏁版嵁婧愬瓧娈碉紝鍙牴鎹繑鍥炲�兼敼鍙樿儗鏅浘銆�',
       required: false,
       allowClear: true,
-      options: []
+      options: [],
+      forbid: isHeader
     },
     {
       type: 'cascader',
@@ -485,19 +567,16 @@
         { value: '', text: '鏃�' },
         { value: 'dynamic', text: '鍔ㄦ��' },
         { value: 'static', text: '闈欐��' }
-      ]
+      ],
+      forbid: isHeader
     },
     {
-      type: 'radio',
+      type: linkTypes.length > 4 ? 'select' : 'radio',
       key: 'linkType',
       label: '閾炬帴绫诲瀷',
       initVal: card.linkType || 'other',
       required: false,
-      options: [
-        { value: 'tel', text: '鐢佃瘽' },
-        { value: 'email', text: '閭' },
-        { value: 'other', text: '鍏朵粬' }
-      ]
+      options: linkTypes
     },
     {
       type: 'radio',
@@ -512,32 +591,40 @@
     },
     {
       type: 'select',
+      key: 'linkmenu',
+      label: '鍏宠仈鑿滃崟',
+      initVal: card.linkmenu || '',
+      required: true,
+      options: appMenus || [],
+      forbid: !['pc', 'mob'].includes(appType)
+    },
+    {
+      type: 'select',
       key: 'linkurl',
       label: '閾炬帴鍦板潃',
       initVal: card.linkurl || '',
+      tooltip: ['pc', 'mob'].includes(appType) ? '褰撻摼鎺ョ被鍨嬩负鈥滃叾浠栤�濓紝涓旈摼鎺ュ湴鍧�浠menuid@寮�澶存椂锛屽叾鍚庡唴瀹瑰皢琚涓鸿彍鍗旾D銆�' : '',
       required: true,
       options: []
+    },
+    {
+      type: 'radio',
+      key: 'open',
+      label: '鎵撳紑鏂瑰紡',
+      initVal: card.open || 'blank',
+      tooltip: '鑿滃崟鎵撳紑鏂瑰紡锛岄摼鎺ユ棤鏁堛��',
+      required: true,
+      forbid: !['pc', 'mob'].includes(appType),
+      options: [
+        {value: 'blank', text: appType !== 'mob' ? '鏂扮獥鍙�' : '鏂伴〉闈�'},
+        {value: 'self', text: appType !== 'mob' ? '褰撳墠绐楀彛' : '褰撳墠椤甸潰'},
+      ]
     },
     {
       type: 'radio',
       key: 'joint',
       label: '鎷兼帴鍙傛暟',
       initVal: card.joint || 'true',
-      required: false,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
-      }]
-    },
-    {
-      type: 'radio',
-      key: 'eval',
-      label: '瑙f瀽',
-      initVal: card.eval || 'true',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
       required: false,
       options: [{
         value: 'true',
@@ -570,6 +657,20 @@
     },
     {
       type: 'radio',
+      key: 'alignItems',
+      label: '鍨傜洿瀵归綈',
+      initVal: card.alignItems || '',
+      tooltip: '鍨傜洿鏂瑰悜鐨勫榻愭柟寮忋�傛敞锛氶珮搴︼紙琛岋級澶т簬1鏃舵湁鏁堛��',
+      required: false,
+      options: [
+        { value: '', text: '灞呬笂' },
+        { value: 'center', text: '灞呬腑' },
+        { value: 'end', text: '灞呬笅' }
+      ],
+      forbid: isHeader
+    },
+    {
+      type: 'radio',
       key: 'fixStyle',
       label: '鍓嶅悗缂�',
       initVal: card.fixStyle || '',
@@ -578,7 +679,8 @@
       options: [
         { value: '', text: '缁熶竴鏍峰紡' },
         { value: 'alone', text: '鐙珛鏍峰紡' }
-      ]
+      ],
+      forbid: isHeader
     },
     {
       type: 'radio',
@@ -590,7 +692,8 @@
       options: [
         { value: 'true', text: '鏄�' },
         { value: 'false', text: '鍚�' }
-      ]
+      ],
+      forbid: isHeader
     },
     {
       type: 'number',
@@ -630,6 +733,16 @@
       tooltip: '鍓嶇紑銆佸悗缂�鐨勫彸杈硅窛銆�',
       required: false
     },
+    {
+      type: 'select',
+      key: 'sortField',
+      label: '鎺掑簭瀛楁',
+      initVal: card.sortField || '',
+      required: false,
+      allowClear: true,
+      options: [],
+      forbid: !isHeader
+    },
   ]
 
   return forms
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index 9459118..756e8a2 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -2,6 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Modal, Button } from 'antd'
+import moment from 'moment'
 
 import asyncComponent from '@/utils/asyncComponent'
 import { getCardCellForm } from './formconfig'
@@ -75,7 +76,7 @@
   }
 
   UNSAFE_componentWillReceiveProps(nextProps) {
-    if (this.props.side !== nextProps.side) {
+    if (this.props.side !== nextProps.side && nextProps.side) {
       this.setState({
         elements: fromJS(nextProps.elements).toJS()
       })
@@ -180,12 +181,6 @@
   getStyle = (style) => {
     const { card, elements } = this.state
 
-    // if (card.eleType === 'button') {
-    //   if ((style.paddingLeft || style.paddingRight) && !style.width) {
-    //     style.width = 'auto'
-    //   }
-    // }
-
     let _card = this.resetCardStyle(card, style)
 
     let _elements = elements.map(cell => {
@@ -283,7 +278,7 @@
    * @description 鎸夐挳缂栬緫锛岃幏鍙栨寜閽〃鍗曚俊鎭�
    */
   handleAction = (card) => {
-    const { cards } = this.props
+    const { cards, side } = this.props
 
     let usefulFields = sessionStorage.getItem('permFuncField')
     if (usefulFields) {
@@ -322,11 +317,11 @@
       })
     } else {
       let anchors = MenuUtils.getAnchors(window.GLOB.customMenu.components, cards.uuid) || []
-  
+
       this.setState({
         actvisible: true,
         card: card,
-        formlist: getActionForm(card, functip, cards, usefulFields, modules, anchors)
+        formlist: getActionForm(card, functip, cards, usefulFields, modules, anchors, side)
       })
     }
   }
@@ -361,6 +356,13 @@
     const { elements } = this.state
 
     this.elementFormRef.handleConfirm().then(res => {
+      if (res.width % 0.5) {
+        res.width = parseInt(res.width / 0.5) * 0.5
+      }
+      if (res.width % 1) {
+        res.width = (res.width + '').replace(/.5/, 'x')
+      }
+
       let _elements = elements.map(cell => {
         if (cell.uuid === res.uuid) {
           res.style = cell.style || {}
@@ -436,17 +438,7 @@
         if (cell.uuid === res.uuid) {
           res.eleType = cell.eleType || null
           res.style = cell.style || null
-          // res.modal = cell.modal || null
-          // res.config = cell.config || null
           res.wrapStyle = cell.wrapStyle || null
-          // res = {...cell, ...res}
-
-          // if (!res.control) {
-          //   delete res.controlField
-          //   delete res.controlVal
-          // }
-          
-          // delete res.focus
 
           if (res.OpenType === 'form') {
             if (cell.OpenType !== 'form') {
@@ -458,12 +450,22 @@
             if (res.show === 'link' || res.show === 'icon') {
               style.color = color[cl]
               style.backgroundColor = 'transparent'
+            } else if (res.class === 'default') {
+              style.color = 'rgba(0, 0, 0, 0.65)'
+              style.backgroundColor = '#fff'
+              style.borderColor = '#d9d9d9'
+            } else if (res.class.indexOf('border') > -1) {
+              style.color = color[cl]
+              style.backgroundColor = '#fff'
+              style.borderColor = color[cl]
             } else {
               style.color = '#ffffff'
               style.backgroundColor = color[cl]
             }
             res.style = {...res.style, ...style}
           }
+
+          res.updateTime = moment().format('YYYY-MM-DD HH:mm')
 
           return res
         }
@@ -521,6 +523,7 @@
       let _elements = elements.map(cell => {
         if (cell.uuid === card.uuid) {
           cell.verify = res
+          cell.updateTime = moment().format('YYYY-MM-DD HH:mm')
         }
 
         return cell
@@ -609,10 +612,9 @@
   }
 
   dropButton = (id) => {
-    const { cards, cardCell } = this.props
+    const { cards } = this.props
 
     if (!cards.action) return
-    if (cardCell.type === 'custom') return
 
     let index = cards.action.findIndex(item => item.uuid === id)
 
@@ -706,6 +708,7 @@
       return <VerifyCard
         card={card}
         config={cards}
+        side={side || ''}
         columns={side === 'sub' ? cards.subColumns : cards.columns}
         wrappedComponentRef={(inst) => this.verifyRef = inst}
       />
@@ -735,7 +738,7 @@
     const { elements, visible, actvisible, profVisible, card, record } = this.state
 
     return (
-      <div className="model-menu-card-cell-list">
+      <div className={'model-menu-card-cell-list ' + (cardCell && cardCell.setting && cardCell.setting.layout === 'flex' ? 'mk-flex' : '') }>
         <DragElement
           list={elements}
           parent={cardCell}
@@ -784,7 +787,7 @@
             destroyOnClose
           >
             <ActionForm
-              type={cards.type === 'balcony' ? '' : 'card'}
+              type={cards.type === 'balcony' || cardCell.$cardType === 'extendCard' ? '' : 'card'}
               card={card}
               formlist={this.state.formlist}
               inputSubmit={this.handleActionSubmit}
diff --git a/src/menu/components/card/cardcellcomponent/index.scss b/src/menu/components/card/cardcellcomponent/index.scss
index bd6033c..c8d9688 100644
--- a/src/menu/components/card/cardcellcomponent/index.scss
+++ b/src/menu/components/card/cardcellcomponent/index.scss
@@ -43,4 +43,231 @@
   .card-cell:hover, .card-button-cell:hover {
     box-shadow: 0px 0px 2px #1890ff;
   }
+  .card-detail-row {
+    .ant-col[class*="x"] {
+      float: left;
+      box-sizing: border-box;
+    }
+    >.ant-col-0x {
+      width: 2.08333333%;
+    }
+    >.ant-col-1x {
+      width: 6.25%;
+    }
+    >.ant-col-2x {
+      width: 10.41666667%;
+    }
+    >.ant-col-3x {
+      width: 14.58333333%;
+    }
+    >.ant-col-4x {
+      width: 18.75%;
+    }
+    >.ant-col-5x {
+      width: 22.91666667%;
+    }
+    >.ant-col-6x {
+      width: 27.08333333%;
+    }
+    >.ant-col-7x {
+      width: 31.25%;
+    }
+    >.ant-col-8x {
+      width: 35.41666667%;
+    }
+    >.ant-col-9x {
+      width: 39.58333333%;
+    }
+    >.ant-col-10x {
+      width: 43.75%;
+    }
+    >.ant-col-11x {
+      width: 47.91666667%;
+    }
+    >.ant-col-12x {
+      width: 52.08333333%;
+    }
+    >.ant-col-13x {
+      width: 56.25%;
+    }
+    >.ant-col-14x {
+      width: 60.41666667%;
+    }
+    >.ant-col-15x {
+      width: 64.58333333%;
+    }
+    >.ant-col-16x {
+      width: 68.75%;
+    }
+    >.ant-col-17x {
+      width: 72.91666667%;
+    }
+    >.ant-col-18x {
+      width: 77.08333333%;
+    }
+    >.ant-col-19x {
+      width: 81.25%;
+    }
+    >.ant-col-20x {
+      width: 85.41666667%;
+    }
+    >.ant-col-21x {
+      width: 89.58333333%;
+    }
+    >.ant-col-22x {
+      width: 93.75%;
+    }
+    >.ant-col-23x {
+      width: 97.91666667%;
+    }
+  }
+}
+.model-menu-card-cell-list.mk-flex {
+  >.card-detail-row {
+    display: flex;
+    >.ant-col-1 {
+      flex: 1;
+    }
+    >.ant-col-2 {
+      flex: 2;
+    }
+    >.ant-col-3 {
+      flex: 3;
+    }
+    >.ant-col-4 {
+      flex: 4;
+    }
+    >.ant-col-5 {
+      flex: 5;
+    }
+    >.ant-col-6 {
+      flex: 6;
+    }
+    >.ant-col-7 {
+      flex: 7;
+    }
+    >.ant-col-8 {
+      flex: 8;
+    }
+    >.ant-col-9 {
+      flex: 9;
+    }
+    >.ant-col-10 {
+      flex: 10;
+    }
+    >.ant-col-11 {
+      flex: 11;
+    }
+    >.ant-col-12 {
+      flex: 12;
+    }
+    >.ant-col-13 {
+      flex: 13;
+    }
+    >.ant-col-14 {
+      flex: 14;
+    }
+    >.ant-col-15 {
+      flex: 15;
+    }
+    >.ant-col-16 {
+      flex: 16;
+    }
+    >.ant-col-17 {
+      flex: 17;
+    }
+    >.ant-col-18 {
+      flex: 18;
+    }
+    >.ant-col-19 {
+      flex: 19;
+    }
+    >.ant-col-20 {
+      flex: 20;
+    }
+    >.ant-col-21 {
+      flex: 21;
+    }
+    >.ant-col-22 {
+      flex: 22;
+    }
+    >.ant-col-23 {
+      flex: 23;
+    }
+    >.ant-col-24 {
+      flex: 24;
+    }
+    >.ant-col-0x {
+      flex: 0.5;
+    }
+    >.ant-col-1x {
+      flex: 1.5;
+    }
+    >.ant-col-2x {
+      flex: 2.5;
+    }
+    >.ant-col-3x {
+      flex: 3.5;
+    }
+    >.ant-col-4x {
+      flex: 4.5;
+    }
+    >.ant-col-5x {
+      flex: 5.5;
+    }
+    >.ant-col-6x {
+      flex: 6.5;
+    }
+    >.ant-col-7x {
+      flex: 7.5;
+    }
+    >.ant-col-8x {
+      flex: 8.5;
+    }
+    >.ant-col-9x {
+      flex: 9.5;
+    }
+    >.ant-col-10x {
+      flex: 10.5;
+    }
+    >.ant-col-11x {
+      flex: 11.5;
+    }
+    >.ant-col-12x {
+      flex: 12.5;
+    }
+    >.ant-col-13x {
+      flex: 13.5;
+    }
+    >.ant-col-14x {
+      flex: 14.5;
+    }
+    >.ant-col-15x {
+      flex: 15.5;
+    }
+    >.ant-col-16x {
+      flex: 16.5;
+    }
+    >.ant-col-17x {
+      flex: 17.5;
+    }
+    >.ant-col-18x {
+      flex: 18.5;
+    }
+    >.ant-col-19x {
+      flex: 19.5;
+    }
+    >.ant-col-20x {
+      flex: 20.5;
+    }
+    >.ant-col-21x {
+      flex: 21.5;
+    }
+    >.ant-col-22x {
+      flex: 22.5;
+    }
+    >.ant-col-23x {
+      flex: 23.5;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx
index a7efb6a..0d6a97d 100644
--- a/src/menu/components/card/cardcomponent/index.jsx
+++ b/src/menu/components/card/cardcomponent/index.jsx
@@ -12,6 +12,8 @@
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
+const { confirm } = Modal
+
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
@@ -119,6 +121,7 @@
   }
   
   addElement = () => {
+    const { cards } = this.props
     const { card } = this.state
 
     let newcard = {}
@@ -128,6 +131,12 @@
     newcard.eleType = 'text'
     newcard.datatype = 'dynamic'
     newcard.height = 1
+
+    if (card.$cardType === 'extendCard' && card.setting.cardRole === 'header') {
+      newcard.datatype = 'static'
+    } else if (cards.subtype === 'propcard' && cards.wrap.datatype === 'static') {
+      newcard.datatype = 'static'
+    }
 
     // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
     MKEmitter.emit('cardAddElement', card.uuid, newcard)
@@ -188,6 +197,39 @@
   updateSetting = (res) => {
     const { card, side, appType } = this.state
 
+    if (card.$cardType === 'extendCard' && res.cardRole === 'header') {
+      let _card = {...card, setting: res}
+
+      let originLength = _card.elements.length
+      _card.elements = _card.elements.filter(item => item.eleType === 'text')
+      _card.backElements = []
+
+      delete _card.menus
+
+      if (_card.elements.length < originLength) {
+        const that = this
+
+        confirm({
+          title: '琛ㄦ牸澶翠粎鏀寔鏂囨湰锛岀‘瀹氳鍒囨崲鍗$墖瑙掕壊鍚�?',
+          content: '',
+          okText: '纭畾',
+          cancelText: '鍙栨秷',
+          onOk() {
+            that.setState({ card: _card, side: '', elements: fromJS(_card.elements).toJS() }, () => {
+              that.setState({ side: 'front' })
+            })
+            that.props.updateElement(_card)
+          },
+          onCancel() {}
+        })
+      } else {
+        this.setState({ card: _card, side: 'front' })
+        this.props.updateElement(_card)
+      }
+
+      return
+    }
+
     if (appType === '' && res.menu) {
       let list = null
       try {
@@ -237,8 +279,14 @@
 
     let _uuid = Utils.getuuid()
     
+    if (card.$cardType === 'extendCard' && card.setting.cardRole === 'header' && element.eleType !== 'text') {
+      resolve({status: false, message: '琛ㄦ牸澶翠粎鏀寔鏂囨湰鍏冪礌锛�'})
+      return
+    }
+
     if (element.copyType === 'action') {
       element.eleType = 'button'
+      element.width = element.width || 12
     }
 
     element.uuid = _uuid
@@ -325,16 +373,21 @@
       }
     }
 
+    let tablerole = ''
+    if (card.$cardType === 'extendCard' && card.setting.cardRole === 'header') {
+      tablerole = ' mk-table-header'
+    }
+
     return (
       <Col span={card.setting.width || 6}>
-        <div className={'card-item ' + (card.setting.btnControl || '') + checkAll} style={_style} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard()}} id={card.uuid}>
+        <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}/>
           <div className="card-control" onDoubleClick={(e) => e.stopPropagation()}>
             <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
               <div className="mk-popover-control">
                 <PlusOutlined className="plus" title="娣诲姞鍏冪礌" onClick={this.addElement} />
-                <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} />
+                {!tablerole ? <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} /> : null}
                 <NormalForm title={cards.subtype === 'datacard' && card.$cardType !== 'extendCard' ? '寰幆鍗$墖璁剧疆' : '灞炴�у崱鐗囪缃�'} width={950} update={this.updateSetting} getForms={this.getSettingForms}>
                   <EditOutlined className="edit" title="缂栬緫"/>
                 </NormalForm>
diff --git a/src/menu/components/card/cardcomponent/index.scss b/src/menu/components/card/cardcomponent/index.scss
index 62291ee..930a06f 100644
--- a/src/menu/components/card/cardcomponent/index.scss
+++ b/src/menu/components/card/cardcomponent/index.scss
@@ -93,3 +93,8 @@
     border-radius: 0;
   }
 }
+.card-item.mk-table-header {
+  .sort-wrap {
+    display: inline;
+  }
+}
diff --git a/src/menu/components/card/cardcomponent/options.jsx b/src/menu/components/card/cardcomponent/options.jsx
index 02d46f2..0e8c311 100644
--- a/src/menu/components/card/cardcomponent/options.jsx
+++ b/src/menu/components/card/cardcomponent/options.jsx
@@ -61,6 +61,24 @@
     },
     {
       type: 'radio',
+      field: 'cardRole',
+      label: '鍗$墖瑙掕壊',
+      initval: setting.cardRole || 'card',
+      required: false,
+      options: [
+        {value: 'card', label: '灞炴�у崱'},
+        {value: 'header', label: '琛ㄦ牸澶�'},
+      ],
+      controlFields: [
+        {field: 'type', values: ['card']},
+        {field: 'click', values: ['card']},
+        {field: 'btnControl', values: ['card']},
+      ],
+      del: true,
+      forbid: cardType !== 'extendCard'
+    },
+    {
+      type: 'radio',
       field: 'type',
       label: '鍗$墖绫诲瀷',
       initval: setting.type || 'simple',
@@ -214,6 +232,17 @@
     },
     {
       type: 'radio',
+      field: 'layout',
+      label: '鍏冪礌甯冨眬',
+      initval: setting.layout || 'grid',
+      required: false,
+      options: [
+        {value: 'grid', label: '鏍呮牸甯冨眬'},
+        {value: 'flex', label: '寮规�у竷灞�'},
+      ]
+    },
+    {
+      type: 'radio',
       field: 'clickType',
       label: '瑙﹀彂鏂瑰紡',
       initval: setting.clickType || 'normal',
diff --git a/src/menu/components/card/cardsimplecomponent/index.jsx b/src/menu/components/card/cardsimplecomponent/index.jsx
index cf6e1d3..2eb816e 100644
--- a/src/menu/components/card/cardsimplecomponent/index.jsx
+++ b/src/menu/components/card/cardsimplecomponent/index.jsx
@@ -194,6 +194,7 @@
     
     if (element.copyType === 'action') {
       element.eleType = 'button'
+      element.width = element.width || 12
     }
 
     element.uuid = _uuid
diff --git a/src/menu/components/card/cardsimplecomponent/node-wrap/index.jsx b/src/menu/components/card/cardsimplecomponent/node-wrap/index.jsx
index 1b1c12f..52d1867 100644
--- a/src/menu/components/card/cardsimplecomponent/node-wrap/index.jsx
+++ b/src/menu/components/card/cardsimplecomponent/node-wrap/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Modal } from 'antd'
-import { MoreOutlined } from '@ant-design/icons'
+import { EditOutlined } from '@ant-design/icons'
 
 
 import MenusForm from './menus'
@@ -48,12 +48,12 @@
 
     return (
       <>
-        <MoreOutlined style={{color: '#1890ff'}} title="鑺傜偣缁�" onClick={this.trigger}/>
+        <EditOutlined style={{color: '#1890ff'}} title="鑺傜偣缁�" onClick={this.trigger}/>
         <Modal
           title="鑺傜偣缁�"
           wrapClassName="nodes-field-modal"
           visible={visible}
-          width={950}
+          width={1100}
           maskClosable={false}
           onOk={this.submit}
           onCancel={() => { this.setState({ visible: false })}}
diff --git a/src/menu/components/card/cardsimplecomponent/node-wrap/menus/columnform/index.jsx b/src/menu/components/card/cardsimplecomponent/node-wrap/menus/columnform/index.jsx
index 8b50c97..b9a2d59 100644
--- a/src/menu/components/card/cardsimplecomponent/node-wrap/menus/columnform/index.jsx
+++ b/src/menu/components/card/cardsimplecomponent/node-wrap/menus/columnform/index.jsx
@@ -40,25 +40,25 @@
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
-        sm: { span: 8 }
+        sm: { span: 7 }
       },
       wrapperCol: {
         xs: { span: 24 },
-        sm: { span: 16 }
+        sm: { span: 17 }
       }
     }
 
     return (
       <Form {...formItemLayout} className="node-form">
         <Row gutter={24}>
-          <Col span={6}>
+          <Col span={5}>
             <Form.Item label="鏍囪瘑">
               {getFieldDecorator('sign', {
                 initialValue: ''
               })(<Input placeholder="" autoComplete="off" />)}
             </Form.Item>
           </Col>
-          <Col span={8}>
+          <Col span={6}>
             <Form.Item label="棰滆壊">
               {getFieldDecorator('color', {
                 initialValue: '#e8e8e8',
@@ -71,7 +71,7 @@
               })(<ColorSketch />)}
             </Form.Item>
           </Col>
-          <Col span={7}>
+          <Col span={5}>
             <Form.Item label="鍥炬爣">
               {getFieldDecorator('icon', {
                 initialValue: ''
@@ -80,7 +80,14 @@
               )}
             </Form.Item>
           </Col>
-          <Col span={3} className="add">
+          <Col span={6}>
+            <Form.Item label="杩炴帴绾�">
+              {getFieldDecorator('linecolor', {
+                initialValue: '',
+              })(<ColorSketch allowClear/>)}
+            </Form.Item>
+          </Col>
+          <Col span={2} className="add">
             <Button onClick={this.handleConfirm} type="primary" className="mk-green">
               娣诲姞
             </Button>
diff --git a/src/menu/components/card/cardsimplecomponent/node-wrap/menus/index.jsx b/src/menu/components/card/cardsimplecomponent/node-wrap/menus/index.jsx
index 31a0452..5801b94 100644
--- a/src/menu/components/card/cardsimplecomponent/node-wrap/menus/index.jsx
+++ b/src/menu/components/card/cardsimplecomponent/node-wrap/menus/index.jsx
@@ -27,7 +27,7 @@
         editable: true,
         unique: true,
         required: false,
-        width: '25%'
+        width: '20%'
       },
       {
         title: '棰滆壊',
@@ -35,7 +35,7 @@
         inputType: 'color',
         editable: true,
         required: true,
-        width: '25%',
+        width: '20%',
         render: (text, record) => <span style={{display: 'inline-block', width: '40px', height: '25px', background: text}}></span>
       },
       {
@@ -44,8 +44,8 @@
         inputType: 'icon',
         editable: true,
         required: false,
-        width: '25%',
-        render: (text, record) => record.icon ? <MkIcon type={record.icon}/> : ''
+        width: '20%',
+        render: (text, record) => record.icon ? <MkIcon style={{fontSize: '24px'}} type={record.icon}/> : ''
       },
       {
         title: '杩炴帴绾�',
@@ -54,9 +54,18 @@
         editable: true,
         required: false,
         allowClear: true,
-        width: '25%',
+        width: '20%',
         render: (text, record) => text ? <span style={{display: 'inline-block', width: '40px', height: '25px', background: text}}></span> : null
       },
+      {
+        title: '澶囨敞',
+        dataIndex: 'remark',
+        inputType: 'input',
+        editable: true,
+        unique: false,
+        required: false,
+        width: '20%'
+      }
     ]
   }
 
diff --git a/src/menu/components/card/cardsimplecomponent/options.jsx b/src/menu/components/card/cardsimplecomponent/options.jsx
index 06b6740..f6ca23b 100644
--- a/src/menu/components/card/cardsimplecomponent/options.jsx
+++ b/src/menu/components/card/cardsimplecomponent/options.jsx
@@ -218,6 +218,17 @@
     },
     {
       type: 'radio',
+      field: 'layout',
+      label: '鍏冪礌甯冨眬',
+      initval: setting.layout || 'grid',
+      required: false,
+      options: [
+        {value: 'grid', label: '鏍呮牸甯冨眬'},
+        {value: 'flex', label: '寮规�у竷灞�'},
+      ]
+    },
+    {
+      type: 'radio',
       field: 'click',
       label: '鐐瑰嚮浜嬩欢',
       initval: setting.click || '',
diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx
index 92c55a7..3b75676 100644
--- a/src/menu/components/card/data-card/index.jsx
+++ b/src/menu/components/card/data-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -162,8 +162,6 @@
    * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
    */
   updateComponent = (card) => {
-    const { appType } = this.state
-
     card.width = card.wrap.width
     card.name = card.wrap.name
 
@@ -176,71 +174,15 @@
       return
     }
 
-    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.wrap.supType !== 'multi' && !card.setting.supModule) {
-      card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+    card.$c_ac = true
+    card.$c_sc = true
+    
+    card.errors = checkComponent(card)
     
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
-
-    card.action.forEach(cell => {
-      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-        if (!cell.modal || cell.modal.fields.length === 0) {
-          card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-        }
-      }
-    })
-
-    card.subcards.forEach((item, i) => {
-      let linkbtn = item.setting.linkbtn || ''
-      item.elements.forEach(cell => {
-        if (cell.eleType === 'button') {
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          }
-          if (linkbtn && linkbtn === cell.uuid) {
-            linkbtn = ''
-          }
-        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-          card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-        }
-      })
-
-      if (item.setting.type === 'multi' && appType !== 'mob') {
-        item.backElements.forEach(cell => {
-          if (cell.eleType === 'button') {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-            if (linkbtn && linkbtn === cell.uuid) {
-              linkbtn = ''
-            }
-          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-            card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-          }
-        })
-      }
-
-      if (linkbtn) {
-        card.errors.push({ level: 1, detail: `绗�${i + 1}寮犲崱鐗囦腑缁戝畾鎸夐挳宸插垹闄})
-      }
-    })
 
     this.setState({
       card: card
@@ -262,6 +204,9 @@
 
     if (btn) {
       card.action = card.action.filter(item => item.uuid !== btn.uuid)
+      setTimeout(() => {
+        MKEmitter.emit('revertBtn', card.uuid)
+      }, 200)
     }
 
     this.updateComponent(card)
@@ -486,7 +431,7 @@
       res.$cardType = 'extendCard'
       res.setting.width = res.setting.width || 6
 
-      let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton']
+      let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton', 'form']
 
       let elements = []
       res.elements && res.elements.forEach(cell => {
@@ -561,6 +506,10 @@
         this.addSearch(res)
       }
     } else if (type === 'action') {
+      if (res.style) {
+        delete res.style.width
+        delete res.style.float
+      }
       if (appType === 'mob' && !['pop', 'prompt', 'exec', 'innerpage'].includes(res.OpenType)) {
         resolve({status: false, message: '绉诲姩绔笉鏀寔姝ょ被鍨嬬殑鎸夐挳銆�'})
       } else {
@@ -613,18 +562,18 @@
           <ToolOutlined />
         </Popover>
         <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
-        <div className={'float-' + (card.wrap.cardFloat || 'left') + ' select-' + card.wrap.selStyle}>
+        <div className={`float-${card.wrap.cardFloat || 'left'} select-${card.wrap.selStyle || ''}`}>
           {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))}
         </div>
         <div style={{clear: 'both'}}></div>
-        {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType !== 'mob' ? <Pagination total={85} size="small" showTotal={total => `鍏� ${total} 鏉} pageSize={20} defaultCurrent={1}/> : null}
+        {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType !== 'mob' ? <Pagination total={45} size="small" showTotal={total => `1-10 鍏� ${total} 鏉} showSizeChanger={true} pageSize={10} defaultCurrent={1}/> : null}
         {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType === 'mob' ? <MobPagination /> : null}
         {card.wrap.pagestyle === 'more' && card.setting.laypage === 'true' ? <div className="mk-more">鏌ョ湅鏇村<DownOutlined/></div> : null}
         <div className="component-name">
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/card/data-card/index.scss b/src/menu/components/card/data-card/index.scss
index 3ccba56..8c298e3 100644
--- a/src/menu/components/card/data-card/index.scss
+++ b/src/menu/components/card/data-card/index.scss
@@ -51,16 +51,13 @@
       right: -30px;
       font-size: 16px;
     }
+    .page-card {
+      line-height: 55px;
+    }
   }
   .ant-pagination {
     float: right;
     margin: 10px;
-  }
-
-  .model-menu-action-list {
-    .page-card {
-      line-height: 55px;
-    }
   }
   .normal-pagination {
     .am-button::before {
diff --git a/src/menu/components/card/data-card/options.jsx b/src/menu/components/card/data-card/options.jsx
index a98a24c..9f2edb2 100644
--- a/src/menu/components/card/data-card/options.jsx
+++ b/src/menu/components/card/data-card/options.jsx
@@ -103,10 +103,11 @@
       ],
       linkFields: ['priKeyType'],
       controlFields: [
-        {field: 'goback', values: ['dynamic']},
+        {field: 'goback', values: ['dynamic', 'public']},
         {field: 'empty', values: ['dynamic', 'public']},
-        {field: 'jump', values: ['dynamic']},
-        {field: 'autoExec', values: ['dynamic']},
+        {field: 'jump', values: ['dynamic', 'public']},
+        {field: 'broadcast', values: ['dynamic', 'public']},
+        {field: 'autoExec', values: ['dynamic', 'public']},
         {field: 'supModule', values: ['static']},
         {field: 'publicId', values: ['public']},
       ],
@@ -119,7 +120,42 @@
       initval: wrap.publicId || '',
       required: true,
       options: interfaces,
-      forbid: subtype !== 'propcard'
+      reset_source: true,
+      forbid: subtype !== 'propcard',
+      callback: (map, record) => {
+        if (!record.publicId) return
+        
+        let interfaces = window.GLOB.customMenu.interfaces || []
+        
+        let d = interfaces.filter(m => m.uuid === record.publicId && m.status === 'true')[0]
+        
+        if (!d || !d.columns) return
+        let columns = JSON.parse(JSON.stringify(d.columns))
+
+        let _broadcast = map.get('broadcast')
+
+        if (_broadcast && !_broadcast.forbid) {
+          _broadcast.options = columns
+          _broadcast.oriOptions = columns
+          map.set('broadcast', _broadcast)
+        }
+        
+        let _jumpField = map.get('jumpField')
+
+        if (_jumpField && !_jumpField.forbid) {
+          _jumpField.options = columns
+          _jumpField.oriOptions = columns
+          map.set('jumpField', _jumpField)
+        }
+
+        let _link = map.get('link')
+
+        if (_link && !_link.forbid) {
+          _link.options = columns
+          _link.oriOptions = columns
+          map.set('link', _link)
+        }
+      }
     },
     {
       type: 'radio',
@@ -326,7 +362,7 @@
       field: 'broadcast',
       label: '璇煶鎾姤',
       initval: wrap.broadcast || '',
-      tooltip: '璇煶鎾姤鍦ㄧЩ鍔ㄧapp涓湁鏁堛�傛敞锛氫娇鐢ㄨ闊虫挱鎶ユ椂锛屾暟鎹簮涓嶈浣跨敤鍚屾鏌ヨ锛屾坊鍔犲畾鏃跺櫒鏃讹紝鍙惊鐜挱鎶�',
+      tooltip: '璇煶鎾姤鍦ㄧЩ鍔ㄧ鏈夋晥銆傛敞锛氬湪H5涓浣跨敤闊抽閾炬帴锛屾坊鍔犲畾鏃跺櫒鏃讹紝鍙惊鐜挱鎶�',
       required: false,
       options: columns,
       forbid: !columns || appType !== 'mob' || subtype !== 'propcard'
@@ -349,6 +385,7 @@
       field: 'display',
       label: '鏄剧ず鎺у埗',
       initval: wrap.display || 'normal',
+      tooltip: '褰撲娇鐢ㄥ睘鎬у崱杩涜鏌愪簺涓氬姟鎿嶄綔锛屼笖涓嶉渶瑕佸睍绀哄崱鐗囦俊鎭椂锛屽彲璁剧疆涓轰笉鍙銆�',
       required: false,
       options: [
         {value: 'normal', label: '姝e父鏄剧ず'},
@@ -397,6 +434,7 @@
       controlFields: [
         {field: 'jumpField', values: ['menu', 'link']},
         {field: 'joint', values: ['menu', 'link']},
+        {field: 'open', values: ['menu', 'link']},
         {field: 'menu', values: ['menu']},
         {field: 'link', values: ['link']},
       ],
@@ -407,7 +445,7 @@
       field: 'jumpField',
       label: '鎺у埗瀛楁',
       initval: wrap.jumpField || '',
-      tooltip: '褰撳瓧娈靛�间负true鏃�',
+      tooltip: '褰撳瓧娈靛�间负true鏃惰Е鍙戣烦杞��',
       required: true,
       options: columns,
       forbid: subtype !== 'propcard' || appType !== 'mob'
@@ -440,6 +478,18 @@
       options: [
         {value: 'true', label: '鏄�'},
         {value: 'false', label: '鍚�'},
+      ],
+      forbid: subtype !== 'propcard' || appType !== 'mob'
+    },
+    {
+      type: 'radio',
+      field: 'open',
+      label: '鎵撳紑鏂瑰紡',
+      initval: wrap.open || 'blank',
+      required: false,
+      options: [
+        {value: 'blank', label: '鏂扮獥鍙�'},
+        {value: 'self', label: '褰撳墠绐楀彛'},
       ],
       forbid: subtype !== 'propcard' || appType !== 'mob'
     },
@@ -509,13 +559,13 @@
       type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
-      initval: wrap.permission || 'false',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
       type: 'multiselect',
diff --git a/src/menu/components/card/double-data-card/index.jsx b/src/menu/components/card/double-data-card/index.jsx
index 5e709c6..1374635 100644
--- a/src/menu/components/card/double-data-card/index.jsx
+++ b/src/menu/components/card/double-data-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -167,73 +167,15 @@
       return
     }
 
-    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 (!card.setting.subKey) {
-      card.errors.push({ level: 0, detail: '鏈缃瓙琛ㄤ富閿紒'})
-    } else if (!card.setting.subBID) {
-      card.errors.push({ level: 0, detail: '鏈缃瓙琛˙ID锛�'})
-    } else if (!columns.includes(card.setting.primaryKey)) {
-      card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
-    } else if (!card.setting.supModule) {
-      card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+    card.$c_ac = true
+    card.$c_sc = true
+    
+    card.errors = checkComponent(card)
     
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
-
-    card.action.forEach(cell => {
-      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-        if (!cell.modal || cell.modal.fields.length === 0) {
-          card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-        }
-      }
-    })
-
-    card.subcards.forEach((item, i) => {
-      let linkbtn = item.setting.linkbtn || ''
-      item.elements.forEach(cell => {
-        if (cell.eleType === 'button') {
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          }
-          if (linkbtn && linkbtn === cell.uuid) {
-            linkbtn = ''
-          }
-        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-          card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-        }
-      })
-
-      item.backElements.forEach(cell => {
-        if (cell.eleType === 'button') {
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          }
-          if (linkbtn && linkbtn === cell.uuid) {
-            linkbtn = ''
-          }
-        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-          card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-        }
-      })
-
-      if (linkbtn) {
-        card.errors.push({ level: 1, detail: `绗�${i + 1}寮犲崱鐗囦腑缁戝畾鎸夐挳宸插垹闄})
-      }
-    })
 
     this.setState({
       card: card
@@ -255,6 +197,10 @@
 
     if (btn) {
       card.action = card.action.filter(item => item.uuid !== btn.uuid)
+
+      setTimeout(() => {
+        MKEmitter.emit('revertBtn', card.uuid)
+      }, 200)
     }
 
     this.updateComponent(card)
@@ -467,7 +413,7 @@
       res.$cardType = 'extendCard'
       res.setting.width = res.setting.width || 6
 
-      let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton']
+      let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton', 'form']
 
       let elements = []
       res.elements && res.elements.forEach(cell => {
@@ -587,7 +533,7 @@
             <PlusOutlined className="plus" title="娣诲姞鍗$墖" onClick={() => this.addCard()}/>
             {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="娣诲姞鎼滅储" onClick={() => this.addSearch()}/> : null}
             <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={() => this.addButton()}/>
-            <NormalForm title="鏁版嵁鍗¤缃�" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+            <NormalForm title="鍙岄噸鏁版嵁鍗¤缃�" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="datacard" card={card}/>
@@ -602,7 +548,7 @@
           <ToolOutlined />
         </Popover>
         <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
-        <div className={'select-' + card.wrap.selStyle + extraName}>
+        <div className={`select-${card.wrap.selStyle || ''} ${extraName}`}>
           {card.subcards.map(subcard => {
             if (subcard.$cardType === 'extendCard') {
               return (<CardComponent key={subcard.uuid} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>)
@@ -612,14 +558,14 @@
           })}
         </div>
         <div style={{clear: 'both'}}></div>
-        {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType !== 'mob' ? <Pagination total={85} size="small" showTotal={total => `鍏� ${total} 鏉} pageSize={20} defaultCurrent={1}/> : null}
+        {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType !== 'mob' ? <Pagination total={45} size="small" showTotal={total => `1-10 鍏� ${total} 鏉} showSizeChanger={true} pageSize={10} defaultCurrent={1}/> : null}
         {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType === 'mob' ? <MobPagination /> : null}
         {card.wrap.pagestyle === 'more' && card.setting.laypage === 'true' ? <div className="mk-more">鏌ョ湅鏇村<DownOutlined/></div> : null}
         <div className="component-name">
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/card/double-data-card/options.jsx b/src/menu/components/card/double-data-card/options.jsx
index 704da63..522c7ed 100644
--- a/src/menu/components/card/double-data-card/options.jsx
+++ b/src/menu/components/card/double-data-card/options.jsx
@@ -199,16 +199,47 @@
       required: false
     },
     {
+      type: 'number',
+      field: 'minWidth',
+      label: '鏈�灏忓搴�',
+      min: 0,
+      max: 5000,
+      precision: 0,
+      initval: wrap.minWidth,
+      tooltip: '璁剧疆鍗$墖鍖哄煙鐨勬渶灏忓搴︼紝鏄剧ず鍖哄煙灏忎簬姝ゅ�煎皢鍑虹幇妯悜婊氬姩銆�',
+      required: false
+    },
+    {
+      type: 'number',
+      field: 'zHeight',
+      label: '楂樺害',
+      min: 10,
+      max: 5000,
+      precision: 0,
+      initval: wrap.zHeight,
+      tooltip: '鍗$墖鍖哄煙楂樺害锛屽唴瀹硅秴鍑烘椂绾靛悜婊氬姩銆傛敞锛氬皬浜庣瓑浜�100鏃朵负楂樺害鐨勭櫨鍒嗘瘮锛岀涓�涓墿灞曞睘鎬у崱灏嗗畾浣嶅湪椤堕儴銆�',
+      required: false,
+      forbid: appType === 'mob'
+    },
+    {
+      type: 'color',
+      field: 'zBColor',
+      label: '杈规棰滆壊',
+      initval: wrap.zBColor || 'transparent',
+      tooltip: '鍗$墖鍖哄煙璁剧疆楂樺害鎴栨渶灏忓搴︽椂锛屾粴鍔ㄥ尯鍩熻竟妗嗙殑棰滆壊銆�',
+      required: false
+    },
+    {
       type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
-      initval: wrap.permission || 'false',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
       type: 'multiselect',
diff --git a/src/menu/components/card/doublecardcomponent/index.jsx b/src/menu/components/card/doublecardcomponent/index.jsx
index f6d1544..c5853a4 100644
--- a/src/menu/components/card/doublecardcomponent/index.jsx
+++ b/src/menu/components/card/doublecardcomponent/index.jsx
@@ -278,7 +278,7 @@
                   <NormalForm title={'寰幆鍗$墖璁剧疆'} width={950} update={(res) => this.updateSetting(res)} getForms={this.getSettingForms}>
                     <EditOutlined className="edit" title="缂栬緫"/>
                   </NormalForm>
-                  <CopyComponent type="cardcell" card={card}/>
+                  <CopyComponent type="cardcell" card={{...card, backElements: []}}/>
                   <PasteController options={['action', 'customCardElement']} updateConfig={(element, resolve) => this.paste(element, resolve, 'main')} />
                   <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.changeStyle()} />
                 </div>
@@ -298,7 +298,7 @@
                     <NormalForm title={'寰幆瀛愬崱鐗囪缃�'} width={950} update={(res) => this.updateSetting(res, 'sub')} getForms={this.getBackSettingForms}>
                       <EditOutlined className="edit" title="缂栬緫"/>
                     </NormalForm>
-                    <CopyComponent type="cardcell" card={card}/>
+                    <CopyComponent type="cardcell" card={{...card, elements: card.backElements, backElements: []}}/>
                     <PasteController options={['action', 'customCardElement']} updateConfig={(element, resolve) => this.paste(element, resolve, 'sub')} />
                     <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.changeStyle('sub')} />
                   </div>
diff --git a/src/menu/components/card/doublecardcomponent/options.jsx b/src/menu/components/card/doublecardcomponent/options.jsx
index 38a169d..dfdd703 100644
--- a/src/menu/components/card/doublecardcomponent/options.jsx
+++ b/src/menu/components/card/doublecardcomponent/options.jsx
@@ -165,6 +165,17 @@
     },
     {
       type: 'radio',
+      field: 'layout',
+      label: '鍏冪礌甯冨眬',
+      initval: setting.layout || 'grid',
+      required: false,
+      options: [
+        {value: 'grid', label: '鏍呮牸甯冨眬'},
+        {value: 'flex', label: '寮规�у竷灞�'},
+      ]
+    },
+    {
+      type: 'radio',
       field: 'clickType',
       label: '瑙﹀彂鏂瑰紡',
       initval: setting.clickType || 'normal',
diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx
index 5508f0a..12c8c19 100644
--- a/src/menu/components/card/prop-card/index.jsx
+++ b/src/menu/components/card/prop-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../data-card/options'
@@ -123,7 +123,7 @@
 
   mkUpdateInter = (inter, split) => {
     const { card } = this.state
-    
+
     if (card.wrap.datatype === 'public' && card.wrap.publicId === inter.uuid) {
       let _card = {...card, columns: fromJS(inter.columns).toJS()}
 
@@ -139,8 +139,6 @@
    * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
    */
   updateComponent = (card) => {
-    const { appType } = this.state
-
     card.width = card.wrap.width
     card.name = card.wrap.name
 
@@ -153,113 +151,14 @@
       return
     }
 
-    card.errors = []
+    card.$c_ds = card.wrap.datatype === 'dynamic'
+    card.$c_ac = false
+    card.$c_sc = true
+    
+    card.errors = checkComponent(card)
 
-    if (card.subcards.length === 0) {
-      card.errors.push({ level: 0, detail: '鍗$墖涓嶅彲涓虹┖锛�'})
-    }
-
-    if (card.wrap.datatype === 'static') {
+    if (card.errors.length === 0) {
       card.$tables = getTables(card)
-
-      card.subcards.forEach((item, i) => {
-        let linkbtn = item.setting.linkbtn || ''
-
-        item.elements.forEach(cell => {
-          if (cell.eleType === 'button') {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-            if (linkbtn && linkbtn === cell.uuid) {
-              linkbtn = ''
-            }
-          } else if (cell.datatype === 'dynamic' && cell.field) {
-            card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-          }
-        })
-
-        if (item.setting.type === 'multi' && appType !== 'mob') {
-          item.backElements.forEach(cell => {
-            if (cell.eleType === 'button') {
-              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-                if (!cell.modal || cell.modal.fields.length === 0) {
-                  card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-                }
-              }
-              if (linkbtn && linkbtn === cell.uuid) {
-                linkbtn = ''
-              }
-            } else if (cell.datatype === 'dynamic' && cell.field) {
-              card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-            }
-          })
-        }
-
-        if (linkbtn) {
-          card.errors.push({ level: 1, detail: `绗�${i + 1}寮犲崱鐗囦腑缁戝畾鎸夐挳宸插垹闄})
-        }
-      })
-    } else {
-      let columns = card.columns.map(c => c.field)
-
-      if (card.wrap.datatype === 'dynamic') {
-        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: '鏈缃笂绾х粍浠讹紒'})
-        }
-      }
-
-      if (card.errors.length === 0) {
-        card.$tables = getTables(card)
-      }
-
-      card.subcards.forEach((item, i) => {
-        let linkbtn = item.setting.linkbtn || ''
-        item.elements.forEach(cell => {
-          if (cell.eleType === 'button') {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-            if (linkbtn && linkbtn === cell.uuid) {
-              linkbtn = ''
-            }
-          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-            card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-          }
-        })
-
-        if (item.setting.type === 'multi' && appType !== 'mob') {
-          item.backElements.forEach(cell => {
-            if (cell.eleType === 'button') {
-              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-                if (!cell.modal || cell.modal.fields.length === 0) {
-                  card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-                }
-              }
-              if (linkbtn && linkbtn === cell.uuid) {
-                linkbtn = ''
-              }
-            } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-              card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-            }
-          })
-        }
-
-        if (linkbtn) {
-          card.errors.push({ level: 1, detail: `绗�${i + 1}寮犲崱鐗囦腑缁戝畾鎸夐挳宸插垹闄})
-        }
-      })
     }
 
     this.setState({
@@ -381,7 +280,7 @@
     res.setting = res.setting || {}
     res.setting.width = res.setting.width || 6
 
-    let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton']
+    let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton', 'form']
 
     let elements = []
     res.elements && res.elements.forEach(cell => {
@@ -524,7 +423,7 @@
         } trigger="hover">
           <ToolOutlined />
         </Popover>
-        <div className={(card.wrap.layout || 'grid') + '-layout float-' + (card.wrap.cardFloat || 'left') + ' select-' + card.wrap.selStyle}>
+        <div className={`${card.wrap.layout || 'grid'}-layout float-${card.wrap.cardFloat || 'left'} select-${card.wrap.selStyle || ''}`}>
           {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))}
         </div>
         {card.wrap.display === 'hidden' ? <HeatMapOutlined className="prop-hidden"/> : null}
@@ -532,7 +431,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/card/table-card/index.jsx b/src/menu/components/card/table-card/index.jsx
index 3c014f4..5eb5acd 100644
--- a/src/menu/components/card/table-card/index.jsx
+++ b/src/menu/components/card/table-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../data-card/options'
@@ -161,56 +161,15 @@
       return
     }
 
-    card.errors = []
-
-    // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-    // if (supModule === 'empty') {
-    //   supModule = ''
-    // }
-    let columns = card.columns.map(c => c.field)
-    // let lowcols = card.columns.map(c => c.field.toLowerCase())
-
-    if (card.subcards.length === 0) {
-      card.errors.push({ level: 0, detail: '鍗$墖涓嶅彲涓虹┖锛�'})
-    }
-
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+    card.$c_ac = false
+    card.$c_sc = true
+    
+    card.errors = checkComponent(card)
 
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
-
-    card.subcards.forEach((item, i) => {
-      let linkbtn = item.setting.linkbtn || ''
-      item.elements.forEach(cell => {
-        if (cell.eleType === 'button') {
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          }
-          if (linkbtn && linkbtn === cell.uuid) {
-            linkbtn = ''
-          }
-        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-          card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-        }
-      })
-
-      if (linkbtn) {
-        card.errors.push({ level: 1, detail: `绗�${i + 1}寮犲崱鐗囦腑缁戝畾鎸夐挳宸插垹闄})
-      }
-    })
 
     this.setState({
       card: card
@@ -359,7 +318,7 @@
       res.setting = res.setting || {}
       res.setting.width = res.setting.width || 6
 
-      let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton']
+      let mobtypes = ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton', 'form']
 
       let elements = []
       res.elements && res.elements.forEach(cell => {
@@ -515,7 +474,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/carousel/data-card/index.jsx b/src/menu/components/carousel/data-card/index.jsx
index 5a1eee0..5d84aea 100644
--- a/src/menu/components/carousel/data-card/index.jsx
+++ b/src/menu/components/carousel/data-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -127,39 +127,15 @@
       return
     }
 
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+    card.$c_ac = false
+    card.$c_sc = true
+    
+    card.errors = checkComponent(card)
 
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
-
-    card.subcards.forEach((item, i) => {
-      item.elements.forEach(cell => {
-        if (cell.eleType === 'button') {
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          }
-        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-          card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-        }
-      })
-    })
 
     this.setState({
       card: card
@@ -270,7 +246,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/carousel/data-card/options.jsx b/src/menu/components/carousel/data-card/options.jsx
index 8c6e414..20aeec8 100644
--- a/src/menu/components/carousel/data-card/options.jsx
+++ b/src/menu/components/carousel/data-card/options.jsx
@@ -206,13 +206,13 @@
       type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
-      initval: wrap.permission || 'false',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
       type: 'multiselect',
diff --git a/src/menu/components/carousel/prop-card/index.jsx b/src/menu/components/carousel/prop-card/index.jsx
index 9b25463..755b7e7 100644
--- a/src/menu/components/carousel/prop-card/index.jsx
+++ b/src/menu/components/carousel/prop-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../data-card/options'
@@ -126,59 +126,14 @@
       return
     }
 
-    card.errors = []
+    card.$c_ds = card.wrap.datatype === 'dynamic'
+    card.$c_ac = false
+    card.$c_sc = true
+    
+    card.errors = checkComponent(card)
 
-    if (card.subcards.length === 0) {
-      card.errors.push({ level: 0, detail: '鍗$墖涓嶅彲涓虹┖锛�'})
-    }
-
-    if (card.wrap.datatype === 'static') {
+    if (card.errors.length === 0) {
       card.$tables = getTables(card)
-      card.subcards.forEach(item => {
-        item.elements.forEach(cell => {
-          if (cell.eleType === 'button') {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-          } else if (cell.datatype === 'dynamic' && cell.field) {
-            card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-          }
-        })
-      })
-    } else {
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
-
-      if (card.errors.length === 0) {
-        card.$tables = getTables(card)
-      }
-
-      card.subcards.forEach((item, i) => {
-        item.elements.forEach(cell => {
-          if (cell.eleType === 'button') {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-            card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-          }
-        })
-      })
     }
 
     this.setState({
@@ -340,7 +295,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/chart/antv-G6/index.jsx b/src/menu/components/chart/antv-G6/index.jsx
index 81c0e09..652fbe6 100644
--- a/src/menu/components/chart/antv-G6/index.jsx
+++ b/src/menu/components/chart/antv-G6/index.jsx
@@ -8,7 +8,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, getHeight } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, getHeight, checkComponent } from '@/utils/utils-custom.js'
 import './index.scss'
 
 const { Util } = G6
@@ -1137,7 +1137,7 @@
     const { card } = this.state
 
     if (card.plot.subtype === 'mindmap') {
-      this.ponitrender()
+      this.mindrender()
     } else if (card.plot.subtype === 'indentTree') {
       this.indentrender()
     } else if (card.plot.subtype === 'kapmap') {
@@ -1270,9 +1270,9 @@
   }
 
   /**
-   * @description 鏁g偣鍥�
+   * @description 鎬濈淮瀵煎浘
    */
-  ponitrender = () => {
+  mindrender = () => {
     const { card } = this.state
     const plot = card.plot
     const data = this.getdata()
@@ -1348,21 +1348,9 @@
     card.width = card.plot.width
     card.name = card.plot.name
     card.subtype = card.plot.subtype
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+    card.errors = checkComponent(card)
 
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
@@ -1370,6 +1358,15 @@
     
     if (!card.plot.valueField) {
       card.errors.push({ level: 0, detail: '鍥捐〃淇℃伅灏氭湭璁剧疆锛�'})
+    } else {
+      let columns = card.columns.map(c => c.field)
+      if (!columns.includes(card.plot.valueField)) {
+        card.errors.push({ level: 0, detail: '鍊煎瓧娈靛湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+      } else if (!columns.includes(card.plot.labelField)) {
+        card.errors.push({ level: 0, detail: '鏂囨湰瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'})
+      } else if (!columns.includes(card.plot.parentField)) {
+        card.errors.push({ level: 0, detail: '涓婄骇瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'})
+      }
     }
 
     this.setState({
@@ -1407,7 +1404,7 @@
     let _style = resetStyle(card.style)
 
     return (
-      <div className="menu-scatter-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
+      <div className="menu-g6-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}/>
@@ -1421,12 +1418,12 @@
           <ToolOutlined/>
         </Popover>
         <NormalHeader config={card} updateComponent={this.updateComponent}/>
-        <div className="canvas" id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div>
+        <div className="canvas" style={{minHeight: card.plot.height}} id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div>
         <div className="component-name">
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/chart/antv-G6/index.scss b/src/menu/components/chart/antv-G6/index.scss
index 5d8ba6f..8a386a9 100644
--- a/src/menu/components/chart/antv-G6/index.scss
+++ b/src/menu/components/chart/antv-G6/index.scss
@@ -1,4 +1,4 @@
-.menu-scatter-chart-edit-box {
+.menu-g6-chart-edit-box {
   position: relative;
   box-sizing: border-box;
   background: #ffffff;
@@ -42,27 +42,8 @@
     color: rgba(0, 0, 0, 0.85);
     background: rgba(255, 255, 255, 0.55);
   }
-
-  .model-menu-action-list {
-    position: absolute;
-    right: 0px;
-    top: 30px;
-    z-index: 4;
-    font-size: 16px;
-  
-    .ant-row .anticon-plus {
-      float: right;
-    }
-  
-    .page-card {
-      float: right;
-    }
-  }
-  .normal-header + .canvas + .model-menu-action-list {
-    top: 45px;
-  }
 }
-.menu-scatter-chart-edit-box:hover {
+.menu-g6-chart-edit-box:hover {
   z-index: 1;
   box-shadow: 0px 0px 4px #1890ff;
 }
diff --git a/src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx
new file mode 100644
index 0000000..39827f8
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/chartcompile/formconfig.jsx
@@ -0,0 +1,232 @@
+/**
+ * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
+ * @param {object} card       // 鍥捐〃瀵硅薄
+ */
+export function getBaseForm (card, columns) {
+  let appType = sessionStorage.getItem('appType')
+  let roleList = sessionStorage.getItem('sysRoles')
+  if (roleList) {
+    try {
+      roleList = JSON.parse(roleList)
+    } catch (e) {
+      roleList = []
+    }
+  } else {
+    roleList = []
+  }
+
+  let menulist = []
+
+  if (appType === 'pc') {
+    menulist = sessionStorage.getItem('appMenus')
+    if (menulist) {
+      try {
+        menulist = JSON.parse(menulist)
+      } catch (e) {
+        menulist = []
+      }
+    } else {
+      menulist = []
+    }
+  } else if (appType === '') {
+    menulist = sessionStorage.getItem('fstMenuList')
+    if (menulist) {
+      try {
+        menulist = JSON.parse(menulist)
+      } catch (e) {
+        menulist = []
+      }
+    } else {
+      menulist = []
+    }
+  }
+
+  return [
+    {
+      type: 'text',
+      field: 'title',
+      label: '鏍囬',
+      initval: card.title,
+      required: false
+    },
+    {
+      type: 'text',
+      field: 'name',
+      label: '缁勪欢鍚嶇О',
+      initval: card.name,
+      tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�',
+      required: true
+    },
+    {
+      type: 'number',
+      field: 'width',
+      label: '瀹藉害',
+      initval: card.width,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+      min: 1,
+      max: 24,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'styleInput',
+      field: 'height',
+      label: '鍥捐〃楂樺害',
+      initval: card.height,
+      tooltip: '鍥捐〃缁樺浘鍖哄煙鐨勯珮搴︼紝涓嶅寘鎷爣棰樺強鍐呭杈硅窛銆�',
+      required: true,
+      options: ['px', 'vh', 'vw']
+    },
+    {
+      type: 'radio',
+      field: 'permission',
+      label: '鏉冮檺楠岃瘉',
+      initval: card.permission || 'false',
+      required: false,
+      options: [
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'multiselect',
+      field: 'blacklist',
+      label: '榛戝悕鍗�',
+      initval: card.blacklist || [],
+      required: false,
+      options: roleList,
+      forbid: !!appType
+    },
+    {
+      type: 'radio',
+      field: 'click',
+      label: '鐐瑰嚮浜嬩欢',
+      initval: card.click || '',
+      tooltip: '鐐瑰嚮鑺傜偣鏃惰Е鍙戠殑浜嬩欢銆�',
+      required: false,
+      options: [
+        {value: '', label: '鏃�'},
+        {value: 'menu', label: '鑿滃崟'},
+        {value: 'menus', label: '鑿滃崟缁�'}
+      ],
+      controlFields: [
+        {field: 'menu', values: ['menu']},
+        {field: 'menus', values: ['menus']},
+        {field: 'menuType', values: ['menus']},
+        {field: 'open', values: ['menu', 'menus']},
+        {field: 'joint', values: ['menu', 'menus']},
+      ]
+    },
+    {
+      type: appType === '' ? 'cascader' : 'select',
+      field: 'menu',
+      label: '鍏宠仈鑿滃崟',
+      initval: card.menu || (appType === '' ? [] : ''),
+      required: true,
+      extendName: 'MenuNo',
+      options: menulist
+    },
+    {
+      type: 'select',
+      field: 'menuType',
+      label: '鑿滃崟绫诲瀷',
+      initval: card.menuType || '',
+      required: true,
+      options: columns
+    },
+    {
+      type: 'radio',
+      field: 'open',
+      label: '鎵撳紑鏂瑰紡',
+      initval: card.open || 'blank',
+      required: false,
+      options: [
+        {value: 'blank', label: '鏂扮獥鍙�'},
+        {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',
+      field: 'menus',
+      label: '鑿滃崟缁�',
+      initval: card.menus || [],
+      required: true,
+      span: 24,
+      actions: appType === 'pc' ? ['view'] : [],
+      columns: [
+        {
+          title: '鏍囪瘑',
+          dataIndex: 'sign',
+          inputType: 'input',
+          editable: true,
+          unique: true,
+          required: false,
+          width: '35%'
+        },
+        {
+          title: '鑿滃崟',
+          dataIndex: 'menu',
+          inputType: !appType ? 'cascader' : 'select',
+          editable: true,
+          required: true,
+          extends: !appType ? 'Menu' : [{key: 'label', value: 'label'}],
+          width: '35%',
+          render: (text, record) => record.label,
+          options: menulist
+        }
+      ]
+    }
+  ]
+}
+
+/**
+ * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
+ * @param {object} card       // 鍥捐〃瀵硅薄
+ * @param {Array}  columns    // 鏄剧ず鍒�
+ */
+export function getOptionForm (card, columns) {
+  return [
+    {
+      type: 'select',
+      field: 'subtype',
+      label: '绫诲瀷',
+      initval: card.subtype || 'xflow',
+      required: true,
+      options: [{
+        value: 'xflow',
+        label: '娴佺▼鍥�'
+      }, {
+        value: 'indentTree',
+        label: '娉抽亾鍥�'
+      }, {
+        value: 'kapmap',
+        label: '缁勭粐缁撴瀯鍥�'
+      }]
+    },
+    {
+      type: 'radio',
+      field: 'empty',
+      label: '绌哄�奸殣钘�',
+      initval: card.empty || 'show',
+      tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
+      required: false,
+      options: [
+        {value: 'show', label: '鍚�'},
+        {value: 'hidden', label: '鏄�'},
+      ],
+    }
+  ]
+}
diff --git a/src/menu/components/chart/antv-X6/chartcompile/index.jsx b/src/menu/components/chart/antv-X6/chartcompile/index.jsx
new file mode 100644
index 0000000..4396a49
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/chartcompile/index.jsx
@@ -0,0 +1,179 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Modal, Form, Tabs } from 'antd'
+import { EditOutlined } from '@ant-design/icons'
+
+import { getBaseForm, getOptionForm } from './formconfig'
+import asyncComponent from '@/utils/asyncComponent'
+import './index.scss'
+
+const { TabPane } = Tabs
+const NormalForm = asyncComponent(() => import('@/components/normalform/modalform'))
+
+class LineChartDrawerForm extends Component {
+  static propTpyes = {
+    plot: PropTypes.object,
+    config: PropTypes.object,
+    plotchange: PropTypes.func
+  }
+
+  state = {
+    view: 'normal',
+    visible: false,
+    plot: null,
+    formlist: null,
+    baseFormlist: null
+  }
+
+  showDrawer = () => {
+    const { config } = this.props
+
+    this.setState({
+      visible: true,
+      view: 'normal',
+      plot: fromJS(config.plot).toJS(),
+      baseFormlist: getBaseForm(config.plot, config.columns),
+      formlist: getOptionForm(config.plot, config.columns)
+    })
+  }
+
+  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})
+      })
+    } 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})
+      })
+    }
+  }
+
+  changeTab = (tab) => {
+    const { plot, view } = this.state
+
+    if (view === 'normal') {
+      this.norRef.handleConfirm().then(res => {
+        this.setState({
+          plot: {...plot, ...res},
+          view: tab
+        })
+      })
+    } else if (view === 'base') {
+      this.baseRef.handleConfirm().then(res => {
+        this.setState({
+          plot: {...plot, ...res},
+          view: tab
+        })
+      })
+    }
+  }
+
+  render() {
+    const { config } = this.props
+    const { view, visible, baseFormlist, formlist } = this.state
+
+    return (
+      <div className="line-chart-drawer-form">
+        <EditOutlined title="缂栬緫" onClick={this.showDrawer} />
+        <Modal
+          wrapClassName="mk-pop-modal"
+          visible={visible}
+          width={850}
+          maskClosable={false}
+          onOk={this.onSubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          {config.name ? <div className="mk-com-name">{config.name} - 缂栬緫</div> : null}
+          <Tabs activeKey={view} onChange={this.changeTab}>
+            <TabPane tab="缁勪欢璁剧疆" key="base">
+              <NormalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
+            </TabPane>
+            <TabPane tab="鍥捐〃璁剧疆" key="normal">
+              <NormalForm formlist={formlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.norRef = inst}/>
+            </TabPane>
+          </Tabs>
+        </Modal>
+      </div>
+    );
+  }
+}
+
+export default Form.create()(LineChartDrawerForm)
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-X6/chartcompile/index.scss b/src/menu/components/chart/antv-X6/chartcompile/index.scss
new file mode 100644
index 0000000..19ce53c
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/chartcompile/index.scss
@@ -0,0 +1,6 @@
+.line-chart-drawer-form {
+  display: inline-block;
+  > .anticon-edit {
+    color: #1890ff;
+  }
+}
diff --git a/src/menu/components/chart/antv-X6/index.jsx b/src/menu/components/chart/antv-X6/index.jsx
new file mode 100644
index 0000000..6d20b17
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/index.jsx
@@ -0,0 +1,788 @@
+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 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 './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',
+    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(
+  'mk-rect',
+  {
+    inherit: 'rect',
+    width: 66,
+    height: 36,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#5F95FF',
+        fill: '#EFF4FF'
+      },
+      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: 36,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#5F95FF',
+        fill: '#EFF4FF'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-circle',
+  {
+    inherit: 'circle',
+    width: 36,
+    height: 36,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#5F95FF',
+        fill: '#EFF4FF'
+      },
+      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: 36,
+    attrs: {
+      body: {
+        strokeWidth: 1,
+        stroke: '#5F95FF',
+        fill: '#EFF4FF'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+Graph.registerNode(
+  'mk-star',
+  {
+    inherit: 'polygon',
+    width: 36,
+    height: 36,
+    points: '100,10 40,198 190,78 10,78 160,198',
+    attrs: {
+      body: {
+        fill: '#EFF4FF',
+        stroke: '#5F95FF',
+        strokeWidth: 1,
+        fillRule: 'nonzero'
+      },
+      text: {
+        fontSize: 12,
+        fill: '#262626'
+      }
+    },
+    ports: {
+      groups,
+      items: [
+        { group: 'top' },
+        { group: 'right' },
+        { group: 'bottom' },
+        { group: 'left' }
+      ]
+    }
+  },
+  true
+)
+
+class antvX6Chart extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    updateConfig: PropTypes.func,
+    deletecomponent: PropTypes.func,
+  }
+
+  state = {
+    card: null,
+    eventListener: null,
+    toolunfold: true,
+    nodeunfold: true,
+    node: null
+  }
+
+  selectNode = null
+  mkGraph = null
+
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+
+    if (card.isNew) {
+      let _plot = {
+        width: card.width || 24,
+        height: 400,
+        subtype: card.subtype,
+        name: card.name
+      }
+
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        format: 'array',   // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+        pageable: false,   // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+        switchable: true,  // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+        width: _plot.width,
+        name: _plot.name,
+        subtype: card.subtype,
+        setting: { interType: 'system' },
+        style: {
+          borderWidth: '1px', borderColor: 'rgb(217, 217, 217)',
+          marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
+        },
+        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
+        columns: [],
+        scripts: [],
+        search: [],
+        action: [],
+        plot: _plot,
+      }
+
+      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
+    }
+  }
+
+  componentDidMount () {
+    setTimeout(() => {
+      this.viewrender()
+    }, 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 = () => {
+    const { card } = this.state
+
+    // #region 鍒濆鍖栫敾甯�
+    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      // 涓绘缃戞牸绾块棿闅�
+      //     }
+      //   ]
+      // },
+      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: '#A2B1C3',
+                strokeWidth: 2,
+                targetMarker: {
+                  name: 'block',
+                  width: 12,
+                  height: 8
+                }
+              }
+            },
+            zIndex: 0
+          })
+        },
+        validateConnection({ targetMagnet }) {
+          return !!targetMagnet
+        }
+      },
+      highlighting: {
+        magnetAdsorbed: {
+          name: 'stroke',
+          args: {
+            attrs: {
+              fill: '#5F95FF',
+              stroke: '#5F95FF'
+            }
+          }
+        }
+      }
+    })
+
+    // #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
+        }
+      }
+    })
+    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)
+      }
+    } 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)
+      }
+    }
+  }
+
+  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)
+    }
+
+    this.setState({
+      card: card
+    })
+    this.props.updateConfig(card)
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle)
+  }
+
+  getStyle = (style) => {
+    let _card = {...this.state.card, style}
+
+    this.updateComponent(_card)
+  }
+
+  clickComponent = (e) => {
+    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
+      e.stopPropagation()
+      MKEmitter.emit('clickComponent', this.state.card.uuid, null, (style) => {
+        let _card = {...this.state.card}
+        _card.style = {..._card.style, ...style}
+
+        this.updateComponent(_card)
+      })
+    }
+  }
+
+  render() {
+    const { card, toolunfold, nodeunfold, node } = 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}/>
+            <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>
+    )
+  }
+}
+
+export default antvX6Chart
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-X6/index.scss b/src/menu/components/chart/antv-X6/index.scss
new file mode 100644
index 0000000..bb28fcb
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/index.scss
@@ -0,0 +1,233 @@
+.menu-x6-chart-edit-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  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;
+  }
+
+  .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;
+    }
+  }
+
+  .chart-header {
+    position: relative;
+    height: 45px;
+    border-bottom: 1px solid #e8e8e8;
+    overflow: hidden;
+    padding-right: 35px;
+
+    .chart-title {
+      text-decoration: inherit;
+      font-weight: inherit;
+      font-style: inherit;
+      float: left;
+      line-height: 45px;
+      margin-left: 10px;
+      position: relative;
+      z-index: 1;
+    }
+  }
+
+  >.anticon-tool {
+    position: absolute;
+    right: 1px;
+    top: 1px;
+    z-index: 3;
+    font-size: 16px;
+    padding: 5px;
+    cursor: pointer;
+    color: rgba(0, 0, 0, 0.85);
+    background: rgba(255, 255, 255, 0.55);
+  }
+}
+.menu-x6-chart-edit-box:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
diff --git a/src/menu/components/chart/antv-X6/nodeupdate/index.jsx b/src/menu/components/chart/antv-X6/nodeupdate/index.jsx
new file mode 100644
index 0000000..5dcfb27
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/nodeupdate/index.jsx
@@ -0,0 +1,288 @@
+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
new file mode 100644
index 0000000..4434358
--- /dev/null
+++ b/src/menu/components/chart/antv-X6/nodeupdate/index.scss
@@ -0,0 +1,67 @@
+.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-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx
index 8f865eb..4000502 100644
--- a/src/menu/components/chart/antv-bar/index.jsx
+++ b/src/menu/components/chart/antv-bar/index.jsx
@@ -9,7 +9,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, getHeight } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, getHeight, checkComponent } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import { chartColors } from '@/utils/option.js'
 import './index.scss'
@@ -1220,48 +1220,37 @@
 
     card.width = card.plot.width
     card.name = card.plot.name
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+    card.$c_ac = this.state.appType !== 'mob'
+    
+    card.errors = checkComponent(card)
 
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
-    
+
+    let columns = card.columns.map(c => c.field)
     if (!card.plot.Xaxis) {
       card.errors.push({ level: 0, detail: '鍧愭爣杞村皻鏈缃紒'})
     } else if (card.plot.datatype === 'query') {
       if (!columns.includes(card.plot.Xaxis)) {
-        card.errors.push({ level: 1, detail: 'X杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+        card.errors.push({ level: 0, detail: 'X杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
       }
       if (card.plot.Yaxis) {
         card.plot.Yaxis.forEach(m => {
           if (!columns.includes(m)) {
-            card.errors.push({ level: 1, detail: `Y杞翠腑瀛楁鈥�${m}鈥濆凡澶辨晥`})
+            card.errors.push({ level: 0, detail: `Y杞翠腑瀛楁鈥�${m}鈥濆凡澶辨晥`})
           }
         })
       }
     } else if (card.plot.datatype === 'statistics') {
       if (!columns.includes(card.plot.Xaxis)) {
-        card.errors.push({ level: 1, detail: 'X杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
-      }
-      if (!columns.includes(card.plot.InfoType)) {
-        card.errors.push({ level: 1, detail: '鍥捐〃涓粺璁$被鍨嬪瓧娈靛凡澶辨晥'})
-      }
-      if (!columns.includes(card.plot.InfoValue)) {
-        card.errors.push({ level: 1, detail: '鍥捐〃涓粺璁″�煎瓧娈靛凡澶辨晥'})
+        card.errors.push({ level: 0, detail: 'X杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+      } else if (!columns.includes(card.plot.InfoType)) {
+        card.errors.push({ level: 0, detail: '鍥捐〃涓粺璁$被鍨嬪瓧娈靛凡澶辨晥'})
+      } else if (!columns.includes(card.plot.InfoValue)) {
+        card.errors.push({ level: 0, detail: '鍥捐〃涓粺璁″�煎瓧娈靛凡澶辨晥'})
       }
     }
 
@@ -1377,7 +1366,7 @@
           <ToolOutlined/>
         </Popover>
         <NormalHeader config={card} updateComponent={this.updateComponent}/>
-        <div className="canvas" id={card.uuid + 'canvas'}></div>
+        <div className="canvas" style={{minHeight: card.plot.height}} id={card.uuid + 'canvas'}></div>
         {appType !== 'mob' ? <ActionComponent
           config={card}
           updateaction={this.updateComponent}
@@ -1386,7 +1375,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/chart/antv-dashboard/index.jsx b/src/menu/components/chart/antv-dashboard/index.jsx
index b66d1d3..f74d260 100644
--- a/src/menu/components/chart/antv-dashboard/index.jsx
+++ b/src/menu/components/chart/antv-dashboard/index.jsx
@@ -8,7 +8,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, getHeight } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, getHeight, checkComponent } from '@/utils/utils-custom.js'
 import './index.scss'
 
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
@@ -473,30 +473,18 @@
     card.width = card.plot.width
     card.name = card.plot.name
 
-    card.errors = []
-
-    let columns = card.columns.map(c => c.field)
+    card.$c_ds = true
+    card.errors = checkComponent(card)
     
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
-
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
     
+    let columns = card.columns.map(c => c.field)
     if (!card.plot.valueField) {
       card.errors.push({ level: 0, detail: '鏄剧ず鍊煎皻鏈缃紒'})
     } else if (!columns.includes(card.plot.valueField)) {
-      card.errors.push({ level: 1, detail: '鏄剧ず鍊煎湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+      card.errors.push({ level: 0, detail: '鏄剧ず鍊煎湪瀛楁闆嗕腑涓嶅瓨鍦�'})
     }
     
     this.setState({
@@ -550,12 +538,12 @@
           <ToolOutlined/>
         </Popover>
         <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
-        <div className="canvas" id={card.uuid + 'dashboard'}></div>
+        <div className="canvas" style={{minHeight: card.plot.height}} id={card.uuid + 'dashboard'}></div>
         <div className="component-name">
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx
index 3f269b4..304484c 100644
--- a/src/menu/components/chart/antv-pie/index.jsx
+++ b/src/menu/components/chart/antv-pie/index.jsx
@@ -9,7 +9,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, getHeight } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, getHeight, checkComponent } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import './index.scss'
 
@@ -622,22 +622,10 @@
 
     card.width = card.plot.width
     card.name = card.plot.name
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
-
+    
+    card.$c_ds = true
+    card.errors = checkComponent(card)
+    
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
@@ -645,11 +633,11 @@
     if (!card.plot.Xaxis) {
       card.errors.push({ level: 0, detail: '鍚嶇О瀛楁灏氭湭璁剧疆锛�'})
     } else {
+      let columns = card.columns.map(c => c.field)
       if (!columns.includes(card.plot.Xaxis)) {
-        card.errors.push({ level: 1, detail: '鍚嶇О瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'})
-      }
-      if (!columns.includes(card.plot.Yaxis)) {
-        card.errors.push({ level: 1, detail: '鍊煎瓧娈靛湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+        card.errors.push({ level: 0, detail: '鍚嶇О瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'})
+      } else if (!columns.includes(card.plot.Yaxis)) {
+        card.errors.push({ level: 0, detail: '鍊煎瓧娈靛湪瀛楁闆嗕腑涓嶅瓨鍦�'})
       }
     }
     
@@ -724,12 +712,12 @@
           <ToolOutlined />
         </Popover>
         <NormalHeader config={card} updateComponent={this.updateComponent}/>
-        <div className="canvas" id={card.uuid + 'canvas'}></div>
+        <div className="canvas" style={{minHeight: card.plot.height}} id={card.uuid + 'canvas'}></div>
         <div className="component-name">
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/chart/antv-scatter/index.jsx b/src/menu/components/chart/antv-scatter/index.jsx
index 79b4684..bf2a909 100644
--- a/src/menu/components/chart/antv-scatter/index.jsx
+++ b/src/menu/components/chart/antv-scatter/index.jsx
@@ -8,7 +8,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, getHeight } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, getHeight, checkComponent } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import './index.scss'
 
@@ -253,22 +253,12 @@
 
     card.width = card.plot.width
     card.name = card.plot.name
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
-
+    card.$c_ds = true
+    card.$c_ac = this.state.appType !== 'mob'
+    
+    card.errors = checkComponent(card)
+    
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
     }
@@ -276,11 +266,11 @@
     if (!card.plot.Xaxis) {
       card.errors.push({ level: 0, detail: '鍧愭爣杞村皻鏈缃紒'})
     } else {
+      let columns = card.columns.map(c => c.field)
       if (!columns.includes(card.plot.Xaxis)) {
-        card.errors.push({ level: 1, detail: 'X杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
-      }
-      if (!columns.includes(card.plot.Yaxis)) {
-        card.errors.push({ level: 1, detail: 'Y杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+        card.errors.push({ level: 0, detail: 'X杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+      } else if (!columns.includes(card.plot.Yaxis)) {
+        card.errors.push({ level: 0, detail: 'Y杞村湪瀛楁闆嗕腑涓嶅瓨鍦�'})
       }
     }
 
@@ -395,13 +385,13 @@
           <ToolOutlined/>
         </Popover>
         <NormalHeader config={card} updateComponent={this.updateComponent}/>
-        <div className="canvas" id={card.uuid + 'canvas'}></div>
+        <div className="canvas" style={{minHeight: card.plot.height}} id={card.uuid + 'canvas'}></div>
         {appType !== 'mob' ? <ActionComponent config={card} updateaction={this.updateComponent}/> : null}
         <div className="component-name">
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/chart/chart-custom/index.jsx b/src/menu/components/chart/chart-custom/index.jsx
index d601ba4..16d9daf 100644
--- a/src/menu/components/chart/chart-custom/index.jsx
+++ b/src/menu/components/chart/chart-custom/index.jsx
@@ -10,7 +10,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, getHeight } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, getHeight, checkComponent } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import './index.scss'
 
@@ -183,21 +183,9 @@
 
     card.width = card.plot.width
     card.name = card.plot.name
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+    card.errors = checkComponent(card)
 
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
diff --git a/src/menu/components/code/sandbox/codecontent/index.jsx b/src/menu/components/code/sandbox/codecontent/index.jsx
index 42ff7c2..5d15bfd 100644
--- a/src/menu/components/code/sandbox/codecontent/index.jsx
+++ b/src/menu/components/code/sandbox/codecontent/index.jsx
@@ -27,10 +27,13 @@
 
   componentDidMount () {
     const { config } = this.props
-    if (config.js && config.wrap.compileMode !== 'custom') {
+    if (config.js) {
       try {
         // eslint-disable-next-line no-eval
-        eval(config.js)
+        // eval(config.js)
+        // eslint-disable-next-line
+        let evalfunc = eval('(true && function (data) {' + config.js + '})')
+        evalfunc([])
       } catch (e) {
         message.warning(config.name + 'JS 鎵ц澶辫触锛�')
         console.warn(config.name + e)
@@ -53,10 +56,11 @@
       }
     }
     if (config.html !== nextProps.config.html || config.js !== nextProps.config.js) {
-      if (nextProps.config.js && nextProps.config.wrap.compileMode !== 'custom') {
+      if (nextProps.config.js) {
         try {
           // eslint-disable-next-line no-eval
-          eval(nextProps.config.js)
+          let evalfunc = eval('(true && function (data) {' + nextProps.config.js + '})')
+          evalfunc([])
         } catch (e) {
           message.warning(config.name + 'JS 鎵ц澶辫触锛�')
           console.warn(config.name + e)
diff --git a/src/menu/components/code/sandbox/index.jsx b/src/menu/components/code/sandbox/index.jsx
index cced2c3..1df42b8 100644
--- a/src/menu/components/code/sandbox/index.jsx
+++ b/src/menu/components/code/sandbox/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import getWrapForm from './options'
 
@@ -102,20 +102,9 @@
 
     card.errors = []
 
-    let columns = card.columns.map(c => c.field)
-
     if (card.wrap.datatype !== 'static') {
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      card.$c_ds = true
+      card.errors = checkComponent(card)
     }
 
     this.setState({
diff --git a/src/menu/components/code/sandbox/options.jsx b/src/menu/components/code/sandbox/options.jsx
index 55c0cde..f3a940b 100644
--- a/src/menu/components/code/sandbox/options.jsx
+++ b/src/menu/components/code/sandbox/options.jsx
@@ -46,21 +46,21 @@
         {value: 'dynamic', label: '鍔ㄦ��'},
         {value: 'static', label: '闈欐��'},
       ],
-      controlFields: [
-        {field: 'compileMode', values: ['dynamic']}
-      ]
+      // controlFields: [
+      //   {field: 'compileMode', values: ['dynamic']}
+      // ]
     },
-    {
-      type: 'radio',
-      field: 'compileMode',
-      label: '缂栬瘧鏂瑰紡',
-      initval: wrap.compileMode || 'replace',
-      required: false,
-      options: [
-        {value: 'replace', label: '瀛楁鏇挎崲'},
-        {value: 'custom', label: '鑷畾涔�'},
-      ]
-    },
+    // {
+    //   type: 'radio',
+    //   field: 'compileMode',
+    //   label: '缂栬瘧鏂瑰紡',
+    //   initval: wrap.compileMode || 'replace',
+    //   required: false,
+    //   options: [
+    //     {value: 'replace', label: '瀛楁鏇挎崲'},
+    //     {value: 'custom', label: '鑷畾涔�'},
+    //   ]
+    // },
     {
       type: 'radio',
       field: 'permission',
diff --git a/src/menu/components/editor/braft-editor/index.jsx b/src/menu/components/editor/braft-editor/index.jsx
index 444a206..3dfb6b3 100644
--- a/src/menu/components/editor/braft-editor/index.jsx
+++ b/src/menu/components/editor/braft-editor/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { getTables } from '@/utils/utils-custom.js'
+import { getTables, checkComponent } from '@/utils/utils-custom.js'
 import getWrapForm from './options'
 import MKEmitter from '@/utils/events.js'
 
@@ -117,20 +117,9 @@
 
     card.errors = []
 
-    let columns = card.columns.map(c => c.field)
-
     if (card.wrap.datatype !== 'static') {
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      card.$c_ds = true
+      card.errors = checkComponent(card)
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
@@ -199,14 +188,14 @@
     let style = {...card.style}
 
     return (
-      <div className="menu-normal-editor-box" style={style} onClick={this.clickComponent} id={card.uuid}>
+      <div className={'menu-normal-editor-box ' + (card.wrap.firstTr || '')} style={style} onClick={this.clickComponent} 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">
             <NormalForm title="瀵屾枃鏈缃�" width={750} update={this.updateWrap} getForms={this.getWrapForms}>
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
-            <CopyComponent type="normaltable" card={card}/>
+            <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)} />
diff --git a/src/menu/components/editor/braft-editor/index.scss b/src/menu/components/editor/braft-editor/index.scss
index 8830797..aa55923 100644
--- a/src/menu/components/editor/braft-editor/index.scss
+++ b/src/menu/components/editor/braft-editor/index.scss
@@ -25,6 +25,15 @@
     color: #bcbcbc;
   }
 }
+.menu-normal-editor-box.light {
+  .braft-content {
+    table {
+      tr:first-child {
+        background-color:#ffffff;
+      }
+    }
+  }
+}
 .menu-normal-editor-box::after {
   display: block;
   content: ' ';
diff --git a/src/menu/components/editor/braft-editor/options.jsx b/src/menu/components/editor/braft-editor/options.jsx
index 3c33098..908efea 100644
--- a/src/menu/components/editor/braft-editor/options.jsx
+++ b/src/menu/components/editor/braft-editor/options.jsx
@@ -80,14 +80,33 @@
       label: '鏁版嵁婧�',
       initval: wrap.publicId || '',
       required: true,
-      options: interfaces
+      options: interfaces,
+      reset_source: true,
+      callback: (map, record) => {
+        if (!record.publicId) return
+
+        let interfaces = window.GLOB.customMenu.interfaces || []
+
+        let d = interfaces.filter(m => m.uuid === record.publicId && m.status === 'true')[0]
+
+        if (!d || !d.columns) return
+
+        let columns = JSON.parse(JSON.stringify(d.columns))
+
+        let _field = map.get('field')
+
+        if (_field) {
+          _field.options = columns
+          _field.oriOptions = columns
+          map.set('field', _field)
+        }
+      }
     },
     {
       type: 'select',
       field: 'field',
       label: '鏂囨湰瀛楁',
       initval: wrap.field || '',
-      tooltip: '閫夋嫨鍔ㄦ�佸�兼椂锛岄渶璁剧疆鏂囨湰瀛楁鎵嶅彲鐢熸晥锛屼娇鐢ㄥ叕鍏辨暟鎹簮鏃讹紝闇�鍏堜繚瀛樻暟鎹簮鍚庡啀閫夊彇鏂囨湰瀛楁銆�',
       required: false,
       options: columns
     },
@@ -118,6 +137,18 @@
     },
     {
       type: 'radio',
+      field: 'firstTr',
+      label: '琛ㄦ牸棣栬',
+      initval: wrap.firstTr || 'deep',
+      tooltip: '瀵屾枃鏈腑table鐨勯琛岃儗鏅鑹层��',
+      required: false,
+      options: [
+        {value: 'deep', label: '娣辫壊'},
+        {value: 'light', label: '娴呰壊'},
+      ]
+    },
+    {
+      type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
       initval: wrap.permission || 'false',
diff --git a/src/menu/components/form/dragtitle/card.jsx b/src/menu/components/form/dragtitle/card.jsx
index c8b980c..a2eb77d 100644
--- a/src/menu/components/form/dragtitle/card.jsx
+++ b/src/menu/components/form/dragtitle/card.jsx
@@ -9,7 +9,7 @@
 import './index.scss'
 
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
-const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
+const PasteForms = asyncIconComponent(() => import('@/menu/components/share/pasteforms'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 
 const Card = ({ id, card, sort, labelSize, active, moveCard, findCard, closeCard, selectCard, updateGroup, pasteForm }) => {
@@ -51,6 +51,16 @@
   const updateSetting = (res) => {
     let _card = fromJS(card).toJS()
     
+    let buttons = res.buttons
+
+    delete res.buttons
+
+    if (buttons) {
+      res.prevEnable = buttons.includes('prevEnable') ? 'true' : 'false'
+      res.subEnable = buttons.includes('subEnable') ? 'true' : 'false'
+      res.nextEnable = buttons.includes('nextEnable') ? 'true' : 'false'
+    }
+
     if (res.prevEnable) {
       _card.prevButton.enable = res.prevEnable
       delete res.prevEnable
@@ -80,7 +90,7 @@
           <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
         </NormalForm>
         <CopyComponent type="formgroup" card={card}/>
-        <PasteComponent options={['form', 'forms']} updateConfig={(res) => pasteForm(res, id)} />
+        <PasteForms config={card} updateConfig={(res) => pasteForm(res, id)} />
         <CloseOutlined className="close" type="close" onClick={close} />
       </div>
     } trigger="hover">
diff --git a/src/menu/components/form/dragtitle/options.jsx b/src/menu/components/form/dragtitle/options.jsx
index 81c4435..5ffecf1 100644
--- a/src/menu/components/form/dragtitle/options.jsx
+++ b/src/menu/components/form/dragtitle/options.jsx
@@ -19,6 +19,18 @@
     })
   }
 
+  let buttons = []
+
+  if (group.prevButton && group.prevButton.enable === 'true') {
+    buttons.push('prevEnable')
+  }
+  if (!group.subButton.enable || group.subButton.enable === 'true') {
+    buttons.push('subEnable')
+  }
+  if (group.nextButton && group.nextButton.enable === 'true') {
+    buttons.push('nextEnable')
+  }
+
   const groupForm = [
     {
       type: 'text',
@@ -83,18 +95,32 @@
       forbid: appType === 'mob'
     },
     {
-      type: 'radio',
-      field: 'prevEnable',
-      label: '涓婁竴姝�',
-      initval: group.prevButton ? group.prevButton.enable || 'false' : 'false',
-      tooltip: '绗竴缁勪笉鏄剧ず銆傛敞锛氶櫎鍏抽棴鍔熻兘澶栥��',
+      type: 'checkbox',
+      field: 'buttons',
+      label: '鎸夐挳缁�',
+      initval: buttons,
+      tooltip: '涓婁竴姝ュ湪绗竴缁勪腑涓嶆樉绀猴紝璺宠繃鍦ㄦ渶鍚庝竴缁勪笉鏄剧ず锛屾敞锛氶櫎鍏抽棴鍔熻兘澶栥��',
       required: false,
       options: [
-        {value: 'true', label: '鏄剧ず'},
-        {value: 'false', label: '闅愯棌'},
+        {value: 'prevEnable', label: '涓婁竴姝�'},
+        {value: 'subEnable', label: '鎻愪氦'},
+        {value: 'nextEnable', label: '璺宠繃'},
       ],
       forbid: !group.prevButton
     },
+    // {
+    //   type: 'radio',
+    //   field: 'prevEnable',
+    //   label: '涓婁竴姝�',
+    //   initval: group.prevButton ? group.prevButton.enable || 'false' : 'false',
+    //   tooltip: '绗竴缁勪笉鏄剧ず銆傛敞锛氶櫎鍏抽棴鍔熻兘澶栥��',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄剧ず'},
+    //     {value: 'false', label: '闅愯棌'},
+    //   ],
+    //   forbid: !group.prevButton
+    // },
     {
       type: 'radio',
       field: 'subEnable',
@@ -104,21 +130,22 @@
       options: [
         {value: 'true', label: '鏄剧ず'},
         {value: 'false', label: '闅愯棌'},
-      ]
-    },
-    {
-      type: 'radio',
-      field: 'nextEnable',
-      label: '璺宠繃',
-      initval: group.nextButton ? group.nextButton.enable || 'false' : 'false',
-      tooltip: '鏈�鍚庝竴缁勪笉鏄剧ず銆傛敞锛氶櫎鍏抽棴鍔熻兘澶栥��',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄剧ず'},
-        {value: 'false', label: '闅愯棌'},
       ],
-      forbid: !group.nextButton
+      forbid: !!group.prevButton
     },
+    // {
+    //   type: 'radio',
+    //   field: 'nextEnable',
+    //   label: '璺宠繃',
+    //   initval: group.nextButton ? group.nextButton.enable || 'false' : 'false',
+    //   tooltip: '鏈�鍚庝竴缁勪笉鏄剧ず銆傛敞锛氶櫎鍏抽棴鍔熻兘澶栥��',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄剧ず'},
+    //     {value: 'false', label: '闅愯棌'},
+    //   ],
+    //   forbid: !group.nextButton
+    // },
   ]
 
   return groupForm
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index 2b1e483..3f75c5d 100644
--- a/src/menu/components/form/simple-form/index.jsx
+++ b/src/menu/components/form/simple-form/index.jsx
@@ -9,7 +9,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -23,7 +23,7 @@
 const FormAction = asyncComponent(() => import('../formaction'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
-const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
+const PasteForms = asyncIconComponent(() => import('@/menu/components/share/pasteforms'))
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 
@@ -132,19 +132,9 @@
       if (supModule === 'empty') {
         supModule = ''
       }
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      card.$c_ds = true
+      card.errors = checkComponent(card)
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
@@ -367,7 +357,7 @@
         })
       }
 
-      if (item.type === 'switch') {
+      if (item.type === 'switch' || item.type === 'check') {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -443,6 +433,8 @@
           fieldrepet = true
         }
 
+        delete item.focus
+
         if (item.uuid === res.uuid) {
           if (item.style) {
             res.style = item.style
@@ -462,6 +454,8 @@
         return
       }
 
+      window.GLOB.formId = res.uuid
+      
       if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
         this.setState({
           sqlVerifing: true
@@ -511,93 +505,43 @@
     })
   }
 
-  pasteForm = (res) => {
+  pasteForm = (forms, res) => {
     let _config = fromJS(this.state.card).toJS()
+
+    _config.subcards[0].fields = forms
 
     if (res.subButton) {
       let that = this
 
-      _config.subcards[0].setting.focus = res.focus
-      _config.subcards[0].setting.cache = res.cache
-      _config.subcards[0].setting.align = res.align
-      _config.subcards[0].setting.enable = res.enable
-      _config.subcards[0].setting.verticalSpace = res.verticalSpace || ''
-      _config.wrap.focus = res.focus
-      _config.wrap.cache = res.cache
-      _config.wrap.align = res.align
-      _config.wrap.enable = res.enable
-      _config.wrap.verticalSpace = res.verticalSpace || ''
-
-      _config.subcards[0].subButton = res.subButton
+      // _config.subcards[0].setting.focus = res.focus
+      // _config.subcards[0].setting.cache = res.cache
+      // _config.subcards[0].setting.align = res.align
+      // _config.subcards[0].setting.enable = res.enable
+      // _config.subcards[0].setting.verticalSpace = res.verticalSpace || ''
+      // _config.wrap.focus = res.focus
+      // _config.wrap.cache = res.cache
+      // _config.wrap.align = res.align
+      // _config.wrap.enable = res.enable
+      // _config.wrap.verticalSpace = res.verticalSpace || ''
       
-      _config.subcards[0].fields = res.fields.map(item => {
-        item.uuid = Utils.getuuid()
-        return item
-      })
-
       confirm({
-        content: '鏇挎崲琛ㄥ崟鍙婃寜閽厤缃紵',
+        content: '鏄惁鏇挎崲鎸夐挳閰嶇疆锛�',
+        okText: '鏄�',
+        cancelText: '鍚�',
         onOk() {
+          _config.subcards[0].subButton = res.subButton
+          
           that.updateComponent(_config)
         },
-        onCancel() {}
+        onCancel() {
+          that.updateComponent(_config)
+        }
       })
-      return
-    } else if (res.fields) {
-      if (_config.subcards[0].fields.length > 0) {
-        let that = this
-        _config.subcards[0].fields = res.fields.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
+    } else {
+      _config.subcards[0].fields = forms
 
-        confirm({
-          title: '纭畾鏇挎崲琛ㄥ崟鍚楋紵',
-          content: '鍘熻〃鍗曞皢鍒犻櫎銆�',
-          onOk() {
-            that.updateComponent(_config)
-          },
-          onCancel() {}
-        })
-      } else {
-        _config.subcards[0].fields = res.fields.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
-
-        this.updateComponent(_config)
-      }
-
-      return
+      this.updateComponent(_config)
     }
-
-    let fieldrepet = false // 瀛楁閲嶅
-
-    _config.subcards[0].fields.forEach(item => {
-      if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-        fieldrepet = true
-      }
-    })
-
-    if (fieldrepet) {
-      notification.warning({
-        top: 92,
-        message: '瀛楁宸插瓨鍦紒',
-        duration: 10
-      })
-      return
-    }
-    _config.subcards[0].fields.push(res)
-
-    this.updateComponent(_config)
-
-    this.handleForm(res)
-
-    notification.success({
-      top: 92,
-      message: '绮樿创鎴愬姛锛�',
-      duration: 2
-    })
   }
 
   getWrapForms = () => {
@@ -606,6 +550,13 @@
 
   updateWrap = (res) => {
     let _card = fromJS(this.state.card).toJS()
+    let buttons = res.buttons
+
+    delete res.buttons
+
+    res.enable = buttons.includes('enable') ? 'true' : 'false'
+    res.closeEnable = buttons.includes('closeEnable') ? 'true' : 'false'
+
     _card.wrap = res
 
     if (res.datatype === 'static') {
@@ -671,7 +622,7 @@
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="simpleform" card={card}/>
-            <PasteComponent config={card} options={['form', 'forms', 'formgroup']} updateConfig={this.pasteForm} />
+            <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)} />
@@ -712,7 +663,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/form/simple-form/options.jsx b/src/menu/components/form/simple-form/options.jsx
index 2197555..1ace5c6 100644
--- a/src/menu/components/form/simple-form/options.jsx
+++ b/src/menu/components/form/simple-form/options.jsx
@@ -45,6 +45,15 @@
     }
   }
 
+  let buttons = []
+
+  if (!wrap.enable || wrap.enable === 'true') {
+    buttons.push('enable')
+  }
+  if (wrap.closeEnable === 'true') {
+    buttons.push('closeEnable')
+  }
+
   const wrapForm = [
     {
       type: 'text',
@@ -135,28 +144,40 @@
       forbid: appType === 'mob'
     },
     {
-      type: 'radio',
-      field: 'enable',
-      label: '鎻愪氦',
-      initval: wrap.enable || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄剧ず'},
-        {value: 'false', label: '闅愯棌'},
-      ]
-    },
-    {
-      type: 'radio',
-      field: 'closeEnable',
-      label: '鍏抽棴',
-      initval: wrap.closeEnable || 'false',
+      type: 'checkbox',
+      field: 'buttons',
+      label: '鎸夐挳缁�',
+      initval: buttons,
       tooltip: '绠$悊绯荤粺涓細鍏抽棴褰撳墠鏍囩锛屽瓙搴旂敤涓负杩斿洖涓婁竴椤点��',
       required: false,
       options: [
-        {value: 'true', label: '鏄剧ず'},
-        {value: 'false', label: '闅愯棌'},
-      ]
+        {value: 'enable', label: '鎻愪氦'},
+        {value: 'closeEnable', label: '鍏抽棴'},
+      ],
     },
+    // {
+    //   type: 'radio',
+    //   field: 'enable',
+    //   label: '鎻愪氦',
+    //   initval: wrap.enable || 'true',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄剧ず'},
+    //     {value: 'false', label: '闅愯棌'},
+    //   ]
+    // },
+    // {
+    //   type: 'radio',
+    //   field: 'closeEnable',
+    //   label: '鍏抽棴',
+    //   initval: wrap.closeEnable || 'false',
+    //   tooltip: '绠$悊绯荤粺涓細鍏抽棴褰撳墠鏍囩锛屽瓙搴旂敤涓负杩斿洖涓婁竴椤点��',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄剧ず'},
+    //     {value: 'false', label: '闅愯棌'},
+    //   ]
+    // },
     {
       type: 'radio',
       field: 'formStyle',
diff --git a/src/menu/components/form/step-form/index.jsx b/src/menu/components/form/step-form/index.jsx
index 3f37ddf..c5624f9 100644
--- a/src/menu/components/form/step-form/index.jsx
+++ b/src/menu/components/form/step-form/index.jsx
@@ -9,7 +9,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -139,19 +139,9 @@
       if (supModule === 'empty') {
         supModule = ''
       }
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      
+      card.$c_ds = true
+      card.errors = checkComponent(card)
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
@@ -469,7 +459,7 @@
         })
       }
 
-      if (item.type === 'switch') {
+      if (item.type === 'switch' || item.type === 'check') {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -545,6 +535,8 @@
           fieldrepet = true
         }
 
+        delete item.focus
+
         if (item.uuid === res.uuid) {
           if (item.style) {
             res.style = item.style
@@ -564,6 +556,8 @@
         return
       }
 
+      window.GLOB.formId = res.uuid
+      
       if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
         this.setState({
           sqlVerifing: true
@@ -617,60 +611,29 @@
     if (res.subtype === 'simpleform') {
       res = res.subcards[0]
     }
-    if (res.subButton) {
-      let card = fromJS(this.state.card).toJS()
 
-      res.uuid = Utils.getuuid()
-      res.sort = card.subcards.length + 1
+    let card = fromJS(this.state.card).toJS()
 
-      res.fields.forEach(item => {
-        item.uuid = Utils.getuuid()
-      })
+    res.uuid = Utils.getuuid()
+    res.sort = card.subcards.length + 1
 
-      if (!res.prevButton) {
-        res.prevButton = {label: '涓婁竴姝�', type: 'prev', enable: 'false', style: {marginRight: '15px', paddingTop: '5px', paddingBottom: '5px'}}
-      }
-      if (!res.nextButton) {
-        res.nextButton = {label: '璺宠繃', type: 'next', enable: 'false', style: {paddingTop: '5px', paddingBottom: '5px'}}
-      }
-
-      card.subcards.push(res)
-      
-      this.setState({
-        group: res
-      })
-      this.updateComponent(card)
-
-      notification.success({
-        top: 92,
-        message: '绮樿创鎴愬姛锛�',
-        duration: 2
-      })
-      return
-    }
-
-    let _config = fromJS(this.state.group).toJS()
-    let fieldrepet = false // 瀛楁閲嶅
-
-    _config.fields.forEach(item => {
-      if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-        fieldrepet = true
-      }
+    res.fields.forEach(item => {
+      item.uuid = Utils.getuuid()
     })
 
-    if (fieldrepet) {
-      notification.warning({
-        top: 92,
-        message: '瀛楁宸插瓨鍦紒',
-        duration: 10
-      })
-      return
+    if (!res.prevButton) {
+      res.prevButton = {label: '涓婁竴姝�', type: 'prev', enable: 'false', style: {marginRight: '15px', paddingTop: '5px', paddingBottom: '5px'}}
     }
-    _config.fields.push(res)
+    if (!res.nextButton) {
+      res.nextButton = {label: '璺宠繃', type: 'next', enable: 'false', style: {paddingTop: '5px', paddingBottom: '5px'}}
+    }
 
-    this.updateGroup(_config)
-
-    this.handleForm(res)
+    card.subcards.push(res)
+    
+    this.setState({
+      group: res
+    })
+    this.updateComponent(card)
 
     notification.success({
       top: 92,
@@ -721,58 +684,12 @@
     })
   }
 
-  parseForm = (g, res) => {
-    let _group = fromJS(g).toJS()
-    let _confirm = false
-
-    if (res.copyType === 'form') {
-      let fieldrepet = false // 瀛楁閲嶅
-      res.uuid = Utils.getuuid()
-  
-      _group.fields.forEach(item => {
-        if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-      })
-  
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-      _group.fields.push(res)
-    } else {
-      if (_group.fields.length > 0) {
-        _confirm = true
-      }
-
-      _group.fields = res.fields.map(item => {
-        item.uuid = Utils.getuuid()
-        return item
-      })
-    }
-
-    if (_confirm) {
-      let that = this
-      confirm({
-        title: '纭畾鏇挎崲琛ㄥ崟鍚楋紵',
-        content: '鍘熻〃鍗曞皢鍒犻櫎銆�',
-        onOk() {
-          that.updateForms(_group)
-        },
-        onCancel() {}
-      })
-    } else {
-      this.updateForms(_group)
-    }
-  }
-
-  updateForms = (_group) => {
+  parseForm = (g, forms) => {
     const { group } = this.state
     let card = fromJS(this.state.card).toJS()
+    let _group = fromJS(g).toJS()
+
+    _group.fields = forms
 
     card.subcards = card.subcards.map(item => {
       if (item.uuid === _group.uuid) {
@@ -819,7 +736,7 @@
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="stepform" card={card}/>
-            <PasteComponent config={card} options={['form', 'formgroup', 'simpleform']} updateConfig={this.pasteForm} />
+            <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)} />
@@ -870,7 +787,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/form/tab-form/index.jsx b/src/menu/components/form/tab-form/index.jsx
index 65b84aa..ae873e0 100644
--- a/src/menu/components/form/tab-form/index.jsx
+++ b/src/menu/components/form/tab-form/index.jsx
@@ -9,7 +9,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../step-form/options'
@@ -151,19 +151,9 @@
       if (supModule === 'empty') {
         supModule = ''
       }
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      card.$c_ds = true
+      card.errors = checkComponent(card)
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
@@ -474,7 +464,7 @@
         })
       }
 
-      if (item.type === 'switch') {
+      if (item.type === 'switch' || item.type === 'check') {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -550,6 +540,8 @@
           fieldrepet = true
         }
 
+        delete item.focus
+
         if (item.uuid === res.uuid) {
           if (item.style) {
             res.style = item.style
@@ -568,6 +560,8 @@
         })
         return
       }
+
+      window.GLOB.formId = res.uuid
 
       if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
         this.setState({
@@ -622,56 +616,25 @@
     if (res.subtype === 'simpleform') {
       res = res.subcards[0]
     }
-    if (res.subButton) {
-      let card = fromJS(this.state.card).toJS()
 
-      res.uuid = Utils.getuuid()
-      res.sort = card.subcards.length + 1
+    let card = fromJS(this.state.card).toJS()
 
-      res.fields.forEach(item => {
-        item.uuid = Utils.getuuid()
-      })
+    res.uuid = Utils.getuuid()
+    res.sort = card.subcards.length + 1
 
-      delete res.prevButton
-      delete res.nextButton
-
-      card.subcards.push(res)
-      
-      this.setState({
-        group: res
-      })
-      this.updateComponent(card)
-
-      notification.success({
-        top: 92,
-        message: '绮樿创鎴愬姛锛�',
-        duration: 2
-      })
-      return
-    }
-
-    let _config = fromJS(this.state.group).toJS()
-    let fieldrepet = false // 瀛楁閲嶅
-
-    _config.fields.forEach(item => {
-      if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-        fieldrepet = true
-      }
+    res.fields.forEach(item => {
+      item.uuid = Utils.getuuid()
     })
 
-    if (fieldrepet) {
-      notification.warning({
-        top: 92,
-        message: '瀛楁宸插瓨鍦紒',
-        duration: 10
-      })
-      return
-    }
-    _config.fields.push(res)
+    delete res.prevButton
+    delete res.nextButton
 
-    this.updateGroup(_config)
-
-    this.handleForm(res)
+    card.subcards.push(res)
+    
+    this.setState({
+      group: res
+    })
+    this.updateComponent(card)
 
     notification.success({
       top: 92,
@@ -722,58 +685,12 @@
     })
   }
 
-  parseForm = (g, res) => {
-    let _group = fromJS(g).toJS()
-    let _confirm = false
-
-    if (res.copyType === 'form') {
-      let fieldrepet = false // 瀛楁閲嶅
-      res.uuid = Utils.getuuid()
-  
-      _group.fields.forEach(item => {
-        if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-      })
-  
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-      _group.fields.push(res)
-    } else {
-      if (_group.fields.length > 0) {
-        _confirm = true
-      }
-
-      _group.fields = res.fields.map(item => {
-        item.uuid = Utils.getuuid()
-        return item
-      })
-    }
-
-    if (_confirm) {
-      let that = this
-      confirm({
-        title: '纭畾鏇挎崲琛ㄥ崟鍚楋紵',
-        content: '鍘熻〃鍗曞皢鍒犻櫎銆�',
-        onOk() {
-          that.updateForms(_group)
-        },
-        onCancel() {}
-      })
-    } else {
-      this.updateForms(_group)
-    }
-  }
-
-  updateForms = (_group) => {
+  parseForm = (g, forms) => {
     const { group } = this.state
     let card = fromJS(this.state.card).toJS()
+    let _group = fromJS(g).toJS()
+
+    _group.fields = forms
 
     card.subcards = card.subcards.map(item => {
       if (item.uuid === _group.uuid) {
@@ -820,7 +737,7 @@
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="tabform" card={card}/>
-            <PasteComponent config={card} options={['form', 'formgroup', 'simpleform']} updateConfig={this.pasteForm} />
+            <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)} />
@@ -872,7 +789,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/group/normal-group/index.jsx b/src/menu/components/group/normal-group/index.jsx
index b635bea..2786f97 100644
--- a/src/menu/components/group/normal-group/index.jsx
+++ b/src/menu/components/group/normal-group/index.jsx
@@ -1,8 +1,8 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Popover, Button, Modal } from 'antd'
-import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, PrinterOutlined, UngroupOutlined } from '@ant-design/icons'
+import { Popover, Modal } from 'antd'
+import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, UngroupOutlined } from '@ant-design/icons'
 
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
@@ -187,7 +187,7 @@
         } trigger="hover">
           <ToolOutlined />
         </Popover>
-        {group.setting && group.setting.print === 'true' ? <Button className="print-button" onClick={this.print}><PrinterOutlined /></Button> : null}
+        {/* {group.setting && group.setting.print === 'true' ? <Button className="print-button" onClick={this.print}><PrinterOutlined /></Button> : null} */}
         <GroupComponents config={group} handleList={this.updateComponent} deleteCard={this.deleteCard} />
       </div>
     )
diff --git a/src/menu/components/group/normal-group/options.jsx b/src/menu/components/group/normal-group/options.jsx
index 0d128ce..8b4c290 100644
--- a/src/menu/components/group/normal-group/options.jsx
+++ b/src/menu/components/group/normal-group/options.jsx
@@ -42,63 +42,61 @@
       precision: 0,
       required: true
     },
-    {
-      type: 'radio',
-      field: 'print',
-      label: '鎵撳嵃鎸夐挳',
-      initval: setting.print || 'false',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄剧ず'},
-        {value: 'false', label: '闅愯棌'},
-      ],
-      controlFields: [
-        {field: 'pageSize', values: ['true']},
-        {field: 'pageLayout', values: ['true']},
-        {field: 'syncModule', values: ['true']},
-        {field: 'checkAll', values: ['true']},
-        {field: 'hide', values: ['true']},
-      ],
-      forbid: appType === 'mob'
-    },
-    {
-      type: 'radio',
-      field: 'pageSize',
-      label: '鎵撳嵃灏哄',
-      initval: setting.pageSize || 'A4',
-      required: true,
-      options: [
-        {value: 'A3', label: 'A3'},
-        {value: 'A4', label: 'A4'},
-        {value: 'A5', label: 'A5'},
-      ],
-      forbid: appType === 'mob'
-    },
-    {
-      type: 'radio',
-      field: 'pageLayout',
-      label: '鎵撳嵃甯冨眬',
-      initval: setting.pageLayout || 'vertical',
-      required: true,
-      options: [
-        {value: 'vertical', label: '绾靛悜'},
-        {value: 'horizontal', label: '妯悜'},
-      ],
-      forbid: appType === 'mob'
-    },
-    {
-      type: 'checkbox',
-      field: 'hide',
-      label: '闅愯棌鍏冪礌',
-      initval: setting.hide || [],
-      tooltip: '鎵ц鎵撳嵃鏃堕渶瑕侀殣钘忕殑椤甸潰鍏冪礌銆�',
-      required: false,
-      options: [
-        {value: 'search', label: '鎼滅储'},
-        {value: 'button', label: '鎸夐挳'},
-      ],
-      forbid: appType === 'mob'
-    },
+    // {
+    //   type: 'radio',
+    //   field: 'print',
+    //   label: '鎵撳嵃鎸夐挳',
+    //   initval: setting.print || 'false',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄剧ず'},
+    //     {value: 'false', label: '闅愯棌'},
+    //   ],
+    //   controlFields: [
+    //     {field: 'pageSize', values: ['true']},
+    //     {field: 'pageLayout', values: ['true']},
+    //     {field: 'hide', values: ['true']},
+    //   ],
+    //   forbid: appType === 'mob'
+    // },
+    // {
+    //   type: 'radio',
+    //   field: 'pageSize',
+    //   label: '鎵撳嵃灏哄',
+    //   initval: setting.pageSize || 'A4',
+    //   required: true,
+    //   options: [
+    //     {value: 'A3', label: 'A3'},
+    //     {value: 'A4', label: 'A4'},
+    //     {value: 'A5', label: 'A5'},
+    //   ],
+    //   forbid: appType === 'mob'
+    // },
+    // {
+    //   type: 'radio',
+    //   field: 'pageLayout',
+    //   label: '鎵撳嵃甯冨眬',
+    //   initval: setting.pageLayout || 'vertical',
+    //   required: true,
+    //   options: [
+    //     {value: 'vertical', label: '绾靛悜'},
+    //     {value: 'horizontal', label: '妯悜'},
+    //   ],
+    //   forbid: appType === 'mob'
+    // },
+    // {
+    //   type: 'checkbox',
+    //   field: 'hide',
+    //   label: '闅愯棌鍏冪礌',
+    //   initval: setting.hide || [],
+    //   tooltip: '鎵ц鎵撳嵃鏃堕渶瑕侀殣钘忕殑椤甸潰鍏冪礌銆�',
+    //   required: false,
+    //   options: [
+    //     {value: 'search', label: '鎼滅储'},
+    //     {value: 'button', label: '鎸夐挳'},
+    //   ],
+    //   forbid: appType === 'mob'
+    // },
     {
       type: 'radio',
       field: 'permission',
diff --git a/src/menu/components/group/paste/index.jsx b/src/menu/components/group/paste/index.jsx
index 77f15d1..8db0190 100644
--- a/src/menu/components/group/paste/index.jsx
+++ b/src/menu/components/group/paste/index.jsx
@@ -20,7 +20,7 @@
 
   pasteSubmit = () => {
     let appType = sessionStorage.getItem('appType')
-    let options = ['datacard', 'propcard', 'balcony', 'timeline', 'simpleform', 'stepform', 'tabform', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'scatter', 'sandbox']
+    let options = ['datacard', 'propcard', 'balcony', 'timeline', 'simpleform', 'stepform', 'tabform', 'normaltable', 'tablecard', 'editor', 'line', 'bar', 'pie', 'scatter', 'sandbox']
     let types = {
       login: '鐧诲綍',
       navbar: '瀵艰埅鏍�',
@@ -53,7 +53,7 @@
         return
       }
 
-      res = MenuUtils.resetComponentConfig(res)
+      res = MenuUtils.resetComponentConfig(res, appType)
 
       delete res.copyType
       
diff --git a/src/menu/components/iframe/index.jsx b/src/menu/components/iframe/index.jsx
index d0f2d38..f6ef55f 100644
--- a/src/menu/components/iframe/index.jsx
+++ b/src/menu/components/iframe/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import getWrapForm from './options'
 import './index.scss'
@@ -93,19 +93,8 @@
       card.errors = []
 
       if (card.wrap.datatype === 'dynamic') {
-        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: '鏈缃笂绾х粍浠讹紒'})
-        }
+        card.$c_ds = true
+        card.errors = checkComponent(card)
       }
 
       if (card.errors.length === 0) {
@@ -175,7 +164,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/module/voucher/index.jsx b/src/menu/components/module/voucher/index.jsx
index beb0972..905ef23 100644
--- a/src/menu/components/module/voucher/index.jsx
+++ b/src/menu/components/module/voucher/index.jsx
@@ -158,8 +158,8 @@
                 妯℃澘绫诲瀷:
                 <div>鏃ュ父鏀嚭<DownOutlined/></div>
               </div>
-              <Button className="out-background header-btn">鍏抽棴</Button>
-              <Button className="add-background header-btn">淇濆瓨</Button>
+              <Button className="close-temp header-btn">鍏抽棴</Button>
+              <Button className="save-temp header-btn">淇濆瓨</Button>
             </div> : null}
             <VoucherTable config={card}/>
             {card.wrap.type === 'createVoucher' || card.wrap.type === 'checkVoucher' ? <div className="user">鍒跺崟浜猴細</div> : null}
diff --git a/src/menu/components/module/voucher/index.scss b/src/menu/components/module/voucher/index.scss
index f7b22db..964fd36 100644
--- a/src/menu/components/module/voucher/index.scss
+++ b/src/menu/components/module/voucher/index.scss
@@ -134,6 +134,16 @@
     border-color: rgb(50, 197, 210);
     color: #ffffff;
   }
+  .save-temp {
+    background-color: #1890ff;
+    border-color: #1890ff;
+    color: #ffffff;
+  }
+  .close-temp {
+    background-color: #ffffff;
+    border-color: #f5222d;
+    color: #f5222d;
+  }
 
   .system-background {
     background: #1890ff;
diff --git a/src/menu/components/module/voucher/options.jsx b/src/menu/components/module/voucher/options.jsx
index bd1bee2..2d78725 100644
--- a/src/menu/components/module/voucher/options.jsx
+++ b/src/menu/components/module/voucher/options.jsx
@@ -18,6 +18,17 @@
     }
   })
 
+  let menulist = sessionStorage.getItem('fstMenuList')
+  if (menulist) {
+    try {
+      menulist = JSON.parse(menulist)
+    } catch (e) {
+      menulist = []
+    }
+  } else {
+    menulist = []
+  }
+
   modules = modules.filter(item => !bookids.includes(item.value))
 
   const wrapForm = [
@@ -134,6 +145,16 @@
       tooltip: '琛ㄦ牸涓讳綋閮ㄥ垎涓ょ鐨勭┖鐧借窛绂伙紝琛ㄦ牸鍦ㄧ紪杈戞椂涓ょ浼氭湁娣诲姞鍜屽垹闄ゅ浘鏍囥��',
       required: false
     },
+    {
+      type: 'cascader',
+      field: 'linkmenu',
+      label: '鍒锋柊鑿滃崟',
+      initval: wrap.linkmenu || [],
+      tooltip: '鐐瑰嚮鍏抽棴鏃堕渶瑕佸埛鏂扮殑鑿滃崟銆�',
+      required: false,
+      allowClear: true,
+      options: menulist
+    }
   ]
 
   return wrapForm
diff --git a/src/menu/components/module/voucher/voucherTable/index.scss b/src/menu/components/module/voucher/voucherTable/index.scss
index e8175c8..c46fe8d 100644
--- a/src/menu/components/module/voucher/voucherTable/index.scss
+++ b/src/menu/components/module/voucher/voucherTable/index.scss
@@ -31,10 +31,10 @@
       border-right: 1px solid #e9e9e9;
     }
     span:nth-child(3), span:nth-child(6) {
-      border-color: #91d5ff;
+      border-color: #474069;
     }
     span:nth-child(9) {
-      border-color: #ffa39e;
+      border-color: #C48584;
     }
   }
 
@@ -45,11 +45,12 @@
       tr {
         th {
           position: relative;
-          background-color: transparent;
+          background-color: #E3E7F2;
           padding: 0;
           height: 60px;
           line-height: 60px;
           text-align: center;
+          border-right: 1px solid #d8d8d8;
 
           .ant-table-header-column {
             display: block;
@@ -82,12 +83,16 @@
       max-width: 60px;
     }
     .ant-table-tbody {
+      tr:last-child {
+        background-color: #FBF8EF;
+      }
       tr td {
         position: relative;
         background-color: transparent;
         padding: 0;
         height: 60px;
         vertical-align: top;
+        border-right: 1px solid #d8d8d8;
 
         .content-wrap {
           padding: 5px;
@@ -156,104 +161,5 @@
   }
   td.pointer {
     position: relative;
-  }
-  td.pointer {
-    .mk-mask {
-      display: none;
-      cursor: pointer;
-      position: absolute;
-      top: 0;
-      left: 0;
-      bottom: 0;
-      right: 0;
-    }
-  }
-}
-.edit-custom-table.editable {
-  td {
-    background-color: #ffffff!important;
-  }
-  td.pointer .mk-mask {
-    display: block;
-  }
-  .mk-operation {
-    display: none;
-  }
-  .ant-table-placeholder {
-    display: none;
-  }
-}
-.edit-custom-table:not(.fixed-height) {
-  .ant-table-body::-webkit-scrollbar {
-    width: 8px;
-    height: 10px;
-  }
-  ::-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);
-  }
-  ::-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);
-  }
-}
-.edit-custom-table.fixed-height {
-  .ant-table-body {
-    border-bottom: 1px solid rgba(0, 0, 0, .05);
-    .ant-table-fixed {
-      border-bottom: 0;
-    }
-  }
-}
-.edit-custom-table.hidden {
-  thead {
-    display: none;
-  }
-}
-.edit-custom-table.ghost {
-  .ant-table-thead > tr {
-    > th {
-      color: inherit;
-      background: transparent;
-      .ant-table-column-sorter .ant-table-column-sorter-inner {
-        color: inherit;
-      }
-    }
-    > th:hover {
-      background: transparent;
-    }
-  }
-  .ant-table-body {
-    overflow-x: auto;
-    tr {
-      td {
-        background: transparent!important;
-      }
-    }
-    tr:hover td {
-      background: transparent!important;
-    }
-  }
-}
-.image-scale-modal {
-  width: 70vw;
-  min-height: 80vh;
-  top: 10vh;
-  .ant-modal-body {
-    min-height: calc(80vh - 110px);
-    line-height: calc(80vh - 160px);
-    text-align: center;
-  }
-  .ant-modal-footer {
-    text-align: center;
-    span {
-      display: inline-block;
-      color: #1890ff;
-      padding: 5px 15px;
-      cursor: pointer;
-    }
   }
 }
\ No newline at end of file
diff --git a/src/menu/components/search/main-search/dragsearch/card.jsx b/src/menu/components/search/main-search/dragsearch/card.jsx
index 4e36738..666ac3f 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 } from 'antd'
+import { Select, DatePicker, Input, Popover, Form, Switch, Checkbox } from 'antd'
 import { CopyOutlined, EditOutlined, CloseOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -109,6 +109,10 @@
     formItem = (<DateGroup card={card} />)
   } else if (card.type === 'checkcard') {
     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 === 'check') {
+    formItem = <Checkbox style={{lineHeight: '36px'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
   }
 
   return (
diff --git a/src/menu/components/search/main-search/index.jsx b/src/menu/components/search/main-search/index.jsx
index fe83c62..2708d3d 100644
--- a/src/menu/components/search/main-search/index.jsx
+++ b/src/menu/components/search/main-search/index.jsx
@@ -416,7 +416,7 @@
         <div className="component-name">
           <div className="center" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx
index 30473b8..b1d19ea 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -12,6 +12,7 @@
 const { TextArea } = Input
 const { Paragraph } = Typography
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
+const MKTable = asyncComponent(() => import('@/components/normalform/modalform/mkTable'))
 const acTyOptions = {
   pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hidden'],
   prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hidden'],
@@ -92,6 +93,8 @@
 
     let hasclass = true
     this.props.formlist.forEach(item => {
+      if (!item.key) return
+
       this.record[item.key] = item.initVal
 
       if (item.key === 'class') {
@@ -206,6 +209,9 @@
         }
       } else if (intertype === 'inner') {
         shows.push('innerFunc', 'output')
+        if (Ot === 'requiredOnce') { // 鍓嶇疆鍑芥暟
+          shows.push('preFunc')
+        }
         reRequired.innerFunc = true
       } else {
         shows.push('sql', 'sqlType', 'output')
@@ -517,6 +523,10 @@
       }
     }
 
+    if (shows.includes('syncComponent') && this.record.syncComponent[0] === 'multiComponent') {
+      shows.push('syncComponents')
+    }
+
     if (this.record.show === 'icon') {
       reRequired.icon = true
     } else {
@@ -552,7 +562,6 @@
       this.record.pageTemplate = ''
       this.record.funcType = ''
       this.record.sqlType = ''
-
       if (value === 'pop' || value === 'prompt' || value === 'exec') {
         _fieldval.intertype = 'system'
         _fieldval.sqlType = ''
@@ -565,10 +574,10 @@
         _fieldval.Ot = 'notRequired'
         _fieldval.execSuccess = 'grid'
         _fieldval.label = '瀵煎叆Excel'
-        _fieldval.class = 'dgreen'
+        _fieldval.class = 'border-dgreen'
         this.record.Ot = 'notRequired'
         this.record.label = '瀵煎叆Excel'
-        this.record.class = 'dgreen'
+        this.record.class = 'border-dgreen'
         this.record.execSuccess = 'grid'
       } else if (value === 'excelOut') {
         _fieldval.intertype = 'system'
@@ -576,11 +585,12 @@
         _fieldval.class = 'dgreen'
         _fieldval.execSuccess = 'never'
         _fieldval.Ot = 'requiredOnce'
+        _fieldval.control = ''
         this.record.Ot = 'requiredOnce'
         this.record.label = '瀵煎嚭Excel'
         this.record.class = 'dgreen'
         this.record.execSuccess = 'never'
-  
+        this.record.control = ''
       } else if (value === 'popview') {
         _fieldval.display = 'modal'
         _fieldval.Ot = 'requiredSgl'
@@ -600,15 +610,6 @@
       } else if (value === 'funcbutton') {
         // _fieldval.funcType = ''
   
-      }
-      if (value === 'excelIn') {
-        _fieldval.label = '瀵煎叆Excel'
-        _fieldval.class = 'dgreen'
-      } else if (value === 'excelOut') {
-        _fieldval.label = '瀵煎嚭Excel'
-        _fieldval.class = 'dgreen'
-        _fieldval.control = ''
-        this.record.control = ''
       }
 
       if (appType !== 'mob' && _fieldval.Ot === 'notRequired') {
@@ -772,7 +773,7 @@
             { pattern: /^[a-zA-Z0-9@_]+$/, message: '琛ㄥ悕鍙彲浣跨敤瀛楁瘝銆佹暟瀛椾互鍙奯' },
             { max: formRule.func.max, message: formRule.func.maxMessage }
           )
-        } else if (item.key === 'outerFunc' || item.key === 'callbackFunc') {
+        } else if (item.key === 'outerFunc' || item.key === 'callbackFunc' || item.key === 'preFunc') {
           rules.push(
             { pattern: formRule.func.pattern, message: formRule.func.message },
             { max: formRule.func.max, message: formRule.func.maxMessage }
@@ -864,7 +865,14 @@
           { required: item.required, message: '璇烽�夋嫨' + item.label + '!' }
         ]
 
-        content = <Cascader options={item.options || []} expandTrigger="hover" placeholder=""/>
+        content = <Cascader onChange={(value) => {this.optionChange(item.key, value)}} options={item.options || []} expandTrigger="hover" placeholder=""/>
+      } else if (item.type === 'table') {
+        span = 24
+        className = 'textarea'
+        rules = [
+          { required: item.required, message: '璇锋坊鍔�' + item.label + '!' }
+        ]
+        content = (<MKTable tip={''} columns={item.columns || []} actions={[]}/>)
       } else if (item.type === 'icon') {
         rules = [
           { required: item.required, message: '璇烽�夋嫨' + item.label + '!' }
@@ -930,6 +938,59 @@
           values.modal = card.modal || null
           values.config = card.config || null
 
+          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 => {
+                col.required = col.required || 'true'
+                col.type = col.type || 'Nvarchar(50)'
+                col.import = col.import || 'true'
+          
+                if (col.type === 'text' || col.type === 'image') {
+                  col.type = 'Nvarchar(50)'
+                } else if (col.type === 'number') {
+                  col.type = 'Decimal(18,2)'
+                }
+                
+                if (/^Nvarchar/ig.test(col.type)) {
+                  col.limit = col.type.match(/\d+/)[0]
+                } else if (/^Decimal/ig.test(col.type)) {
+                  col.limit = col.type.match(/\d+/ig)[1]
+                } else {
+                  col.limit = ''
+                }
+
+                delete col.output
+                delete col.abs
+                delete col.Width
+          
+                return col
+              })
+
+              values.verify.sheet = values.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 => {
+                col.type = col.type || 'text'
+                col.output = col.output || 'true'
+                col.required = col.required || 'false'
+                col.Width = 20
+          
+                if (!['text', 'image', 'number'].includes(col.type)) {
+                  if (/^Decimal/ig.test(col.type)) {
+                    col.type = 'number'
+                  } else {
+                    col.type = 'text'
+                  }
+                }
+
+                delete col.import
+          
+                return col
+              })
+            }
+          }
+
           if (values.OpenType === 'form') {
             if (values.formType !== 'scan') {
               if (/^(0|[1-9]\d*)$/.test(values.openVal) && /^(0|[1-9]\d*)$/.test(values.closeVal)) {
@@ -953,7 +1014,7 @@
                 values.verify.invalid = 'true'
               }
             }
-          } else if (values.OpenType === 'tab' && values.linkmenu) {
+          } else if (values.OpenType === 'tab' && values.linkmenu && Array.isArray(values.linkmenu)) {
             if (sessionStorage.getItem('thdMenuList')) {
               let list = null
               try {
@@ -994,7 +1055,7 @@
               }
             })
           }
-          
+
           resolve(values)
         } else {
           reject(err)
diff --git a/src/menu/components/share/actioncomponent/dragaction/card.jsx b/src/menu/components/share/actioncomponent/dragaction/card.jsx
index 3163444..4735517 100644
--- a/src/menu/components/share/actioncomponent/dragaction/card.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/card.jsx
@@ -97,6 +97,11 @@
     )
   }
 
+  let updateTime = null
+  if (card.updateTime && card.updateTime.indexOf(window.GLOB.curDate) > -1) {
+    updateTime = card.updateTime.substr(11)
+  }
+
   return (
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
       <div className="mk-popover-control">
@@ -105,6 +110,7 @@
         <CloseOutlined className="close" onClick={() => delCard(id)} />
         {type !== 'datacard' && type !== 'basetable' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)}/> : ''}
         {hasProfile ? <ProfileOutlined className="profile" title="楠岃瘉" onClick={() => profileCard(id)} /> : null}
+        {updateTime}
       </div>
     } trigger="hover">
       <div className="page-card" style={{ opacity: opacity}}>
diff --git a/src/menu/components/share/actioncomponent/dragaction/index.jsx b/src/menu/components/share/actioncomponent/dragaction/index.jsx
index e797df7..cab1425 100644
--- a/src/menu/components/share/actioncomponent/dragaction/index.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/index.jsx
@@ -1,6 +1,7 @@
 import React, { useState } from 'react'
 import { useDrop } from 'react-dnd'
 import { is, fromJS } from 'immutable'
+import { message } from 'antd'
 import update from 'immutability-helper'
 
 import Utils from '@/utils/utils.js'
@@ -69,7 +70,6 @@
     }
 
     copycard.uuid = Utils.getuuid()
-    copycard.originCard = card
 
     try {
       delete _val.$srcId
@@ -92,13 +92,17 @@
       oInput.select()
       document.execCommand('Copy')
       document.body.removeChild(oInput)
+
+      message.success('澶嶅埗鎴愬姛銆�')
+    } else {
+      message.warning('澶嶅埗澶辫触銆�')
     }
 
-    const { index: overIndex } = findCard(id)
+    // const { index: overIndex } = findCard(id)
 
-    const _cards = update(cards, { $splice: [[overIndex + 1, 0, copycard]] })
+    // const _cards = update(cards, { $splice: [[overIndex + 1, 0, copycard]] })
 
-    handleList(_cards, copycard)
+    // handleList(_cards, copycard)
   }
 
   const [, drop] = useDrop({
@@ -122,7 +126,7 @@
 
         if (newcard.OpenType === 'excelIn') {
           newcard.label = item.text
-          newcard.class = 'dgreen'
+          newcard.class = 'border-dgreen'
           newcard.Ot = 'notRequired'
         } else if (newcard.OpenType === 'excelOut') {
           newcard.label = item.text
diff --git a/src/menu/components/share/actioncomponent/formconfig.jsx b/src/menu/components/share/actioncomponent/formconfig.jsx
index 135daca..9d6f7b7 100644
--- a/src/menu/components/share/actioncomponent/formconfig.jsx
+++ b/src/menu/components/share/actioncomponent/formconfig.jsx
@@ -1,4 +1,4 @@
-import { btnCustomClasses, btnClasses } from '@/utils/option.js'
+import { btnClasses } from '@/utils/option.js'
 
 
 /**
@@ -9,13 +9,13 @@
  * @param {*} usefulFields   瀛樺偍杩囩▼鍙敤鐨勫紑濮嬪瓧娈�
  * @param {*} type           鎸夐挳绫诲瀷锛岀敤浜庡尯鍒嗗彲閫夌殑鎵撳紑鏂瑰紡
  */
-export function getActionForm (card, functip, config, usefulFields, modules = [], anchors = []) {
+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 = config.columns || []
+  let columns = side === 'sub' && config.subColumns ? config.subColumns : (config.columns || [])
   let appMenus = []
   let menulist = []
   let type = ''
@@ -97,7 +97,6 @@
     { value: 'print', text: '鏍囩鎵撳嵃' },
     { value: 'refund', text: '閫�娆�' },
     { value: 'closetab', text: '鏍囩鍏抽棴' },
-    { value: 'changeuser', text: '鍒囨崲鐢ㄦ埛' },
     { value: 'megvii', text: '鏃疯闈㈡澘鏈�' },
     { value: 'filezip', text: '鏂囦欢鍘嬬缉鍖�' },
   ]
@@ -113,6 +112,7 @@
     } else {
       appMenus = []
     }
+    appMenus.push({value: 'goback', text: '杩斿洖锛堜笂涓�椤碉級'})
   } else {
     menulist = sessionStorage.getItem('fstMenuList')
     if (menulist) {
@@ -150,7 +150,6 @@
     opentypes = opentypes.filter(item => item.value !== 'tab')
     funTypes = [
       { value: 'print', text: '鏍囩鎵撳嵃' },
-      { value: 'changeuser', text: '鍒囨崲鐢ㄦ埛' },
     ]
     pageTemps = [
       { value: 'linkpage', text: '鍏宠仈鑿滃崟' },
@@ -158,6 +157,25 @@
       { value: 'pay', text: '鏀粯' },
       { value: 'custom', text: '閾炬帴' }
     ]
+  } else {
+    if (card.pageTemplate === 'print') { // 鍘熺被鍨嬫敮鎸�
+      pageTemps.unshift({ value: 'print', text: '鏍囩鎵撳嵃妯℃澘' })
+    } else if (card.pageTemplate === 'billprintTemp') { // 鍘熺被鍨嬫敮鎸�
+      pageTemps.unshift({ value: 'billprintTemp', text: '鍗曟嵁鎵撳嵃妯℃澘' })
+    }
+  }
+
+  if (card.funcType === 'changeuser') { // 鍘熺被鍨嬫敮鎸�
+    funTypes.unshift({ value: 'changeuser', text: '鍒囨崲鐢ㄦ埛' })
+  }
+
+  if (config.subtype === 'editable') { // 缂栬緫琛ㄧ殑娣诲姞銆佸垹闄�
+    funTypes.push(
+      { value: 'addline', text: '澧炲姞琛岋紙缂栬緫琛級' },
+      { value: 'delline', text: '鍒犻櫎琛岋紙缂栬緫琛級' }
+    )
+  } else if (card.funcType === 'addline' || card.funcType === 'delline') {
+    card.funcType = ''
   }
   
   if (type === 'chart' && appType !== 'mob') {
@@ -170,7 +188,10 @@
 
   let refresh = []
   if (viewType === 'popview') { // 寮圭獥鏍囩
-    opentypes = opentypes.filter(item => item.value !== 'popview' && item.value !== 'funcbutton')
+    opentypes = opentypes.filter(item => item.value !== 'popview')
+
+    funTypes = funTypes.filter(item => item.value !== 'print')
+
     refresh.push({
       value: 'closepoptab', // 鍏抽棴寮圭獥鏍囩
       text: '鍏抽棴寮圭獥'
@@ -535,7 +556,7 @@
       key: 'execSuccess',
       label: '鎴愬姛鍚�',
       initVal: card.execSuccess || 'grid',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
       required: true,
       options: [{
         value: 'never',
@@ -558,7 +579,7 @@
       key: 'execError',
       label: '澶辫触鍚�',
       initVal: card.execError || 'never',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
       required: true,
       options: [{
         value: 'never',
@@ -671,7 +692,7 @@
       tooltip: '姝ら鑹蹭负鎸夐挳鍒濆鍖栭鑹诧紝鍙湪鏍峰紡璋冩暣涓慨鏀广��',
       required: false,
       forbid: type === 'datacard' && appType === 'mob', // 绉诲姩绔紝婊戝姩鏄剧ず鐨勬寜閽笉璁剧疆閫氱敤棰滆壊
-      options: btnCustomClasses
+      options: btnClasses
     },
     {
       type: 'radio',
@@ -695,6 +716,9 @@
       }, {
         value: 'light',
         text: '鐏�'
+      }, {
+        value: 'system',
+        text: '绯荤粺'
       }]
     },
     {
@@ -725,7 +749,7 @@
       initVal: card.syncComponent || [],
       tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧脊绐楁爣绛惧叧闂椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
       required: false,
-      options: modules
+      options: modules.length ? [...modules, {value: 'multiComponent', label: '澶氱粍浠�'}] : []
     },
     {
       type: 'radio',
@@ -796,7 +820,7 @@
       extendName: 'MenuNo',
       required: false,
       allowClear: true,
-      options: appType === 'mob' || appType === 'pc' ? [...appMenus, {value: 'goback', text: '杩斿洖锛堜笂涓�椤碉級'}] : menulist,
+      options: appType === 'mob' || appType === 'pc' ? appMenus : menulist,
       forbid: viewType === 'popview'
     },
     {
@@ -949,6 +973,15 @@
         value: 'bottom',
         text: '搴曢儴'
       }]
+    },
+    {
+      type: 'text',
+      key: 'preFunc',
+      label: '鍓嶇疆鍑芥暟',
+      initVal: card.preFunc || '',
+      tooltip: '鍓嶇疆鍑芥暟鎵ц瀹屾垚鍚庯紝缁撴灉浼氫紶鍏ュ唴閮ㄥ嚱鏁颁腑锛屾鏃跺唴閮ㄥ嚱鏁颁細寮傛鎵ц锛涘綋鍓嶇疆鍑芥暟杩斿洖涓璄rrCode绛変簬-1鏃讹紝灏嗕笉鍐嶆墽琛屽唴閮ㄥ嚱鏁般��',
+      required: false,
+      forbid: appType === 'mob'
     },
     {
       type: 'radio',
@@ -1135,6 +1168,27 @@
         value: 'progressbar',
         text: '杩涘害鏉�'
       }]
+    },
+    {
+      type: 'table',
+      key: 'syncComponents',
+      label: '缁勪欢鍒楄〃',
+      initVal: card.syncComponents || [],
+      required: true,
+      actions: [],
+      columns: [
+        {
+          title: '缁勪欢',
+          dataIndex: 'syncComId',
+          inputType: 'cascader',
+          editable: true,
+          required: true,
+          extends: [{key: 'label', value: 'label'}],
+          width: '70%',
+          render: (text, record) => record.label,
+          options: modules
+        }
+      ]
     }
   ]
 
@@ -1194,14 +1248,23 @@
     { value: 'custom', text: '鑷畾涔�' }
   ]
 
+  if (card.pageTemplate === 'print') { // 鍘熺被鍨嬫敮鎸�
+    pageTemps.unshift({ value: 'print', text: '鏍囩鎵撳嵃妯℃澘' })
+  } else if (card.pageTemplate === 'billprintTemp') { // 鍘熺被鍨嬫敮鎸�
+    pageTemps.unshift({ value: 'billprintTemp', text: '鍗曟嵁鎵撳嵃妯℃澘' })
+  }
+
   let funTypes = [
     { value: 'print', text: '鏍囩鎵撳嵃' },
     { value: 'refund', text: '閫�娆�' },
     { value: 'closetab', text: '鏍囩鍏抽棴' },
-    { value: 'changeuser', text: '鍒囨崲鐢ㄦ埛' },
     { value: 'megvii', text: '鏃疯闈㈡澘鏈�' },
     { value: 'filezip', text: '鏂囦欢鍘嬬缉鍖�' },
   ]
+
+  if (card.funcType === 'changeuser') { // 鍘熺被鍨嬫敮鎸�
+    funTypes.unshift({ value: 'changeuser', text: '鍒囨崲鐢ㄦ埛' })
+  }
 
   let menulist = sessionStorage.getItem('fstMenuList')
   if (menulist) {
@@ -1216,7 +1279,10 @@
 
   let refresh = []
   if (viewType === 'popview') { // 寮圭獥鏍囩
-    opentypes = opentypes.filter(item => item.value !== 'popview' && item.value !== 'funcbutton')
+    opentypes = opentypes.filter(item => item.value !== 'popview')
+
+    funTypes = funTypes.filter(item => item.value !== 'print')
+
     refresh.push({
       value: 'closepoptab', // 鍏抽棴寮圭獥鏍囩
       text: '鍏抽棴寮圭獥'
@@ -1516,7 +1582,7 @@
       key: 'execSuccess',
       label: '鎴愬姛鍚�',
       initVal: card.execSuccess || 'grid',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍笺�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
       required: true,
       options: [{
         value: 'never',
@@ -1538,7 +1604,7 @@
       key: 'execError',
       label: '澶辫触鍚�',
       initVal: card.execError || 'never',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓��',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳涓缃叧闂悗鍒锋柊鍝竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂拌〃鏍硷紝娉細涓婄骇缁勪欢鍦ㄦ暟鎹簮涓坊鍔犮�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭腑鍖呭惈@close_tab@銆丂close_popup@銆丂goback@ 浼氭墽琛岋紙鍏抽棴鏍囩-绠$悊绯荤粺锛夈�侊紙鍏抽棴寮圭獥锛夈�侊紙杩斿洖涓婁竴椤�-瀛愬簲鐢級绛夊姩浣溿��',
       required: true,
       options: [{
         value: 'never',
@@ -1659,7 +1725,7 @@
       initVal: card.syncComponent || [],
       tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧脊绐楁爣绛惧叧闂椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
       required: false,
-      options: modules
+      options: modules.length ? [...modules, {value: 'multiComponent', label: '澶氱粍浠�'}] : []
     },
     {
       type: 'radio',
@@ -1789,6 +1855,14 @@
       }]
     },
     {
+      type: 'text',
+      key: 'preFunc',
+      label: '鍓嶇疆鍑芥暟',
+      initVal: card.preFunc || '',
+      tooltip: '鍓嶇疆鍑芥暟鎵ц瀹屾垚鍚庯紝缁撴灉浼氫紶鍏ュ唴閮ㄥ嚱鏁颁腑锛屾鏃跺唴閮ㄥ嚱鏁颁細寮傛鎵ц锛涘綋鍓嶇疆鍑芥暟杩斿洖涓璄rrCode绛変簬-1鏃讹紝灏嗕笉鍐嶆墽琛屽唴閮ㄥ嚱鏁般��',
+      required: false
+    },
+    {
       type: 'radio',
       key: 'control',
       label: '鎸夐挳鎺у埗',
@@ -1878,6 +1952,27 @@
         value: 'progressbar',
         text: '杩涘害鏉�'
       }]
+    },
+    {
+      type: 'table',
+      key: 'syncComponents',
+      label: '缁勪欢鍒楄〃',
+      initVal: card.syncComponents || [],
+      required: true,
+      actions: [],
+      columns: [
+        {
+          title: '缁勪欢',
+          dataIndex: 'syncComId',
+          inputType: 'cascader',
+          editable: true,
+          required: true,
+          extends: [{key: 'label', value: 'label'}],
+          width: '70%',
+          render: (text, record) => record.label,
+          options: modules
+        }
+      ]
     }
   ]
 
diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx
index 82fe3f2..5746ac8 100644
--- a/src/menu/components/share/actioncomponent/index.jsx
+++ b/src/menu/components/share/actioncomponent/index.jsx
@@ -2,6 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Modal, notification, Button } from 'antd'
+import moment from 'moment'
 
 import Utils, { FuncUtils } from '@/utils/utils.js'
 import { getActionForm, getBaseTableActionForm } from './formconfig'
@@ -60,7 +61,7 @@
   }
 
   componentDidMount () {
-    MKEmitter.addListener('revert', this.revert)
+    MKEmitter.addListener('revertBtn', this.revertBtn)
     MKEmitter.addListener('addButton', this.addButton)
     MKEmitter.addListener('submitModal', this.handleSave)
   }
@@ -76,12 +77,12 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('revert', this.revert)
+    MKEmitter.removeListener('revertBtn', this.revertBtn)
     MKEmitter.removeListener('addButton', this.addButton)
     MKEmitter.removeListener('submitModal', this.handleSave)
   }
 
-  revert = (id) => {
+  revertBtn = (id) => {
     if (id && id !== this.props.config.uuid) return
 
     this.setState({
@@ -257,11 +258,133 @@
    */
   handleSubmit = () => {
     const { config } = this.props
-    let color = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#666666', default: 'rgba(0, 0, 0, 0.65)' }
+    let color = { 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 _actionlist = fromJS(this.state.actionlist).toJS()
     
     this.actionFormRef.handleConfirm().then(btn => {
       _actionlist = _actionlist.filter(item => !item.origin || item.uuid === btn.uuid)
+
+      if ((btn.OpenType === 'excelIn' || btn.OpenType === 'excelOut') && (!btn.verify || !btn.verify.columns) && (config.subtype === 'basetable' || config.subtype === 'normaltable')) {
+        let columns = []
+        let maps = []
+        let labels = {}
+        if (config.subtype === 'normaltable') {
+          config.columns.forEach(col => {
+            labels[col.field] = col.label
+          })
+        }
+
+        if (btn.OpenType === 'excelOut') {
+          let pushcol = (item) => {
+            let cell = {
+              Column: item.field,
+              Text: item.label,
+              Width: 20,
+              abs: 'false',
+              output: 'true',
+              required: 'false',
+              type: 'text',
+              uuid: Utils.getuuid()
+            }
+  
+            if (item.type === 'number') {
+              cell.type = 'number'
+              cell.decimal = item.decimal
+            }
+  
+            columns.push(cell)
+          }
+
+          config.cols.forEach(item => {
+            if (item.Hide === 'true') return
+
+            if (config.subtype === 'normaltable') {
+              if (item.type === 'colspan') {
+                item.subcols.forEach(cell => {
+                  if (!cell.field || cell.Hide === 'true' || maps.includes(cell.field)) return
+                  maps.push(cell.field)
+  
+                  pushcol(cell)
+                })
+              } else if (item.type === 'custom') {
+                item.elements.forEach(cell => {
+                  if (!cell.field || maps.includes(cell.field)) return
+                  maps.push(cell.field)
+  
+                  pushcol({...cell, label: labels[cell.field]})
+                })
+              }
+            }
+
+            if (!item.field || maps.includes(item.field)) return
+            maps.push(item.field)
+  
+            pushcol(item)
+          })
+
+          btn.verify = btn.verify || {enable: 'false', dataType: 'default', scripts: []}
+          btn.verify.columns = columns
+        } else {
+          let pushcol = (item) => {
+            let _type = 'Nvarchar(50)'
+            let _limit = '50'
+            if (item.type === 'number' && !item.decimal) {
+              _type = 'Int'
+              _limit = ''
+            } else if (item.type === 'number') {
+              _type = 'Decimal(18,' + item.decimal + ')'
+              _limit = item.decimal
+            }
+
+            let _cell = {
+              uuid: Utils.getuuid(),
+              Column: item.field,
+              Text: item.label,
+              type: _type,
+              limit: _limit,
+              import: 'true',
+              required: 'true'
+            }
+
+            if (_type !== 'Nvarchar(50)') {
+              _cell.min = 0
+              _cell.max = 999999
+            }
+  
+            columns.push(_cell)
+          }
+
+          config.cols.forEach(item => {
+            if (item.Hide === 'true') return
+
+            if (config.subtype === 'normaltable') {
+              if (item.type === 'colspan') {
+                item.subcols.forEach(cell => {
+                  if (!cell.field || cell.Hide === 'true' || maps.includes(cell.field)) return
+                  maps.push(cell.field)
+  
+                  pushcol(cell)
+                })
+              } else if (item.type === 'custom') {
+                item.elements.forEach(cell => {
+                  if (!cell.field || maps.includes(cell.field)) return
+                  maps.push(cell.field)
+  
+                  pushcol({...cell, label: labels[cell.field]})
+                })
+              }
+            }
+
+            if (!item.field || maps.includes(item.field)) return
+            maps.push(item.field)
+  
+            pushcol(item)
+          })
+
+          btn.verify = btn.verify || {sheet: 'Sheet1', default: 'true', range: 1, scripts: [], uniques: []}
+          btn.verify.columns = columns
+        }
+      }
 
       let labelrepet = false
       _actionlist = _actionlist.map(item => {
@@ -276,21 +399,43 @@
               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[_c], backgroundColor: '#fff', borderColor: color[_c], marginRight: '15px'}
+            } else if (btn.class === 'gray') {
+              btn.style = {color: 'rgba(0, 0, 0, 0.65)', backgroundColor: color[_c], borderColor: color[_c], marginRight: '15px'}
             } else {
               btn.style = {color: '#fff', backgroundColor: color[_c], borderColor: color[_c], marginRight: '15px'}
             }
           } else {
             btn.style = item.style || {}
-            if (btn.class !== item.class || btn.show !== item.show || !btn.style.color || item.focus) {
-              if (btn.show === 'icon') {
-                btn.style.color = color[btn.class]
-                btn.style.backgroundColor = 'transparent'
-              } else {
-                btn.style.color = '#ffffff'
-                btn.style.backgroundColor = color[btn.class]
+            if (btn.class) {
+              if (btn.class !== item.class || btn.show !== item.show || !btn.style.color || (item.focus && !btn.style.color)) {
+                if (btn.show === 'icon') {
+                  btn.style.color = color[btn.class]
+                  btn.style.backgroundColor = 'transparent'
+                } else if (btn.class === 'default') {
+                  btn.style.color = 'rgba(0, 0, 0, 0.65)'
+                  btn.style.backgroundColor = '#fff'
+                  btn.style.borderColor = '#d9d9d9'
+                } else if (btn.class.indexOf('border') > -1) {
+                  let _c = btn.class.replace('border-', '')
+                  btn.style.color = color[_c]
+                  btn.style.backgroundColor = '#fff'
+                  btn.style.borderColor = color[_c]
+                } else if (btn.class === 'gray') {
+                  btn.style.color = 'rgba(0, 0, 0, 0.65)'
+                  btn.style.backgroundColor = color[btn.class]
+                  btn.style.borderColor = color[btn.class]
+                } else {
+                  btn.style.color = '#ffffff'
+                  btn.style.backgroundColor = color[btn.class]
+                  btn.style.borderColor = color[btn.class]
+                }
               }
+            } else if (btn.color) {
+              btn.style = {}
             }
           }
+
+          btn.updateTime = moment().format('YYYY-MM-DD HH:mm')
           return btn
         } else {
           return item
@@ -363,6 +508,7 @@
       _actionlist = _actionlist.map(item => {
         if (item.uuid === card.uuid) {
           item.verify = res
+          item.updateTime = moment().format('YYYY-MM-DD HH:mm')
         }
   
         return item
@@ -457,7 +603,7 @@
     let _col = null
     if (config.type === 'table') {
       config.cols.forEach(col => {
-        if (col.type !== 'action') return
+        if (col.type !== 'custom') return
 
         col.elements = col.elements.filter(item => {
           if (item.uuid === id) {
@@ -467,6 +613,24 @@
           return item.uuid !== id
         })
       })
+    } else if (config.type === 'card' && config.subcards) {
+      config.subcards.forEach(scard => {
+        scard.elements = scard.elements.filter(item => {
+          if (item.uuid === id) {
+            btn = item
+            _col = scard
+          }
+          return item.uuid !== id
+        })
+        scard.backElements = scard.backElements.filter(item => {
+          if (item.uuid === id) {
+            btn = item
+            _col = scard
+          }
+          return item.uuid !== id
+        })
+        return scard
+      })
     }
 
     if (!btn) return
diff --git a/src/menu/components/share/actioncomponent/index.scss b/src/menu/components/share/actioncomponent/index.scss
index 63c17eb..193c640 100644
--- a/src/menu/components/share/actioncomponent/index.scss
+++ b/src/menu/components/share/actioncomponent/index.scss
@@ -55,5 +55,8 @@
     .swiper-light {
       background-color: #cccccc;
     }
+    .swiper-system {
+      background-color: #1890ff;
+    }
   }
 }
\ No newline at end of file
diff --git a/src/menu/components/share/clockcomponent/settingform/index.jsx b/src/menu/components/share/clockcomponent/settingform/index.jsx
index 0978f22..f31fb1c 100644
--- a/src/menu/components/share/clockcomponent/settingform/index.jsx
+++ b/src/menu/components/share/clockcomponent/settingform/index.jsx
@@ -100,7 +100,7 @@
                 })(<InputNumber min={0} max={500} precision={0} />)}
               </Form.Item>
             </Col> : null}
-            {config.type === 'card' && (config.subtype === 'balcony' || config.subtype === 'propcard') && timer && timer !== '2s' ? <Col span={22}>
+            {timer && timer !== '2s' ? <Col span={22}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title="鍙互鎸囧畾瀛楁鐢ㄤ簬鎺у埗瀹氭椂鍣ㄧ殑鍏抽棴銆�">
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -116,7 +116,7 @@
                 )}
               </Form.Item>
             </Col> : null}
-            {(config.subtype === 'balcony' || config.subtype === 'propcard') && clearField && timer && timer !== '2s' ? <Col span={22}>
+            {clearField && timer && timer !== '2s' ? <Col span={22}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title="褰撳瓧娈靛�间笌鍏抽棴鍊肩浉绛夋椂锛屽叧闂畾鏃跺櫒锛屽涓�煎彲鐢ㄩ�楀彿鍒嗛殧銆�">
                   <QuestionCircleOutlined className="mk-form-tip" />
diff --git a/src/menu/components/share/markcomponent/index.jsx b/src/menu/components/share/markcomponent/index.jsx
index 53a2a73..c188601 100644
--- a/src/menu/components/share/markcomponent/index.jsx
+++ b/src/menu/components/share/markcomponent/index.jsx
@@ -34,6 +34,15 @@
         editable: true,
         inputType: 'cascader',
         options: [],
+        rules: [{
+          validator: (rule, value, callback) => {
+            if (value[1] === 'dynamic' && value[0] === value[2]) {
+              callback('瀵规瘮瀛楁涓嶅彲鐩稿悓锛�')
+            } else {
+              callback()
+            }
+          }
+        }],
         render: text => {
           return (
             <div>{text[0]}  VS  {text[2] ? text[2] : '闈欐�佸��'}</div>
diff --git a/src/menu/components/share/markcomponent/markform/index.jsx b/src/menu/components/share/markcomponent/markform/index.jsx
index f4adc4d..0603b31 100644
--- a/src/menu/components/share/markcomponent/markform/index.jsx
+++ b/src/menu/components/share/markcomponent/markform/index.jsx
@@ -53,6 +53,15 @@
                   {
                     required: true,
                     message: '璇烽�夋嫨瀵规瘮瀛楁!'
+                  },
+                  {
+                    validator: (rule, value, callback) => {
+                      if (value[1] === 'dynamic' && value[0] === value[2]) {
+                        callback('瀵规瘮瀛楁涓嶅彲鐩稿悓锛�')
+                      } else {
+                        callback()
+                      }
+                    }
                   }
                 ]
               })(
diff --git a/src/menu/components/share/pastebasetable/index.jsx b/src/menu/components/share/pastebasetable/index.jsx
index adb2c56..5c8eb9a 100644
--- a/src/menu/components/share/pastebasetable/index.jsx
+++ b/src/menu/components/share/pastebasetable/index.jsx
@@ -39,42 +39,27 @@
         return cell
       })
 
-      let loopCol = (col) => {
-        col.subcols = col.subcols.map(c => {
-          c.uuid = Utils.getuuid()
+      let loopCol = (cols) => {
+        return cols.map(col => {
+          col.uuid = Utils.getuuid()
+          
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
 
-          if (c.type === 'colspan' && c.subcols) {
-            c = loopCol(c)
-          } else if (c.type === 'custom' && c.elements) {
-            c.elements = c.elements.map(cell => {
+          if (col.type === 'colspan' && col.subcols) {
+            col.subcols = loopCol(col.subcols)
+          } else if (col.type === 'custom' && col.elements) {
+            col.elements = col.elements.map(cell => {
               cell.uuid = Utils.getuuid()
               return cell
             })
           }
-          return c
+          return col
         })
-
-        return col
       }
 
-      res.cols = res.cols.map(col => {
-        col.uuid = Utils.getuuid()
-
-        if (col.type === 'colspan' && col.subcols) {
-          col = loopCol(col)
-        } else if (col.type === 'custom' && col.elements) {
-          col.elements = col.elements.map(cell => {
-            cell.uuid = Utils.getuuid()
-            return cell
-          })
-        } else if (col.type === 'action' && col.elements) {
-          col.elements = col.elements.map(cell => {
-            cell.uuid = Utils.getuuid()
-            return cell
-          })
-        }
-        return col
-      })
+      res.cols = loopCol(res.cols)
 
       let oriUids = {}
       res.action = res.action.map(cell => {
diff --git a/src/menu/components/share/pastecomponent/index.jsx b/src/menu/components/share/pastecomponent/index.jsx
index 477e3e0..5c2b417 100644
--- a/src/menu/components/share/pastecomponent/index.jsx
+++ b/src/menu/components/share/pastecomponent/index.jsx
@@ -7,7 +7,7 @@
 import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
-import './index.scss'
+// import './index.scss'
 
 const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform'))
 
@@ -56,6 +56,11 @@
       item.setting.width = item.setting.width || 6
       delete item.$cardType
 
+      if (config.type === 'carousel') {
+        delete item.setting.linkbtn
+        delete item.backElements
+      }
+
       if (item.elements) {
         item.elements = item.elements.map(cell => {
           cell.uuid = Utils.getuuid()
@@ -69,41 +74,27 @@
         })
       }
     } else if (item.copyType === 'cols') {
-      let loopCol = (col) => {
-        col.subcols = col.subcols.map(c => {
-          c.uuid = Utils.getuuid()
+      let loopCol = (cols) => {
+        return cols.map(col => {
+          col.uuid = Utils.getuuid()
 
-          if (c.type === 'colspan' && c.subcols) {
-            c = loopCol(c)
-          } else if (c.type === 'custom' && c.elements) {
-            c.elements = c.elements.map(cell => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
+
+          if (col.type === 'colspan' && col.subcols) {
+            col.subcols = loopCol(col.subcols)
+          } else if (col.type === 'custom' && col.elements) {
+            col.elements = col.elements.map(cell => {
               cell.uuid = Utils.getuuid()
               return cell
             })
           }
-          return c
+          return col
         })
-
-        return col
       }
 
-      item.cols = item.cols.map(_item => {
-        _item.uuid = Utils.getuuid()
-        if (_item.type === 'colspan' && _item.subcols) {
-          _item = loopCol(_item)
-        } else if (_item.type === 'custom' && _item.elements) {
-          _item.elements = _item.elements.map(cell => {
-            cell.uuid = Utils.getuuid()
-            return cell
-          })
-        } else if (_item.type === 'action' && _item.elements) {
-          _item.elements = _item.elements.map(cell => {
-            cell.uuid = Utils.getuuid()
-            return cell
-          })
-        }
-        return _item
-      })
+      item.cols = loopCol(item.cols)
     }
 
     return item
@@ -134,6 +125,10 @@
         this.setState({visible: false})
         return
       } else if (type === 'action') {
+        if (res.style) {
+          delete res.style.width
+          delete res.style.float
+        }
         if (['line', 'bar', 'scatter'].includes(config.type) && !['excelOut', 'excelIn'].includes(res.OpenType)) {
           notification.warning({ top: 92, message: '鍥捐〃涓笉鏀寔姝ょ被鎸夐挳锛�', duration: 5 })
           return
diff --git a/src/menu/components/share/pasteforms/index.jsx b/src/menu/components/share/pasteforms/index.jsx
new file mode 100644
index 0000000..6cf98a8
--- /dev/null
+++ b/src/menu/components/share/pasteforms/index.jsx
@@ -0,0 +1,178 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Modal, notification, Button } from 'antd'
+import { SnippetsOutlined, QuestionCircleOutlined } from '@ant-design/icons'
+
+import Utils from '@/utils/utils.js'
+import asyncComponent from '@/utils/asyncComponent'
+import './index.scss'
+
+const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform'))
+
+class PasteForms extends Component {
+  static propTpyes = {
+    config: PropTypes.object,        // 缁勪欢閰嶇疆
+    update: PropTypes.func
+  }
+
+  state = {
+    visible: false,
+    choVisible: false,
+    result: null
+  }
+
+  pasteSubmit = () => {
+    const { config } = this.props
+
+    this.pasteFormRef.handleConfirm().then(res => {
+      if (res.copyType === 'search' && ['text', 'select', 'multiselect', 'link', 'checkcard', 'date', 'datemonth'].includes(res.type)) {
+        res.copyType = 'form'
+      }
+
+      if (!['form', 'forms', 'formgroup', 'simpleform'].includes(res.copyType)) {
+        notification.warning({ top: 92, message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', duration: 5 })
+        return
+      }
+
+      if (res.copyType === 'form') {
+        delete res.copyType
+        res = {fields: [res]}
+      }
+
+      res.fields = res.fields || []
+      res.fields = res.fields.map(item => {
+        item.uuid = Utils.getuuid()
+        return item
+      })
+
+      let fields = res.fields.map(item => item.field ? item.field.toLowerCase() : '')
+
+      let repeat = false
+      let forms = []
+      if (config.fields) {
+        forms = fromJS(config.fields).toJS()
+        forms.forEach(item => {
+          if (item.field && fields.includes(item.field.toLowerCase())) {
+            repeat = true
+          }
+        })
+      }
+
+      if (repeat) {
+        this.setState({result: res, choVisible: true, visible: false})
+        return
+      } else {
+        forms.push(...res.fields)
+      }
+
+      this.props.update(forms, res)
+
+      this.setState({visible: false})
+
+      notification.success({
+        top: 92,
+        message: '绮樿创鎴愬姛锛�',
+        duration: 2
+      })
+    })
+  }
+
+  replaceForms = () => {
+    const { config } = this.props
+    const { result } = this.state
+
+    let forms = fromJS(config.fields).toJS()
+    let fields = fromJS(result.fields).toJS()
+    let repeats = []
+
+    forms = forms.map(item => {
+      if (!item.field) return item
+
+      let cell = fields.filter(m => m.field && m.field.toLowerCase() === item.field.toLowerCase())[0]
+      if (cell) {
+        repeats.push(cell.field)
+        return cell
+      }
+
+      return item
+    })
+    
+    fields = fields.filter(m => !m.field || !repeats.includes(m.field))
+
+    forms.push(...fields)
+
+    this.props.update(forms, result)
+
+    this.setState({choVisible: false})
+  }
+  
+  jumpForms = () => {
+    const { config } = this.props
+    const { result } = this.state
+
+    let forms = fromJS(config.fields).toJS()
+    let fields = fromJS(result.fields).toJS()
+    let repeats = []
+
+    forms = forms.map(item => {
+      if (!item.field) return item
+
+      let cell = fields.filter(m => m.field && m.field.toLowerCase() === item.field.toLowerCase())[0]
+      if (cell) {
+        repeats.push(cell.field)
+      }
+
+      return item
+    })
+    
+    fields = fields.filter(m => !m.field || !repeats.includes(m.field))
+
+    forms.push(...fields)
+
+    this.props.update(forms, result)
+
+    this.setState({choVisible: false})
+  }
+
+  render() {
+    const { type } = this.props
+    const { visible, choVisible } = this.state
+
+    return (
+      <div style={{display: 'inline-block'}}>
+        {type === 'toolbar' ? <Button icon="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} >绮樿创</Button> :
+        <SnippetsOutlined style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} />}
+        <Modal
+          title="绮樿创"
+          visible={visible}
+          width={600}
+          maskClosable={false}
+          onOk={this.pasteSubmit}
+          onCancel={() => {this.setState({visible: false})}}
+          destroyOnClose
+        >
+          <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/>
+        </Modal>
+        <Modal
+          title=""
+          visible={choVisible}
+          width={450}
+          closable={false}
+          maskClosable={false}
+          onCancel={() => {this.setState({choVisible: false, result: null})}}
+          footer={[
+            <Button key="cancel" onClick={() => this.setState({choVisible: false, result: null})}>鍙栨秷</Button>,
+            <Button key="replace" className="mk-border-purple" style={{color: 'purple'}} onClick={this.replaceForms}>鏇挎崲</Button>,
+            <Button key="confirm" type="primary" onClick={this.jumpForms}>璺宠繃</Button>
+          ]}
+          destroyOnClose
+        >
+          <QuestionCircleOutlined style={{color: 'orange', fontSize: '24px', margin: '15px 10px', position: 'relative', top: '2px'}}/>瀛樺湪閲嶅琛ㄥ崟锛岃閫夋嫨澶勭悊鏂瑰紡銆�
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default PasteForms
\ No newline at end of file
diff --git a/src/menu/components/share/pasteforms/index.scss b/src/menu/components/share/pasteforms/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/menu/components/share/pasteforms/index.scss
diff --git a/src/menu/components/share/searchcomponent/dragsearch/card.jsx b/src/menu/components/share/searchcomponent/dragsearch/card.jsx
index 2b6bbe1..7c6754f 100644
--- a/src/menu/components/share/searchcomponent/dragsearch/card.jsx
+++ b/src/menu/components/share/searchcomponent/dragsearch/card.jsx
@@ -1,6 +1,6 @@
 import React from 'react'
 import { useDrag, useDrop } from 'react-dnd'
-import { Select, DatePicker, Input, Popover, Form } from 'antd'
+import { Select, DatePicker, Input, Popover, Form, Switch, Checkbox } from 'antd'
 import { EditOutlined, CopyOutlined, CloseOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -107,6 +107,10 @@
     />
   } else if (card.type === 'group') {
     formItem = <DateGroup card={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 === 'check') {
+    formItem = <Checkbox style={{lineHeight: '36px'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
   }
 
   let labelwidth = card.labelwidth || 33.3
diff --git a/src/menu/components/share/usercomponent/index.jsx b/src/menu/components/share/usercomponent/index.jsx
index 07c968b..8862fa6 100644
--- a/src/menu/components/share/usercomponent/index.jsx
+++ b/src/menu/components/share/usercomponent/index.jsx
@@ -82,36 +82,30 @@
       return item
     })
 
-    _config.cols = _config.cols.map(col => {
-      if (col.type === 'colspan' && col.subcols) {
-        col = this.loopCol(col)
-      } else if (col.type === 'custom' && col.elements) {
-        col.elements = col.elements.map(cell => this.resetElement(cell))
-      } else if (col.type === 'action' && col.elements) {
-        col.elements = col.elements.map(cell => {
-          cell.verify = null
-          return cell
-        })
-      }
-      col.marks = null
-      return col
-    })
+    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
-  }
-
-  loopCol = (col) => {
-    col.subcols = col.subcols.map(c => {
-      if (c.type === 'colspan' && c.subcols) {
-        c = this.loopCol(c)
-      } else if (c.type === 'custom' && c.elements) {
-        c.elements = c.elements.map(cell => this.resetElement(cell))
-      }
-      c.marks = null
-      return c
-    })
-
-    return col
   }
 
   resetElement = (item) => {
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 29bf27a..e139d76 100644
--- a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -58,11 +58,9 @@
     text: '搴忓彿'
   }]
 
-  if (!card.isSub) {
-    options.push({
-      value: 'action',
-      text: '鎿嶄綔'
-    })
+  let decimal = card.decimal === undefined ? 0 : card.decimal
+  if (card.type === 'formula' && typeof(card.decimal) !== 'number') {
+    decimal = ''
   }
 
   return [
@@ -71,7 +69,11 @@
       key: 'label',
       label: '鍒楀ご鏂囧瓧',
       initVal: card.label,
-      required: true
+      required: true,
+      rules: [{
+        max: 100,
+        message: '鏈�澶�100涓瓧绗︺��'
+      }]
     },
     {
       type: 'select',
@@ -87,14 +89,25 @@
       label: '瀛楁',
       initVal: card.field,
       required: true,
-      options: card.isSub ? fields : []
+      options: card.isSub ? fields : [],
+      rules: [{
+        pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
+        message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶃�佹眽瀛椾互鍙奯'
+      }, {
+        max: 100,
+        message: '鏈�澶�100涓瓧绗︺��'
+      }]
     },
     {
       type: 'text',
       key: 'nameField',
       label: '鍚嶇О瀛楁',
       initVal: card.nameField || '',
-      required: false
+      required: false,
+      rules: [{
+        max: 100,
+        message: '鏈�澶�100涓瓧绗︺��'
+      }]
     },
     {
       type: 'number',
@@ -147,6 +160,18 @@
         value: 'false',
         text: '鍚�'
       }]
+    },
+    {
+      type: 'radio',
+      key: 'eval',
+      label: '瑙f瀽',
+      initVal: card.eval || 'false',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      required: false,
+      options: [
+        { value: 'true', text: '鏄�' },
+        { value: 'false', text: '鍚�' }
+      ]
     },
     {
       type: 'radio',
@@ -231,7 +256,7 @@
       max: 18,
       decimal: 0,
       label: '灏忔暟浣�',
-      initVal: card.decimal === undefined ? 0 : card.decimal,
+      initVal: decimal,
       required: !card.isSub
     },
     {
@@ -280,7 +305,11 @@
       label: '鍓嶇紑',
       initVal: card.prefix || '',
       required: false,
-      readonly: false
+      readonly: false,
+      rules: [{
+        max: 100,
+        message: '鏈�澶�100涓瓧绗︺��'
+      }]
     },
     {
       type: 'text',
@@ -288,7 +317,11 @@
       label: '鍚庣紑',
       initVal: card.postfix || '',
       required: false,
-      readonly: false
+      readonly: false,
+      rules: [{
+        max: 100,
+        message: '鏈�澶�100涓瓧绗︺��'
+      }]
     },
     {
       type: 'number',
@@ -390,18 +423,6 @@
       initVal: card.linkfields || [],
       required: false,
       options: fields,
-    },
-    {
-      type: 'radio',
-      key: 'eval',
-      label: '瑙f瀽',
-      initVal: card.eval || 'true',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
-      required: false,
-      options: [
-        { value: 'true', text: '鏄�' },
-        { value: 'false', text: '鍚�' }
-      ]
     },
     {
       type: 'textarea',
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 f7b9799..16ae1ca 100644
--- a/src/menu/components/table/base-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -1,11 +1,10 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal } from 'antd'
+import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal, Checkbox, Popover } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import { getColumnForm } from './formconfig'
-import { formRule } from '@/utils/option.js'
 import './index.scss'
 
 const { TextArea } = Input
@@ -17,7 +16,7 @@
   picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span'],
   video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'fieldlength', 'blacklist', 'aspectRatio'],
   colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
-  custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'],
+  custom: ['label', 'type', 'Align', 'Width', 'blacklist'],
   action: ['label', 'type', 'Align', 'Width'],
   formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
   index: ['label', 'type', 'Align', 'Width']
@@ -25,7 +24,6 @@
 
 class NormalTableColumn extends Component {
   static propTpyes = {
-    visible: PropTypes.bool,
     column: PropTypes.object,
     fields: PropTypes.array,
     submitCol: PropTypes.func,  // 鎻愪氦浜嬩欢
@@ -36,6 +34,8 @@
     visible: false,
     formlist: null
   }
+
+  record = null
 
   UNSAFE_componentWillReceiveProps (nextProps) {
     if (nextProps.column && !is(fromJS(this.props.column), fromJS(nextProps.column))) {
@@ -50,20 +50,26 @@
     })
     
     let formlist = getColumnForm(column, fields)
-    let _options = fromJS(columnTypeOptions[column.type]).toJS()
-    if (column.type === 'text' || column.type === 'number') {
-      if (column.perspective === 'linkmenu') {
-        _options.push('linkmenu', 'linkfields', 'open')
-      } else if (column.perspective === 'linkurl') {
-        _options.push('linkurl', 'linkfields', 'open')
-      }
-    }
+
+    this.record = {}
+
+    formlist.forEach(item => {
+      this.record[item.key] = item.initVal
+    })
+    
+    let _options = this.getOptions()
 
     this.setState({
       visible: true,
-      type: column.type,
       formlist: formlist.map(item => {
         item.hidden = !_options.includes(item.key)
+
+        if (item.key === 'formula') {
+          item.fields = this.props.fields.map(col => col.field)
+          item.fields = item.fields.join(', ')
+        } else if (this.record.type === 'formula' && item.key === 'decimal') {
+          item.required = false
+        }
 
         return item
       })
@@ -80,13 +86,41 @@
     }
   }
 
+  getOptions = () => {
+    let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
+
+    if (this.record.type === 'text' || this.record.type === 'number') {
+      if (this.record.perspective === 'linkmenu') {
+        _options.push('linkmenu', 'linkfields', 'open')
+      } else if (this.record.perspective === 'linkurl') {
+        _options.push('linkurl', 'linkfields', 'open')
+      }
+    }
+    
+    if (this.record.type === 'formula' && this.record.eval === 'true') {
+      _options.push('decimal')
+    }
+
+    return _options
+  }
+
   typeChange = (key, value, option) => {
+    const { column } = this.props
+    this.record[key] = value
+
     if (key === 'type') {
-      let _options = fromJS(columnTypeOptions[value]).toJS()
+      let _options = this.getOptions()
 
       this.setState({
-        type: value,
         formlist: this.state.formlist.map(item => {
+          if (item.key === 'decimal') {
+            item.required = !(column.isSub || value === 'formula')
+            if (value === 'formula') {
+              this.record.decimal = ''
+            }
+          }
+
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
 
           return item
@@ -96,8 +130,10 @@
           this.props.form.setFieldsValue({IsSort: 'false'})
         } else if (value === 'text' || value === 'number') {
           this.props.form.setFieldsValue({perspective: ''})
-        } else if (value === 'action' || value === 'colspan') {
+        } else if (value === 'colspan') {
           this.props.form.setFieldsValue({Align: 'center'})
+        } else if (value === 'index') {
+          this.props.form.setFieldsValue({label: '搴忓彿'})
         }
       })
     } else if (key === 'field') {
@@ -113,13 +149,18 @@
         values.type = 'text'
       }
 
-      if (values.type !== this.state.type) {
+      let _type = this.record.type
+      this.record.type = values.type
+
+      if (values.type !== _type) {
         values.perspective = ''
-        let _options = fromJS(columnTypeOptions[values.type]).toJS()
+        this.record.perspective = ''
+
+        let _options = this.getOptions()
 
         this.setState({
-          type: values.type,
           formlist: this.state.formlist.map(item => {
+            item.initVal = this.record[item.key]
             item.hidden = !_options.includes(item.key)
 
             return item
@@ -132,21 +173,12 @@
       }
     } else if (key === 'format' && value === 'percent') {
       this.props.form.setFieldsValue({postfix: '%'})
-    }
-  }
-
-  changeRadio = (key, value) => {
-    if (key === 'perspective') {
-      let _options = fromJS(columnTypeOptions[this.state.type]).toJS()
-
-      if (value === 'linkmenu') {
-        _options.push('linkmenu', 'linkfields', 'open')
-      } else if (value === 'linkurl') {
-        _options.push('linkurl', 'linkfields', 'open')
-      }
+    } else if (['perspective', 'eval'].includes(key)) {
+      let _options = this.getOptions()
 
       this.setState({
         formlist: this.state.formlist.map(item => {
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
 
           return item
@@ -166,21 +198,6 @@
       if (item.hidden || item.forbid) return
 
       if (item.type === 'text') {
-        let rules = []
-        if (item.key === 'field') {
-          rules = [{
-            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
-            message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶃�佹眽瀛椾互鍙奯'
-          }, {
-            max: formRule.input.max,
-            message: formRule.input.message
-          }]
-        } else if (item.key !== 'linkurl') {
-          rules = [{
-            max: formRule.input.max,
-            message: formRule.input.message
-          }]
-        }
         fields.push(
           <Col span={12} key={index}>
             <Form.Item label={item.tooltip ?
@@ -196,7 +213,7 @@
                     required: !!item.required,
                     message: '璇疯緭鍏�' + item.label + '!'
                   },
-                  ...rules
+                  ...item.rules
                 ]
               })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
             </Form.Item>
@@ -271,15 +288,30 @@
                   }
                 ]
               })(
-                <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}>
-                  {
-                    item.options.map(option => {
-                      return (
-                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
-                      )
-                    })
-                  }
+                <Radio.Group onChange={(e) => {this.typeChange(item.key, e.target.value)}}>
+                  {item.options.map(option => {
+                    return (<Radio key={option.value} value={option.value}>{option.text}</Radio>)
+                  })}
                 </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'checkbox') {
+        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
+              })(
+                <Checkbox.Group>
+                  {item.options.map(option => <Checkbox key={option.value} value={option.value}>{option.text}</Checkbox>)}
+                </Checkbox.Group>
               )}
             </Form.Item>
           </Col>
@@ -327,35 +359,76 @@
           </Col>
         )
       } else if (item.type === 'textarea') {
-        fields.push(
-          <Col span={24} key={index} className="textarea">
-            <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 + '!'
-                  }
-                ]
-              })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''}/>)}
-            </Form.Item>
-          </Col>
-        )
+        if (item.key === 'formula') {
+          fields.push(
+            <Col span={24} className="textarea" 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 + '!'
+                    }
+                  ]
+                })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
+              </Form.Item>
+              <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click">
+                <span className="formula-icon">瀛楁闆�</span>
+              </Popover>
+            </Col>
+          )
+        } else {
+          fields.push(
+            <Col span={24} key={index} className="textarea">
+              <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 + '!'
+                    }
+                  ]
+                })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''}/>)}
+              </Form.Item>
+            </Col>
+          )
+        }
       }
     })
     return fields
   }
 
   handleSubmit = () => {
+    const { fields } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     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)) {
+          let cols = []
+          fields.forEach(col => {
+            if (/^(Int|Decimal)/ig.test(col.datatype)) {
+              cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
+            }
+          })
+
+          cols.forEach(col => {
+            values.formula = values.formula.replace(col.reg, col.value)
+          })
+        }
+
         this.props.submitCol(values, () => {
           this.setState({visible: false, formlist: null})
         })
diff --git a/src/menu/components/table/base-table/columns/editColumn/index.scss b/src/menu/components/table/base-table/columns/editColumn/index.scss
index 9885df8..e653f84 100644
--- a/src/menu/components/table/base-table/columns/editColumn/index.scss
+++ b/src/menu/components/table/base-table/columns/editColumn/index.scss
@@ -14,4 +14,27 @@
       width: 88%;
     }
   }
+  .formula-icon {
+    position: absolute;
+    bottom: 5px;
+    right: 15px;
+    cursor: pointer;
+    font-size: 12px;
+    color: #1890ff;
+  }
+  >.ant-row >.ant-col {
+    display: inline-block;
+    vertical-align: top;
+    float: none;
+  }
+}
+.formula-fields {
+  z-index: 1200!important;
+
+  .ant-popover-inner-content {
+    div {
+      max-width: 750px;
+      word-break: break-all;
+    }
+  }
 }
diff --git a/src/menu/components/table/base-table/columns/index.jsx b/src/menu/components/table/base-table/columns/index.jsx
index 27b02ee..d1da3b4 100644
--- a/src/menu/components/table/base-table/columns/index.jsx
+++ b/src/menu/components/table/base-table/columns/index.jsx
@@ -3,7 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider, DragSource, DropTarget } from 'react-dnd'
 import { Table, Popover, Modal, message, notification } from 'antd'
-import { PlusOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined, InfoOutlined } from '@ant-design/icons'
+import { PlusOutlined, PlusSquareOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined, InfoOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -46,63 +46,45 @@
 
     return !is(fromJS(this.props.column), fromJS(nextProps.column)) ||
       !is(fromJS(this.props.fields), fromJS(nextProps.fields)) ||
-      this.props.index !== nextProps.index
+      this.props.index !== nextProps.index ||
+      window.GLOB.columnId === nextProps.column.uuid || window.GLOB.precolumnId === nextProps.column.uuid
   }
 
   render() {
-    const { connectDragSource, connectDropTarget, moveCol, addElement, dropCol, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
+    const { connectDragSource, connectDropTarget, moveCol, componentId, addElement, dropCol, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
 
-    if (index !== undefined) {
-      let style = {cursor: 'move', textAlign: align}
-      if (column.Width) {
-        style.width = column.Width
-        style.minWidth = column.Width
-      }
+    if (!column) return (
+      <th {...restProps}>{children}</th>
+    )
 
-      return connectDragSource(
-        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => column && this.props.editColumn(column)}>
-          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
-              {column && ['custom', 'colspan', 'action'].includes(column.type) ?
-                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
-              }
-              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
-              {column && column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              {column && (column.type === 'custom' || column.type === 'action') ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
-              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
-            </div>
-          } trigger="hover">
-            {children}
-          </Popover>
-        </th>),
-      )
-    } else if (column) {
-      let style = {textAlign: align}
-      if (column.Width) {
-        style.width = column.Width
-        style.minWidth = column.Width
-      }
-      return (
-        <th {...restProps} style={style} key={column.uuid} onDoubleClick={() => this.props.editColumn(column)}>
-          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
-              {column && ['custom', 'colspan'].includes(column.type) ?
-                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
-              }
-              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
-              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
-            </div>
-          } trigger="hover">
-            {children}
-          </Popover>
-        </th>
-      )
-    } else {
-      return (<th {...restProps}>{children}</th>)
+    let style = {cursor: 'move', textAlign: align}
+    if (column.Width) {
+      style.width = column.Width
+      style.minWidth = column.Width
     }
+
+    if (window.GLOB.columnId === column.uuid) {
+      style.color = '#1890ff'
+    }
+
+    return connectDragSource(
+      connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => this.props.editColumn(column)}>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
+            {column.type === 'colspan' ? <PlusOutlined className="plus" title="娣诲姞鍒�" onClick={() => this.props.addElement(column)} /> : null}
+            {column.type === 'custom' ? <PlusOutlined className="plus" title="娣诲姞鍏冪礌" onClick={() => this.props.addElement(column)} /> : null}
+            {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={() => this.props.addElement(column, 'button')} /> : null}
+            <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
+            {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
+            {column.type === 'custom' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
+            <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
+            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
+          </div>
+        } trigger="hover">
+          {children}
+        </Popover>
+      </th>),
+    )
   }
 }
 
@@ -117,17 +99,28 @@
 const ColTarget = {
   drop(props, monitor) {
     const item = monitor.getItem()
-    const dragIndex = item.index
-    const hoverIndex = props.index
+    let dragIndex = item.index
+    let hoverIndex = props.index
 
     if (item.$init) {
-      props.dropCol(item, hoverIndex)
+      if (/sub_/.test(hoverIndex)) {
+        message.warning('鍚堝苟鍒楀瓙鍏冪礌鏆備笉鏀寔鎷栨嫿娣诲姞銆�')
+      } else {
+        props.dropCol(item, hoverIndex.replace(new RegExp(props.componentId + '@', 'ig'), ''))
+      }
       return
     } else if (dragIndex === undefined || hoverIndex === undefined || dragIndex === hoverIndex) {
       return
+    } else {
+      let reg = new RegExp(props.componentId + '@', 'ig')
+      if (reg.test(dragIndex)) {
+        props.moveCol(dragIndex.replace(reg, ''), hoverIndex.replace(reg, ''))
+      } else {
+        message.warning('鎷栧姩鍏冪礌涓嶅湪褰撳墠缁勪欢涓��')
+        return
+      }
     }
 
-    props.moveCol(dragIndex, hoverIndex)
     monitor.getItem().index = hoverIndex
   },
 }
@@ -190,12 +183,6 @@
     if (column && column.type === 'custom') {
       return (
         <td style={{padding: 0, ...(column.style || {})}} className={className}>
-          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
-        </td>
-      )
-    } else if (column && column.type === 'action') {
-      return (
-        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
           <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
         </td>
       )
@@ -300,7 +287,17 @@
   moveCol = (dragIndex, hoverIndex) => {
     let _columns = fromJS(this.state.columns).toJS()
 
-    _columns.splice(hoverIndex, 0, ..._columns.splice(dragIndex, 1))
+    if (/^sub_/.test(dragIndex) || /^sub_/.test(hoverIndex)) {
+      let sign1 = dragIndex.split('_')
+      let sign2 = hoverIndex.split('_')
+      if (sign1[1] !== sign2[1]) {
+        message.warning('鎷栧姩鍏冪礌涓嶅湪鍚屼竴涓悎骞跺垪涓��')
+        return
+      }
+      this.loopMoveCol(_columns, sign1[1], sign1[2], sign2[2])
+    } else {
+      _columns.splice(hoverIndex, 0, ..._columns.splice(dragIndex, 1))
+    }
 
     this.setState({
       columns: _columns
@@ -309,14 +306,22 @@
     })
   }
 
+  loopMoveCol = (columns, colId, dragIndex, hoverIndex) => {
+    columns.forEach(column => {
+      if (column.type === 'colspan' && column.uuid === colId) {
+        column.subcols.splice(hoverIndex, 0, ...column.subcols.splice(dragIndex, 1))
+      } else if (column.type === 'colspan') {
+        this.loopMoveCol(column.subcols, colId, dragIndex, hoverIndex)
+      }
+    })
+  }
+
   dropCol = (item, hoverIndex) => {
     let _columns = fromJS(this.state.columns).toJS()
 
-    let col = { focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: item.subType, elements: [] }
+    let col = { focus: true, uuid: Utils.getuuid(), Width: 120, label: 'label', field: '', type: item.subType, elements: [] }
     if (col.type === 'colspan') {
       col.subcols = []
-    } else if (col.type === 'action') {
-      col.label = '鎿嶄綔'
     } else if (col.type === 'index') {
       col.label = '搴忓彿'
     }
@@ -354,7 +359,7 @@
         config.action = config.action.filter(item => item.uuid !== btn.uuid)
 
         setTimeout(() => {
-          MKEmitter.emit('revert', config.uuid)
+          MKEmitter.emit('revertBtn', config.uuid)
         }, 200)
       }
 
@@ -371,14 +376,23 @@
   pasteCell = (col, cell, resolve) => {
     resolve({status: true})
     
-    delete cell.copyType
     cell.uuid = Utils.getuuid()
     cell.focus = true
+    
+    if (!cell.eleType) {
+      if (cell.copyType === 'action') {
+        cell.eleType = 'button'
+        cell.width = cell.width || 12
+      } else {
+        cell.eleType = 'text'
+      }
+    }
+    delete cell.copyType
     
     MKEmitter.emit('cardAddElement', col.uuid, cell)
   }
 
-  addElement = (col) => {
+  addElement = (col, type) => {
     let column = fromJS(col).toJS()
 
     if (column.type === 'colspan') {
@@ -391,26 +405,28 @@
       })
       this.updateCol(column)
     } else if (column.type === 'custom') {
-      let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
+      if (type === 'button') {
+        let newcard = {
+          uuid: Utils.getuuid(),
+          focus: true,
+          eleType: 'button',
+          label: 'button',
+          OpenType: 'prompt',
+          class: 'primary',
+          intertype: 'system',
+          execSuccess: 'grid',
+          execError: 'never',
+          show: 'link'
+        }
   
-      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
-      MKEmitter.emit('cardAddElement', column.uuid, newcard)
-    } else if (column.type === 'action') {
-      let newcard = {
-        uuid: Utils.getuuid(),
-        focus: true,
-        eleType: 'button',
-        label: 'button',
-        OpenType: 'prompt',
-        class: 'primary',
-        intertype: 'system',
-        execSuccess: 'grid',
-        execError: 'never',
-        show: 'link'
+        // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+        MKEmitter.emit('cardAddElement', column.uuid, newcard)
+      } else {
+        let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
+    
+        // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+        MKEmitter.emit('cardAddElement', column.uuid, newcard)
       }
-
-      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
-      MKEmitter.emit('cardAddElement', column.uuid, newcard)
     }
   }
 
@@ -426,9 +442,6 @@
     } else if (col.type === 'custom') {
       col.style = card.style || {}
       col.elements = card.type === 'custom' ? (card.elements || []) : []
-    } else if (col.type === 'action') {
-      col.style = card.style || {}
-      col.elements = card.type === 'action' ? (card.elements || []) : []
     }
 
     if (!col.field || col.isSub) {
@@ -452,6 +465,9 @@
         resolve()
       }
     }
+
+    window.GLOB.precolumnId = window.GLOB.columnId || ''
+    window.GLOB.columnId = col.uuid
 
     this.setState({card: null})
     this.updateCol(col)
@@ -541,7 +557,7 @@
     document.body.removeChild(oInput)
   }
 
-  handlecolumns = (columns, fields, config, isSub) => {
+  handlecolumns = (columns, fields, config, pId) => {
     return columns.map((col, index) => {
       return {
         title: col.label,
@@ -555,8 +571,9 @@
           upComponent: this.updateCol
         }),
         onHeaderCell: () => ({
-          index: isSub ? undefined : index,
+          index: pId ? config.uuid + '@sub_' + pId + '_' + index : config.uuid + '@' + index,
           column: col,
+          componentId: config.uuid,
           fields: fields,
           align: col.Align,
           moveCol: this.moveCol,
@@ -568,7 +585,7 @@
           changeStyle: this.changeStyle,
           deleteCol: this.deleteCol,
         }),
-        children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, true) : null,
+        children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, col.uuid) : null,
       }
     })
   }
@@ -596,7 +613,7 @@
     let n = []
 
     config.columns.forEach(col => {
-      m.push(`${col.field}(${col.label})`)
+      m.push(`${col.field} ${col.datatype}`)
       n.push(col.field)
     })
 
diff --git a/src/menu/components/table/base-table/columns/index.scss b/src/menu/components/table/base-table/columns/index.scss
index 46cb41d..45da4dc 100644
--- a/src/menu/components/table/base-table/columns/index.scss
+++ b/src/menu/components/table/base-table/columns/index.scss
@@ -36,11 +36,6 @@
         }
       }
     }
-    .action-column {
-      .card-detail-row:empty {
-        min-height: 40px;
-      }
-    }
     tr:hover td {
       background: #ffffff!important;
     }
@@ -99,8 +94,14 @@
   .ant-table-small > .ant-table-content > .ant-table-body {
     margin: 0;
   }
+  .ant-table-small > .ant-table-content .ant-table-thead > tr > th {
+    background-color: #fafafa!important;
+  }
+  .ant-table-small.ant-table-bordered {
+    border-right: 1px solid #e8e8e8;
+  }
 
-  table, tr, th, td {
+  table, tr, th, td, .ant-table-small {
     border-color: var(--mk-table-border-color)!important;
   }
   table tr {
diff --git a/src/menu/components/table/base-table/index.jsx b/src/menu/components/table/base-table/index.jsx
index 86ba414..e301f10 100644
--- a/src/menu/components/table/base-table/index.jsx
+++ b/src/menu/components/table/base-table/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { getTables } from '@/utils/utils-custom.js'
+import { getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import getWrapForm from './options'
 import Utils from '@/utils/utils.js'
@@ -99,39 +99,6 @@
     MKEmitter.removeListener('completeSave', this.completeSave)
   }
 
-  // updateFix = (card) => {
-  //   let fixs = {}
-
-  //   card.cols.forEach(col => {
-  //     if (!col.field) return
-  //     if (col.postfix || col.prefix) {
-  //       fixs[col.field] = col
-  //     }
-  //   })
-
-  //   card.cols.forEach(col => {
-  //     if (col.type === 'custom') {
-  //       col.elements.forEach(cell => {
-  //         if (cell.datatype === 'dynamic') {
-  //           cell.height = ''
-  //           cell.innerHeight = 'auto'
-
-  //           if (fixs[cell.field]) {
-  //             if (!cell.prefix && fixs[cell.field].prefix) {
-  //               cell.prefix = fixs[cell.field].prefix
-  //             }
-  //             if (!cell.postfix && fixs[cell.field].postfix) {
-  //               cell.postfix = fixs[cell.field].postfix
-  //             }
-  //           }
-  //         }
-  //       })
-  //     }
-  //   })
-
-  //   return card
-  // }
-
   completeSave = () => {
     const { card } = this.state
 
@@ -142,7 +109,9 @@
       item.cols = item.cols.filter(a => !a.origin)
 
       delete item.isNew
-      this.setState({card: item}, () => { MKEmitter.emit('revert') })
+      this.setState({card: null}, () => {
+        this.setState({card: item})
+      })
     }
   }
 
@@ -168,64 +137,14 @@
    */
   updateComponent = (card) => {
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
-      card.errors = []
-
-      let doubleClick = card.wrap.doubleClick || ''
-  
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      card.$c_ds = true
+      card.$c_ac = true
+      card.$c_cl = true
+      
+      card.errors = checkComponent(card)
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
-      }
-
-      card.action.forEach(cell => {
-        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-          if (!cell.modal || cell.modal.fields.length === 0) {
-            card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-          }
-        }
-        if (doubleClick === cell.uuid) {
-          doubleClick = ''
-        }
-      })
-  
-      card.cols.forEach(col => {
-        if (col.type === 'action') {
-          col.elements.forEach(cell => {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-            if (doubleClick === cell.uuid) {
-              doubleClick = ''
-            }
-          })
-        } else if (col.type === 'custom') {
-          col.elements.forEach(cell => {
-            if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-              card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑鍔ㄦ�佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-            }
-          })
-        } else if (col.field && !columns.includes(col.field)) {
-          card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑瀛楁鈥�${col.field}鈥濇棤鏁坄})
-        }
-      })
-      
-      if (doubleClick) {
-        card.errors.push({ level: 1, detail: `缁戝畾鐨勫弻鍑绘寜閽凡鍒犻櫎`})
       }
     }
 
@@ -303,8 +222,13 @@
     let _actions = [...action]
 
     cols.forEach(col => {
-      if (col.type !== 'action') return
-      _actions.push(...col.elements)
+      if (col.type === 'custom') {
+        col.elements.forEach(cell => {
+          if (cell.eleType !== 'button') return
+
+          _actions.push(cell)
+        })
+      }
     })
 
     return getWrapForm(wrap, _actions, columns)
@@ -396,6 +320,8 @@
     const { card } = this.state
     let options = ['action', 'search', 'form', 'cols']
 
+    if (!card) return null
+
     return (
       <div className="menu-base-table-edit-box" style={card.style} id={card.uuid}>
         <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
diff --git a/src/menu/components/table/base-table/index.scss b/src/menu/components/table/base-table/index.scss
index 36252f5..408f2e5 100644
--- a/src/menu/components/table/base-table/index.scss
+++ b/src/menu/components/table/base-table/index.scss
@@ -48,6 +48,9 @@
       min-height: 55px;
     }
   }
+  .model-menu-action-list:not(.length0):not(.length1):not(.length2):not(.length3):not(.length4):not(.length5):not(.length6):not(.length7):not(.length8):not(.length9) {
+    margin-bottom: 20px;
+  }
 
   .ant-btn.mk-link {
     padding: 0;
diff --git a/src/menu/components/table/base-table/options.jsx b/src/menu/components/table/base-table/options.jsx
index 22efc6a..3db5e1e 100644
--- a/src/menu/components/table/base-table/options.jsx
+++ b/src/menu/components/table/base-table/options.jsx
@@ -32,12 +32,23 @@
     {
       type: 'radio',
       field: 'actionfixed',
-      label: '鎸夐挳鍥哄畾',
-      initval: wrap.actionfixed || 'false',
+      label: '鍥哄畾鎸夐挳',
+      initval: wrap.actionfixed !== 'true' ? 'false' : 'true',
       required: false,
       options: [
         {value: 'true', label: '鏄�'},
         {value: 'false', label: '鍚�'},
+      ]
+    },
+    {
+      type: 'checkbox',
+      field: 'colfixed',
+      label: '鍥哄畾鍒�',
+      initval: wrap.colfixed || [],
+      required: false,
+      options: [
+        {value: 'first', label: '棣栧垪'},
+        {value: 'last', label: '灏惧垪'},
       ]
     },
     {
@@ -142,7 +153,7 @@
       field: 'height',
       label: '琛ㄦ牸楂樺害',
       initval: wrap.height || '',
-      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆�',
+      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100鏃朵负楂樺害鐨勭櫨鍒嗘瘮銆�',
       min: 10,
       max: 3000,
       precision: 0,
@@ -160,6 +171,16 @@
     },
     {
       type: 'select',
+      field: 'tipField',
+      label: '淇℃伅鎻愮ず',
+      initval: wrap.tipField || '',
+      tooltip: '榧犳爣鎮诞浜庤涓婃柟鏃剁殑鎻愮ず淇℃伅銆�',
+      required: false,
+      allowClear: true,
+      options: columns
+    },
+    {
+      type: 'select',
       field: 'controlField',
       label: '绂佺敤瀛楁',
       initval: wrap.controlField || '',
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 6120716..263da80 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -14,7 +14,6 @@
     roleList = []
   }
 
-  // if (['picture', 'link', 'colspan'].includes(card.type)) {
   if (['picture', 'link'].includes(card.type)) {
     card.type = 'text'
   }
@@ -34,9 +33,6 @@
   }, {
     value: 'colspan',
     text: '鍚堝苟鍒�'
-  // }, {
-  //   value: 'action',
-  //   text: '鎿嶄綔'
   }, {
     value: 'formula',
     text: '鍏紡'
@@ -44,13 +40,6 @@
     value: 'index',
     text: '搴忓彿'
   }]
-
-  if (!card.isSub) {
-    options.push({
-      value: 'action',
-      text: '鎿嶄綔'
-    })
-  }
 
   let editCols = [
     {
@@ -66,22 +55,30 @@
       label: '鏃犲姩浣�'
     }
   ]
-  columns.forEach(col => {
-    if (col.editable === 'true' && col.uuid !== card.uuid) {
-      editCols.push({
-        field: col.uuid,
-        label: col.label
-      })
-    } else if (col.type === 'colspan') {
-      col.subcols.forEach(subcol => {
-        if (subcol.editable === 'true' && subcol.uuid !== card.uuid) {
-          editCols.push({
-            field: subcol.uuid,
-            label: col.label + '-' + subcol.label
-          })
-        }
-      })
-    }
+
+  let cols = []
+  let getcols = (columns, suplabel = '') => {
+    columns.forEach(col => {
+      if (col.editable === 'true' && col.uuid !== card.uuid) {
+        cols.push({
+          field: col.uuid,
+          label: suplabel + col.label
+        })
+      } else if (col.type === 'colspan') {
+        getcols(col.subcols, col.label + '-')
+      }
+    })
+  }
+
+  getcols(columns)
+ 
+  editCols.push(...cols)
+
+  cols.forEach(col => {
+    editCols.push({
+      field: '$next_' + col.field,
+      label: col.label + '锛堜笅涓�琛岋級'
+    })
   })
 
   return [
@@ -148,6 +145,18 @@
     },
     {
       type: 'radio',
+      key: 'eval',
+      label: '瑙f瀽',
+      initVal: card.eval || 'false',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      required: false,
+      options: [
+        { value: 'true', text: '鏄�' },
+        { value: 'false', text: '鍚�' }
+      ]
+    },
+    {
+      type: 'radio',
       key: 'Align',
       label: '瀵归綈鏂瑰紡',
       initVal: card.Align || 'left',
@@ -161,21 +170,6 @@
       }, {
         value: 'right',
         text: '鍙冲榻�'
-      }]
-    },
-    {
-      type: 'radio',
-      key: 'sum',
-      label: '鏄剧ず鍚堣',
-      initVal: card.sum || 'false',
-      tooltip: '鍚堣淇℃伅鍙湪浣跨敤绯荤粺鏁版嵁婧愭椂鏈夋晥銆�',
-      required: false,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
       }]
     },
     {
@@ -260,16 +254,6 @@
       }]
     },
     {
-      type: 'select',
-      key: 'editField',
-      label: '缂栬緫瀛楁',
-      initVal: card.editField || '',
-      tooltip: '褰撳�间笌鎻愮ず鏂囧瓧涓嶅悓鏃讹紝鍙澶栨坊鍔犵紪杈戝瓧娈碉紝浣滀负瀹為檯鍊肩殑褰曞叆瀛楁銆�',
-      allowClear: true,
-      required: false,
-      options: fields
-    },
-    {
       type: 'options',
       key: 'options',
       label: '閫夐」',
@@ -281,6 +265,7 @@
       key: 'dataSource',
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆�',
       required: true,
     },
     {
@@ -370,27 +355,28 @@
       type: 'select',
       key: 'enter',
       label: '鍥炶溅鍒囨崲',
-      initVal: card.enter || '$next',
+      initVal: card.enter || '$noAct',
       tooltip: '鍖呮嫭鏂囨湰鎴栨暟鍊煎洖杞︿簨浠躲�佷笅鎷夎彍鍗曢�変腑浜嬩欢銆佸紑鍏冲垏鎹簨浠躲��',
       options: editCols
     },
-    // {
-    //   type: 'radio',
-    //   key: 'footEnter',
-    //   label: '鏈鍥炶溅',
-    //   initVal: card.footEnter || 'false',
-    //   tooltip: '鏂板鍔熻兘浠呭湪琛ㄦ牸鍙柊澧炴椂鏈夋晥銆�',
-    //   options: [{
-    //     value: 'sub',
-    //     text: '鎻愪氦'
-    //   }, {
-    //     value: 'add',
-    //     text: '鏂板'
-    //   }, {
-    //     value: 'false',
-    //     text: '鏃犲姩浣�'
-    //   }]
-    // },
+    {
+      type: 'select',
+      key: 'ctrlField',
+      label: '绂佺敤瀛楁',
+      initVal: card.ctrlField || '',
+      tooltip: '鎺у埗鍗曞厓鏍兼槸鍚﹀彲浠ョ紪杈戙��',
+      allowClear: true,
+      required: false,
+      options: fields
+    },
+    {
+      type: 'text',
+      key: 'ctrlValue',
+      label: '绂佺敤鍊�',
+      initVal: card.ctrlValue || '',
+      tooltip: '澶氫釜鍊肩敤閫楀彿鍒嗛殧銆�',
+      required: false
+    },
     {
       type: 'number',
       key: 'decimal',
@@ -398,7 +384,7 @@
       max: 18,
       precision: 0,
       label: '灏忔暟浣�',
-      initVal: card.decimal || 0,
+      initVal: card.decimal,
       required: false
     },
     {
@@ -472,18 +458,6 @@
       required: false,
     },
     {
-      type: 'radio',
-      key: 'eval',
-      label: '瑙f瀽',
-      initVal: card.eval || 'true',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
-      required: false,
-      options: [
-        { value: 'true', text: '鏄�' },
-        { value: 'false', text: '鍚�' }
-      ]
-    },
-    {
       type: 'textarea',
       key: 'formula',
       label: '鍏紡',
@@ -501,6 +475,21 @@
       options: fields
     },
     {
+      type: 'radio',
+      key: 'noValue',
+      label: '绌哄��',
+      initVal: card.noValue || 'show',
+      tooltip: '褰撳�间负0鏃舵槸鍚︽樉绀�',
+      required: false,
+      options: [{
+        value: 'show',
+        text: '鏄剧ず'
+      }, {
+        value: 'hide',
+        text: '闅愯棌'
+      }]
+    },
+    {
       type: 'multiselect',
       key: 'blacklist',
       label: '榛戝悕鍗�',
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 e445b43..06b4348 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -1,9 +1,12 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Modal, notification } from 'antd'
+import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Modal, notification, Popover } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
+import moment from 'moment'
 
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
 import { getColumnForm } from './formconfig'
 import { formRule } from '@/utils/option.js'
 import CodeMirror from '@/templates/zshare/codemirror'
@@ -16,7 +19,7 @@
   text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'editable', 'initval', 'blacklist'],
   number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'editable', 'initval', 'sum', 'blacklist'],
   textarea: ['label', 'field', 'type', 'Align', 'Hide', 'Width', 'prefix', 'initval', 'postfix', 'blacklist'],
-  custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'],
+  custom: ['label', 'type', 'Align', 'Width', 'blacklist'],
   colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
   action: ['label', 'type', 'Align', 'Width'],
   formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
@@ -25,7 +28,6 @@
 
 class EdiTableColumn extends Component {
   static propTpyes = {
-    visible: PropTypes.bool,
     column: PropTypes.object,
     columns: PropTypes.array,
     fields: PropTypes.array,
@@ -35,11 +37,12 @@
 
   state = {
     visible: false,
+    loading: false,
     formlist: null,
     transfield: {}
   }
 
-  column = null
+  record = null
 
   UNSAFE_componentWillMount() {
     let transfield = {}
@@ -57,18 +60,22 @@
   }
 
   getOptions = () => {
-    let _options = fromJS(columnTypeOptions[this.column.type]).toJS()
+    let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
 
-    if (this.column.editable === 'true') {
-      if (this.column.type === 'text') {
+    if (['number', 'text'].includes(this.record.type) && this.record.editable === 'true') {
+      _options.push('ctrlField')
+      if (this.record.ctrlField) {
+        _options.push('ctrlValue')
+      }
+      if (this.record.type === 'text') {
         _options.push('editType')
 
-        if (this.column.editType === 'switch') {
+        if (this.record.editType === 'switch') {
           _options.push('enter', 'openVal', 'closeVal', 'openText', 'closeText', 'editField')
-        } else if (this.column.editType === 'select') {
+        } else if (this.record.editType === 'select') {
           _options.push('required', 'enter', 'resourceType', 'linkSubField', 'editField', 'dropdown')
 
-          if (this.column.resourceType === '0') {
+          if (this.record.resourceType === '0') {
             _options.push('options')
           } else {
             _options.push('dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'disableField', 'database')
@@ -76,9 +83,15 @@
         } else {
           _options.push('required', 'enter')
         }
-      } else if (this.column.type === 'number') {
+      } else if (this.record.type === 'number') {
         _options.push('max', 'min', 'enter')
       }
+    }
+    if (this.record.type === 'formula' && this.record.eval === 'true') {
+      _options.push('decimal')
+    }
+    if (['number', 'formula'].includes(this.record.type) && this.record.Hide !== 'true') {
+      _options.push('noValue')
     }
 
     return _options
@@ -91,10 +104,11 @@
     })
 
     let formlist = getColumnForm(column, fields, this.props.columns)
+    this.record = {}
 
-    this.column = fromJS(column).toJS()
-    this.column.editType = this.column.editType || 'text'
-    this.column.resourceType = this.column.resourceType || '0'
+    formlist.forEach(item => {
+      this.record[item.key] = item.initVal
+    })
     
     let _options = this.getOptions()
 
@@ -102,6 +116,11 @@
       visible: true,
       formlist: formlist.map(item => {
         item.hidden = !_options.includes(item.key)
+
+        if (item.key === 'formula') {
+          item.fields = this.props.fields.map(col => col.field)
+          item.fields = item.fields.join(', ')
+        }
 
         return item
       })
@@ -119,21 +138,34 @@
   }
 
   typeChange = (key, value, option) => {
-    this.column[key] = value
+    this.record[key] = value
 
     if (key === 'type') {
       let _options = this.getOptions()
 
+      let _field = ''
+      if (value === 'formula') {
+        _field = this.props.form.getFieldValue('field') || ''
+      }
+
       this.setState({
         formlist: this.state.formlist.map(item => {
-          item.initVal = this.column[item.key] || item.initVal
+          if (item.key === 'decimal' && value === 'formula') {
+            this.record.decimal = ''
+          }
+
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
 
           return item
         })
       }, () => {
-        if (value === 'action' || value === 'colspan') {
+        if (value === 'colspan') {
           this.props.form.setFieldsValue({Align: 'center'})
+        } else if (value === 'formula' && _field) {
+          this.props.form.setFieldsValue({formula: '@' + _field + '@'})
+        } else if (value === 'index') {
+          this.props.form.setFieldsValue({label: '搴忓彿'})
         }
       })
     } else if (key === 'field') {
@@ -149,15 +181,15 @@
         values.type = 'text'
       }
 
-      let _type = this.column.type
-      this.column.type = values.type
+      let _type = this.record.type
+      this.record.type = values.type
 
       if (values.type !== _type) {
         let _options = this.getOptions()
 
         this.setState({
           formlist: this.state.formlist.map(item => {
-            item.initVal = this.column[item.key] || item.initVal
+            item.initVal = this.record[item.key]
             item.hidden = !_options.includes(item.key)
 
             return item
@@ -170,12 +202,12 @@
       }
     } else if (key === 'format' && value === 'percent') {
       this.props.form.setFieldsValue({postfix: '%'})
-    } else if (key === 'editable' || key === 'editType' || key === 'resourceType') {
+    } else if (['editable', 'editType', 'resourceType', 'ctrlField', 'eval', 'Hide'].includes(key)) {
       let _options = this.getOptions()
 
       this.setState({
         formlist: this.state.formlist.map(item => {
-          item.initVal = this.column[item.key] || item.initVal
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
 
           return item
@@ -187,7 +219,7 @@
   multiselectChange = (key, value) => {
     if (key !== 'linkSubField') return
 
-    this.column[key] = value
+    this.record[key] = value
   }
 
   handleEmpty = () => {
@@ -225,7 +257,7 @@
   }
 
   changeOptions = (data) => {
-    this.column.options = data || []
+    this.record.options = data || []
   }
 
   getFields() {
@@ -310,6 +342,28 @@
           { required: item.required, message: '璇疯緭鍏�' + item.label + '!' }
         ]
 
+        if (item.key === 'formula') {
+          fields.push(
+            <Col span={span} key={index}>
+              <Form.Item className={className} extra={extra} label={item.tooltip ?
+                <Tooltip placement="topLeft" title={item.tooltip}>
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  {item.label}
+                </Tooltip> : item.label
+              }>
+                {getFieldDecorator(item.key, {
+                  initialValue: initVal,
+                  rules: rules
+                })(<TextArea rows={item.rows || 2}/>)}
+              </Form.Item>
+              <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click">
+                <span className="formula-icon">瀛楁闆�</span>
+              </Popover>
+            </Col>
+          )
+          return
+        }
+
         content = <TextArea rows={item.rows || 2}/>
       } else if (item.type === 'codemirror') {
         rules = [
@@ -319,13 +373,16 @@
         className = 'text-area'
 
         extra = <span className="add-resource-empty" onClick={this.handleEmpty}>绌�</span>
+        if (item.placeholder) {
+          extra = <><span className="resource-public-var">{item.placeholder}</span>{extra}</>
+        }
 
         content = <CodeMirror />
       } else if (item.type === 'options') {
         span = 24
         className = 'text-area'
 
-        let linkSubFields = this.column.linkSubField || []
+        let linkSubFields = this.record.linkSubField || []
       
         content = <EditTable type={'select'} module="form" transfield={transfield} linkSubFields={linkSubFields} onChange={this.changeOptions}/>
       }
@@ -350,34 +407,96 @@
   }
 
   handleSubmit = () => {
-    // const { columns } = this.props
+    const { fields } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
-        // if (values.field && columns.filter(col => col.field && col.uuid !== values.uuid && col.field === values.field).length > 0) {
-        //   notification.warning({
-        //     top: 92,
-        //     message: '瀛楁宸叉坊鍔狅紒',
-        //     duration: 5
-        //   })
-        //   return
-        // }
-        this.setState({visible: false, formlist: null})
-        this.props.submitCol(values)
+        if (values.type === 'number' && values.editable === 'true') {
+          if (typeof(values.max) === 'number' && typeof(values.min) === 'number' && values.max < values.min) {
+            notification.warning({
+              top: 92,
+              message: '鏈�澶у�间笉鍙皬浜庢渶灏忓�硷紒',
+              duration: 5
+            })
+            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)) {
+          let cols = []
+          fields.forEach(col => {
+            if (/^(Int|Decimal)/ig.test(col.datatype)) {
+              cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
+            }
+          })
 
-        this.column = null
+          cols.forEach(col => {
+            values.formula = values.formula.replace(col.reg, col.value)
+          })
+        }
+
+        if (values.dataSource && /\s/.test(values.dataSource)) {
+          let error = Utils.verifySql(values.dataSource)
+
+          if (error) {
+            notification.warning({
+              top: 92,
+              message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error,
+              duration: 5
+            })
+            return
+          }
+
+          this.setState({
+            loading: 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)
+              ${values.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 && values.database === 'sso') {
+            param.rduri = window.GLOB.mainSystemApi
+          }
+          
+          Api.genericInterface(param).then(result => {
+            if (result.status) {
+              this.setState({visible: false, loading: false, formlist: null})
+              this.props.submitCol(values)
+              this.record = null
+            } else {
+              this.setState({loading: false})
+              Modal.error({
+                title: result.message
+              })
+            }
+          })
+        } else {
+          this.setState({visible: false, formlist: null})
+          this.props.submitCol(values)
+          this.record = null
+        }
       }
     })
   }
 
   editModalCancel = () => {
-    this.setState({visible: false, formlist: null})
+    this.setState({visible: false, loading: false, formlist: null})
 
     this.props.cancelCol()
   }
 
   render() {
-    const { visible } = this.state
+    const { visible, loading } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -398,6 +517,7 @@
           maskClosable={false}
           onOk={this.handleSubmit}
           onCancel={this.editModalCancel}
+          confirmLoading={loading}
           destroyOnClose
         >
           <Form {...formItemLayout} className="commontable-column-form" id="edit-table-column-winter">
diff --git a/src/menu/components/table/edit-table/columns/editColumn/index.scss b/src/menu/components/table/edit-table/columns/editColumn/index.scss
index e9dd7c5..05b0e19 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/index.scss
+++ b/src/menu/components/table/edit-table/columns/editColumn/index.scss
@@ -17,6 +17,14 @@
       height: 150px;
     }
   }
+  .formula-icon {
+    position: absolute;
+    bottom: 5px;
+    right: 15px;
+    cursor: pointer;
+    font-size: 12px;
+    color: #1890ff;
+  }
   .ant-form-extra {
     padding-top: 0px;
     min-height: 0px;
@@ -29,4 +37,25 @@
     cursor: pointer;
     font-size: 14px;
   }
+  .resource-public-var {
+    position: absolute;
+    left: 0px;
+    top: -25px;
+    font-size: 14px;
+  }
+  >.ant-row >.ant-col {
+    display: inline-block;
+    vertical-align: top;
+    float: none;
+  }
 }
+.formula-fields {
+  z-index: 1200!important;
+
+  .ant-popover-inner-content {
+    div {
+      max-width: 750px;
+      word-break: break-all;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/table/edit-table/columns/index.jsx b/src/menu/components/table/edit-table/columns/index.jsx
index afa1eba..ba13cb7 100644
--- a/src/menu/components/table/edit-table/columns/index.jsx
+++ b/src/menu/components/table/edit-table/columns/index.jsx
@@ -3,7 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider, DragSource, DropTarget } from 'react-dnd'
 import { Table, Popover, Modal, message, Button, Typography } from 'antd'
-import { PlusOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
+import { PlusOutlined, PlusSquareOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -47,69 +47,45 @@
 
     return !is(fromJS(this.props.column), fromJS(nextProps.column)) ||
       !is(fromJS(this.props.fields), fromJS(nextProps.fields)) ||
-      this.props.index !== nextProps.index
+      this.props.index !== nextProps.index ||
+      window.GLOB.columnId === nextProps.column.uuid || window.GLOB.precolumnId === nextProps.column.uuid
   }
 
   render() {
-    const { connectDragSource, connectDropTarget, moveCol, dropCol, addElement, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
+    const { connectDragSource, connectDropTarget, moveCol, componentId, dropCol, addElement, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
 
     if (!column) return (
-      <th {...restProps} index={index}>
-        {children}
-      </th>
+      <th {...restProps}>{children}</th>
     )
 
-    if (index !== undefined) {
-      let style = {cursor: 'move', textAlign: align}
-      if (column.Width) {
-        style.width = column.Width
-        style.minWidth = column.Width
-      }
-
-      return connectDragSource(
-        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => this.props.editColumn(column)}>
-          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
-              {['custom', 'colspan', 'action'].includes(column.type) ?
-                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
-              }
-              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
-              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              {column.type === 'action' ? <PasteComponent options={['action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              {column.type === 'custom' || column.type === 'action' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
-              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-              {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
-            </div>
-          } trigger="hover">
-            {children}
-          </Popover>
-        </th>),
-      )
-    } else if (column) {
-      let style = {textAlign: align}
-      if (column.Width) {
-        style.width = column.Width
-        style.minWidth = column.Width
-      }
-
-      return (
-        <th {...restProps} style={style} key={column.uuid} onDoubleClick={() => this.props.editColumn(column)}>
-          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
-              {['custom', 'colspan'].includes(column.type) ?
-                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
-              }
-              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
-              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
-            </div>
-          } trigger="hover">
-            {children}
-          </Popover>
-        </th>
-      )
+    let style = {cursor: 'move', textAlign: align}
+    if (column.Width) {
+      style.width = column.Width
+      style.minWidth = column.Width
     }
+
+    if (window.GLOB.columnId === column.uuid) {
+      style.color = '#1890ff'
+    }
+
+    return connectDragSource(
+      connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => this.props.editColumn(column)}>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
+            {column.type === 'colspan' ? <PlusOutlined className="plus" title="娣诲姞鍒�" onClick={() => this.props.addElement(column)} /> : null}
+            {column.type === 'custom' ? <PlusOutlined className="plus" title="娣诲姞鍏冪礌" onClick={() => this.props.addElement(column)} /> : null}
+            {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={() => this.props.addElement(column, 'button')} /> : null}
+            <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
+            {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
+            {column.type === 'custom' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
+            <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
+            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
+          </div>
+        } trigger="hover">
+          {children}
+        </Popover>
+      </th>),
+    )
   }
 }
 
@@ -124,17 +100,28 @@
 const ColTarget = {
   drop(props, monitor) {
     const item = monitor.getItem()
-    const dragIndex = item.index
-    const hoverIndex = props.index
+    let dragIndex = item.index
+    let hoverIndex = props.index
 
     if (item.$init) {
-      props.dropCol(item, hoverIndex)
+      if (/sub_/.test(hoverIndex)) {
+        message.warning('鍚堝苟鍒楀瓙鍏冪礌鏆備笉鏀寔鎷栨嫿娣诲姞銆�')
+      } else {
+        props.dropCol(item, hoverIndex.replace(new RegExp(props.componentId + '@', 'ig'), ''))
+      }
       return
     } else if (dragIndex === undefined || hoverIndex === undefined || dragIndex === hoverIndex) {
       return
+    } else {
+      let reg = new RegExp(props.componentId + '@', 'ig')
+      if (reg.test(dragIndex)) {
+        props.moveCol(dragIndex.replace(reg, ''), hoverIndex.replace(reg, ''))
+      } else {
+        message.warning('鎷栧姩鍏冪礌涓嶅湪褰撳墠缁勪欢涓��')
+        return
+      }
     }
-
-    props.moveCol(dragIndex, hoverIndex)
+    
     monitor.getItem().index = hoverIndex
   },
 }
@@ -169,12 +156,6 @@
     if (column && column.type === 'custom') {
       return (
         <td style={{padding: 0, ...(column.style || {})}} className={className}>
-          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
-        </td>
-      )
-    } else if (column && column.type === 'action') {
-      return (
-        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
           <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
         </td>
       )
@@ -280,7 +261,17 @@
   moveCol = (dragIndex, hoverIndex) => {
     let _columns = fromJS(this.state.columns).toJS()
 
-    _columns.splice(hoverIndex, 0, ..._columns.splice(dragIndex, 1))
+    if (/^sub_/.test(dragIndex) || /^sub_/.test(hoverIndex)) {
+      let sign1 = dragIndex.split('_')
+      let sign2 = hoverIndex.split('_')
+      if (sign1[1] !== sign2[1]) {
+        message.warning('鎷栧姩鍏冪礌涓嶅湪鍚屼竴涓悎骞跺垪涓��')
+        return
+      }
+      this.loopMoveCol(_columns, sign1[1], sign1[2], sign2[2])
+    } else {
+      _columns.splice(hoverIndex, 0, ..._columns.splice(dragIndex, 1))
+    }
 
     this.setState({
       columns: _columns
@@ -289,19 +280,27 @@
     })
   }
 
+  loopMoveCol = (columns, colId, dragIndex, hoverIndex) => {
+    columns.forEach(column => {
+      if (column.type === 'colspan' && column.uuid === colId) {
+        column.subcols.splice(hoverIndex, 0, ...column.subcols.splice(dragIndex, 1))
+      } else if (column.type === 'colspan') {
+        this.loopMoveCol(column.subcols, colId, dragIndex, hoverIndex)
+      }
+    })
+  }
+
   dropCol = (item, hoverIndex) => {
     let _columns = fromJS(this.state.columns).toJS()
     let type = item.subType
 
-    if (!['text', 'number', 'textarea', 'custom', 'action', 'formula', 'index', 'colspan'].includes(item.subType)) {
+    if (!['text', 'number', 'textarea', 'custom', 'formula', 'index', 'colspan'].includes(item.subType)) {
       type = 'text'
     }
 
-    let col = { focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: type, elements: [] }
+    let col = { focus: true, uuid: Utils.getuuid(), Width: 120, label: 'label', field: '', type: type, elements: [] }
     if (col.type === 'colspan') {
       col.subcols = []
-    } else if (col.type === 'action') {
-      col.label = '鎿嶄綔'
     } else if (col.type === 'index') {
       col.label = '搴忓彿'
     }
@@ -339,7 +338,7 @@
         config.action = config.action.filter(item => item.uuid !== btn.uuid)
 
         setTimeout(() => {
-          MKEmitter.emit('revert', config.uuid)
+          MKEmitter.emit('revertBtn', config.uuid)
         }, 200)
       }
 
@@ -356,14 +355,23 @@
   pasteCell = (col, cell, resolve) => {
     resolve({status: true})
     
-    delete cell.copyType
     cell.uuid = Utils.getuuid()
     cell.focus = true
+    
+    if (!cell.eleType) {
+      if (cell.copyType === 'action') {
+        cell.eleType = 'button'
+        cell.width = cell.width || 12
+      } else {
+        cell.eleType = 'text'
+      }
+    }
+    delete cell.copyType
     
     MKEmitter.emit('cardAddElement', col.uuid, cell)
   }
 
-  addElement = (col) => {
+  addElement = (col, type) => {
     let column = fromJS(col).toJS()
 
     if (column.type === 'colspan') {
@@ -376,26 +384,28 @@
       })
       this.updateCol(column)
     } else if (column.type === 'custom') {
-      let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
+      if (type === 'button') {
+        let newcard = {
+          uuid: Utils.getuuid(),
+          focus: true,
+          eleType: 'button',
+          label: 'button',
+          OpenType: 'prompt',
+          class: 'primary',
+          intertype: 'system',
+          execSuccess: 'grid',
+          execError: 'never',
+          show: 'link'
+        }
   
-      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
-      MKEmitter.emit('cardAddElement', column.uuid, newcard)
-    } else if (column.type === 'action') {
-      let newcard = {
-        uuid: Utils.getuuid(),
-        focus: true,
-        eleType: 'button',
-        label: 'button',
-        OpenType: 'prompt',
-        class: 'primary',
-        intertype: 'system',
-        execSuccess: 'grid',
-        execError: 'never',
-        show: 'link'
+        // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+        MKEmitter.emit('cardAddElement', column.uuid, newcard)
+      } else {
+        let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
+    
+        // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+        MKEmitter.emit('cardAddElement', column.uuid, newcard)
       }
-
-      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
-      MKEmitter.emit('cardAddElement', column.uuid, newcard)
     }
   }
 
@@ -411,10 +421,10 @@
     } else if (col.type === 'custom') {
       col.style = card.style || {}
       col.elements = card.type === 'custom' ? (card.elements || []) : []
-    } else if (col.type === 'action') {
-      col.style = card.style || {}
-      col.elements = card.type === 'action' ? (card.elements || []) : []
     }
+
+    window.GLOB.precolumnId = window.GLOB.columnId || ''
+    window.GLOB.columnId = col.uuid
 
     this.setState({card: null})
     this.updateCol(col)
@@ -472,7 +482,22 @@
   deleteCol = (col) => {
     let _columns = fromJS(this.state.columns).toJS()
 
-    _columns = this.loopDelCol(_columns, col)
+    if (col.type === 'colspan' && col.subcols && col.subcols.length > 0) {
+      let Index = _columns.findIndex(item => item.uuid === col.uuid)
+
+      if (Index !== -1) {
+        let list = col.subcols.map(item => {
+          item.isSub = false
+          return item
+        })
+
+        _columns.splice(Index, 1, ...list)
+      } else {
+        _columns = this.loopDelCol(_columns, col)
+      }
+    } else {
+      _columns = this.loopDelCol(_columns, col)
+    }
 
     this.setState({
       columns: _columns
@@ -538,7 +563,6 @@
       } else {
         cell.type = 'number'
         cell.format = 'none'
-        cell.sum = 'false'
         cell.decimal = item.decimal || 0
         cell.Width = 80
       }
@@ -600,7 +624,7 @@
     MKEmitter.removeListener('submitStyle', this.getStyle)
   }
 
-  handlecolumns = (columns, fields, config, isSub) => {
+  handlecolumns = (columns, fields, config, pId) => {
     return columns.map((col, index) => {
       let title = col.label
       if (col.editable === 'true') {
@@ -619,8 +643,9 @@
           upComponent: this.updateCol
         }),
         onHeaderCell: () => ({
-          index: isSub ? undefined : index,
+          index: pId ? config.uuid + '@sub_' + pId + '_' + index : config.uuid + '@' + index,
           column: col,
+          componentId: config.uuid,
           fields: fields,
           align: col.Align,
           moveCol: this.moveCol,
@@ -632,7 +657,7 @@
           changeStyle: this.changeStyle,
           deleteCol: this.deleteCol,
         }),
-        children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, true) : null,
+        children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, col.uuid) : null,
       }
     })
   }
@@ -695,8 +720,7 @@
         </DndProvider>
         <EditColumn column={card} columns={this.state.columns} fields={fields} submitCol={this.submitCol} cancelCol={this.cancelCol}/>
         <Modal
-          wrapClassName="model-table-action-verify-modal"
-          title={'缂栬緫'}
+          wrapClassName="mk-pop-modal"
           visible={visible}
           width={'75vw'}
           maskClosable={false}
@@ -705,10 +729,7 @@
           destroyOnClose
         >
           <TableVerify
-            card={config.submit}
-            setting={config.setting}
-            cols={config.cols}
-            columns={config.columns}
+            config={config}
             wrappedComponentRef={(inst) => this.verifyRef = inst}
           />
         </Modal>
diff --git a/src/menu/components/table/edit-table/columns/index.scss b/src/menu/components/table/edit-table/columns/index.scss
index 0accff1..613cfb2 100644
--- a/src/menu/components/table/edit-table/columns/index.scss
+++ b/src/menu/components/table/edit-table/columns/index.scss
@@ -15,11 +15,14 @@
     max-width: 60px;
   }
   .submit-btn {
-    min-height: 24px;
+    min-height: 28px;
+    min-width: 65px;
     height: auto;
     margin-right: 10px;
+    margin-bottom: 10px!important;
     background-color: #1890ff;
     border-width: 0;
+    top: -2px;
   }
   .ant-table-thead > tr > th .ant-table-header-column .ant-table-column-sorters > .ant-table-column-title {
     position: unset;
@@ -69,11 +72,6 @@
         >.profile + .close-col {
           right: 20px;
         }
-      }
-    }
-    .action-column {
-      .card-detail-row:empty {
-        min-height: 40px;
       }
     }
     tr:hover td {
@@ -128,8 +126,14 @@
   .ant-table-small > .ant-table-content > .ant-table-body {
     margin: 0;
   }
+  .ant-table-small > .ant-table-content .ant-table-thead > tr > th {
+    background-color: #fafafa!important;
+  }
+  .ant-table-small.ant-table-bordered {
+    border-right: 1px solid #e8e8e8;
+  }
 
-  table, tr, th, td {
+  table, tr, th, td, .ant-table-small {
     border-color: var(--mk-table-border-color)!important;
   }
   table tr {
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 fa48a0f..a4a7025 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
@@ -47,19 +47,37 @@
   }
 
   edit = (record) => {
+    const { type } = this.props
+
     this.setState({
       editItem: record
     })
 
-    this.props.form.setFieldsValue({
-      sql: record.sql,
-      position: record.position || 'back'
-    })
+    if (type === 'fullscreen') {
+      this.props.form.setFieldsValue({
+        sql: record.sql
+      })
+    } else {
+      this.props.form.setFieldsValue({
+        sql: record.sql,
+        position: record.position || 'back'
+      })
+    }
   }
 
   handleConfirm = () => {
+    const { type } = this.props
+    const { editItem } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
+      if (type === 'fullscreen' && err) {
+        notification.warning({
+          top: 92,
+          message: '璇疯緭鍏ql!',
+          duration: 5
+        })
+        return
+      }
       if (!err) {
         if (/^[\s\n]+$/.test(values.sql)) {
           notification.warning({
@@ -71,6 +89,10 @@
         }
         
         values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        if (type === 'fullscreen' && editItem) {
+          values.status = editItem.status || 'true'
+        }
 
         let _quot = values.sql.match(/'{1}/g)
         let _lparen = values.sql.match(/\({1}/g)
@@ -98,6 +120,13 @@
           notification.warning({
             top: 92,
             message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 5
+          })
+          return
+        } else if (/,,/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇杩炵画鐨勮嫳鏂囬�楀彿锛�,,锛�',
             duration: 5
           })
           return
@@ -190,7 +219,7 @@
               this.props.scriptsChange(values)
             })
             this.props.form.setFieldsValue({
-              sql: ''
+              sql: ' '
             })
           } else {
             this.setState({loading: false})
@@ -236,6 +265,9 @@
     }
 
     let _sql = this.props.form.getFieldValue('sql')
+    if (/^\s+$/.test(_sql)) {
+      _sql = ''
+    }
     if (_sql) {
       _sql = _sql + ` 
 
@@ -254,8 +286,8 @@
   }
 
   render() {
-    const { systemScripts, btn } = this.props
-    const { usefulfields } = this.state
+    const { systemScripts, btn, type } = this.props
+    const { usefulfields, editItem } = this.state
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
       labelCol: {
@@ -271,24 +303,24 @@
     return (
       <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
         <Row gutter={24}>
-          {btn.sheet ? <Col span={8}>
+          {!type && btn.sheet ? <Col span={8}>
             <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
               {btn.sheet}
             </Form.Item>
           </Col> : null}
-          <Col span={10}>
+          {!type ? <Col span={10}>
             <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
               ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
             </Form.Item>
-          </Col>
-          {usefulfields ? <Col span={24} className="sqlfield">
+          </Col> : null}
+          {!type ? <Col span={24} className="sqlfield">
             <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锛�
             </Form.Item>
           </Col> : null}
-          <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" />
@@ -305,8 +337,8 @@
                 </Radio.Group>
               )}
             </Form.Item>
-          </Col>
-          <Col span={10}>
+          </Col> : null}
+          {!type ? <Col span={10}>
             <Form.Item style={{marginBottom: 0}} label={'蹇嵎娣诲姞'}>
               <Select
                 showSearch
@@ -327,10 +359,10 @@
                 )}
               </Select>
             </Form.Item>
-          </Col>
+          </Col> : null}
           <Col span={6} className="add">
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
-              淇濆瓨
+              {type === 'fullscreen' && !editItem ? '娣诲姞' : '淇濆瓨'}
             </Button>
             <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
               鍙栨秷
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 144df97..8d5c18e 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -1,13 +1,14 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Tabs, Row, Col, Input, Button, Table, Popconfirm, notification, Modal, message, InputNumber, Radio, Typography } from 'antd'
-import { StopTwoTone, CheckCircleTwoTone, EditOutlined, ArrowUpOutlined, ArrowDownOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
+import { Form, Tabs, Row, Col, Input, Button, Popconfirm, notification, Modal, message, Cascader, Tooltip, InputNumber, Radio, Typography } from 'antd'
+import { StopTwoTone, CheckCircleTwoTone, EditOutlined, SwapOutlined, DeleteOutlined, QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-
+import MKEmitter from '@/utils/events.js'
+import MenuUtils from '@/utils/utils-custom.js'
 import UniqueForm from './uniqueform'
 import CustomScript from './customscript'
 import asyncComponent from '@/utils/asyncComponent'
@@ -17,6 +18,7 @@
 const { confirm } = Modal
 const { Paragraph } = Typography
 const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
+const FullScripts = asyncComponent(() => import('@/templates/zshare/verifycard/fullScripts'))
 
 class VerifyTableCard extends Component {
   static propTpyes = {
@@ -27,6 +29,7 @@
   state = {
     verify: {},
     fields: [],
+    modules: [],
     fieldLabel: {},
     systemScripts: [],
     activeKey: 'basemsg',
@@ -47,7 +50,7 @@
       {
         title: '鎶ラ敊缂栫爜',
         dataIndex: 'errorCode',
-        width: '12%',
+        width: '10%',
         editable: true,
         inputType: 'select',
         options: [
@@ -60,13 +63,24 @@
       {
         title: '楠岃瘉绫诲瀷',
         dataIndex: 'verifyType',
-        width: '12%',
-        render: (text, record) => record.verifyType === 'logic' ? '閫昏緫楠岃瘉' : '鐗╃悊楠岃瘉',
+        width: '14%',
+        render: (text, record) => {
+          let names = {
+            physical: '鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級',
+            logic: '閫昏緫楠岃瘉锛堝叏閲忛獙璇侊級',
+            physical_temp: '鐗╃悊楠岃瘉锛堜粎涓存椂琛級',
+            logic_temp: '閫昏緫楠岃瘉锛堜粎涓存椂琛級',
+          }
+
+          return names[text] || '鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級'
+        },
         inputType: 'select',
         editable: true,
         options: [
-          { value: 'physical', text: '鐗╃悊楠岃瘉' },
-          { value: 'logic', text: '閫昏緫楠岃瘉' }
+          { value: 'physical', text: '鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級' },
+          { value: 'logic', text: '閫昏緫楠岃瘉锛堝叏閲忛獙璇侊級' },
+          { value: 'physical_temp', text: '鐗╃悊楠岃瘉锛堜粎涓存椂琛級' },
+          { value: 'logic_temp', text: '閫昏緫楠岃瘉锛堜粎涓存椂琛級' }
         ]
       },
       {
@@ -114,15 +128,13 @@
         dataIndex: 'position',
         width: '10%',
         render: (text, record) => {
-          let _text = ''
-          if (record.position === 'front') {
-            _text = 'sql鍓�'
-          } else if (record.position === 'init') {
-            _text = '鍒濆鍖�'
+          if (record.position === 'init') {
+            return <span style={{color: 'orange'}}>鍒濆鍖�</span>
+          } else if (record.position === 'front') {
+            return <span style={{color: '#26C281'}}>sql鍓�</span>
           } else {
-            _text = 'sql鍚�'
+            return <span style={{color: '#1890ff'}}>sql鍚�</span>
           }
-          return _text
         }
       },
       {
@@ -149,10 +161,8 @@
         width: '20%',
         dataIndex: 'operation',
         render: (text, record) =>
-          (<div>
+          (<div style={{textAlign: 'center'}}>
             <span className="operation-btn" onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><EditOutlined /></span>
-            <span className="operation-btn" onClick={() => this.handleUpDown(record, 'scripts', 'up')} style={{color: '#1890ff'}}><ArrowUpOutlined /></span>
-            <span className="operation-btn" onClick={() => this.handleUpDown(record, 'scripts', 'down')} style={{color: '#ff4d4f'}}><ArrowDownOutlined /></span>
             <span className="operation-btn" title="鐘舵�佸垏鎹�" onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
             <Popconfirm
               overlayClassName="popover-confirm"
@@ -167,27 +177,32 @@
   }
 
   UNSAFE_componentWillMount() {
-    const { columns, card, setting } = this.props
-    let _verify = fromJS(card).toJS()
+    const { columns, submit, setting, uuid } = this.props.config
+    let _verify = fromJS(submit).toJS()
     _verify.sheet = _verify.sheet || setting.tableName
 
     let fieldLabel = {}
-    // let _columns = []
-    // let _fields = {}
 
     columns.forEach(col => {
       fieldLabel[col.field] = col.label
-      // _fields[col.field] = col
     })
-    // cols.forEach(col => {
-    //   if (!col.field || col.type === 'index' || !_fields[col.field]) return
-      
-    //   _columns.push(_fields[col.field])
-    // })
+
+    let supId = ''
+    if (setting && setting.supModule) {
+      let pid = setting.supModule[setting.supModule.length - 1]
+      if (pid && pid !== 'empty') {
+        supId = pid
+      } else {
+        supId = ''
+      }
+    }
+    
+    let modules = MenuUtils.getSubModules(window.GLOB.customMenu.components, uuid, supId)
 
     this.setState({
       fields: fromJS(columns).toJS().filter(item => item.field !== setting.primaryKey),
       fieldLabel,
+      modules: modules,
       verify: _verify
     }, () => {
       this.resetUniqueColumns()
@@ -313,6 +328,8 @@
       verify.scripts.push(values)
     }
 
+    MKEmitter.emit('editLineId', values.uuid)
+
     this.setState({
       verify: verify
     })
@@ -371,51 +388,6 @@
           return item
         }
       })
-    }
-
-    this.setState({
-      verify: verify
-    })
-  }
-
-  handleUpDown = (record, type, direction) => {
-    let verify = JSON.parse(JSON.stringify(this.state.verify))
-    let index = 0
-
-    if (type === 'unique') {
-      verify.uniques = verify.uniques.filter((item, i) => {
-        if (item.uuid === record.uuid) {
-          index = i
-        }
-
-        return item.uuid !== record.uuid
-      })
-      if ((index === 0 && direction === 'up') || (index === verify.uniques.length && direction === 'down')) {
-        return
-      }
-
-      if (direction === 'up') {
-        verify.uniques.splice(index - 1, 0, record)
-      } else {
-        verify.uniques.splice(index + 1, 0, record)
-      }
-    } else if (type === 'scripts') {
-      verify.scripts = verify.scripts.filter((item, i) => {
-        if (item.uuid === record.uuid) {
-          index = i
-        }
-
-        return item.uuid !== record.uuid
-      })
-      if ((index === 0 && direction === 'up') || (index === verify.scripts.length && direction === 'down')) {
-        return
-      }
-
-      if (direction === 'up') {
-        verify.scripts.splice(index - 1, 0, record)
-      } else {
-        verify.scripts.splice(index + 1, 0, record)
-      }
     }
 
     this.setState({
@@ -526,7 +498,7 @@
   }
 
   render() {
-    const { verify, scriptsColumns, uniqueColumns, activeKey, fields } = this.state
+    const { verify, scriptsColumns, uniqueColumns, activeKey, fields, modules } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -597,6 +569,16 @@
                     </Radio.Group>
                   </Form.Item>
                 </Col> : null}
+                <Col span={8}>
+                  <Form.Item label={
+                    <Tooltip placement="topLeft" title="鎵ц鎴愬姛鍚庯紙鎴栧脊绐楁爣绛惧叧闂椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滀笂绾э紙琛岋級鈥濄��">
+                      <QuestionCircleOutlined className="mk-form-tip" />
+                      鍒锋柊缁勪欢
+                    </Tooltip>
+                  }>
+                    <Cascader options={modules} value={verify.syncComponent || []} expandTrigger="hover" allowClear placeholder="" onChange={(val) => this.onOptionChange(val, 'syncComponent')}/>
+                  </Form.Item>
+                </Col>
               </Row>
             </Form>
           </TabPane>
@@ -615,6 +597,23 @@
               {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
             </span>
           } key="scripts">
+            <FullScripts
+              verify={verify}
+              getScriptsFullForm={() => this.scriptsFullForm}
+              getScriptsForm={() => this.scriptsForm}
+              handleStatus={this.handleStatus}
+              handleDelete={this.handleDelete}
+            >
+              <CustomScript
+                type="fullscreen"
+                btn={verify}
+                usefulfields={fields}
+                scripts={verify.scripts}
+                systemScripts={this.state.systemScripts}
+                scriptsChange={this.scriptsChange}
+                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
+              />
+            </FullScripts>
             <CustomScript
               btn={verify}
               usefulfields={fields}
@@ -623,20 +622,13 @@
               scriptsChange={this.scriptsChange}
               wrappedComponentRef={(inst) => this.scriptsForm = inst}
             />
-            <Table
-              bordered
-              rowKey="uuid"
-              className="custom-table"
-              dataSource={verify.scripts}
-              columns={scriptsColumns}
-              pagination={false}
-            />
+            <EditTable actions={['move']} data={verify.scripts} columns={scriptsColumns} onChange={(scripts) => {this.setState({verify: {...verify, scripts}})}}/>
           </TabPane>
           <TabPane tab="淇℃伅鎻愮ず" key="tip">
             <Form {...formItemLayout}>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> S </span>
                     <Button onClick={() => {this.showError('S')}} type="primary" size="small">
                       鏌ョ湅
@@ -644,14 +636,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> Y </span>
                     <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
                       鏌ョ湅
@@ -661,7 +653,15 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -1 </span>
+                    鎵ц鎴愬姛鏃犳彁绀恒��
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> N </span>
                     <Button onClick={() => {this.showError('N')}} type="primary" size="small">
                       鏌ョ湅
@@ -669,14 +669,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> F </span>
                     <Button onClick={() => {this.showError('F')}} type="primary" size="small">
                       鏌ョ湅
@@ -684,14 +684,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> E </span>
                     <Button onClick={() => {this.showError('E')}} type="primary" size="small">
                       鏌ョ湅
@@ -701,7 +701,7 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> NM </span>
                     <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
                       鏌ョ湅
@@ -711,9 +711,9 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
-                    <span className="errorval"> -1 </span>
-                    涓嶆彁绀�
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -2 </span>
+                    鎵ц澶辫触鏃犳彁绀�
                   </Form.Item>
                 </Col>
               </Row>
diff --git a/src/menu/components/table/edit-table/columns/tableIn/index.scss b/src/menu/components/table/edit-table/columns/tableIn/index.scss
index 39e908f..16b42cb 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/index.scss
+++ b/src/menu/components/table/edit-table/columns/tableIn/index.scss
@@ -77,4 +77,12 @@
       z-index: 1;
     }
   }
+  .full-scripts {
+    position: absolute;
+    right: 24px;
+    top: 0px;
+    font-size: 16px;
+    color: #1890ff;
+    z-index: 1;
+  }
 }
\ No newline at end of file
diff --git a/src/menu/components/table/edit-table/columns/tableIn/uniqueform/index.jsx b/src/menu/components/table/edit-table/columns/tableIn/uniqueform/index.jsx
index a83668d..fc5ff7d 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/uniqueform/index.jsx
+++ b/src/menu/components/table/edit-table/columns/tableIn/uniqueform/index.jsx
@@ -108,8 +108,10 @@
                 ]
               })(
                 <Select>
-                  <Select.Option value="physical"> 鐗╃悊楠岃瘉 </Select.Option>
-                  <Select.Option value="logic"> 閫昏緫楠岃瘉 </Select.Option>
+                  <Select.Option value="physical"> 鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級 </Select.Option>
+                  <Select.Option value="logic"> 閫昏緫楠岃瘉锛堝叏閲忛獙璇侊級 </Select.Option>
+                  <Select.Option value="physical_temp"> 鐗╃悊楠岃瘉锛堜粎涓存椂琛級 </Select.Option>
+                  <Select.Option value="logic_temp"> 閫昏緫楠岃瘉锛堜粎涓存椂琛級  </Select.Option>
                 </Select>
               )}
             </Form.Item>
diff --git a/src/menu/components/table/edit-table/index.jsx b/src/menu/components/table/edit-table/index.jsx
index ac0caff..6c0dc8d 100644
--- a/src/menu/components/table/edit-table/index.jsx
+++ b/src/menu/components/table/edit-table/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+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'
@@ -96,18 +96,9 @@
               cell.uuid = Utils.getuuid()
               return cell
             })
-          } else if (col.type === 'action' && col.elements) {
-            col.elements = col.elements.map(cell => {
-              cell.uuid = Utils.getuuid()
-              return cell
-            })
           }
           return col
         })
-        
-        if (_card.wrap.doubleClick) {
-          _card.wrap.doubleClick = oriUids[_card.wrap.doubleClick] || ''
-        }
       }
 
       this.updateComponent(_card)
@@ -145,7 +136,9 @@
 
       delete item.isNew
 
-      this.setState({card: item})
+      this.setState({card: null}, () => {
+        this.setState({card: item})
+      })
     }
   }
 
@@ -157,53 +150,19 @@
     card.name = card.wrap.name
 
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
-      card.errors = []
+      card.$c_ds = true
+      card.$c_ac = true
+      card.$c_cl = true
+      
+      card.errors = checkComponent(card)
 
-      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: '鏈缃笂绾х粍浠讹紒'})
+      if (!card.submit.sheet) {
+        card.errors.push({ level: 0, detail: '鎻愪氦鎸夐挳鏈缃紒'})
       }
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
       }
-  
-      card.action.forEach(cell => {
-        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-          if (!cell.modal || cell.modal.fields.length === 0) {
-            card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-          }
-        }
-      })
-  
-      card.cols.forEach(col => {
-        if (col.type === 'action') {
-          col.elements.forEach(cell => {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-          })
-        } else if (col.type === 'custom') {
-          col.elements.forEach(cell => {
-            if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-              card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑鍔ㄦ�佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-            }
-          })
-        } else if (col.field && !columns.includes(col.field)) {
-          card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑瀛楁鈥�${col.field}鈥濇棤鏁坄})
-        }
-      })
     }
 
     this.setState({
@@ -256,7 +215,7 @@
   addColumns = () => {
     let card = fromJS(this.state.card).toJS()
 
-    card.cols.push({ focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
+    card.cols.push({ focus: true, Width: 120, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
 
     this.setState({card})
   }
@@ -315,9 +274,9 @@
   }
 
   getWrapForms = () => {
-    const { wrap, action } = this.state.card
+    const { wrap, columns } = this.state.card
 
-    return getWrapForm(wrap, action)
+    return getWrapForm(wrap, columns)
   }
 
   updateWrap = (res) => {
@@ -385,8 +344,11 @@
 
   render() {
     const { card, appType } = this.state
+    
+    if (!card) return null
+    
     let _style = resetStyle(card.style)
-
+    
     return (
       <div className="menu-editable-table-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
         <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
@@ -415,7 +377,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/table/edit-table/options.jsx b/src/menu/components/table/edit-table/options.jsx
index 9e47b44..9fd58b0 100644
--- a/src/menu/components/table/edit-table/options.jsx
+++ b/src/menu/components/table/edit-table/options.jsx
@@ -1,7 +1,7 @@
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
  */
-export default function (wrap, action = []) {
+export default function (wrap, columns = []) {
   let roleList = sessionStorage.getItem('sysRoles')
   let appType = sessionStorage.getItem('appType')
 
@@ -47,59 +47,59 @@
       field: 'height',
       label: '楂樺害',
       initval: wrap.height || '',
-      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆�',
+      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100鏃朵负楂樺害鐨勭櫨鍒嗘瘮銆�',
       min: 10,
       max: 3000,
       precision: 0,
       required: false
     },
-    {
-      type: 'radio',
-      field: 'editable',
-      label: '鍒濆鍖�',
-      initval: wrap.editable || 'false',
-      required: false,
-      options: [
-        {value: 'true', label: '鍙紪杈�'},
-        {value: 'false', label: '涓嶅彲缂栬緫'},
-      ],
-      controlFields: [
-        {field: 'switchable', values: ['true']},
-      ]
-    },
-    {
-      type: 'radio',
-      field: 'submittal',
-      label: '鎻愪氦鍚�',
-      initval: wrap.submittal || 'false',
-      required: false,
-      options: [
-        {value: 'true', label: '鍙紪杈�'},
-        {value: 'false', label: '涓嶅彲缂栬緫'},
-      ]
-    },
-    {
-      type: 'radio',
-      field: 'addable',
-      label: '鍙柊澧�',
-      initval: wrap.addable || 'false',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ]
-    },
-    {
-      type: 'radio',
-      field: 'delable',
-      label: '鍙垹闄�',
-      initval: wrap.delable || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ]
-    },
+    // {
+    //   type: 'radio',
+    //   field: 'editable',
+    //   label: '鍒濆鍖�',
+    //   initval: wrap.editable || 'false',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鍙紪杈�'},
+    //     {value: 'false', label: '涓嶅彲缂栬緫'},
+    //   ],
+    //   controlFields: [
+    //     {field: 'switchable', values: ['true']},
+    //   ]
+    // },
+    // {
+    //   type: 'radio',
+    //   field: 'submittal',
+    //   label: '鎻愪氦鍚�',
+    //   initval: wrap.submittal || 'false',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鍙紪杈�'},
+    //     {value: 'false', label: '涓嶅彲缂栬緫'},
+    //   ]
+    // },
+    // {
+    //   type: 'radio',
+    //   field: 'addable',
+    //   label: '鍙柊澧�',
+    //   initval: wrap.addable || 'false',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄�'},
+    //     {value: 'false', label: '鍚�'},
+    //   ]
+    // },
+    // {
+    //   type: 'radio',
+    //   field: 'delable',
+    //   label: '鍙垹闄�',
+    //   initval: wrap.delable || 'false',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄�'},
+    //     {value: 'false', label: '鍚�'},
+    //   ]
+    // },
     {
       type: 'radio',
       field: 'commit',
@@ -113,18 +113,18 @@
         {value: 'simple', label: '鍗曢」'},
       ]
     },
-    {
-      type: 'radio',
-      field: 'operType',
-      label: '缂栬緫鎸夐挳',
-      initval: wrap.operType || 'btnMode',
-      tooltip: '缂栬緫鏃剁殑娣诲姞銆佸垹闄ゆ寜閽樉绀轰綅缃紝娉細浣跨敤娴爣鏃惰〃鏍兼í鍚戞粴鍔ㄥけ鏁堬紝琛ㄦ牸璁剧疆楂樺害鏃舵诞鏍囨棤鏁堛��',
-      required: false,
-      options: [
-        {value: 'btnMode', label: '鎸夐挳寮�'},
-        {value: 'buoyMode', label: '娴爣寮�'},
-      ]
-    },
+    // {
+    //   type: 'radio',
+    //   field: 'operType',
+    //   label: '缂栬緫鎸夐挳',
+    //   initval: wrap.operType || 'btnMode',
+    //   tooltip: '缂栬緫鏃剁殑娣诲姞銆佸垹闄ゆ寜閽樉绀轰綅缃紝娉細浣跨敤娴爣鏃惰〃鏍兼í鍚戞粴鍔ㄥけ鏁堬紝琛ㄦ牸璁剧疆楂樺害鏃舵诞鏍囨棤鏁堛��',
+    //   required: false,
+    //   options: [
+    //     {value: 'btnMode', label: '鎸夐挳寮�'},
+    //     {value: 'buoyMode', label: '娴爣寮�'},
+    //   ]
+    // },
     {
       type: 'radio',
       field: 'editType',
@@ -274,25 +274,47 @@
       type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
-      initval: wrap.permission || 'false',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
     },
+    // {
+    //   type: 'radio',
+    //   field: 'switchable',
+    //   label: '鐘舵�佸垏鎹�',
+    //   initval: wrap.switchable || 'true',
+    //   tooltip: '鏄惁鍙互鍦ㄧ紪杈戝拰榛樿table鐘舵�侀棿鍒囨崲銆�',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鍚敤'},
+    //     {value: 'false', label: '绂佺敤'},
+    //   ]
+    // },
     {
       type: 'radio',
-      field: 'switchable',
-      label: '鐘舵�佸垏鎹�',
-      initval: wrap.switchable || 'true',
-      tooltip: '鏄惁鍙互鍦ㄧ紪杈戝拰榛樿table鐘舵�侀棿鍒囨崲銆�',
+      field: 'empty',
+      label: '绌哄�奸殣钘�',
+      initval: wrap.empty || 'show',
+      tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
-        {value: 'false', label: '绂佺敤'},
-      ]
+        {value: 'show', label: '鍚�'},
+        {value: 'hidden', label: '鏄�'},
+      ],
+    },
+    {
+      type: 'select',
+      field: 'tipField',
+      label: '淇℃伅鎻愮ず',
+      initval: wrap.tipField || '',
+      tooltip: '榧犳爣鎮诞浜庤涓婃柟鏃剁殑鎻愮ず淇℃伅銆�',
+      required: false,
+      allowClear: true,
+      options: columns
     },
     {
       type: 'multiselect',
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 f1ff2b1..e4c73d2 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -65,13 +65,6 @@
     text: '搴忓彿'
   }]
 
-  if (!card.isSub) {
-    options.push({
-      value: 'action',
-      text: '鎿嶄綔'
-    })
-  }
-
   if (!card.linkurl && (!card.linkmenu || card.linkmenu.length === 0)) {
     card.perspective = ''
   }
@@ -159,6 +152,18 @@
         value: 'false',
         text: '鍚�'
       }]
+    },
+    {
+      type: 'radio',
+      key: 'eval',
+      label: '瑙f瀽',
+      initVal: card.eval || 'false',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      required: false,
+      options: [
+        { value: 'true', text: '鏄�' },
+        { value: 'false', text: '鍚�' }
+      ]
     },
     {
       type: 'radio',
@@ -409,18 +414,6 @@
       options: [
         { value: 'blank', text: '鏂扮獥鍙�' },
         { value: 'self', text: '褰撳墠绐楀彛' }
-      ]
-    },
-    {
-      type: 'radio',
-      key: 'eval',
-      label: '瑙f瀽',
-      initVal: card.eval || 'true',
-      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
-      required: false,
-      options: [
-        { value: 'true', text: '鏄�' },
-        { value: 'false', text: '鍚�' }
       ]
     },
     {
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 19aa359..df3913f 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/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, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal } from 'antd'
+import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal, Checkbox, Popover } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import { getColumnForm } from './formconfig'
@@ -17,7 +17,7 @@
   picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span'],
   video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'blacklist', 'aspectRatio'],
   colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
-  custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'],
+  custom: ['label', 'type', 'Align', 'Width', 'blacklist'],
   action: ['label', 'type', 'Align', 'Width'],
   formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
   index: ['label', 'type', 'Align', 'Width']
@@ -25,7 +25,6 @@
 
 class NormalTableColumn extends Component {
   static propTpyes = {
-    visible: PropTypes.bool,
     column: PropTypes.object,
     fields: PropTypes.array,
     submitCol: PropTypes.func,  // 鎻愪氦浜嬩欢
@@ -36,6 +35,8 @@
     visible: false,
     formlist: null
   }
+
+  record = null
 
   UNSAFE_componentWillReceiveProps (nextProps) {
     if (nextProps.column && !is(fromJS(this.props.column), fromJS(nextProps.column))) {
@@ -50,20 +51,23 @@
     })
     
     let formlist = getColumnForm(column, fields)
-    let _options = fromJS(columnTypeOptions[column.type]).toJS()
-    if (column.type === 'text' || column.type === 'number') {
-      if (column.perspective === 'linkmenu') {
-        _options.push('linkmenu', 'linkfields', 'open')
-      } else if (column.perspective === 'linkurl') {
-        _options.push('linkurl', 'linkfields', 'open')
-      }
-    }
+    this.record = {}
+
+    formlist.forEach(item => {
+      this.record[item.key] = item.initVal
+    })
+    
+    let _options = this.getOptions()
 
     this.setState({
       visible: true,
-      type: column.type,
       formlist: formlist.map(item => {
         item.hidden = !_options.includes(item.key)
+
+        if (item.key === 'formula') {
+          item.fields = this.props.fields.map(col => col.field)
+          item.fields = item.fields.join(', ')
+        }
 
         return item
       })
@@ -80,13 +84,42 @@
     }
   }
 
+  getOptions = () => {
+    let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
+
+    if (this.record.type === 'text' || this.record.type === 'number') {
+      if (this.record.perspective === 'linkmenu') {
+        _options.push('linkmenu', 'linkfields', 'open')
+      } else if (this.record.perspective === 'linkurl') {
+        _options.push('linkurl', 'linkfields', 'open')
+      }
+    }
+    
+    if (this.record.type === 'formula' && this.record.eval === 'true') {
+      _options.push('decimal')
+    }
+
+    return _options
+  }
+
   typeChange = (key, value, option) => {
+    this.record[key] = value
+
     if (key === 'type') {
-      let _options = fromJS(columnTypeOptions[value]).toJS()
+      let _options = this.getOptions()
+
+      let _field = ''
+      if (value === 'formula') {
+        _field = this.props.form.getFieldValue('field') || ''
+      }
 
       this.setState({
-        type: value,
         formlist: this.state.formlist.map(item => {
+          if (item.key === 'decimal' && value === 'formula') {
+            this.record.decimal = ''
+          }
+
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
 
           return item
@@ -96,8 +129,12 @@
           this.props.form.setFieldsValue({IsSort: 'false'})
         } else if (value === 'text' || value === 'number') {
           this.props.form.setFieldsValue({perspective: ''})
-        } else if (value === 'action' || value === 'colspan') {
+        } else if (value === 'colspan') {
           this.props.form.setFieldsValue({Align: 'center'})
+        } else if (value === 'formula' && _field) {
+          this.props.form.setFieldsValue({formula: '@' + _field + '@'})
+        } else if (value === 'index') {
+          this.props.form.setFieldsValue({label: '搴忓彿'})
         }
       })
     } else if (key === 'field') {
@@ -113,13 +150,18 @@
         values.type = 'text'
       }
 
-      if (values.type !== this.state.type) {
+      let _type = this.record.type
+      this.record.type = values.type
+
+      if (values.type !== _type) {
         values.perspective = ''
-        let _options = fromJS(columnTypeOptions[values.type]).toJS()
+        this.record.perspective = ''
+
+        let _options = this.getOptions()
 
         this.setState({
-          type: values.type,
           formlist: this.state.formlist.map(item => {
+            item.initVal = this.record[item.key]
             item.hidden = !_options.includes(item.key)
 
             return item
@@ -132,21 +174,12 @@
       }
     } else if (key === 'format' && value === 'percent') {
       this.props.form.setFieldsValue({postfix: '%'})
-    }
-  }
-
-  changeRadio = (key, value) => {
-    if (key === 'perspective') {
-      let _options = fromJS(columnTypeOptions[this.state.type]).toJS()
-
-      if (value === 'linkmenu') {
-        _options.push('linkmenu', 'linkfields', 'open')
-      } else if (value === 'linkurl') {
-        _options.push('linkurl', 'linkfields', 'open')
-      }
+    } else if (['perspective', 'eval'].includes(key)) {
+      let _options = this.getOptions()
 
       this.setState({
         formlist: this.state.formlist.map(item => {
+          item.initVal = this.record[item.key]
           item.hidden = !_options.includes(item.key)
 
           return item
@@ -263,15 +296,30 @@
                   }
                 ]
               })(
-                <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}>
-                  {
-                    item.options.map(option => {
-                      return (
-                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
-                      )
-                    })
-                  }
+                <Radio.Group onChange={(e) => {this.typeChange(item.key, e.target.value)}}>
+                  {item.options.map(option => {
+                    return (<Radio key={option.value} value={option.value}>{option.text}</Radio>)
+                  })}
                 </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'checkbox') {
+        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
+              })(
+                <Checkbox.Group>
+                  {item.options.map(option => <Checkbox key={option.value} value={option.value}>{option.text}</Checkbox>)}
+                </Checkbox.Group>
               )}
             </Form.Item>
           </Col>
@@ -319,35 +367,75 @@
           </Col>
         )
       } else if (item.type === 'textarea') {
-        fields.push(
-          <Col span={24} key={index} className="textarea">
-            <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 + '!'
-                  }
-                ]
-              })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''}/>)}
-            </Form.Item>
-          </Col>
-        )
+        if (item.key === 'formula') {
+          fields.push(
+            <Col span={24} className="textarea" 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 + '!'
+                    }
+                  ]
+                })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
+              </Form.Item>
+              <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click">
+                <span className="formula-icon">瀛楁闆�</span>
+              </Popover>
+            </Col>
+          )
+        } else {
+          fields.push(
+            <Col span={24} key={index} className="textarea">
+              <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 + '!'
+                    }
+                  ]
+                })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''}/>)}
+              </Form.Item>
+            </Col>
+          )
+        }
       }
     })
     return fields
   }
 
   handleSubmit = () => {
+    const { fields } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     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)) {
+          let cols = []
+          fields.forEach(col => {
+            if (/^(Int|Decimal)/ig.test(col.datatype)) {
+              cols.push({reg: new RegExp('@' + col.field + '@', 'ig'), value: `(@${col.field}@)`})
+            }
+          })
+
+          cols.forEach(col => {
+            values.formula = values.formula.replace(col.reg, col.value)
+          })
+        }
         this.setState({visible: false, formlist: null})
         this.props.submitCol(values)
       }
diff --git a/src/menu/components/table/normal-table/columns/editColumn/index.scss b/src/menu/components/table/normal-table/columns/editColumn/index.scss
index 9885df8..e653f84 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/index.scss
+++ b/src/menu/components/table/normal-table/columns/editColumn/index.scss
@@ -14,4 +14,27 @@
       width: 88%;
     }
   }
+  .formula-icon {
+    position: absolute;
+    bottom: 5px;
+    right: 15px;
+    cursor: pointer;
+    font-size: 12px;
+    color: #1890ff;
+  }
+  >.ant-row >.ant-col {
+    display: inline-block;
+    vertical-align: top;
+    float: none;
+  }
+}
+.formula-fields {
+  z-index: 1200!important;
+
+  .ant-popover-inner-content {
+    div {
+      max-width: 750px;
+      word-break: break-all;
+    }
+  }
 }
diff --git a/src/menu/components/table/normal-table/columns/index.jsx b/src/menu/components/table/normal-table/columns/index.jsx
index 917976c..1713c3c 100644
--- a/src/menu/components/table/normal-table/columns/index.jsx
+++ b/src/menu/components/table/normal-table/columns/index.jsx
@@ -3,7 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider, DragSource, DropTarget } from 'react-dnd'
 import { Table, Popover, Modal, message, Typography } from 'antd'
-import { PlusOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
+import { PlusOutlined, PlusSquareOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -47,65 +47,45 @@
 
     return !is(fromJS(this.props.column), fromJS(nextProps.column)) ||
       !is(fromJS(this.props.fields), fromJS(nextProps.fields)) ||
-      this.props.index !== nextProps.index
+      this.props.index !== nextProps.index ||
+      window.GLOB.columnId === nextProps.column.uuid || window.GLOB.precolumnId === nextProps.column.uuid
   }
 
   render() {
-    const { connectDragSource, connectDropTarget, moveCol, dropCol, addElement, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
+    const { connectDragSource, connectDropTarget, moveCol, componentId, dropCol, addElement, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
 
-    if (index !== undefined) {
-      let style = {cursor: 'move', textAlign: align}
-      if (column.Width) {
-        style.width = column.Width
-        style.minWidth = column.Width
-      }
+    if (!column) return (
+      <th {...restProps}>{children}</th>
+    )
 
-      return connectDragSource(
-        connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => column && this.props.editColumn(column)}>
-          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
-              {column && ['custom', 'colspan', 'action'].includes(column.type) ?
-                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
-              }
-              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
-              {column && column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              {column && column.type === 'action' ? <PasteComponent options={['action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              {column && (column.type === 'custom' || column.type === 'action') ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
-              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
-            </div>
-          } trigger="hover">
-            {children}
-          </Popover>
-        </th>),
-      )
-    } else if (column) {
-      let style = {textAlign: align}
-      if (column.Width) {
-        style.width = column.Width
-        style.minWidth = column.Width
-      }
-
-      return (
-        <th {...restProps} style={style} key={column.uuid} onDoubleClick={() => this.props.editColumn(column)}>
-          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
-              {column && ['custom', 'colspan'].includes(column.type) ?
-                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
-              }
-              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
-              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
-              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
-            </div>
-          } trigger="hover">
-            {children}
-          </Popover>
-        </th>
-      )
-    } else {
-      return (<th {...restProps}>{children}</th>)
+    let style = {cursor: 'move', textAlign: align}
+    if (column.Width) {
+      style.width = column.Width
+      style.minWidth = column.Width
     }
+
+    if (window.GLOB.columnId === column.uuid) {
+      style.color = '#1890ff'
+    }
+
+    return connectDragSource(
+      connectDropTarget(<th {...restProps} index={index} style={style} onDoubleClick={() => this.props.editColumn(column)}>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
+            {column.type === 'colspan' ? <PlusOutlined className="plus" title="娣诲姞鍒�" onClick={() => this.props.addElement(column)} /> : null}
+            {column.type === 'custom' ? <PlusOutlined className="plus" title="娣诲姞鍏冪礌" onClick={() => this.props.addElement(column)} /> : null}
+            {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={() => this.props.addElement(column, 'button')} /> : null}
+            <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
+            {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
+            {column.type === 'custom' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
+            <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
+            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
+          </div>
+        } trigger="hover">
+          {children}
+        </Popover>
+      </th>),
+    )
   }
 }
 
@@ -120,17 +100,28 @@
 const ColTarget = {
   drop(props, monitor) {
     const item = monitor.getItem()
-    const dragIndex = item.index
-    const hoverIndex = props.index
+    let dragIndex = item.index
+    let hoverIndex = props.index
 
     if (item.$init) {
-      props.dropCol(item, hoverIndex)
+      if (/sub_/.test(hoverIndex)) {
+        message.warning('鍚堝苟鍒楀瓙鍏冪礌鏆備笉鏀寔鎷栨嫿娣诲姞銆�')
+      } else {
+        props.dropCol(item, hoverIndex.replace(new RegExp(props.componentId + '@', 'ig'), ''))
+      }
       return
     } else if (dragIndex === undefined || hoverIndex === undefined || dragIndex === hoverIndex) {
       return
+    } else {
+      let reg = new RegExp(props.componentId + '@', 'ig')
+      if (reg.test(dragIndex)) {
+        props.moveCol(dragIndex.replace(reg, ''), hoverIndex.replace(reg, ''))
+      } else {
+        message.warning('鎷栧姩鍏冪礌涓嶅湪褰撳墠缁勪欢涓��')
+        return
+      }
     }
 
-    props.moveCol(dragIndex, hoverIndex)
     monitor.getItem().index = hoverIndex
   },
 }
@@ -165,12 +156,6 @@
     if (column && column.type === 'custom') {
       return (
         <td style={{padding: 0, ...(column.style || {})}} className={className}>
-          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
-        </td>
-      )
-    } else if (column && column.type === 'action') {
-      return (
-        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
           <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
         </td>
       )
@@ -276,12 +261,32 @@
   moveCol = (dragIndex, hoverIndex) => {
     let _columns = fromJS(this.state.columns).toJS()
 
-    _columns.splice(hoverIndex, 0, ..._columns.splice(dragIndex, 1))
+    if (/^sub_/.test(dragIndex) || /^sub_/.test(hoverIndex)) {
+      let sign1 = dragIndex.split('_')
+      let sign2 = hoverIndex.split('_')
+      if (sign1[1] !== sign2[1]) {
+        message.warning('鎷栧姩鍏冪礌涓嶅湪鍚屼竴涓悎骞跺垪涓��')
+        return
+      }
+      this.loopMoveCol(_columns, sign1[1], sign1[2], sign2[2])
+    } else {
+      _columns.splice(hoverIndex, 0, ..._columns.splice(dragIndex, 1))
+    }
 
     this.setState({
       columns: _columns
     }, () => {
       this.props.updatecolumn({...this.props.config, cols: _columns})
+    })
+  }
+
+  loopMoveCol = (columns, colId, dragIndex, hoverIndex) => {
+    columns.forEach(column => {
+      if (column.type === 'colspan' && column.uuid === colId) {
+        column.subcols.splice(hoverIndex, 0, ...column.subcols.splice(dragIndex, 1))
+      } else if (column.type === 'colspan') {
+        this.loopMoveCol(column.subcols, colId, dragIndex, hoverIndex)
+      }
     })
   }
 
@@ -291,8 +296,6 @@
     let col = { focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: item.subType, elements: [] }
     if (col.type === 'colspan') {
       col.subcols = []
-    } else if (col.type === 'action') {
-      col.label = '鎿嶄綔'
     } else if (col.type === 'index') {
       col.label = '搴忓彿'
     }
@@ -330,7 +333,7 @@
         config.action = config.action.filter(item => item.uuid !== btn.uuid)
 
         setTimeout(() => {
-          MKEmitter.emit('revert', config.uuid)
+          MKEmitter.emit('revertBtn', config.uuid)
         }, 200)
       }
 
@@ -347,14 +350,24 @@
   pasteCell = (col, cell, resolve) => {
     resolve({status: true})
     
-    delete cell.copyType
     cell.uuid = Utils.getuuid()
     cell.focus = true
+
+    if (!cell.eleType) {
+      if (cell.copyType === 'action') {
+        cell.eleType = 'button'
+        cell.width = cell.width || 12
+      } else {
+        cell.eleType = 'text'
+      }
+    }
+
+    delete cell.copyType
     
     MKEmitter.emit('cardAddElement', col.uuid, cell)
   }
 
-  addElement = (col) => {
+  addElement = (col, type) => {
     let column = fromJS(col).toJS()
 
     if (column.type === 'colspan') {
@@ -367,26 +380,28 @@
       })
       this.updateCol(column)
     } else if (column.type === 'custom') {
-      let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
+      if (type === 'button') {
+        let newcard = {
+          uuid: Utils.getuuid(),
+          focus: true,
+          eleType: 'button',
+          label: 'button',
+          OpenType: 'prompt',
+          class: 'primary',
+          intertype: 'system',
+          execSuccess: 'grid',
+          execError: 'never',
+          show: 'link'
+        }
   
-      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
-      MKEmitter.emit('cardAddElement', column.uuid, newcard)
-    } else if (column.type === 'action') {
-      let newcard = {
-        uuid: Utils.getuuid(),
-        focus: true,
-        eleType: 'button',
-        label: 'button',
-        OpenType: 'prompt',
-        class: 'primary',
-        intertype: 'system',
-        execSuccess: 'grid',
-        execError: 'never',
-        show: 'link'
+        // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+        MKEmitter.emit('cardAddElement', column.uuid, newcard)
+      } else {
+        let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
+    
+        // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+        MKEmitter.emit('cardAddElement', column.uuid, newcard)
       }
-
-      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
-      MKEmitter.emit('cardAddElement', column.uuid, newcard)
     }
   }
 
@@ -402,10 +417,10 @@
     } else if (col.type === 'custom') {
       col.style = card.style || {}
       col.elements = card.type === 'custom' ? (card.elements || []) : []
-    } else if (col.type === 'action') {
-      col.style = card.style || {}
-      col.elements = card.type === 'action' ? (card.elements || []) : []
     }
+
+    window.GLOB.precolumnId = window.GLOB.columnId || ''
+    window.GLOB.columnId = col.uuid
 
     this.setState({card: null})
     this.updateCol(col)
@@ -495,7 +510,7 @@
     document.body.removeChild(oInput)
   }
 
-  handlecolumns = (columns, fields, config, isSub) => {
+  handlecolumns = (columns, fields, config, pId) => {
     return columns.map((col, index) => {
       return {
         title: col.label,
@@ -509,8 +524,9 @@
           upComponent: this.updateCol
         }),
         onHeaderCell: () => ({
-          index: isSub ? undefined : index,
+          index: pId ? config.uuid + '@sub_' + pId + '_' + index : config.uuid + '@' + index,
           column: col,
+          componentId: config.uuid,
           fields: fields,
           align: col.Align,
           moveCol: this.moveCol,
@@ -522,7 +538,7 @@
           changeStyle: this.changeStyle,
           deleteCol: this.deleteCol,
         }),
-        children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, true) : null,
+        children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, col.uuid) : null,
       }
     })
   }
diff --git a/src/menu/components/table/normal-table/columns/index.scss b/src/menu/components/table/normal-table/columns/index.scss
index 5de869d..af1deb4 100644
--- a/src/menu/components/table/normal-table/columns/index.scss
+++ b/src/menu/components/table/normal-table/columns/index.scss
@@ -62,11 +62,6 @@
         }
       }
     }
-    .action-column {
-      .card-detail-row:empty {
-        min-height: 40px;
-      }
-    }
     tr:hover td {
       background: #ffffff!important;
     }
@@ -119,8 +114,11 @@
   .ant-table-small > .ant-table-content > .ant-table-body {
     margin: 0;
   }
+  .ant-table-small.ant-table-bordered {
+    border-right: 1px solid #e8e8e8;
+  }
 
-  table, tr, th, td {
+  table, tr, th, td, .ant-table-small {
     border-color: var(--mk-table-border-color)!important;
   }
   table tr {
@@ -137,6 +135,11 @@
     color: var(--mk-table-color);
   }
 }
+.normal-table-columns:not(.ghost) {
+  .ant-table-small > .ant-table-content .ant-table-thead > tr > th {
+    background-color: #fafafa!important;
+  }
+}
 .normal-table-columns.false {
   .ant-pagination {
     display: none;
diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx
index 873c345..2934bd9 100644
--- a/src/menu/components/table/normal-table/index.jsx
+++ b/src/menu/components/table/normal-table/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+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'
@@ -106,11 +106,6 @@
               cell.uuid = Utils.getuuid()
               return cell
             })
-          } else if (col.type === 'action' && col.elements) {
-            col.elements = col.elements.map(cell => {
-              cell.uuid = Utils.getuuid()
-              return cell
-            })
           }
           return col
         })
@@ -166,7 +161,9 @@
 
       delete item.isNew
 
-      this.setState({card: item}, () => { MKEmitter.emit('revert') })
+      this.setState({card: null}, () => {
+        this.setState({card: item})
+      })
     }
   }
 
@@ -195,64 +192,14 @@
     card.name = card.wrap.name
 
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
-      card.errors = []
-
-      let doubleClick = card.wrap.doubleClick || ''
-  
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      card.$c_ds = true
+      card.$c_ac = true
+      card.$c_cl = true
+      
+      card.errors = checkComponent(card)
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
-      }
-
-      card.action.forEach(cell => {
-        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-          if (!cell.modal || cell.modal.fields.length === 0) {
-            card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-          }
-        }
-        if (doubleClick === cell.uuid) {
-          doubleClick = ''
-        }
-      })
-  
-      card.cols.forEach(col => {
-        if (col.type === 'action') {
-          col.elements.forEach(cell => {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-            if (doubleClick === cell.uuid) {
-              doubleClick = ''
-            }
-          })
-        } else if (col.type === 'custom') {
-          col.elements.forEach(cell => {
-            if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-              card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑鍔ㄦ�佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-            }
-          })
-        } else if (col.field && !columns.includes(col.field)) {
-          card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑瀛楁鈥�${col.field}鈥濇棤鏁坄})
-        }
-      })
-      
-      if (doubleClick) {
-        card.errors.push({ level: 1, detail: `缁戝畾鐨勫弻鍑绘寜閽凡鍒犻櫎`})
       }
     }
 
@@ -372,8 +319,13 @@
     let _actions = [...action]
 
     cols.forEach(col => {
-      if (col.type !== 'action') return
-      _actions.push(...col.elements)
+      if (col.type === 'custom') {
+        col.elements.forEach(cell => {
+          if (cell.eleType !== 'button') return
+
+          _actions.push(cell)
+        })
+      }
     })
 
     return getWrapForm(wrap, _actions, columns)
@@ -438,6 +390,9 @@
 
   render() {
     const { card, appType } = this.state
+    
+    if (!card) return null
+
     let options = ['action', 'search', 'form', 'cols']
     let _style = resetStyle(card.style)
     
@@ -474,7 +429,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/table/normal-table/options.jsx b/src/menu/components/table/normal-table/options.jsx
index b876e95..688c674 100644
--- a/src/menu/components/table/normal-table/options.jsx
+++ b/src/menu/components/table/normal-table/options.jsx
@@ -47,7 +47,7 @@
       field: 'height',
       label: '楂樺害',
       initval: wrap.height || '',
-      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆�',
+      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100鏃朵负楂樺害鐨勭櫨鍒嗘瘮銆�',
       min: 10,
       max: 3000,
       precision: 0,
@@ -79,6 +79,30 @@
         {value: 'true', label: '鏈�'},
         {value: 'false', label: '鏃�'},
       ]
+    },
+    {
+      type: 'radio',
+      field: 'actionfixed',
+      label: '鍥哄畾鎸夐挳',
+      initval: wrap.actionfixed !== 'true' ? 'false' : 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '鏄�'},
+        {value: 'false', label: '鍚�'},
+      ],
+      forbid: appType === 'mob' || appType === 'pc'
+    },
+    {
+      type: 'checkbox',
+      field: 'colfixed',
+      label: '鍥哄畾鍒�',
+      initval: wrap.colfixed || [],
+      required: false,
+      options: [
+        {value: 'first', label: '棣栧垪'},
+        {value: 'last', label: '灏惧垪'},
+      ],
+      forbid: appType === 'mob' || appType === 'pc'
     },
     {
       type: 'radio',
@@ -142,31 +166,6 @@
         {value: 'sign', label: '閫変腑鏍囪'}
       ],
     },
-    // {
-    //   type: 'radio',
-    //   field: 'selected',
-    //   label: '棣栬閫変腑',
-    //   initval: wrap.selected || 'false',
-    //   tooltip: '褰撴寜閽墽琛屽畬鎴愬苟杩斿洖涓婚敭鍊兼椂锛岄粯璁ら�変腑涓婚敭鍊煎搴旇銆�',
-    //   required: false,
-    //   options: [
-    //     {value: 'false', label: '鏃�'},
-    //     {value: 'init', label: '鍒濆鍖�'},
-    //     {value: 'always', label: '鏁版嵁鍔犺浇'},
-    //   ]
-    // },
-    // {
-    //   type: 'radio',
-    //   field: 'show',
-    //   label: '鎼滅储鎸夐挳',
-    //   initval: wrap.show || 'true',
-    //   tooltip: '鎼滅储鏉′欢瀛樺湪鏃讹紝鍙�夋嫨鏄惁鏄剧ず鎼滅储鎸夐挳銆�',
-    //   required: false,
-    //   options: [
-    //     {value: 'true', label: '鏄剧ず'},
-    //     {value: 'false', label: '闅愯棌'},
-    //   ]
-    // },
     {
       type: 'color',
       field: 'borderColor',
@@ -188,36 +187,6 @@
         {value: 'bottom', label: '鍚戜笅'},
       ]
     },
-    // {
-    //   type: 'color',
-    //   field: 'color',
-    //   label: '瀛椾綋棰滆壊',
-    //   initval: wrap.color || 'rgba(0, 0, 0, 0.65)',
-    //   tooltip: '榛樿鍊� rgba(0, 0, 0, 0.65)銆�',
-    //   required: false
-    // },
-    // {
-    //   type: 'number',
-    //   field: 'fontSize',
-    //   label: '瀛椾綋澶у皬',
-    //   initval: wrap.fontSize || 14,
-    //   min: 12,
-    //   max: 30,
-    //   precision: 0,
-    //   required: false
-    // },
-    // {
-    //   type: 'number',
-    //   field: 'advanceWidth',
-    //   label: '楂樼骇鎼滅储',
-    //   initval: wrap.advanceWidth || 1000,
-    //   tooltip: '楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��',
-    //   min: 10,
-    //   max: 3000,
-    //   precision: 0,
-    //   required: false,
-    //   forbid: appType === 'mob'
-    // },
     {
       type: 'number',
       field: 'btnlimit',
@@ -240,6 +209,16 @@
       allowClear: true,
       options: action.map(item => ({value: item.uuid, label: item.label})),
       forbid: appType === 'mob'
+    },
+    {
+      type: 'select',
+      field: 'tipField',
+      label: '淇℃伅鎻愮ず',
+      initval: wrap.tipField || '',
+      tooltip: '榧犳爣鎮诞浜庤涓婃柟鏃剁殑鎻愮ず淇℃伅銆�',
+      required: false,
+      allowClear: true,
+      options: columns
     },
     {
       type: 'select',
@@ -290,13 +269,13 @@
       type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
-      initval: wrap.permission || 'false',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
     },
     {
       type: 'multiselect',
diff --git a/src/menu/components/tabs/paste/index.jsx b/src/menu/components/tabs/paste/index.jsx
index 346f029..9391b7c 100644
--- a/src/menu/components/tabs/paste/index.jsx
+++ b/src/menu/components/tabs/paste/index.jsx
@@ -19,7 +19,7 @@
     visible: false
   }
 
-  resetconfig = (item) => {
+  resetconfig = (item, appType) => {
     if (item.type === 'tabs') {
       item.uuid = MenuUtils.getuuid()
       item.setting.name = item.setting.name + MenuUtils.getSignName()
@@ -29,7 +29,7 @@
         tab.uuid = MenuUtils.getuuid()
 
         tab.components = tab.components.map(cell => {
-          cell = this.resetconfig(cell)
+          cell = this.resetconfig(cell, appType)
           return cell
         })
       })
@@ -39,12 +39,12 @@
       item.name = item.setting.name
 
       item.components = item.components.map(cell => {
-        cell = MenuUtils.resetComponentConfig(cell)
+        cell = MenuUtils.resetComponentConfig(cell, appType)
 
         return cell
       })
     } else {
-      item = MenuUtils.resetComponentConfig(item)
+      item = MenuUtils.resetComponentConfig(item, appType)
     }
 
     return item
@@ -53,7 +53,7 @@
   pasteSubmit = () => {
     const { Tab } = this.props
     let appType = sessionStorage.getItem('appType')
-    let options = ['tabs', 'group', 'datacard', 'propcard', 'timeline', 'balcony', 'normaltable', 'mainsearch', 'simpleform', 'stepform', 'tabform', 'tablecard', 'line', 'bar', 'pie', 'scatter', 'sandbox']
+    let options = ['tabs', 'group', 'datacard', 'propcard', 'timeline', 'balcony', 'normaltable', 'mainsearch', 'simpleform', 'stepform', 'tabform', 'editor', 'tablecard', 'line', 'bar', 'pie', 'scatter', 'sandbox']
     let types = {
       login: '鐧诲綍',
       navbar: '瀵艰埅鏍�',
@@ -83,7 +83,7 @@
         return
       }
 
-      res = this.resetconfig(res)
+      res = this.resetconfig(res, appType)
 
       delete res.copyType
       
diff --git a/src/menu/components/timeline/normal-timeline/index.jsx b/src/menu/components/timeline/normal-timeline/index.jsx
index 79df605..cb58209 100644
--- a/src/menu/components/timeline/normal-timeline/index.jsx
+++ b/src/menu/components/timeline/normal-timeline/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -109,39 +109,14 @@
     card.width = card.wrap.width
     card.name = card.wrap.name
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
-      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: '鏈缃笂绾х粍浠讹紒'})
-      }
+      card.$c_ds = true
+      card.$c_sc = true
+      
+      card.errors = checkComponent(card)
 
       if (card.errors.length === 0) {
         card.$tables = getTables(card)
       }
-
-      card.subcards.forEach(col => {
-        col.elements.forEach(cell => {
-          if (cell.eleType === 'button') {
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            }
-          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
-            card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
-          }
-        })
-      })
     }
     
     this.setState({
@@ -219,7 +194,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/components/timeline/normal-timeline/options.jsx b/src/menu/components/timeline/normal-timeline/options.jsx
index 8d0ddb9..f9537e1 100644
--- a/src/menu/components/timeline/normal-timeline/options.jsx
+++ b/src/menu/components/timeline/normal-timeline/options.jsx
@@ -56,6 +56,8 @@
         {field: 'mode', values: ['vertical']},
         {field: 'hmode', values: ['horizontal']},
         {field: 'label', values: ['vertical']},
+        {field: 'iconSize', values: ['horizontal']},
+        {field: 'dotSign', values: ['horizontal']},
       ]
     },
     {
@@ -112,6 +114,35 @@
       ]
     },
     {
+      type: 'radio',
+      field: 'dotSign',
+      label: '鑺傜偣娓叉煋',
+      initval: wrap.dotSign || 'background',
+      tooltip: '鑺傜偣鐨勬覆鏌撴柟寮忥紝鍦ㄨ妭鐐圭粍涓缃殑棰滆壊娓叉煋鍥炬爣杩樻槸娓叉煋鑳屾櫙鑹层��',
+      required: false,
+      options: [
+        {value: 'background', label: '鑳屾櫙鑹�'},
+        {value: 'icon', label: '鍥炬爣'},
+      ]
+    },
+    {
+      type: 'select',
+      field: 'iconSize',
+      label: '鍥炬爣澶у皬',
+      initval: wrap.iconSize || '',
+      tooltip: '鍥炬爣鍙湪鑺傜偣缁勪腑娣诲姞銆�',
+      required: false,
+      options: [
+        {value: '', label: '榛樿(14px)'},
+        {value: 'size16', label: '16px'},
+        {value: 'size18', label: '18px'},
+        {value: 'size20', label: '20px'},
+        {value: 'size22', label: '22px'},
+        {value: 'size24', label: '24px'},
+        {value: 'adaptive', label: '鑷�傚簲'},
+      ]
+    },
+    {
       type: 'select',
       field: 'label',
       label: '鏍囩',
@@ -134,13 +165,26 @@
       type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
-      initval: wrap.permission || 'false',
+      initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !appType || sessionStorage.getItem('editMenuType') === 'popview'
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
+      type: 'radio',
+      field: 'empty',
+      label: '绌哄�奸殣钘�',
+      initval: wrap.empty || 'show',
+      tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
+      required: false,
+      skip: true,
+      options: [
+        {value: 'show', label: '鍚�'},
+        {value: 'hidden', label: '鏄�'},
+      ],
     },
     {
       type: 'multiselect',
diff --git a/src/menu/components/tree/antd-tree/index.jsx b/src/menu/components/tree/antd-tree/index.jsx
index 8e91c46..c7afa92 100644
--- a/src/menu/components/tree/antd-tree/index.jsx
+++ b/src/menu/components/tree/antd-tree/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -101,21 +101,9 @@
     card.width = card.wrap.width
     card.name = card.wrap.name
 
-    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: '鏈缃笂绾х粍浠讹紒'})
-    }
+    card.$c_ds = true
+      
+    card.errors = checkComponent(card)
 
     if (card.errors.length === 0) {
       card.$tables = getTables(card)
@@ -123,6 +111,15 @@
 
     if (!card.wrap.parentField || !card.wrap.valueField || !card.wrap.labelField) {
       card.errors.push({ level: 0, detail: '鏈缃熀鏈俊鎭紒'})
+    } else {
+      let columns = card.columns.map(c => c.field)
+      if (!columns.includes(card.wrap.parentField)) {
+        card.errors.push({ level: 0, detail: '涓婄骇瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'})
+      } else if (!columns.includes(card.wrap.valueField)) {
+        card.errors.push({ level: 0, detail: '鍊煎瓧娈靛湪瀛楁闆嗕腑涓嶅瓨鍦�'})
+      } else if (!columns.includes(card.wrap.labelField)) {
+        card.errors.push({ level: 0, detail: '鏂囨湰瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'})
+      }
     }
 
     this.setState({
@@ -259,7 +256,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/menu/datasource/index.jsx b/src/menu/datasource/index.jsx
index c40ff35..27d9a81 100644
--- a/src/menu/datasource/index.jsx
+++ b/src/menu/datasource/index.jsx
@@ -162,6 +162,8 @@
           }
           return item
         })
+
+        res.columns.reverse()
       }
 
       let maxScript = 0
@@ -200,6 +202,14 @@
 
       if (config.subtype !== 'dualdatacard') {
         delete res.subColumns
+      } else {
+        res.subColumns.reverse()
+      }
+
+      if (this.verifyRef.state.debugId) {
+        res.setting.debugId = this.verifyRef.state.debugId
+      } else {
+        delete res.setting.debugId
       }
 
       this.setState({loading: false, visible: false})
diff --git a/src/menu/datasource/verifycard/customscript/index.jsx b/src/menu/datasource/verifycard/customscript/index.jsx
index 85de3e6..bca6509 100644
--- a/src/menu/datasource/verifycard/customscript/index.jsx
+++ b/src/menu/datasource/verifycard/customscript/index.jsx
@@ -140,6 +140,13 @@
             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')
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index dcb2c3d..ddd14c0 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -1,9 +1,10 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message, Button } from 'antd'
+import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message, Button, Input } from 'antd'
 import { StopOutlined, CheckCircleOutlined, EditOutlined, SwapOutlined, DeleteOutlined, CopyOutlined, BorderOutlined, SnippetsOutlined } from '@ant-design/icons'
 import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -20,6 +21,7 @@
 
 const { TabPane } = Tabs
 const { Paragraph } = Typography
+const { Search } = Input
 
 const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
@@ -32,9 +34,11 @@
 
   state = {
     columns: [],
+    debugId: '',
     subColumns: [],
     activeKey: 'setting',
     loading: false,
+    searchKey: '',
     initsql: '',          // sql楠岃瘉鏃跺彉閲忓0鏄庡強璧嬪��
     usefulfields: '',
     defaultsql: '',       // 榛樿Sql
@@ -60,6 +64,7 @@
         inputType: 'input',
         editable: true,
         unique: true,
+        strict: true,
         copy: true,
         rules: [{
           pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
@@ -194,15 +199,22 @@
 
     _search = _search.replace(/@\$@/ig, '')
     _search = _search ? 'where ' + _search : ''
+    let columns = config.columns ? fromJS(config.columns).toJS() : []
+    let subColumns = config.subColumns ? fromJS(config.subColumns).toJS() : []
+
+    columns.reverse()
+    subColumns.reverse()
 
     this.setState({
       scripts,
-      columns: config.columns ? fromJS(config.columns).toJS() : [],
-      subColumns: config.subColumns ? fromJS(config.subColumns).toJS() : [],
+      columns: columns,
+      subColumns: subColumns,
       setting: _setting,
       median: _setting,
       searches: search,
-      defaultSearch: _search
+      defaultSearch: _search,
+      searchKey: '',
+      debugId: _setting.debugId || ''
     })
 
     this.getsysScript()
@@ -273,7 +285,7 @@
 
     values.uuid = Utils.getuuid()
 
-    this.setState({ columns: [...columns, values] })
+    this.setState({ columns: [values, ...columns] })
   }
 
   subColumnChange = (values, resolve) => {
@@ -293,7 +305,7 @@
 
     values.uuid = Utils.getuuid()
 
-    this.setState({ subColumns: [...subColumns, values] })
+    this.setState({ subColumns: [values, ...subColumns] })
   }
 
   deleteScript = (record) => {
@@ -645,7 +657,7 @@
   }
 
   sqlverify = (resolve, reject, change = false, testScripts) => {
-    const { columns, setting, scripts, searches, defaultSearch } = this.state
+    const { columns, setting, scripts, searches, defaultSearch, debugId } = this.state
 
     let _scripts = scripts.filter(item => item.status !== 'false')
 
@@ -669,7 +681,14 @@
 
     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, timestamp)
+      let r = SettingUtils.getDebugSql(setting, _scripts, columns, searches, defaultSearch, '2023-04-20 15:29:37')
+
+      let _debugId = md5(r.sql)
+
+      if (debugId === _debugId) {
+        resolve()
+        return
+      }
 
       if (r.errors) {
         notification.warning({
@@ -705,7 +724,9 @@
           if (sumParam) {
             Api.genericInterface(sumParam).then(res => {
               if (res.status) {
-                resolve()
+                this.setState({debugId: _debugId}, () => {
+                  resolve()
+                })
               } else {
                 reject()
                 Modal.error({
@@ -714,7 +735,9 @@
               }
             })
           } else {
-            resolve()
+            this.setState({debugId: _debugId}, () => {
+              resolve()
+            })
           }
         } else {
           reject()
@@ -884,7 +907,7 @@
     let n = []
 
     columns.forEach(col => {
-      m.push(`${col.field}(${col.label})`)
+      m.push(`${col.field} ${col.datatype}`)
       n.push(col.field)
     })
 
@@ -905,7 +928,7 @@
     let n = []
 
     subColumns.forEach(col => {
-      m.push(`${col.field}(${col.label})`)
+      m.push(`${col.field} ${col.datatype}`)
       n.push(col.field)
     })
 
@@ -931,7 +954,7 @@
 
   render() {
     const { config } = this.props
-    const { columns, subColumns, median, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql, visible, pvisible, reload, script, scriptValue } = this.state
+    const { columns, subColumns, median, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql, visible, pvisible, reload, script, scriptValue, searchKey } = this.state
 
     return (
       <div className="model-data-source-wrap">
@@ -965,7 +988,7 @@
               type="fields"
               updatefield={this.updatefields}
             />
-            <EditTable actions={['edit', 'move', 'copy', 'del', 'clear']} type="datasourcefield" wrappedComponentRef={(inst) => this.datasource = inst} data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/>
+            <EditTable actions={['edit', 'move', 'copy', 'del', 'clear']} searchKey={searchKey} type="datasourcefield" wrappedComponentRef={(inst) => this.datasource = inst} data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/>
           </TabPane> : null}
           {config.subtype === 'dualdatacard' ? <TabPane tab={
             <span>
@@ -979,7 +1002,7 @@
               type="fields"
               updatefield={this.updateSubfields}
             />
-            <EditTable actions={['edit', 'move', 'copy', 'del', 'clear']} type="datasourcefield" wrappedComponentRef={(inst) => this.subdatasource = inst} data={subColumns} columns={colColumns} onChange={(subColumns) => this.setState({subColumns})}/>
+            <EditTable actions={['edit', 'move', 'copy', 'del', 'clear']} searchKey={searchKey} type="datasourcefield" wrappedComponentRef={(inst) => this.subdatasource = inst} data={subColumns} columns={colColumns} onChange={(subColumns) => this.setState({subColumns})}/>
           </TabPane> : null}
           <TabPane tab={
             <span>
@@ -989,6 +1012,7 @@
               {config.type !== 'interface' && activeKey === 'setting' ? <SnippetsOutlined title="瀵煎叆鏁版嵁婧�" className="mk-paste-datasource" onClick={(e) => {e.stopPropagation();this.setState({pvisible: true})}}/> : null}
               {activeKey === 'columns' ? <CopyOutlined title="浠ラ�楀彿鎷兼帴褰㈠紡澶嶅埗瀛楁" className="mk-copy-fields" onClick={(e) => {e.stopPropagation();this.copyColumns()}}/> : null}
               {activeKey === 'subcolumns' ? <CopyOutlined title="浠ラ�楀彿鎷兼帴褰㈠紡澶嶅埗瀛楁" className="mk-copy-fields" onClick={(e) => {e.stopPropagation();this.copySubColumns()}}/> : null}
+              {activeKey === 'subcolumns' || activeKey === 'columns' ? <span onClick={(e) => {e.stopPropagation()}}><Search className="mk-search-fields" defaultValue={searchKey} allowClear onSearch={(val, e) => {e.stopPropagation();this.setState({searchKey: val})}} /></span> : null}
             </span>
           } key="scripts" disabled={median.interType !== 'system'} id="mk-scripts-tabpane">
             {scripts.length ? <BorderOutlined className="full-scripts" onClick={() => {
diff --git a/src/menu/datasource/verifycard/index.scss b/src/menu/datasource/verifycard/index.scss
index b9bc0fe..c8e00e8 100644
--- a/src/menu/datasource/verifycard/index.scss
+++ b/src/menu/datasource/verifycard/index.scss
@@ -45,6 +45,34 @@
     .mk-copy-fields:hover, .mk-copy-datasource:hover, .mk-paste-datasource:hover {
       opacity: 1;
     }
+    .mk-search-fields {
+      position: absolute;
+      cursor: pointer;
+      width: 150px;
+      z-index: 1;
+      top: 10px;
+      right: -240px;
+      display: inline-block;
+      .ant-input {
+        border-radius: 40px;
+        height: 30px;
+        transition: opacity 0.2s;
+      }
+      .ant-input:not(:hover):not(:active):not(:focus) {
+        opacity: 0.6;
+      }
+      .ant-input:not(:hover):not(:active):not(:focus) + .ant-input-suffix {
+        opacity: 0.6;
+      }
+    }
+    .mk-search-fields:hover {
+      .ant-input {
+        opacity: 1;
+      }
+      .ant-input-suffix {
+        opacity: 1;
+      }
+    }
     .count-tip {
       position: absolute;
       top: 0px;
diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx
index de02f21..235cd21 100644
--- a/src/menu/datasource/verifycard/settingform/index.jsx
+++ b/src/menu/datasource/verifycard/settingform/index.jsx
@@ -97,6 +97,10 @@
             values.onload = 'true'
           }
 
+          if (values.interType === 'system' && values.onload === 'false') {
+            values.sync = 'false'
+          }
+
           // 鏁版嵁婧愬墠绔獙璇�
           if (values.interType === 'system' && values.execute !== 'false' && values.dataresource) {
             let _quot = values.dataresource.match(/'{1}/g)
@@ -127,6 +131,14 @@
               notification.warning({
                 top: 92,
                 message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜板瓧绗� -- 锛屾敞閲婅鐢� /*鍐呭*/',
+                duration: 5
+              })
+              reject()
+              return
+            } else if (/,,/ig.test(values.dataresource)) {
+              notification.warning({
+                top: 92,
+                message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜拌繛缁殑鑻辨枃閫楀彿锛�,,锛�',
                 duration: 5
               })
               reject()
@@ -460,9 +472,9 @@
               </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' ? <Col span={8}>
+            {!['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}>
               <Form.Item label={
-                <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹紝娉細浠呭湪浣跨敤绯荤粺鍑芥暟锛屼笖鍒濆鍖栧姞杞芥暟鎹椂鏈夋晥锛屽垎椤佃姹傛椂鏃犳晥銆�'}>
+                <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹紝娉細濡傝彍鍗曟湭浣跨敤鍚庣缂撳瓨锛屽垯鏌ヨ璇彞澶т簬8000瀛楃鏃舵棤鏁堛��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
                   鍚屾鏌ヨ
                 </Tooltip>
@@ -516,13 +528,30 @@
                 {getFieldDecorator('onload', {
                   initialValue: setting.onload || 'true'
                 })(
-                  <Radio.Group>
+                  <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'onload')}}>
                     <Radio value="true">鍔犺浇</Radio>
                     <Radio value="false">涓嶅姞杞�</Radio>
                   </Radio.Group>
                 )}
               </Form.Item>
             </Col> : null}
+            {config.type === 'interface' && setting.supModule && setting.supModule[0] === 'empty' ? <Col span={8}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鍒濆鍖栧姞杞藉皢鍦ㄩ〉闈㈠姞杞藉墠鎵ц銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鍔犺浇鏂瑰紡
+                </Tooltip>
+              }>
+                {getFieldDecorator('loadlevel', {
+                  initialValue: setting.loadlevel || 'default'
+                })(
+                  <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'loadlevel')}}>
+                    <Radio value="default">榛樿</Radio>
+                    <Radio value="init">鍒濆鍖�</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
             {config.type === 'interface' ? <Col span={8}>
               <Form.Item label="瀹氭椂鍣�">
                 {getFieldDecorator('timer', {
diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx
index 467795d..1719f71 100644
--- a/src/menu/menushell/card.jsx
+++ b/src/menu/menushell/card.jsx
@@ -32,6 +32,7 @@
 const Account = asyncComponent(() => import('@/menu/components/module/account'))
 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 Card = ({ id, card, moveCard, findCard, delCard, unGroup, updateConfig }) => {
   const originalIndex = findCard(id).index
@@ -123,12 +124,23 @@
       return (<Iframe 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 === '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}>
       {getCardComponent()}
diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx
index 9533aa5..06b1c59 100644
--- a/src/menu/menushell/index.jsx
+++ b/src/menu/menushell/index.jsx
@@ -118,6 +118,7 @@
         balcony: '娴姩鍗�',
         timeline: '鏃堕棿杞�',
         antvG6: '鏍戝浘',
+        antvX6: '娴佺▼鍥�',
         iframe: 'iframe',
         module: '妯″潡',
         card: '鍗$墖'
diff --git a/src/menu/modalconfig/controller.jsx b/src/menu/modalconfig/controller.jsx
index 683598d..5a7c777 100644
--- a/src/menu/modalconfig/controller.jsx
+++ b/src/menu/modalconfig/controller.jsx
@@ -35,6 +35,8 @@
       config: fromJS(config).toJS(),
       btn: fromJS(btn).toJS()
     })
+
+    window.GLOB.formId = ''
   }
 
   handleBack = () => {
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index c0da35b..a6741f2 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -20,8 +20,9 @@
 
 const { Panel } = Collapse
 const { confirm } = Modal
+const TableComponent = asyncComponent(() => import('./tablecomponent'))
 const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
-const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent'))
+const PasteForms = asyncComponent(() => import('@/menu/components/share/pasteforms'))
 const DragElement = asyncComponent(() => import('@/templates/modalconfig/dragelement'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 
@@ -137,7 +138,7 @@
         })
       }
 
-      if (item.type === 'switch') {
+      if (item.type === 'switch' || item.type === 'check') {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -238,6 +239,8 @@
           fieldrepet = true
         }
 
+        delete item.focus
+
         if (item.uuid === res.uuid) {
           if (item.style) {
             res.style = item.style
@@ -256,6 +259,8 @@
         })
         return
       }
+
+      window.GLOB.formId = res.uuid
 
       if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
         this.setState({
@@ -456,44 +461,8 @@
     })
   }
 
-  plusFields = (items, type) => {
+  plusFields = (items) => {
     let _config = fromJS(this.state.config).toJS()
-
-    if (type === 'forms') {
-      if (_config.fields.length > 0) {
-        let that = this
-        _config.fields = items.fields.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
-
-        confirm({
-          title: '纭畾鏇挎崲琛ㄥ崟鍚楋紵',
-          content: '鍘熻〃鍗曞皢鍒犻櫎銆�',
-          onOk() {
-            that.setState({
-              config: _config
-            })
-          },
-          onCancel() {}
-        })
-      } else {
-        _config.fields = items.fields.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
-
-        this.setState({
-          config: _config
-        })
-        notification.success({
-          top: 92,
-          message: '绮樿创鎴愬姛锛�',
-          duration: 2
-        })
-      }
-      return
-    }
 
     _config.fields.push(...items)
 
@@ -503,6 +472,15 @@
       if (items.length === 1 && items[0].focus) {
         this.handleForm(items[0])
       }
+    })
+  }
+
+  pasteFields = (items) => {
+    let _config = fromJS(this.state.config).toJS()
+    _config.fields = items
+
+    this.setState({
+      config: _config
     })
   }
 
@@ -541,13 +519,16 @@
 
   render () {
     const { btn } = this.props
-    const { config, saving } = this.state
+    const { config, saving, card } = this.state
 
     return (
       <div className="modal-form-board">
         <DndProvider backend={HTML5Backend}>
           <div className="tools">
             <Collapse accordion defaultActiveKey="1" bordered={false}>
+              <Panel header="鍩烘湰淇℃伅" key="0">
+                <TableComponent />
+              </Panel>
               <Panel header="琛ㄥ崟" key="1">
                 <div className="search-element">
                   {SearchItems.map((item, index) => {
@@ -562,7 +543,7 @@
             <Card title="琛ㄥ崟閰嶇疆" bordered={false} extra={
               <div>
                 <Button type="danger" onClick={this.clearConfig}>娓呯┖</Button>
-                <EditComponent options={['form', 'forms']} type="formboard" config={this.state.config} plusFields={this.plusFields}/>
+                <PasteForms type="toolbar" config={config} update={this.pasteFields}/>
                 <Button type="primary" id="save-modal-config" loading={saving} onClick={this.submitConfig}>淇濆瓨</Button>
                 <Button onClick={this.cancelConfig}>杩斿洖</Button>
               </div>
@@ -606,7 +587,7 @@
           </div>
         </DndProvider>
         <Modal
-          title="缂栬緫"
+          title={card && card.$copy ? '澶嶅埗' : '缂栬緫'}
           visible={this.state.visible}
           width={950}
           maskClosable={false}
@@ -616,7 +597,7 @@
           destroyOnClose
         >
           <ModalForm
-            card={this.state.card}
+            card={card}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
             standardform={this.state.standardform}
diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss
index 4e0d628..723def0 100644
--- a/src/menu/modalconfig/index.scss
+++ b/src/menu/modalconfig/index.scss
@@ -93,20 +93,20 @@
       position: relative;
       padding: 0;
 
-      .modal-fields-row.up_down {
-        .ant-form-item {
-          display: block!important;
-          .ant-form-item-label {
-            width: 100%!important;
-            text-align: left;
-            height: 24px;
-            line-height: 28px;
-          }
-          .ant-form-item-control-wrapper {
-            width: 100%!important;
-          }
-        }
-      }
+      // .modal-fields-row.up_down {
+      //   .ant-form-item {
+      //     display: block!important;
+      //     .ant-form-item-label {
+      //       width: 100%!important;
+      //       text-align: left;
+      //       height: 24px;
+      //       line-height: 28px;
+      //     }
+      //     .ant-form-item-control-wrapper {
+      //       width: 100%!important;
+      //     }
+      //   }
+      // }
 
       .ant-modal-content {
         max-width: 95%;
diff --git a/src/menu/modalconfig/tablecomponent/index.jsx b/src/menu/modalconfig/tablecomponent/index.jsx
new file mode 100644
index 0000000..01fd0f2
--- /dev/null
+++ b/src/menu/modalconfig/tablecomponent/index.jsx
@@ -0,0 +1,163 @@
+import React, {Component} from 'react'
+import { fromJS } from 'immutable'
+import { Tooltip, Select, List, notification } from 'antd'
+import { QuestionCircleOutlined, CloseOutlined } from '@ant-design/icons'
+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'
+
+import './index.scss'
+
+const { Option } = Select
+
+class TablesComponent extends Component {
+  state = {
+    tables: [],          // 绯荤粺琛�
+    selectedTables: [],  // 宸查�夎〃
+  }
+
+  /**
+   * @description 鎼滅储鏉′欢鍒濆鍖�
+   */
+  UNSAFE_componentWillMount () {
+    this.setState({
+      selectedTables: window.GLOB.publicTables ? fromJS(window.GLOB.publicTables).toJS() : []
+    })
+  }
+
+  componentDidMount () {
+    this.gettables()
+  }
+
+  /**
+   * @description 鑾峰彇绯荤粺琛�
+   */
+  gettables = () => {
+    let param = {
+      func: 'sPC_Get_SelectedList',
+      LText: queryTableSql,
+      obj_name: 'data',
+      arr_field: 'TbName,Remark'
+    }
+
+    param.LText = Utils.formatOptions(param.LText)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
+
+    if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
+      param.rduri = options.cloudServiceApi
+      param.userid = sessionStorage.getItem('CloudUserID') || ''
+      param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
+    }
+
+    Api.getSystemCacheConfig(param).then(res => {
+      if (res.status) {
+        this.setState({
+          tables: res.data
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  /**
+   * @description 娣诲姞琛ㄥ悕
+   */
+  onTableChange = (value) => {
+    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]
+
+      MKEmitter.emit('publicTableChange', value, 'plus')
+
+      this.setState({
+        selectedTables: _tables
+      })
+    }
+  }
+
+  /**
+   * @description 鍒犻櫎琛ㄥ悕
+   */
+  deleteTable = (table) => {
+    const { selectedTables } = this.state
+
+    let _tables = selectedTables.filter(item => item.TbName !== table.TbName)
+
+    MKEmitter.emit('publicTableChange', table, 'del')
+
+    this.setState({
+      selectedTables: _tables
+    })
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { tables, selectedTables } = this.state
+
+    return (
+      <div className="model-tablename-manage-view">
+        {/* 琛ㄥ悕娣诲姞 */}
+        <div className="ant-col ant-form-item-label">
+          <label>
+            <Tooltip placement="topLeft" title="姝ゅ鍙互娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃銆�">
+              <QuestionCircleOutlined className="mk-form-tip" />
+              琛ㄥ悕
+            </Tooltip>
+          </label>
+        </div>
+        <Select
+          showSearch
+          className="tables"
+          style={{ width: '100%' }}
+          optionFilterProp="children"
+          value="璇烽�夋嫨琛ㄥ悕"
+          onSelect={this.onTableChange}
+          dropdownClassName="mk-tables"
+          dropdownMatchSelectWidth={false}
+          showArrow={false}
+          filterOption={(input, option) => {
+            return option.props.children[0].toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
+              option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0
+          }}
+        > 
+          {tables.map((table, index) => (
+            <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}<br/>{table.TbName}</Option>
+          ))}
+        </Select>
+        {selectedTables.length > 0 && <List
+          size="small"
+          bordered
+          dataSource={selectedTables}
+          renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}>
+            {item.Remark + ' (' + item.TbName + ')'}
+            <CloseOutlined onClick={() => this.deleteTable(item)}/>
+          </List.Item>}
+        />}
+      </div>
+    )
+  }
+}
+
+export default TablesComponent
\ No newline at end of file
diff --git a/src/menu/modalconfig/tablecomponent/index.scss b/src/menu/modalconfig/tablecomponent/index.scss
new file mode 100644
index 0000000..92d6c69
--- /dev/null
+++ b/src/menu/modalconfig/tablecomponent/index.scss
@@ -0,0 +1,36 @@
+.model-tablename-manage-view {
+  >.ant-list {
+    margin-top: 20px;
+    .ant-list-item {
+      display: -webkit-box;
+      padding-right: 20px;
+      position: relative;
+      padding-left: 5px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+      min-height: 55px;
+      width: 100%;
+      .anticon {
+        position: absolute;
+        top: 0px;
+        right: 0px;
+        padding: 3px 3px 10px 10px;
+        cursor: pointer;
+      }
+    }
+  }
+  .tables {
+    width: 66.66666667%!important;
+    .ant-select-selection-selected-value {
+      opacity: 0.4!important;
+    }
+  }
+  >.ant-form-item-label {
+    width: 33.33333333%;
+  }
+}
+.mk-tables {
+  max-width: 300px;
+}
\ No newline at end of file
diff --git a/src/menu/modulecell/index.jsx b/src/menu/modulecell/index.jsx
index b8841a6..e88c740 100644
--- a/src/menu/modulecell/index.jsx
+++ b/src/menu/modulecell/index.jsx
@@ -100,8 +100,7 @@
           { subType: 'custom', text: '鑷畾涔夊垪', type: 'col', $init: true },
           { subType: 'colspan', text: '鍚堝苟鍒�', type: 'col', $init: true },
           { subType: 'formula', text: '鍏紡', type: 'col', $init: true },
-          { subType: 'index', text: '搴忓彿', type: 'col', $init: true },
-          { subType: 'action', text: '鎿嶄綔', type: 'col', $init: true }
+          { subType: 'index', text: '搴忓彿', type: 'col', $init: true }
         ]
       }
     ]
diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx
index 696b3a5..50d70b5 100644
--- a/src/menu/modulesource/option.jsx
+++ b/src/menu/modulesource/option.jsx
@@ -1,7 +1,6 @@
 import bar from '@/assets/mobimg/bar.png'
 import bar1 from '@/assets/mobimg/bar1.png'
 import line from '@/assets/mobimg/line.png'
-// import line1 from '@/assets/mobimg/line1.png'
 import tabs from '@/assets/mobimg/tabs.png'
 import group from '@/assets/mobimg/group.png'
 import card1 from '@/assets/mobimg/card1.png'
@@ -30,6 +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 Voucher from '@/assets/mobimg/voucher.png'
 import Account from '@/assets/mobimg/account.png'
 
@@ -52,7 +52,6 @@
   { type: 'menu', url: timeline, component: 'timeline', subtype: 'timeline', title: '鏃堕棿杞�', width: 12 },
   { 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: line1, component: 'line', subtype: 'line1', title: '闃舵鎶樼嚎鍥�', width: 24 },
   { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '鏌辩姸鍥�', width: 24 },
   { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�', width: 24 },
   { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '楗煎浘', width: 12 },
@@ -65,8 +64,9 @@
   { 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: chart, component: 'chart', subtype: 'custom', title: '鑷畾涔夊浘琛�', width: 24, forbid: ['billPrint'] },
-  { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', 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 },
   { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24, forbid: ['billPrint'] },
   { type: 'menu', url: Iframe, component: 'iframe', subtype: 'iframe', title: 'iframe', width: 24, forbid: ['billPrint'] },
diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx
index d816e9d..5179037 100644
--- a/src/menu/pastecontroller/index.jsx
+++ b/src/menu/pastecontroller/index.jsx
@@ -18,9 +18,7 @@
     visible: false
   }
 
-  resetconfig = (item) => {
-    let appType = sessionStorage.getItem('appType')
-    
+  resetconfig = (item, appType) => {
     if (item.type === 'tabs') {
       item.uuid = MenuUtils.getuuid()
       item.setting.name = item.setting.name + MenuUtils.getSignName()
@@ -34,7 +32,7 @@
         }
 
         tab.components = tab.components.map(cell => {
-          cell = this.resetconfig(cell)
+          cell = this.resetconfig(cell, appType)
           return cell
         })
       })
@@ -44,11 +42,11 @@
       item.name = item.setting.name
 
       item.components = item.components.map(cell => {
-        cell = MenuUtils.resetComponentConfig(cell)
+        cell = MenuUtils.resetComponentConfig(cell, appType)
         return cell
       })
     } else {
-      item = MenuUtils.resetComponentConfig(item)
+      item = MenuUtils.resetComponentConfig(item, appType)
     }
 
     return item
@@ -56,16 +54,16 @@
 
   pasteSubmit = () => {
     let appType = sessionStorage.getItem('appType')
-    let options = ['tabs', 'timeline', 'datacard', 'propcard', 'mainsearch', 'simpleform', 'stepform', 'tabform', 'balcony', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'scatter', 'iframe', 'sandbox']
+    let options = ['tabs', 'timeline', 'datacard', 'propcard', 'simpleform', 'stepform', 'tabform', 'balcony', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'editor', 'pie', 'scatter', 'iframe', 'sandbox']
 
     if (appType === 'mob') {
       if (sessionStorage.getItem('editMenuType') !== 'popview') {
-        options.push('menubar', 'topbar')
+        options.push('menubar', 'topbar', 'singleSearch')
       } else {
-        options.push('menubar')
+        options.push('menubar', 'singleSearch')
       }
     } else {
-      options.push('editable', 'antvG6', 'tree', 'dashboard', 'chart')
+      options.push('editable', 'mainsearch', 'antvG6', 'tree', 'dashboard', 'chart')
     }
 
     this.pasteFormRef.handleConfirm().then(res => {
@@ -78,7 +76,7 @@
         return
       }
 
-      res = this.resetconfig(res)
+      res = this.resetconfig(res, appType)
 
       // delete res.copyType
       
diff --git a/src/menu/replaceField/index.jsx b/src/menu/replaceField/index.jsx
index 64353b0..df1506a 100644
--- a/src/menu/replaceField/index.jsx
+++ b/src/menu/replaceField/index.jsx
@@ -9,7 +9,6 @@
 import Utils from '@/utils/utils.js'
 import SettingForm from './settingform'
 import { queryTableSql } from '@/utils/option.js'
-import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
 class ReplaceField extends Component {
@@ -359,34 +358,32 @@
           if (item.cols) {
             let _update = (cols) => {
               return cols.map(col => {
-                if (col.type === 'action' && col.elements) {
+                if (col.type === 'custom' && col.elements) {
                   col.elements = col.elements.map(m => {
-                    if (m.modal && m.modal.fields) {
-                      m.modal.fields = m.modal.fields.map(col => {
-                        if (col.field && map[col.field.toLowerCase()]) {
-                          col.field = map[col.field.toLowerCase()].FieldName
-                        }
-                        return col
-                      })
-                    }
-                    if (m.verify && m.verify.columns) {
-                      m.verify.columns = m.verify.columns.map(col => {
-                        if (col.Column && map[col.Column.toLowerCase()]) {
-                          col.Column = map[col.Column.toLowerCase()].FieldName
-                        }
-                        return col
-                      })
-                    }
-                    if (m.config && m.config.components) {
-                      m.config.components = _replace(m.config.components)
-                    }
-
-                    return m
-                  })
-                } else if (col.type === 'custom' && col.elements) {
-                  col.elements = col.elements.map(m => {
-                    if (m.datatype === 'dynamic' && map[m.field.toLowerCase()]) {
-                      m.field = map[m.field.toLowerCase()].FieldName
+                    if (m.eleType === 'button') {
+                      if (m.modal && m.modal.fields) {
+                        m.modal.fields = m.modal.fields.map(col => {
+                          if (col.field && map[col.field.toLowerCase()]) {
+                            col.field = map[col.field.toLowerCase()].FieldName
+                          }
+                          return col
+                        })
+                      }
+                      if (m.verify && m.verify.columns) {
+                        m.verify.columns = m.verify.columns.map(col => {
+                          if (col.Column && map[col.Column.toLowerCase()]) {
+                            col.Column = map[col.Column.toLowerCase()].FieldName
+                          }
+                          return col
+                        })
+                      }
+                      if (m.config && m.config.components) {
+                        m.config.components = _replace(m.config.components)
+                      }
+                    } else {
+                      if (m.datatype === 'dynamic' && map[m.field.toLowerCase()]) {
+                        m.field = map[m.field.toLowerCase()].FieldName
+                      }
                     }
 
                     return m
@@ -420,35 +417,35 @@
       }
 
       config.components = _replace(config.components)
-    } else if (type === 'table') {
-      config.columns = config.columns.map(col => {
-        if (col.field && map[col.field.toLowerCase()]) {
-          col.field = map[col.field.toLowerCase()].FieldName
-        }
-        return col
-      })
+    // } else if (type === 'table') {
+    //   config.columns = config.columns.map(col => {
+    //     if (col.field && map[col.field.toLowerCase()]) {
+    //       col.field = map[col.field.toLowerCase()].FieldName
+    //     }
+    //     return col
+    //   })
 
-      config.search = config.search.map(col => {
-        if (col.field && map[col.field.toLowerCase()]) {
-          col.field = map[col.field.toLowerCase()].FieldName
-        }
-        if (col.datefield && map[col.datefield.toLowerCase()]) {
-          col.datefield = map[col.datefield.toLowerCase()].FieldName
-        }
-        return col
-      })
+    //   config.search = config.search.map(col => {
+    //     if (col.field && map[col.field.toLowerCase()]) {
+    //       col.field = map[col.field.toLowerCase()].FieldName
+    //     }
+    //     if (col.datefield && map[col.datefield.toLowerCase()]) {
+    //       col.datefield = map[col.datefield.toLowerCase()].FieldName
+    //     }
+    //     return col
+    //   })
 
-      config.action = config.action.map(m => {
-        if (m.verify && m.verify.columns) {
-          m.verify.columns = m.verify.columns.map(col => {
-            if (col.Column && map[col.Column.toLowerCase()]) {
-              col.Column = map[col.Column.toLowerCase()].FieldName
-            }
-            return col
-          })
-        }
-        return m
-      })
+    //   config.action = config.action.map(m => {
+    //     if (m.verify && m.verify.columns) {
+    //       m.verify.columns = m.verify.columns.map(col => {
+    //         if (col.Column && map[col.Column.toLowerCase()]) {
+    //           col.Column = map[col.Column.toLowerCase()].FieldName
+    //         }
+    //         return col
+    //       })
+    //     }
+    //     return m
+    //   })
     } else if (type === 'form') {
       config.fields = config.fields.map(col => {
         if (col.field && map[col.field.toLowerCase()]) {
@@ -469,10 +466,6 @@
       duration: 3
     })
     this.props.updateConfig(config)
-
-    setTimeout(() => {
-      MKEmitter.emit('revert')
-    }, 300)
   }
 
   // 渚濇嵁瀛楁鏇挎崲鍚嶇О
@@ -537,26 +530,28 @@
           if (item.cols) {
             let _update = (cols) => {
               return cols.map(col => {
-                if (col.type === 'action' && col.elements) {
+                if (col.type === 'custom' && col.elements) {
                   col.elements = col.elements.map(m => {
-                    if (m.modal && m.modal.fields) {
-                      m.modal.fields = m.modal.fields.map(col => {
-                        if (col.field && map[col.field.toLowerCase()]) {
-                          col.label = map[col.field.toLowerCase()].FieldDec
-                        }
-                        return col
-                      })
-                    }
-                    if (m.verify && m.verify.columns) {
-                      m.verify.columns = m.verify.columns.map(col => {
-                        if (col.Column && map[col.Column.toLowerCase()]) {
-                          col.Text = map[col.Column.toLowerCase()].FieldDec
-                        }
-                        return col
-                      })
-                    }
-                    if (m.config && m.config.components) {
-                      m.config.components = _replace(m.config.components)
+                    if (m.eleType === 'button') {
+                      if (m.modal && m.modal.fields) {
+                        m.modal.fields = m.modal.fields.map(col => {
+                          if (col.field && map[col.field.toLowerCase()]) {
+                            col.label = map[col.field.toLowerCase()].FieldDec
+                          }
+                          return col
+                        })
+                      }
+                      if (m.verify && m.verify.columns) {
+                        m.verify.columns = m.verify.columns.map(col => {
+                          if (col.Column && map[col.Column.toLowerCase()]) {
+                            col.Text = map[col.Column.toLowerCase()].FieldDec
+                          }
+                          return col
+                        })
+                      }
+                      if (m.config && m.config.components) {
+                        m.config.components = _replace(m.config.components)
+                      }
                     }
 
                     return m
@@ -590,32 +585,32 @@
       }
 
       config.components = _replace(config.components)
-    } else if (type === 'table') {
-      config.columns = config.columns.map(col => {
-        if (col.field && map[col.field.toLowerCase()]) {
-          col.label = map[col.field.toLowerCase()].FieldDec
-        }
-        return col
-      })
+    // } else if (type === 'table') {
+    //   config.columns = config.columns.map(col => {
+    //     if (col.field && map[col.field.toLowerCase()]) {
+    //       col.label = map[col.field.toLowerCase()].FieldDec
+    //     }
+    //     return col
+    //   })
       
-      config.search = config.search.map(col => {
-        if (col.field && map[col.field.toLowerCase()]) {
-          col.label = map[col.field.toLowerCase()].FieldDec
-        }
-        return col
-      })
+    //   config.search = config.search.map(col => {
+    //     if (col.field && map[col.field.toLowerCase()]) {
+    //       col.label = map[col.field.toLowerCase()].FieldDec
+    //     }
+    //     return col
+    //   })
 
-      config.action = config.action.map(m => {
-        if (m.verify && m.verify.columns) {
-          m.verify.columns = m.verify.columns.map(col => {
-            if (col.Column && map[col.Column.toLowerCase()]) {
-              col.Text = map[col.Column.toLowerCase()].FieldDec
-            }
-            return col
-          })
-        }
-        return m
-      })
+    //   config.action = config.action.map(m => {
+    //     if (m.verify && m.verify.columns) {
+    //       m.verify.columns = m.verify.columns.map(col => {
+    //         if (col.Column && map[col.Column.toLowerCase()]) {
+    //           col.Text = map[col.Column.toLowerCase()].FieldDec
+    //         }
+    //         return col
+    //       })
+    //     }
+    //     return m
+    //   })
     } else if (type === 'form') {
       config.fields = config.fields.map(col => {
         if (col.field && map[col.field.toLowerCase()]) {
@@ -636,9 +631,6 @@
       duration: 3
     })
     this.props.updateConfig(config)
-    setTimeout(() => {
-      MKEmitter.emit('revert')
-    }, 500)
   }
 
   render() {
diff --git a/src/menu/stylecontroller/index.jsx b/src/menu/stylecontroller/index.jsx
index e06a198..6acd6cc 100644
--- a/src/menu/stylecontroller/index.jsx
+++ b/src/menu/stylecontroller/index.jsx
@@ -1,7 +1,7 @@
 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 } from 'antd'
+import { Collapse, Form, Col, InputNumber, Input, Select, Radio, Drawer, Button, message } from 'antd'
 import {
   ColumnHeightOutlined,
   FontSizeOutlined,
@@ -29,7 +29,7 @@
   ArrowLeftOutlined,
   ArrowRightOutlined,
   SwapOutlined,
-  EnterOutlined,
+  EnterOutlined
 } from '@ant-design/icons'
 
 import MKEmitter from '@/utils/events.js'
@@ -42,6 +42,7 @@
 const { Panel } = Collapse
 const { Option } = Select
 const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
+const PasteBoard = asyncComponent(() => import('@/components/pasteboard'))
 const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
 
 class MobController extends Component {
@@ -453,6 +454,77 @@
     this.updateStyle({[type]: val})
   }
 
+  copy = () => {
+    const { card, options } = this.state
+
+    let msg = { copyType: 'style' }
+
+    msg.data = card
+    msg.options = options
+
+    try {
+      msg = window.btoa(window.encodeURIComponent(JSON.stringify(msg)))
+    } catch (e) {
+      console.warn('Stringify Failure')
+      msg = ''
+    }
+
+    if (msg) {
+      let oInput = document.createElement('input')
+      oInput.value = msg
+      document.body.appendChild(oInput)
+      oInput.select()
+      document.execCommand('Copy')
+      document.body.removeChild(oInput)
+      message.success('澶嶅埗鎴愬姛銆�')
+    }
+  }
+
+  paste = (res, callback) => {
+    const { options } = this.state
+
+    if (res.copyType !== 'style') {
+      message.warning('閰嶇疆淇℃伅鏍煎紡閿欒锛�', 5)
+      return
+    } else if (JSON.stringify(res.options) !== JSON.stringify(options)) {
+      message.warning('鏍峰紡閫夐」涓嶄竴鑷达紝涓嶅彲绮樿创锛�', 5)
+      return
+    }
+
+    let style = res.data || {}
+
+    let backgroundImage = ''
+    if (style.backgroundImage && /^url/ig.test(style.backgroundImage)) {
+      backgroundImage = style.backgroundImage.replace(/^url\(/ig, '').replace(/\)$/ig, '')
+    }
+
+    let borposition = 'outer'
+
+    if (!style.borderWidth) {
+      if (style.borderLeftWidth) {
+        borposition = 'left'
+      } else if (style.borderRightWidth) {
+        borposition = 'right'
+      } else if (style.borderTopWidth) {
+        borposition = 'top'
+      } else if (style.borderBottomWidth) {
+        borposition = 'bottom'
+      }
+    }
+
+    this.setState({
+      card: style,
+      borposition,
+      backgroundImage
+    })
+
+    this.callback && this.callback(style)
+
+    callback()
+
+    message.success('绮樿创鎴愬姛銆�')
+  }
+
   render () {
     const { card, options, backgroundImage, borposition, fonts, type } = this.state
     const formItemLayout = {
@@ -561,7 +633,7 @@
                     label={<FontColorsOutlined title="瀛椾綋棰滆壊"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <ColorSketch value={card.color || 'rgba(0, 0, 0, 0.85)'} onChange={this.changeFontColor} />
+                    <ColorSketch value={card.color || ''} onChange={this.changeFontColor} />
                   </Form.Item>
                   <Form.Item
                     colon={false}
@@ -771,11 +843,11 @@
                     label={<BgColorsOutlined title="杈规棰滆壊"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    {borposition === 'outer' ? <ColorSketch value={card.borderColor || 'transparent'} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'left' ? <ColorSketch value={card.borderLeftColor || 'transparent'} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'right' ? <ColorSketch value={card.borderRightColor || 'transparent'} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'top' ? <ColorSketch value={card.borderTopColor || 'transparent'} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'bottom' ? <ColorSketch value={card.borderBottomColor || 'transparent'} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'outer' ? <ColorSketch value={card.borderColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'left' ? <ColorSketch value={card.borderLeftColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'right' ? <ColorSketch value={card.borderRightColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'top' ? <ColorSketch value={card.borderTopColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'bottom' ? <ColorSketch value={card.borderBottomColor || ''} onChange={this.changeBorderColor} /> : null}
                   </Form.Item>
                   <Form.Item
                     colon={false}
@@ -802,7 +874,7 @@
                     label={<BgColorsOutlined title="闃村奖棰滆壊"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <ColorSketch value={card.shadowColor || 'transparent'} onChange={this.changeShadowColor} />
+                    <ColorSketch value={card.shadowColor || ''} onChange={this.changeShadowColor} />
                   </Form.Item>
                   <Form.Item
                     colon={false}
@@ -972,8 +1044,12 @@
               </Panel> : null}
             </Collapse> : null}
           </Form>
-          <div style={{textAlign: 'right'}}>
-            <Button style={{margin: '30px 10px 30px 0px'}} onClick={this.onCloseDrawer}>鍏抽棴</Button>
+          <div style={{textAlign: 'right', lineHeight: '60px', marginBottom: '30px'}}>
+            <div style={{float: 'left'}}>
+              <Button onClick={() => this.copy()} className="mk-border-green" style={{marginRight: '10px'}}>澶嶅埗</Button>
+              <PasteBoard getPasteValue={this.paste}><Button style={{borderColor: 'rgb(64, 169, 255)', color: 'rgb(64, 169, 255)'}}>绮樿创</Button></PasteBoard>
+            </div>
+            <Button style={{marginRight: '10px'}} onClick={this.onCloseDrawer}>鍏抽棴</Button>
           </div>
         </div>
       </Drawer>
diff --git a/src/menu/sysinterface/index.jsx b/src/menu/sysinterface/index.jsx
index 240fea2..a486c0e 100644
--- a/src/menu/sysinterface/index.jsx
+++ b/src/menu/sysinterface/index.jsx
@@ -52,7 +52,6 @@
         dataIndex: 'operation',
         render: (text, record) =>
           (<div style={{textAlign: 'center'}}>
-            <DataSource config={record} updateConfig={this.update}/>
             <span onClick={() => this.handleStatus(record)} style={{color: '#8E44AD', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><SwapOutlined /></span>
             <span onClick={() => this.copy(record)} style={{color: '#26C281', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><CopyOutlined /></span>
             <Popconfirm
@@ -60,8 +59,9 @@
               title="纭畾鍒犻櫎锛�"
               onConfirm={() => this.deleteScript(record)
             }>
-              <span style={{color: '#ff4d4f', cursor: 'pointer', fontSize: '16px'}}><DeleteOutlined /></span>
+              <span style={{color: '#ff4d4f', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><DeleteOutlined /></span>
             </Popconfirm>
+            <DataSource config={record} updateConfig={this.update}/>
           </div>)
       }
     ]
@@ -221,6 +221,7 @@
     this.setState({ interfaces })
     this.props.updateConfig({...config, interfaces})
 
+    MKEmitter.emit('editLineId', record.uuid)
     setTimeout(() => {
       MKEmitter.emit('mkUpdateInter', record, {delay: 0})
     }, 10)
@@ -253,7 +254,7 @@
 
     return (
       <div className="mk-sys-interface" style={{display: 'inline-block'}}>
-        <Button className="mk-border-green" onClick={this.trigger}><DatabaseOutlined /> 鍏叡鏁版嵁婧�</Button>
+        <Button className="mk-border-danger" onClick={this.trigger}><DatabaseOutlined /> 鍏叡鏁版嵁婧�</Button>
         <Modal
           title="鍏叡鏁版嵁婧�"
           wrapClassName="interface-controller-modal"
diff --git a/src/menu/transfer/index.jsx b/src/menu/transfer/index.jsx
index 15b6805..6eeecbf 100644
--- a/src/menu/transfer/index.jsx
+++ b/src/menu/transfer/index.jsx
@@ -83,8 +83,9 @@
               }
             }
           })
+          tab.components[0].cols = tab.components[0].cols.filter(col => !(col.field && col.Hide === 'true'))
           tab.components[0].cols.forEach(col => {
-            if (col.type !== 'action') return
+            if (col.type !== 'custom') return
             col.elements.forEach(btn => {
               if (btn.OpenType === 'popview' && btn.config) {
                 btn.config.Template = 'CustomPage'
@@ -108,8 +109,9 @@
             }
           }
         })
+        item.cols = item.cols.filter(col => !(col.field && col.Hide === 'true'))
         item.cols.forEach(col => {
-          if (col.type !== 'action') return
+          if (col.type !== 'custom') return
           col.elements.forEach(btn => {
             if (btn.OpenType === 'popview' && btn.config) {
               btn.config.Template = 'CustomPage'
diff --git a/src/mob/colorsketch/index.jsx b/src/mob/colorsketch/index.jsx
index 6f1ba7a..63abecf 100644
--- a/src/mob/colorsketch/index.jsx
+++ b/src/mob/colorsketch/index.jsx
@@ -9,8 +9,9 @@
 const presetColors = [
   '#1890ff', '#f5222d', '#fa541c', '#fa8c16', '#faad14', '#fadb14', '#a0d911', '#52c41a', '#13c2c2', '#2f54eb', '#722ed1',
   '#eb2f96', '#aeb303', '#c32539', '#1d3661', '#ffd591', '#ffe58f', '#fffb8f', '#eaff8f', '#b7eb8f', '#87e8de', '#91d5ff',
-  '#adc6ff', '#d3adf7', '#EBE9E9', '#d9d9d9', '#434343', '#000000', '#ffffff', 'transparent'
+  '#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]
 
 class ColorSketch extends Component {
   static propTpyes = {
@@ -20,6 +21,7 @@
   }
   state = {
     color: '',
+    initVal: '',
     colors: [],
     allowClear: false
   }
@@ -38,6 +40,21 @@
 
     let _colors = sessionStorage.getItem('app_colors')
     let colors = JSON.parse(JSON.stringify(presetColors))
+    let normal_colors = localStorage.getItem(_href + 'normal_colors')
+
+    if (normal_colors) {
+      try {
+        normal_colors = JSON.parse(normal_colors)
+      } catch (e) {
+        normal_colors = []
+      }
+      
+      normal_colors.forEach(item => {
+        colors.push({color: item, title: '甯哥敤鑹诧細' + item})
+      })
+    } else {
+      normal_colors = []
+    }
 
     if (_colors) {
       try {
@@ -47,13 +64,19 @@
       }
       
       _colors.forEach(item => {
-        if (!colors.includes(item.linkurl)) {
-          colors.push(item.linkurl)
-        }
+        if (normal_colors.includes(item.linkurl)) return
+        
+        colors.push({color: item.linkurl, title: '绯荤粺鑹诧細' + item.linkurl})
       })
     }
 
-    this.setState({color: initVal, allowClear: allowClear === true, colors})
+    if (colors.length < 40) {
+      for (let i = colors.length; i < 40; i++) {
+        colors.push({color: 'transparent', title: '' + i})
+      }
+    }
+
+    this.setState({color: initVal, initVal, allowClear: allowClear === true, colors})
   }
 
   handleChange = (color) => {
@@ -77,18 +100,47 @@
     }
   }
 
+  onVisibleChange = (status) => {
+    const { initVal, color } = this.state
+    
+    if (!status && color && color !== initVal && color !== 'rgba(0, 0, 0, 0)' && color !== 'transparent' && !/rgba\(\d+,\s*\d+,\s*\d+,\s*0\)/.test(color)) {
+      let normal_colors = localStorage.getItem(_href + 'normal_colors')
+
+      if (normal_colors) {
+        try {
+          normal_colors = JSON.parse(normal_colors)
+        } catch (e) {
+          normal_colors = []
+        }
+      } else {
+        normal_colors = []
+      }
+
+      normal_colors.unshift(color)
+      normal_colors = Array.from(new Set(normal_colors))
+
+      if (normal_colors.length > 10) {
+        normal_colors.length = 10
+      }
+
+      localStorage.setItem(_href + 'normal_colors', JSON.stringify(normal_colors))
+    }
+  }
+
+  
+
   render() {
     const { color, allowClear, colors } = this.state
     return (
       <div className="color-sketch-block">
         <Popover content={
           <SketchPicker color={ color } presetColors={colors} onChange={ this.handleChange } />
-        } overlayClassName="color-sketch-popover" placement="bottomRight" title="" trigger="click">
+        } overlayClassName="color-sketch-popover" placement="bottomRight" title="" trigger="click" onVisibleChange={this.onVisibleChange}>
           <div className="color-sketch-block-box">
             <div className="color-sketch-block-inner" style={ {background: color} }></div>
           </div>
         </Popover>
-        <div className="color-sketch-value">{color}{allowClear && color ? <CloseCircleFilled onClick={this.clear}/> : null}</div>
+        <div className="color-sketch-value">{color || <span style={{color: '#ff4d4f'}}>鏃�</span>}{allowClear && color ? <CloseCircleFilled onClick={this.clear}/> : null}</div>
       </div>
     )
   }
diff --git a/src/mob/colorsketch/index.scss b/src/mob/colorsketch/index.scss
index 9aa1fc3..b08c92e 100644
--- a/src/mob/colorsketch/index.scss
+++ b/src/mob/colorsketch/index.scss
@@ -58,6 +58,23 @@
     padding: 0;
     .sketch-picker {
       width: 250px!important;
+
+      .flexbox-fix:last-child {
+        overflow: hidden;
+        >div:nth-child(30) {
+          position: relative;
+          margin-bottom: 20px!important;
+        }
+        >div:nth-child(30)::after {
+          content: ' ';
+          display: block;
+          border-bottom: 1px solid #d9d9d9;
+          position: absolute;
+          width: 300px;
+          bottom: -10px;
+          right: -20px;
+        }
+      }
     }
   }
 }
\ No newline at end of file
diff --git a/src/mob/components/formdragelement/card.jsx b/src/mob/components/formdragelement/card.jsx
index 1ca1c3b..0da78cd 100644
--- a/src/mob/components/formdragelement/card.jsx
+++ b/src/mob/components/formdragelement/card.jsx
@@ -79,10 +79,8 @@
     formItem = (<div className={'am-list-item input ' + (card.place || '')}><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval ? card.initval : <span style={{color: '#bcbcbc'}}>{card.placeholder || <span style={{color: 'transparent'}}>input</span>}</span> }</div>{card.scan && card.scan !== 'false' ? <div className="am-list-extra"><ScanOutlined /></div> : null}</div></div>)
   } else if (card.type === 'number') {
     formItem = (<div className={'am-list-item input ' + (card.place || '')}><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval || 0}</div>{card.placeholder ? <div className="am-list-extra" style={{color: '#999999', width: 'auto', lineHeight: 1.5, height: '22px'}}>{card.placeholder}</div> : null}</div></div>)
-  } else if (card.type === 'number') {
-    formItem = (<div className="am-list-item input"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval || <span style={{color: 'transparent'}}>input</span>}</div></div></div>)
   } else if (card.type === 'select' || card.type === 'link' || card.type === 'cascader') {
-    formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{selectval || '璇烽�夋嫨'}</div><div className="am-list-extra"><RightOutlined /></div></div></div>)
+    formItem = (<div className={'am-list-item picker ' + (card.place || '')}><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{selectval || '璇烽�夋嫨'}</div><div className="am-list-extra"><RightOutlined /></div></div></div>)
   } else if (card.type === 'date') {
     let format = 'YYYY-MM-DD'
     if (card.precision === 'hour') {
@@ -92,14 +90,14 @@
     } else if (card.precision === 'second') {
       format = 'YYYY-MM-DD HH:mm:ss'
     }
-    formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format(format) : '璇烽�夋嫨'}</div><div className="am-list-extra"><RightOutlined /></div></div></div>)
+    formItem = (<div className={'am-list-item picker ' + (card.place || '')}><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format(format) : '璇烽�夋嫨'}</div><div className="am-list-extra"><RightOutlined /></div></div></div>)
   } else if (card.type === 'datemonth') {
-    formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'month').format('YYYY-MM') : '璇烽�夋嫨'}</div><div className="am-list-extra"><RightOutlined /></div></div></div>)
+    formItem = (<div className={'am-list-item picker ' + (card.place || '')}><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'month').format('YYYY-MM') : '璇烽�夋嫨'}</div><div className="am-list-extra"><RightOutlined /></div></div></div>)
   } else if (card.type === 'datetime') {
     formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD HH:mm') : '璇烽�夋嫨'}</div><div className="am-list-extra"><RightOutlined /></div></div></div>)
   } else if (card.type === 'textarea') {
     let height = (card.maxRows || 2) * 25
-    formItem = (<div className="am-list-item check-card">
+    formItem = (<div className={'am-list-item check-card ' + (card.place || '')}>
       <div className="am-list-line">
         <div className="am-input-label">{card.label}</div>
         <div className="am-input-control">
@@ -129,6 +127,8 @@
     formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.linkfield}</div></div></div>)
   } else if (card.type === 'switch') {
     formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-list-switch"><Switch checked={card.initval}/></div></div></div>)
+  } else if (card.type === 'check') {
+    formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-list-switch"><Checkbox checked={card.initval}>{card.checkTip}</Checkbox></div></div></div>)
   } else if (card.type === 'radio') {
     let options = null
     if (card.options && card.options.length > 0) {
@@ -142,7 +142,7 @@
     }
 
     formItem = (
-    <div className={'am-list-item checkbox mk-radio ' + (card.arrange || '')}>
+    <div className={'am-list-item checkbox mk-radio ' + (card.arrange || '') + ' ' + (card.place || '')}>
       <div className="am-list-line">
         <div className="am-input-label">{card.label}</div>
         <div className="am-input-control">
@@ -171,7 +171,7 @@
     }
 
     formItem = (
-      <div className={'am-list-item checkbox ' + (card.arrange || '')}>
+      <div className={'am-list-item checkbox ' + (card.arrange || '') + ' ' + (card.place || '')}>
         <div className="am-list-line">
           <div className="am-input-label">{card.label}</div>
           <div className="am-input-control">
@@ -204,7 +204,7 @@
   } else if (card.type === 'split') {
     formItem = <div className="split-line">{card.label}</div>
   } else if (card.type === 'checkcard') {
-    formItem = (<div className="am-list-item check-card">
+    formItem = (<div className={'am-list-item check-card ' + (card.place || '')}>
       <div className="am-list-line">
         {card.hidelabel !== 'true' ? <div className="am-input-label">{card.label}</div> : null}
         <div className="am-input-control">
@@ -214,6 +214,12 @@
     </div>)
   } else if (card.type === 'vercode') {
     formItem = <div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control"><span style={{color: '#bcbcbc'}}>{card.placeholder || ''}</span></div><div className="am-list-extra" style={{width: 'auto', height: 'auto', backgroundColor: '#fafafa', padding: '0 15px'}}>鑾峰彇楠岃瘉鐮�</div></div></div>
+  }
+
+  let className = `${card.required === 'true' ? 'required' : ''} ${card.type === 'split' ? 'split-wrap' : ''} ${card.splitline === 'false' ? 'no-boder' : ''}`
+
+  if (window.GLOB.formId === card.uuid) {
+    className += ' actived'
   }
 
   let style = {...card.style}
@@ -238,13 +244,12 @@
         <div ref={node => drag(drop(node))} style={{ border: '0.5px solid transparent'}} onDoubleClick={edit}>
           <Form.Item
             style={style}
-            // style={{marginTop: card.marginTop || 0, marginBottom: card.marginBottom || 0}}
-            className={(card.required === 'true' ? ' required' : '') + (card.type === 'split' ? ' split-wrap' : '') + (card.splitline === 'false' ? ' no-boder' : '')}
+            className={className}
           >
             {formItem}
             <div></div>
             {showField && card.field ? <div className="field-name" style={card.writein === 'false' ? {color: 'orange'} : {}}>
-              {card.field}{card.hidden === 'true' || card.type === 'funcvar' ? '锛堥殣钘忥級' : ''}{card.readonly === 'true' ? '锛堝彧璇伙級' : ''}{card.linkField ? <span style={{color: '#1890ff'}}>{`锛堝叧鑱�${card.linkField}锛塦}</span> : ''}{card.supField ? <span style={{color: '#8E44AD'}}>{`锛堜笂绾�${card.supField}锛塦}</span> : ''}
+              {card.field}{card.hidden === 'true' || card.type === 'funcvar' ? '锛堥殣钘忥級' : ''}{card.readonly === 'true' ? '锛堝彧璇伙級' : ''}{card.readin === 'false' ? '锛堟湭濉厖锛�' : ''}{card.linkField ? <span style={{color: '#1890ff'}}>{`锛堝叧鑱�${card.linkField}锛塦}</span> : ''}{card.supField ? <span style={{color: '#8E44AD'}}>{`锛堜笂绾�${card.supField}锛塦}</span> : ''}
             </div> : ''}
           </Form.Item>
         </div>
diff --git a/src/mob/components/formdragelement/index.jsx b/src/mob/components/formdragelement/index.jsx
index bfeaf84..838e79d 100644
--- a/src/mob/components/formdragelement/index.jsx
+++ b/src/mob/components/formdragelement/index.jsx
@@ -62,6 +62,8 @@
     let val = JSON.parse(JSON.stringify(_card))
     val.copyType = 'form'
 
+    _card.$copy = true
+
     delete val.$srcId
     
     let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
diff --git a/src/mob/components/formdragelement/index.scss b/src/mob/components/formdragelement/index.scss
index 436e4e2..5aeda26 100644
--- a/src/mob/components/formdragelement/index.scss
+++ b/src/mob/components/formdragelement/index.scss
@@ -88,6 +88,14 @@
       }
     }
   }
+  .am-list-item:not(.up_down) {
+    .am-list-line {
+      .am-input-label {
+        width: 28%;
+        max-width: 120px;
+      }
+    }
+  }
   .am-list-item.up_down {
     height: auto;
     .am-list-line {
@@ -107,6 +115,31 @@
       }
     }
   }
+  .am-list-item.picker:not(.up_down) {
+    .am-list-line {
+      .am-input-control {
+        padding-right: 0px;
+      }
+    }
+  }
+  .am-list-item.up_down.picker {
+    .am-list-line {
+      .am-input-control {
+        line-height: 40px;
+        padding-right: 20px;
+      }
+      .am-list-extra {
+        top: auto;
+        right: 10px;
+        bottom: 13px;
+      }
+    }
+  }
+  .ant-form-item.actived {
+    .am-input-label {
+      color: #1890ff;
+    }
+  }
   .am-list-item.check-card {
     height: auto;
     .am-list-line {
@@ -117,6 +150,16 @@
       }
       .am-input-label {
         width: auto;
+      }
+    }
+  }
+  .am-list-item.check-card.left_right {
+    .am-list-line {
+      display: flex;
+      .am-input-label {
+        width: 28%;
+        max-width: 120px;
+        line-height: 1;
       }
     }
   }
@@ -225,6 +268,17 @@
       }
     }
   }
+  .am-list-item.checkbox.left_right {
+    .am-list-line {
+      display: flex;
+      .ant-checkbox-group {
+        float: right;
+      }
+      .am-input-control {
+        padding-right: 0px;
+      }
+    }
+  }
   .am-list-item.checkbox.mk-radio {
     .ant-checkbox-inner {
       border-radius: 50%;
@@ -302,6 +356,17 @@
       content: '*';
     }
   }
+  .ant-form-item:not(.required) {
+    .am-input-label::before {
+      display: inline-block;
+      margin-right: 4px;
+      color: transparent;
+      font-size: 14px;
+      font-family: SimSun, sans-serif;
+      line-height: 1;
+      content: '*';
+    }
+  }
   .ant-form-item.no-boder {
     .am-list-line {
       border-bottom: none;
diff --git a/src/mob/components/search/single-search/index.jsx b/src/mob/components/search/single-search/index.jsx
index 514a906..05f64e5 100644
--- a/src/mob/components/search/single-search/index.jsx
+++ b/src/mob/components/search/single-search/index.jsx
@@ -11,6 +11,7 @@
 import './index.scss'
 
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
+const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 
 class SingleSearchComponent extends Component {
   static propTpyes = {
@@ -133,6 +134,7 @@
             <NormalForm title="鎼滅储璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
+            <CopyComponent type="singleSearch" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <DeleteOutlined className="close" onClick={() => this.props.deletecomponent(card.uuid)} />
           </div>
@@ -142,7 +144,7 @@
         <div className="component-name">
           <div className="center" onDoubleClick={() => {
             let oInput = document.createElement('input')
-            oInput.value = card.uuid
+            oInput.value = 'anchor' + card.uuid
             document.body.appendChild(oInput)
             oInput.select()
             document.execCommand('Copy')
diff --git a/src/mob/components/tabs/antv-tabs/options.jsx b/src/mob/components/tabs/antv-tabs/options.jsx
index 21005e5..9c4ddc7 100644
--- a/src/mob/components/tabs/antv-tabs/options.jsx
+++ b/src/mob/components/tabs/antv-tabs/options.jsx
@@ -151,6 +151,7 @@
       options: modules,
       controlFields: [
         {field: 'controlField', notNull: true},
+        {field: 'swiper', values: ['']},
       ],
     },
     {
@@ -162,6 +163,17 @@
       required: true
     },
     {
+      type: 'radio',
+      field: 'swiper',
+      label: '婊戝姩鍒囨崲',
+      initval: setting.swiper || 'false',
+      required: false,
+      options: [
+        {value: 'false', label: '绂佺敤'},
+        {value: 'true', label: '鍚敤'},
+      ],
+    },
+    {
       type: 'text',
       field: 'selectField',
       label: '閫変腑瀛楁',
diff --git a/src/mob/modalconfig/index.jsx b/src/mob/modalconfig/index.jsx
index 8bcad78..285307a 100644
--- a/src/mob/modalconfig/index.jsx
+++ b/src/mob/modalconfig/index.jsx
@@ -20,8 +20,9 @@
 
 const { Panel } = Collapse
 const { confirm } = Modal
-const PasteComponent = asyncComponent(() => import('./pastecomponent'))
+const TableComponent = asyncComponent(() => import('@/menu/modalconfig/tablecomponent'))
 const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
+const PasteForms = asyncComponent(() => import('@/menu/components/share/pasteforms'))
 const DragElement = asyncComponent(() => import('@/mob/components/formdragelement'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 
@@ -61,6 +62,7 @@
   }
 
   componentDidMount () {
+    window.GLOB.formId = ''
     MKEmitter.addListener('submitStyle', this.getStyle)
     MKEmitter.addListener('completeSave', this.completeSave)
   }
@@ -158,7 +160,7 @@
         })
       }
 
-      if (item.type === 'switch') {
+      if (item.type === 'switch' || item.type === 'check') {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -234,6 +236,8 @@
           fieldrepet = true
         }
 
+        delete item.focus
+
         if (item.uuid === res.uuid) {
           if (item.style) {
             res.style = item.style
@@ -252,6 +256,8 @@
         })
         return
       }
+
+      window.GLOB.formId = res.uuid
 
       if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
         this.setState({
@@ -409,49 +415,12 @@
     })
   }
 
-  insert = (config, type) => {
-    if (type === 'forms') {
-      let _config = fromJS(this.state.config).toJS()
-
-      if (_config.fields.length > 0) {
-        let that = this
-        _config.fields = config.fields.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
-
-        confirm({
-          title: '纭畾鏇挎崲琛ㄥ崟鍚楋紵',
-          content: '鍘熻〃鍗曞皢鍒犻櫎銆�',
-          onOk() {
-            that.setState({
-              config: _config
-            })
-          },
-          onCancel() {}
-        })
-      } else {
-        _config.fields = config.fields.map(item => {
-          item.uuid = Utils.getuuid()
-          return item
-        })
-
-        this.setState({
-          config: _config
-        })
-        notification.success({
-          top: 92,
-          message: '绮樿创鎴愬姛锛�',
-          duration: 2
-        })
-      }
-      return
-    }
+  pasteFields = (items) => {
+    let _config = fromJS(this.state.config).toJS()
+    _config.fields = items
 
     this.setState({
-      config
-    }, () => {
-      this.handleForm(config.fields[config.fields.length - 1])
+      config: _config
     })
   }
 
@@ -503,13 +472,16 @@
 
   render () {
     const { btn } = this.props
-    const { config, saving } = this.state
+    const { config, saving, card } = this.state
 
     return (
       <div className="mob-form-board">
         <DndProvider backend={HTML5Backend}>
           <div className="tools">
             <Collapse accordion defaultActiveKey="1" bordered={false}>
+              <Panel header="鍩烘湰淇℃伅" key="0">
+                <TableComponent />
+              </Panel>
               <Panel header="琛ㄥ崟" key="1">
                 <div className="search-element">
                   {SearchItems.map((item, index) => {
@@ -525,7 +497,7 @@
             <Button type="primary" id="save-modal-config" loading={saving} onClick={this.submitConfig}>淇濆瓨</Button>
             <Button onClick={this.cancelConfig}>杩斿洖</Button>
             <Button type="primary" style={{background: '#26C281', border: 'none'}} onClick={this.triggerCopy}>澶嶅埗</Button>
-            <PasteComponent config={config} updateConfig={this.insert} />
+            <PasteForms type="toolbar" config={config} update={this.pasteFields}/>
             <Button type="danger" onClick={this.clearConfig}>娓呯┖</Button>
             <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
           </div>
@@ -552,7 +524,7 @@
           </div>
         </DndProvider>
         <Modal
-          title="缂栬緫"
+          title={card && card.$copy ? '澶嶅埗' : '缂栬緫'}
           visible={this.state.visible}
           width={950}
           maskClosable={false}
@@ -562,7 +534,7 @@
           destroyOnClose
         >
           <ModalForm
-            card={this.state.card}
+            card={card}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
             standardform={this.state.standardform}
diff --git a/src/pc/components/login/normal-login/index.jsx b/src/pc/components/login/normal-login/index.jsx
index 60a3e17..e5e741d 100644
--- a/src/pc/components/login/normal-login/index.jsx
+++ b/src/pc/components/login/normal-login/index.jsx
@@ -197,7 +197,7 @@
           <div className="center">
             <div className="title" onDoubleClick={() => {
               let oInput = document.createElement('input')
-              oInput.value = card.uuid
+              oInput.value = 'anchor' + card.uuid
               document.body.appendChild(oInput)
               oInput.select()
               document.execCommand('Copy')
diff --git a/src/pc/components/navbar/normal-navbar/index.jsx b/src/pc/components/navbar/normal-navbar/index.jsx
index f14e91b..c25dd43 100644
--- a/src/pc/components/navbar/normal-navbar/index.jsx
+++ b/src/pc/components/navbar/normal-navbar/index.jsx
@@ -121,7 +121,9 @@
   }
 
   changeMenu = (menu) => {
-    if (menu.property === 'link') {
+    if (menu.property === 'text') {
+      return
+    } else if (menu.property === 'link') {
       window.open(menu.link)
       return
     }
diff --git a/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx b/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx
index 41ab933..531c3b9 100644
--- a/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx
+++ b/src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx
@@ -109,11 +109,12 @@
                 <Radio.Group onChange={this.changeProperty}>
                   <Radio value="link">閾炬帴</Radio>
                   <Radio value="linkmenu">鍏宠仈鑿滃崟</Radio>
+                  <Radio value="text">鏂囨湰</Radio>
                 </Radio.Group>
               )}
             </Form.Item>
           </Col>
-          <Col span={22}>
+          {property !== 'text' ? <Col span={22}>
             <Form.Item label="鎵撳紑鏂瑰紡">
               {getFieldDecorator('open', {
                 initialValue: menu.open || 'blank'
@@ -124,7 +125,7 @@
                 </Radio.Group>
               )}
             </Form.Item>
-          </Col>
+          </Col> : null}
           {property === 'link' ? <Col span={22}>
             <Form.Item label="閾炬帴鍦板潃">
               {getFieldDecorator('link', {
diff --git a/src/router/index.js b/src/router/index.js
index b384ad4..5a7b168 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,7 +1,5 @@
 import React, {Component} from 'react'
 import {HashRouter, Switch, Route, Redirect} from 'react-router-dom'
-import md5 from 'md5'
-import moment from 'moment'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncLoadComponent from '@/utils/asyncLoadComponent'
 
@@ -28,59 +26,36 @@
 const SystemProc = asyncLoadComponent(() => import('@/views/systemproc'))
 
 const routers = [
-  {path: '/login', name: 'login', component: Login, auth: false},
-  {path: '/main', name: 'main', component: Main, auth: true},
-  {path: '/pay/:param', name: 'pay', component: Pay, auth: false},
-  {path: '/print/:param', name: 'print', component: PrintT, auth: false},
-  {path: '/ssologin/:param', name: 'ssologin', component: Sso, auth: false},
-  {path: '/design', name: 'design', component: Design, auth: true},
-  {path: '/appmanage', name: 'appmanage', component: AppManage, auth: true},
-  {path: '/appcheck', name: 'appcheck', component: AppCheck, auth: true},
-  {path: '/pcdesign/:param', name: 'pcdesign', component: PCDesign, auth: true},
-  {path: '/mobdesign/:param', name: 'mobdesign', component: MobDesign, auth: true},
-  {path: '/imdesign/:param', name: 'imdesign', component: ImDesign, auth: true},
-  {path: '/menudesign/:param', name: 'menudesign', component: MenuDesign, auth: true},
-  {path: '/basedesign/:param', name: 'basedesign', component: BaseDesign, auth: true},
-  {path: '/tabledesign/:param', name: 'tabledesign', component: TableDesign, auth: true},
-  {path: '/billprint/:param', name: 'billprint', component: BillPrint, auth: true},
-  {path: '/docprint/:menuId', name: 'docprint', component: BillPrint, auth: false},
-  {path: '/docprint/:menuId/:id', name: 'docprint', component: BillPrint, auth: false},
-  {path: '/tab/:menuId', name: 'tab', component: MainParams, auth: false},
-  {path: '/role/:param', name: 'role', component: RoleManage, auth: true},
-  {path: '/hs', name: 'hs', component: SystemFunc, auth: true},
-  {path: '/proc', name: 'proc', component: SystemProc, auth: true},
-  {path: '/interface', name: 'interface', component: Interface, auth: true}
+  {path: '/login', name: 'login', component: Login},
+  {path: '/main', name: 'main', component: Main},
+  {path: '/pay/:param', name: 'pay', component: Pay},
+  {path: '/print/:param', name: 'print', component: PrintT},
+  {path: '/ssologin/:param', name: 'ssologin', component: Sso},
+  {path: '/design', name: 'design', component: Design},
+  {path: '/appmanage', name: 'appmanage', component: AppManage},
+  {path: '/appcheck', name: 'appcheck', component: AppCheck},
+  {path: '/pcdesign/:param', name: 'pcdesign', component: PCDesign},
+  {path: '/mobdesign/:param', name: 'mobdesign', component: MobDesign},
+  {path: '/imdesign/:param', name: 'imdesign', component: ImDesign},
+  {path: '/menudesign/:param', name: 'menudesign', component: MenuDesign},
+  {path: '/basedesign/:param', name: 'basedesign', component: BaseDesign},
+  {path: '/tabledesign/:param', name: 'tabledesign', component: TableDesign},
+  {path: '/billprint/:param', name: 'billprint', component: BillPrint},
+  {path: '/docprint/:menuId', name: 'docprint', component: BillPrint},
+  {path: '/docprint/:menuId/:id', name: 'docprint', component: BillPrint},
+  {path: '/tab/:menuId', name: 'tab', component: MainParams},
+  {path: '/role/:param', name: 'role', component: RoleManage},
+  {path: '/hs', name: 'hs', component: SystemFunc},
+  {path: '/proc', name: 'proc', component: SystemProc},
+  {path: '/interface', name: 'interface', component: Interface}
 ]
 
 export default class RouteConfig extends Component {
-  controlRoute (item, props) {
-    if (!item.auth) { // 涓嶉渶瑕佹巿鏉冿紝鐩存帴璺宠浆
-      return (<item.component {...props}/>)
-    }
-    
-    let userId = sessionStorage.getItem('UserID') // 鍒ゆ柇鐧诲綍淇℃伅鏄惁瀛樺湪锛屾敞鐢ㄦ埛鍙兘淇濆瓨涓婚〉閾炬帴
-    let authCode = localStorage.getItem(window.location.href.split('#')[0] + 'AuthCode') // 鍒ゆ柇绯荤粺鏄惁鍦ㄦ巿鏉冩湡闄愬唴
-    let _s = md5('mksoft' + moment().format('YYYYMMDD'))
-    let isauth = authCode && authCode.includes(_s)
-    let key = md5(window.GLOB.appId + 'minke_software' + window.GLOB.appkey).toUpperCase().substr(-6)
-    let key1 = window.GLOB.licenseKey ? window.GLOB.licenseKey.substring(0, 6) : ''
-
-    if (key1 === key) {
-      isauth = true
-    }
-
-    if (userId && isauth) {
-      return (<item.component {...props}/>)
-    } else {
-      return (<Redirect to={{ pathname: '/login'}}/>)
-    }
-  }
-
   render () {
     return (
       <HashRouter>
         <Switch>
-          {routers.map((item, index) => <Route key={index} path={item.path} name={item.name} exact render={ props => this.controlRoute(item, props)}/>)}
+          {routers.map((item, index) => <Route key={index} path={item.path} name={item.name} exact render={ props => <item.component {...props}/>}/>)}
           <Redirect exact from="/" to="login"/>
           <Route component= {NotFound}/>
         </Switch>
diff --git a/src/tabviews/basetable/index.jsx b/src/tabviews/basetable/index.jsx
index e6a783a..59932b9 100644
--- a/src/tabviews/basetable/index.jsx
+++ b/src/tabviews/basetable/index.jsx
@@ -316,6 +316,8 @@
             return false
           } else if (col.Hide === 'true') {
             return false
+          } else if (col.type === 'action') {
+            col.type = 'custom'
           }
           
           if (col.type === 'number') {
@@ -334,8 +336,58 @@
               return false
             }
           } else if (col.type === 'custom') {
-            col.elements = col.elements.map(cell => {
-              if (['text', 'number', 'formula'].includes(cell.eleType)) {
+            col.elements = col.elements.filter(cell => {
+              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
+                    }
+                  }
+                }
+
+                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]
+              } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
                 if (!cell.height) {
                   cell.innerHeight = 'auto'
                 }
@@ -346,8 +398,12 @@
                   }
                 }
               }
-              return cell
+              return true
             })
+
+            if (col.elements.length === 0) {
+              return false
+            }
           }
     
           if (col.linkmenu && col.linkmenu.length > 0) {
@@ -377,10 +433,29 @@
           cell.$view = 'popview'
           cell.$toolbtn = true
 
-          if (cell.syncComponentId === item.setting.supModule) {
-            cell.syncComponentId = ''
-            if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-              cell.execSuccess = 'mainline'
+          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
+              }
             }
           }
 
@@ -399,43 +474,6 @@
           return skip || permAction[cell.uuid]
         })
       }
-
-      item.cols = item.cols.filter(col => {
-        if (col.type !== 'action') return true
-        col.elements = col.elements.filter(cell => {
-          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 === item.setting.supModule) {
-            cell.syncComponentId = ''
-            if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-              cell.execSuccess = 'mainline'
-            }
-          }
-
-          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]
-        })
-        return col.elements.length !== 0
-      })
       
       return true
     })
diff --git a/src/tabviews/basetable/index.scss b/src/tabviews/basetable/index.scss
index ca8acd1..8581886 100644
--- a/src/tabviews/basetable/index.scss
+++ b/src/tabviews/basetable/index.scss
@@ -43,12 +43,6 @@
   .ant-btn-link:hover {
     opacity: 0.8;
   }
-  .button-list.toolbar-button {
-    button {
-      height: auto;
-      min-height: 28px;
-    }
-  }
 }
 .custom-table-wrap.loading {
   .ant-spin-spinning:not(.view-spin) {
diff --git a/src/tabviews/calendar/index.scss b/src/tabviews/calendar/index.scss
index 74f1a08..23d25cf 100644
--- a/src/tabviews/calendar/index.scss
+++ b/src/tabviews/calendar/index.scss
@@ -6,7 +6,7 @@
   .box404 {
     padding-top: 30px;
   }
-  >.top-search {
+  >.mk-search-wrap {
     padding: 0px 24px 5px;
     border-bottom: 1px solid #efefef;
   }
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index a1c9987..2428d19 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -4,8 +4,6 @@
 import { notification, Spin, Tabs, Switch, 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 options from '@/store/options.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -41,7 +39,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id
     BID: null,            // 椤甸潰璺宠浆鏃舵惡甯D
     loadingview: true,    // 椤甸潰鍔犺浇涓�
@@ -111,7 +108,7 @@
         this.setState({
           loadingview: false,
           viewlost: true,
-          lostmsg: this.state.dict['main.view.unenabled']
+          lostmsg: '鎶辨瓑锛屾偍璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��'
         })
         return
       }
@@ -784,7 +781,7 @@
           item.$Index = start + index + ''
 
           if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField])) {
+            if (setting.controlVal.includes(item[setting.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -1198,7 +1195,6 @@
                       setting={setting}
                       actions={actions}
                       columns={columns}
-                      dict={this.state.dict}
                       MenuID={MenuID}
                       selectedData={selectedData}
                     />
@@ -1214,7 +1210,6 @@
                       setting={setting}
                       columns={columns}
                       pageSize={pageSize}
-                      dict={this.state.dict}
                       data={this.state.data}
                       total={this.state.total}
                       loading={this.state.loading}
@@ -1262,7 +1257,6 @@
               setting={setting}
               actions={actions}
               columns={columns}
-              dict={this.state.dict}
               MenuID={MenuID}
               selectedData={selectedData}
             />
@@ -1278,7 +1272,6 @@
               setting={setting}
               columns={columns}
               pageSize={pageSize}
-              dict={this.state.dict}
               data={this.state.data}
               total={this.state.total}
               loading={this.state.loading}
@@ -1313,8 +1306,8 @@
         }
         {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} dict={this.state.dict} /> : null}
-        {!window.GLOB.mkHS && setting ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts || []}/> : 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/commontable/index.scss b/src/tabviews/commontable/index.scss
index 242cdf2..12b410e 100644
--- a/src/tabviews/commontable/index.scss
+++ b/src/tabviews/commontable/index.scss
@@ -6,7 +6,7 @@
   .box404 {
     padding-top: 30px;
   }
-  >.top-search {
+  >.mk-search-wrap {
     padding: 0px 24px 5px;
     border-bottom: 1px solid #efefef;
   }
diff --git a/src/tabviews/custom/components/card/balcony/index.jsx b/src/tabviews/custom/components/card/balcony/index.jsx
index 724f839..1697e66 100644
--- a/src/tabviews/custom/components/card/balcony/index.jsx
+++ b/src/tabviews/custom/components/card/balcony/index.jsx
@@ -86,7 +86,7 @@
 
     if (_config.wrap.position === 'fixed' || _config.wrap.position === 'absolute') {
       _config.style.position = _config.wrap.position
-      _config.style.zIndex = 3
+      _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 || ''
@@ -94,7 +94,7 @@
       _config.style.transform = _config.wrap.transform || ''
       _config.style.width = _config.wrap.realwidth || ''
     } else {
-      _config.style.zIndex = 3
+      _config.style.zIndex = 1
       _config.style.left = _config.wrap.left || ''
       _config.style.right = _config.wrap.right || ''
       _config.style.top = _config.wrap.top || ''
@@ -364,9 +364,9 @@
         loading: false
       })
 
-      if (config.timer && config.clearField) {
+      if (config.timer && config.clearField && result.data && result.data[0]) {
         let vals = (config.clearValue || '').split(',')
-        if (vals.includes(_data[config.clearField])) {
+        if (vals.includes(result.data[0][config.clearField])) {
           this.timer && this.timer.stop()
         }
       }
diff --git a/src/tabviews/custom/components/card/balcony/index.scss b/src/tabviews/custom/components/card/balcony/index.scss
index 11921aa..d13e2fa 100644
--- a/src/tabviews/custom/components/card/balcony/index.scss
+++ b/src/tabviews/custom/components/card/balcony/index.scss
@@ -5,6 +5,7 @@
   background-size: cover;
   position: relative;
   display: flex;
+  overflow: hidden;
 
   >.check-all {
     width: 70px;
diff --git a/src/tabviews/custom/components/card/cardItem/index.jsx b/src/tabviews/custom/components/card/cardItem/index.jsx
index 92777c5..c378930 100644
--- a/src/tabviews/custom/components/card/cardItem/index.jsx
+++ b/src/tabviews/custom/components/card/cardItem/index.jsx
@@ -40,14 +40,16 @@
     }
   }
 
-  openView = () => {
+  openView = (e) => {
     const { card, data, cards, onClick } = this.props
 
     onClick && onClick()
     
     if (!card.setting.click || data.$disabled) return
 
-    if (card.setting.click === 'menus' && cards.subtype === 'datacard' && card.$cardType !== 'extendCard') {
+    e.stopPropagation()
+
+    if (card.setting.click === 'menus') {
       let menu = null
       
       if (card.menus && card.menus.length > 0) {
@@ -57,14 +59,7 @@
           menu = m
         })
       }
-      if (!menu || !menu.MenuID) {
-        notification.warning({
-          top: 92,
-          message: '鏈煡璇㈠埌鑿滃崟淇℃伅锛�',
-          duration: 5
-        })
-        return
-      }
+      if (!menu) return
 
       let newtab = {
         MenuID: menu.MenuID,
@@ -79,12 +74,13 @@
 
         Object.keys(data).forEach(key => {
           if (/^\$/.test(key)) return
+          if (key === 'children') return
           newtab.param[key] = data[key]
         })
       }
 
       MKEmitter.emit('modifyTabs', newtab, true)
-    } else if (card.setting.click === 'menu' && card.setting.menu) {
+    } else if (card.setting.click === 'menu') {
       let menuId = card.setting.MenuID || card.setting.menu.slice(-1)[0]
       let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
 
@@ -116,6 +112,7 @@
         
         Object.keys(data).forEach(key => {
           if (/^\$/.test(key)) return
+          if (key === 'children') return
           newtab.param[key] = data[key]
         })
       }
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index 8d010da..030841b 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -24,6 +24,7 @@
 const PrintButton = asyncComponent(() => import('@/tabviews/zshare/actionList/printbutton'))
 const FuncMegvii = asyncComponent(() => import('@/tabviews/zshare/actionList/funcMegvii'))
 const FuncZip = asyncComponent(() => import('@/tabviews/zshare/actionList/funczip'))
+const 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'))
@@ -35,6 +36,37 @@
   '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%'
 }
 
+class TextCell extends Component {
+  componentDidMount() {
+    if (this.node && this.node.scrollHeight > this.node.offsetHeight) {
+      this.node.style.display = 'block'
+    }
+  }
+
+  componentDidUpdate() {
+    if (this.node) {
+      if (this.node.scrollHeight > this.node.offsetHeight) {
+        this.node.style.display = 'block'
+      } else {
+        this.node.style.display = 'flex'
+      }
+    }
+  }
+
+  render() {
+    const { card, className, value } = this.props
+
+    let lineStyle = {height: card.innerHeight}
+    lineStyle.display = 'flex'
+    lineStyle.alignItems = card.alignItems
+    lineStyle.justifyContent = card.style.textAlign || 'left'
+  
+    return (
+      <div ref={ref => this.node = ref} className={className} style={lineStyle}>{value}</div>
+    )
+  }
+}
+
 class CardCellComponent extends Component {
   static propTpyes = {
     cards: PropTypes.object,         // 鑿滃崟閰嶇疆淇℃伅
@@ -44,10 +76,8 @@
     elements: PropTypes.array,       // 鍏冪礌闆�
   }
 
-  state = {}
-
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props), fromJS(nextProps))
+    return !is(fromJS(this.props), fromJS(nextProps))
   }
 
   /**
@@ -70,7 +100,7 @@
       node && node.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'})
     }
 
-    if (!card.link) return
+    if (!card.link || (card.linkType === 'qywx' || card.linkType === 'linkmenu')) return
     e.stopPropagation()
     
     let url = ''
@@ -100,6 +130,8 @@
         _url = _url + `?subject=鏉ヨ嚜${fullName}鐨勯偖浠禶
       }
       window.open(_url)
+      return
+    } else if (card.linkType === 'other' && /^@menuid@/ig.test(url)) {
       return
     }
 
@@ -249,15 +281,15 @@
           className = mark.signType
         }
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
             <div style={card.style}>
               <div className={'ant-mk-text line1' + className} style={{height: card.innerHeight || 'auto'}}><span className="sequence-wrap" style={_style}>{data.$Index || ''}</span></div>
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'text') {
         let val = ''
-        let _style = card.style ? {...card.style} : {}
+        let _style = {...card.style}
   
         if (card.datatype === 'static') {
           val = card.value || ''
@@ -267,12 +299,25 @@
             let city = sessionStorage.getItem('city') || ''
             let bid = data.$$BID || ''
             val = val.replace(/@username@/ig, userName).replace(/@fullName@/ig, fullName).replace(/@mk_city@/ig, city).replace(/@bid@/ig, bid)
+          } else if (/@month@/ig.test(val)) {
+            val = val.replace(/@month@/ig, new Date().toLocaleString('en-US', { month: 'long' }))
+          } else if (/@week@/ig.test(val)) {
+            val = val.replace(/@week@/ig, (() => {
+              let day = new Date().getDay()
+              let weeks = ['鏄熸湡鏃�', '鏄熸湡涓�', '鏄熸湡浜�', '鏄熸湡涓�', '鏄熸湡鍥�', '鏄熸湡浜�', '鏄熸湡鍏�']
+              return weeks[day]
+            })())
+          } else if (/@day@/ig.test(val)) {
+            val = val.replace(/@day@/ig, (() => {
+              let day = new Date().getDate()
+              return day < 10 ? '0' + day : day
+            })())
           }
         } else if (data.hasOwnProperty(card.field)) {
           val = data[card.field]
         }
   
-        if (val === '' && card.noValue === 'hide') { // 绌哄�奸殣钘�
+        if (!val && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
         }
   
@@ -362,6 +407,9 @@
               val = <Paragraph copyable={{ text: orival }}>{val}</Paragraph>
             }
           }
+        } else if (card.fixStyle === 'alone') {
+          let _s = {fontSize: card.fixSize, color: card.fixColor, marginLeft: card.fixLeft, marginRight: card.fixRight}
+          val = <span style={_s}>{card.prefix || ''}{card.postfix || ''}</span>
         }
   
         let className = ''
@@ -389,15 +437,16 @@
         }
   
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
             <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
-              <div className={'ant-mk-text line' + (card.height || '') + className} style={{height: card.innerHeight || 'auto'}}>{val}</div>
+              {card.alignItems ? <TextCell card={card} className={'ant-mk-text line' + (card.height || '') + className} value={val}/> : 
+              <div className={'ant-mk-text line' + (card.height || '') + className} style={{height: card.innerHeight}}>{val}</div>}
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'number') {
         let val = ''
-        let _style = card.style ? {...card.style} : {}
+        let _style = {...card.style}
   
         if (card.datatype === 'static') {
           val = card.value
@@ -409,7 +458,8 @@
           return null
         }
   
-        if (typeof(val) === 'number') {
+        if (!isNaN(val) && val !== '') {
+          val = +val
           if (card.round) {
             val = Math.round(val * card.round) / card.round
           }
@@ -439,6 +489,9 @@
           } else {
             val = `${card.prefix || ''}${val}${card.postfix || ''}`
           }
+        } else if (card.fixStyle === 'alone') {
+          let _s = {fontSize: card.fixSize, color: card.fixColor, marginLeft: card.fixLeft, marginRight: card.fixRight}
+          val = <span style={_s}>{card.prefix || ''}{card.postfix || ''}</span>
         }
         
         let className = ''
@@ -456,18 +509,18 @@
           }
           className = mark.signType
         }
-  
+
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <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 || '') + className} style={{height: card.innerHeight || 'auto'}}>{val}</div>
+              {card.alignItems ? <TextCell card={card} className={'ant-mk-text line' + (card.height || '') + className} value={val}/> : 
+              <div className={'ant-mk-text line' + (card.height || '') + className} style={{height: card.innerHeight}}>{val}</div>}
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'icon') {
         let val = ''
         let icon = ''
-        let height = card.innerHeight
 
         if (card.datatype === 'dynamic') {
           icon = data[card.field] || ''
@@ -478,20 +531,6 @@
         if (!icon && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
         }
-
-        if (!height) { // 鍏煎
-          let fontSize = 14
-          let lineHeight = 1.5
-    
-          if (card.style.fontSize) {
-            fontSize = parseInt(card.style.fontSize)
-          }
-          if (card.style.lineHeight) {
-            lineHeight = parseFloat(card.style.lineHeight)
-          }
-    
-          height = fontSize * lineHeight
-        }
   
         if (data.hasOwnProperty(card.tooltip)) {
           val = data[card.tooltip]
@@ -500,13 +539,13 @@
         }
   
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <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: height}} type={icon}/>
-              </Tooltip> : <MkIcon className="ant-mk-icon" style={{height: height}} type={icon}/>}
+                <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>
+              </Tooltip> : <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>}
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'slider') {
         let val = 0
@@ -530,15 +569,15 @@
         }
   
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
             <div style={card.style}>
               <MkProgress value={val} config={card} color={color}/>
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'picture') {
         let _imagestyle = {}
-        let _style = card.style ? {margin: '0 auto', ...card.style} : {}
+        let _style = {margin: '0 auto', ...card.style}
         let url = ''
         if (card.maxWidth) {
           _style.maxWidth = card.maxWidth
@@ -582,22 +621,22 @@
         let urls = url ? url.split(',').filter(Boolean) : ['']
 
         urls.forEach((u, i) => {
-          contents.push(<Col key={card.uuid + i} style={_style_} span={card.width}>
+          contents.push(<div className={'ant-col ant-col-' + card.width} key={card.uuid + i} style={_style_} span={card.width}>
             <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
               <MkPicture style={_imagestyle} scale={scale} url={u} urls={urls}/>
             </div>
-          </Col>)
+          </div>)
         })
       } else if (card.eleType === 'splitline') {
         let _borderWidth = card.borderWidth === undefined ? 1 : card.borderWidth
         _style_ = _style_ || {}
         _style_.minHeight = _borderWidth
         contents.push(
-          <Col key={card.uuid} span={card.width} style={_style_}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} span={card.width} style={_style_}>
             <div style={card.style}>
               <div className="ant-mk-splitline" style={{borderColor: card.color, borderWidth: _borderWidth}}></div>
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'barcode') {
         let val = ''
@@ -608,18 +647,18 @@
           val = data[card.field] || ''
         }
   
-        if (val === '' && card.noValue === 'hide') { // 绌哄�奸殣钘�
+        if (!val && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
         }
   
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
             <div style={card.style}>
               <div style={{height: card.innerHeight || 25}}>
                 {val ? <BarCode card={card} value={val}/> : null}
               </div>
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'video') {
         let url = ''
@@ -630,7 +669,7 @@
           url = data[card.field] || ''
         }
   
-        if (url === '' && card.noValue === 'hide') { // 绌哄�奸殣钘�
+        if (!url && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
         }
   
@@ -646,11 +685,11 @@
   
         urls.forEach((u, i) => {
           contents.push(
-            <Col key={card.uuid + i} style={_style_} span={card.width}>
+            <div className={'ant-col ant-col-' + card.width} key={card.uuid + i} style={_style_} span={card.width}>
               <div className="video-wrap" style={card.style}>
                 <Video card={card} poster={poster} value={u}/>
               </div>
-            </Col>
+            </div>
           )
         })
       } else if (card.eleType === 'qrcode') {
@@ -662,18 +701,18 @@
           val = data[card.field] || ''
         }
   
-        if (val === '' && card.noValue === 'hide') { // 绌哄�奸殣钘�
+        if (!val && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
         }
   
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
             <div style={card.style}>
               <div style={{minHeight: card.qrWidth || 50}}>
                 {val ? <QrCode card={card} value={val}/> : null}
               </div>
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'currentDate') {
         let val = moment().format(card.dateFormat || 'YYYY-MM-DD')
@@ -686,16 +725,16 @@
         }
   
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
             <div style={card.style}>
               <div className="ant-mk-text line1" style={{height: card.innerHeight || 'auto'}}>{val}</div>
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'formula') {
         let val = 0
-        let _style = card.style ? {...card.style} : {}
-  
+        let _style = {...card.style}
+
         if (card.$sync) {
           if (card.eval === 'false') {
             val = ''
@@ -711,6 +750,10 @@
                 // eslint-disable-next-line
                 _val = eval(_val)
               } catch (e) {
+                if (window.debugger) {
+                  console.info(_val)
+                  console.warn(e)
+                }
                 _val = 0
               }
             }
@@ -719,32 +762,47 @@
   
             val += _val
           })
+        } else if (data && data.$$empty) {
+          val = ''
         } else if (data) {
           let _val = card.formula
           Object.keys(data).forEach(key => {
             let reg = new RegExp('@' + key + '@', 'ig')
             _val = _val.replace(reg, data[key])
           })
-  
+
           if (card.eval !== 'false') {
             try {
               // eslint-disable-next-line
               _val = eval(_val)
             } catch (e) {
+              if (window.debugger) {
+                console.info(_val)
+                console.warn(e)
+              }
               _val = ''
             }
           }
   
           val = _val === undefined ? '' : _val
         }
-  
-        if (val === '' && card.noValue === 'hide') { // 绌哄�奸殣钘�
+
+        if (!val && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
+        }
+
+        if (card.round && typeof(val) === 'number') {
+          val = Math.round(val * card.round) / card.round
+          val = val.toFixed(card.decimal)
         }
   
         if (val !== '') {
           if (val && typeof(val) === 'string') {
-            val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+            val = val.replace(/\n/ig, '<br/>')
+            if (!/<(span|div|p|a|img)\s/g.test(val)) {
+              val = val.replace(/\s/ig, '&nbsp;')
+            }
+
             val = <span dangerouslySetInnerHTML={{__html: val}}></span>
           }
   
@@ -752,10 +810,13 @@
             let _s = {fontSize: card.fixSize, color: card.fixColor, marginLeft: card.fixLeft, marginRight: card.fixRight}
             val = <><span style={_s}>{card.prefix || ''}</span>{val}<span style={_s}>{card.postfix || ''}</span></>
           } else {
-            val = `${card.prefix || ''}${val}${card.postfix || ''}`
+            val = <>{card.prefix || ''}{val}{card.postfix || ''}</>
           }
+        } else if (card.fixStyle === 'alone') {
+          let _s = {fontSize: card.fixSize, color: card.fixColor, marginLeft: card.fixLeft, marginRight: card.fixRight}
+          val = <span style={_s}>{card.prefix || ''}{card.postfix || ''}</span>
         }
-  
+
         let className = ''
         if (card.marks) {
           let mark = getMark(card.marks, data, _style)
@@ -771,13 +832,14 @@
           }
           className = mark.signType
         }
-  
+
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <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 || '') + className} style={{height: card.innerHeight || 'auto'}}>{val}</div>
+              {card.alignItems ? <TextCell card={card} className={'ant-mk-text line' + (card.height || '') + className} value={val}/> : 
+              <div className={'ant-mk-text line' + (card.height || '') + className} style={{height: card.innerHeight}}>{val}</div>}
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'color') {
         let color = ''
@@ -788,7 +850,7 @@
           color = data[card.field] || ''
         }
   
-        if (color === '' && card.noValue === 'hide') { // 绌哄�奸殣钘�
+        if (!color && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
         }
 
@@ -805,7 +867,7 @@
         }
 
         contents.push(
-          <Col key={card.uuid} style={_style_} span={card.width}>
+          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
             <div className="ant-mk-color" style={card.style}>
               <div style={_bgstyle} onClick={(e) => {
                 if (card.copyable === 'true') {
@@ -822,7 +884,7 @@
                 }
               }}></div>
             </div>
-          </Col>
+          </div>
         )
       } else if (card.eleType === 'button') {
         let _disabled = data.$disabled
@@ -843,7 +905,7 @@
   
         if (['exec', 'prompt', 'pop', 'form'].includes(card.OpenType)) {
           contents.push(
-            <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
               <NormalButton
                 btn={card}
                 BID={data.$$BID}
@@ -853,11 +915,11 @@
                 columns={cards.columns}
                 selectedData={_data}
               />
-            </Col>
+            </div>
           )
         } else if (card.OpenType === 'excelIn') {
           contents.push(
-            <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
               <ExcelInButton
                 btn={card}
                 BID={data.$$BID}
@@ -866,11 +928,11 @@
                 setting={cards.setting}
                 selectedData={_data}
               />
-            </Col>
+            </div>
           )
         } else if (card.OpenType === 'excelOut') {
           contents.push(
-            <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
               <ExcelOutButton
                 btn={card}
                 BID={data.$$BID}
@@ -879,11 +941,11 @@
                 setting={cards.setting}
                 selectedData={_data}
               />
-            </Col>
+            </div>
           )
         } else if (card.OpenType === 'popview') {
           contents.push(
-            <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
               <PopupButton
                 btn={card}
                 BID={data.$$BID}
@@ -892,11 +954,11 @@
                 setting={cards.setting}
                 selectedData={_data}
               />
-            </Col>
+            </div>
           )
         } else if (card.OpenType === 'tab') {
           contents.push(
-            <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
               <TabButton
                 btn={card}
                 BID={data.$$BID}
@@ -904,23 +966,23 @@
                 disabled={_disabled}
                 selectedData={_data}
               />
-            </Col>
+            </div>
           )
         } else if (card.OpenType === 'innerpage') {
           contents.push(
-            <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+            <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
               <NewPageButton
                 btn={card}
                 BData={data.$$BData || ''}
                 disabled={_disabled}
                 selectedData={_data}
               />
-            </Col>
+            </div>
           )
         } else if (card.OpenType === 'funcbutton') {
           if (card.funcType === 'changeuser' || card.funcType === 'closetab') {
             contents.push(
-              <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                 <ChangeUserButton
                   btn={card}
                   BID={data.$$BID}
@@ -929,11 +991,11 @@
                   setting={cards.setting}
                   selectedData={_data}
                 />
-              </Col>
+              </div>
             )
           } else if (card.funcType === 'print') {
             contents.push(
-              <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                 <PrintButton
                   btn={card}
                   BID={data.$$BID}
@@ -943,11 +1005,11 @@
                   columns={cards.columns}
                   selectedData={_data}
                 />
-              </Col>
+              </div>
             )
           } else if (card.funcType === 'megvii') {
             contents.push(
-              <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                 <FuncMegvii
                   btn={card}
                   BID={data.$$BID}
@@ -955,11 +1017,11 @@
                   setting={cards.setting}
                   selectedData={_data}
                 />
-              </Col>
+              </div>
             )
           } else if (card.funcType === 'filezip') {
             contents.push(
-              <Col key={card.uuid} className="mk-cell-btn" style={_style_} span={card.width}>
+              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
                 <FuncZip
                   btn={card}
                   BID={data.$$BID}
@@ -967,7 +1029,17 @@
                   setting={cards.setting}
                   selectedData={_data}
                 />
-              </Col>
+              </div>
+            )
+          } else if (card.funcType === 'addline' || card.funcType === 'delline') {
+            contents.push(
+              <div className={'ant-col mk-cell-btn ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+                <EditLine
+                  btn={card}
+                  disabled={_disabled}
+                  selectedData={_data}
+                />
+              </div>
             )
           }
         }
@@ -978,9 +1050,12 @@
   }
 
   render() {
+    const { cardCell } = this.props
+    
     return (
-      <div className="card-cell-list">
+      <div className={'card-cell-list ' + (cardCell && cardCell.setting && cardCell.setting.layout === 'flex' ? 'mk-flex' : '')}>
         {this.getContent()}
+        <Col style={{display: 'none'}} span={24}></Col>
       </div>
     )
   }
diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss
index 2ce260c..4fc1ddf 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.scss
+++ b/src/tabviews/custom/components/card/cardcellList/index.scss
@@ -193,9 +193,233 @@
     width: 26px;
     height: 26px;
   }
+
+  .ant-col[class*="x"] {
+    float: left;
+    box-sizing: border-box;
+  }
+  >.ant-col-0x {
+    width: 2.08333333%;
+  }
+  >.ant-col-1x {
+    width: 6.25%;
+  }
+  >.ant-col-2x {
+    width: 10.41666667%;
+  }
+  >.ant-col-3x {
+    width: 14.58333333%;
+  }
+  >.ant-col-4x {
+    width: 18.75%;
+  }
+  >.ant-col-5x {
+    width: 22.91666667%;
+  }
+  >.ant-col-6x {
+    width: 27.08333333%;
+  }
+  >.ant-col-7x {
+    width: 31.25%;
+  }
+  >.ant-col-8x {
+    width: 35.41666667%;
+  }
+  >.ant-col-9x {
+    width: 39.58333333%;
+  }
+  >.ant-col-10x {
+    width: 43.75%;
+  }
+  >.ant-col-11x {
+    width: 47.91666667%;
+  }
+  >.ant-col-12x {
+    width: 52.08333333%;
+  }
+  >.ant-col-13x {
+    width: 56.25%;
+  }
+  >.ant-col-14x {
+    width: 60.41666667%;
+  }
+  >.ant-col-15x {
+    width: 64.58333333%;
+  }
+  >.ant-col-16x {
+    width: 68.75%;
+  }
+  >.ant-col-17x {
+    width: 72.91666667%;
+  }
+  >.ant-col-18x {
+    width: 77.08333333%;
+  }
+  >.ant-col-19x {
+    width: 81.25%;
+  }
+  >.ant-col-20x {
+    width: 85.41666667%;
+  }
+  >.ant-col-21x {
+    width: 89.58333333%;
+  }
+  >.ant-col-22x {
+    width: 93.75%;
+  }
+  >.ant-col-23x {
+    width: 97.91666667%;
+  }
 }
 .card-cell-list::after {
   content: ' ';
   display: block;
   clear: both;
+}
+.card-cell-list.mk-flex {
+  display: flex;
+  >.ant-col-1 {
+    flex: 1;
+  }
+  >.ant-col-2 {
+    flex: 2;
+  }
+  >.ant-col-3 {
+    flex: 3;
+  }
+  >.ant-col-4 {
+    flex: 4;
+  }
+  >.ant-col-5 {
+    flex: 5;
+  }
+  >.ant-col-6 {
+    flex: 6;
+  }
+  >.ant-col-7 {
+    flex: 7;
+  }
+  >.ant-col-8 {
+    flex: 8;
+  }
+  >.ant-col-9 {
+    flex: 9;
+  }
+  >.ant-col-10 {
+    flex: 10;
+  }
+  >.ant-col-11 {
+    flex: 11;
+  }
+  >.ant-col-12 {
+    flex: 12;
+  }
+  >.ant-col-13 {
+    flex: 13;
+  }
+  >.ant-col-14 {
+    flex: 14;
+  }
+  >.ant-col-15 {
+    flex: 15;
+  }
+  >.ant-col-16 {
+    flex: 16;
+  }
+  >.ant-col-17 {
+    flex: 17;
+  }
+  >.ant-col-18 {
+    flex: 18;
+  }
+  >.ant-col-19 {
+    flex: 19;
+  }
+  >.ant-col-20 {
+    flex: 20;
+  }
+  >.ant-col-21 {
+    flex: 21;
+  }
+  >.ant-col-22 {
+    flex: 22;
+  }
+  >.ant-col-23 {
+    flex: 23;
+  }
+  >.ant-col-24 {
+    flex: 24;
+  }
+  >.ant-col-0x {
+    flex: 0.5;
+  }
+  >.ant-col-1x {
+    flex: 1.5;
+  }
+  >.ant-col-2x {
+    flex: 2.5;
+  }
+  >.ant-col-3x {
+    flex: 3.5;
+  }
+  >.ant-col-4x {
+    flex: 4.5;
+  }
+  >.ant-col-5x {
+    flex: 5.5;
+  }
+  >.ant-col-6x {
+    flex: 6.5;
+  }
+  >.ant-col-7x {
+    flex: 7.5;
+  }
+  >.ant-col-8x {
+    flex: 8.5;
+  }
+  >.ant-col-9x {
+    flex: 9.5;
+  }
+  >.ant-col-10x {
+    flex: 10.5;
+  }
+  >.ant-col-11x {
+    flex: 11.5;
+  }
+  >.ant-col-12x {
+    flex: 12.5;
+  }
+  >.ant-col-13x {
+    flex: 13.5;
+  }
+  >.ant-col-14x {
+    flex: 14.5;
+  }
+  >.ant-col-15x {
+    flex: 15.5;
+  }
+  >.ant-col-16x {
+    flex: 16.5;
+  }
+  >.ant-col-17x {
+    flex: 17.5;
+  }
+  >.ant-col-18x {
+    flex: 18.5;
+  }
+  >.ant-col-19x {
+    flex: 19.5;
+  }
+  >.ant-col-20x {
+    flex: 20.5;
+  }
+  >.ant-col-21x {
+    flex: 21.5;
+  }
+  >.ant-col-22x {
+    flex: 22.5;
+  }
+  >.ant-col-23x {
+    flex: 23.5;
+  }
 }
\ No newline at end of file
diff --git a/src/tabviews/custom/components/card/data-card/index.jsx b/src/tabviews/custom/components/card/data-card/index.jsx
index 95fde61..6d1c6ea 100644
--- a/src/tabviews/custom/components/card/data-card/index.jsx
+++ b/src/tabviews/custom/components/card/data-card/index.jsx
@@ -15,6 +15,7 @@
 import './index.scss'
 
 const CardItem = asyncComponent(() => import('../cardItem'))
+const TableHeader = asyncComponent(() => import('../tableHeader'))
 const MainAction = asyncComponent(() => import('@/tabviews/zshare/actionList'))
 const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
 
@@ -31,6 +32,9 @@
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     search: null,              // 鎼滅储鏉′欢
     pageIndex: 1,              // 椤电爜
+    pageSize: 10,
+    orderBy: '',
+    pageOptions: [],
     activeKey: '',             // 閫変腑鍗�
     selectKeys: [],            // 澶氶�夋椂閫変腑鍗$墖
     selectedData: [],          // 閫変腑鏁版嵁锛岀敤浜庡伐鍏锋爮鎸夐挳
@@ -76,6 +80,8 @@
       }
     }
 
+    _config.$extend = false
+
     _config.subcards.forEach(item => {
       if (item.setting.click === 'button' && !item.setting.linkbtn) {
         item.elements.forEach(ele => {
@@ -91,8 +97,10 @@
       if (item.$cardType !== 'extendCard') {
         _card = item
       } else if (!_card) {
+        _config.$extend = true
         precards.push(item)
       } else {
+        _config.$extend = true
         nextcards.push(item)
       }
     })
@@ -126,7 +134,7 @@
         item.$Index = index + 1 + ''
 
         if (_config.wrap.controlField) {
-          if (_config.wrap.controlVal.includes(item[_config.wrap.controlField])) {
+          if (_config.wrap.controlVal.includes(item[_config.wrap.controlField] + '')) {
             item.$disabled = true
           }
         }
@@ -157,7 +165,23 @@
 
     this.loaded = _data !== null
 
+    let pageOptions = ['10', '25', '50', '100', '500', '1000']
+
+    if (!_config.setting.laypage) {
+      _config.wrap.pagestyle = 'none'
+    }
+
+    if (_config.wrap.pagestyle === 'page') {
+      let size = (_config.setting.pageSize || 10) + ''
+      if (!pageOptions.includes(size)) {
+        pageOptions.push(size)
+        pageOptions = pageOptions.sort((a, b) => a - b)
+      }
+    }
+
     this.setState({
+      pageSize: _config.setting.pageSize || 10,
+      pageOptions,
       supComs,
       selected,
       precards,
@@ -208,7 +232,7 @@
           item.$Index = index + 1 + ''
 
           if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField])) {
+            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -240,7 +264,7 @@
           item.$Index = index + 1 + ''
 
           if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField])) {
+            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -472,6 +496,7 @@
   checkAll = () => {
     const { config, data, selectedData } = this.state
 
+    if (config.wrap.cardType !== 'checkbox') return
     if (!data || data.length === 0) return
     
     if (selectedData.length === 0 || selectedData.length < data.length) {
@@ -564,7 +589,7 @@
    */
   queryModuleParam = (menuId, callback) => {
     const { mainSearch } = this.props
-    const { arr_field, config, search } = this.state
+    const { arr_field, config, search, orderBy } = this.state
 
     if (config.uuid !== menuId) return
 
@@ -580,7 +605,7 @@
 
     callback({
       arr_field: arr_field,
-      orderBy: config.setting.order || '',
+      orderBy: orderBy ||config.setting.order || '',
       search: searches,
       menuName: config.name
     })
@@ -588,7 +613,7 @@
 
   async loadData (id, type) {
     const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, search, BID, BData, selected } = this.state
+    const { config, arr_field, pageIndex, pageSize, search, BID, BData, selected, orderBy } = this.state
 
     if (config.setting.supModule && !BID && config.wrap.supKey !== 'false') { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.loaded = true
@@ -640,14 +665,14 @@
       })
     }
 
-    let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID)
+    let _orderBy = orderBy || config.setting.order || ''
+    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let start = 1
       if (config.setting.laypage) {
-        start = config.setting.pageSize * (pageIndex - 1) + 1
+        start = pageSize * (pageIndex - 1) + 1
       }
 
       this.loaded = true
@@ -681,7 +706,7 @@
           item.$Index = index + 1 + ''
 
           if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField])) {
+            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -696,7 +721,7 @@
           item.$Index = index + start + ''
 
           if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField])) {
+            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -712,6 +737,13 @@
         total: result.total,
         loading: false
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
@@ -736,7 +768,7 @@
    */ 
   async loadLinedata (id) {
     const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, search, BID, BData } = this.state
+    const { config, arr_field, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
 
     let searches = fromJS(search).toJS()
     if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
@@ -752,8 +784,8 @@
       loading: true
     })
 
-    let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID, id)
+    let _orderBy = orderBy || config.setting.order || ''
+    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -798,9 +830,9 @@
   }
 
   loadMore = () => {
-    const { total, pageIndex, loading, config } = this.state
+    const { total, pageIndex, pageSize, loading } = this.state
 
-    if (loading || config.setting.pageSize * pageIndex >= total) {
+    if (loading || pageSize * pageIndex >= total) {
       return
     }
 
@@ -824,8 +856,8 @@
   }
 
   nextPage = () => {
-    const { config, pageIndex, total } = this.state
-    let _total = config.setting.pageSize * pageIndex
+    const { pageIndex, pageSize, total } = this.state
+    let _total = pageSize * pageIndex
 
     if (_total >= total) return
 
@@ -848,6 +880,15 @@
     this.setState({
       search: list,
       pageIndex: 1
+    }, () => {
+      this.loadData()
+    })
+  }
+
+  pageSizeChange = (current, size) => {
+    this.setState({
+      pageIndex: current,
+      pageSize: size
     }, () => {
       this.loadData()
     })
@@ -898,22 +939,38 @@
     }
   }
 
+  refreshByHeader = (sorter) => {
+    this.setState({
+      orderBy: sorter || ''
+    }, () => {
+      this.loadData()
+    })
+  }
+
   render() {
-    const { config, precards, nextcards, loading, data, pageIndex, total, card, activeKey, BID, BData, selectedData, selectKeys } = this.state
+    const { config, precards, nextcards, loading, data, pageIndex, pageSize, total, card, activeKey, BID, BData, selectedData, selectKeys } = this.state
 
     if (config.wrap.empty === 'hidden' && (!data || data.length === 0)) return null
 
     let _total = 0
     let switchable = false
-    if (config.wrap.pagestyle === 'switch' && config.pageable && config.setting.laypage && total > config.setting.pageSize && data) {
-      _total = config.setting.pageSize * pageIndex
+    if (config.wrap.pagestyle === 'switch' && total > pageSize && data) {
+      _total = pageSize * pageIndex
       switchable = true
     }
 
-    let extendData = {$$BID: BID, $$BData: BData, $$selectedData: selectedData, $$type: 'extendCard'}
+    let extendData = null
 
-    if (data && data[0]) {
-      extendData = {...extendData, ...data[0]}
+    if (config.$extend) {
+      extendData = {$$BID: BID, $$BData: BData, $$selectedData: selectedData, $$type: 'extendCard'}
+      
+      if (data && data[0]) {
+        if (selectedData[0]) {
+          extendData = {...extendData, ...selectedData[0]}
+        } else {
+          extendData = {...extendData, ...data[0]}
+        }
+      }
     }
 
     let checkAll = ''
@@ -947,9 +1004,11 @@
           <Row className={'card-row-list ' + config.wrap.layout}>
             {precards.map((item, index) => (
               <Col key={'pre' + index} className="extend-card" span={item.setting.width || 6}>
-                <CardItem card={item} cards={config} data={extendData}>
+                {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}
-                </CardItem>
+                </TableHeader> : <CardItem card={item} cards={config} data={extendData}>
+                  {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
+                </CardItem>}
               </Col>
             ))}
             {data && data.map((item, index) => {
@@ -977,17 +1036,19 @@
             })}
             {nextcards.map((item, index) => (
               <Col key={'next' + index} className="extend-card" span={item.setting.width || 6}>
-                <CardItem card={item} cards={config} data={extendData}>
+                {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}
-                </CardItem>
+                </TableHeader> : <CardItem card={item} cards={config} data={extendData}>
+                  {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
+                </CardItem>}
               </Col>
             ))}
           </Row>
           {switchable ? <div className={'prev-page ' + (total <= _total ? 'disabled' : '')} onClick={this.nextPage}><div><div><img src={nextImg} alt=""/></div></div></div> : null}
-          {precards.length === 0 && nextcards.length === 0 && (!data || data.length === 0) ? <Empty description={false}/> : null}
+          {!config.$extend && (!data || data.length === 0) ? <Empty description={false}/> : null}
         </div>
-        {config.wrap.pagestyle === 'page' && config.setting.laypage && data ? <Pagination size="small" total={total} showTotal={t => `鍏� ${t} 鏉} pageSize={config.setting.pageSize} onChange={this.changePageIndex} current={pageIndex}/> : null}
-        {config.wrap.pagestyle === 'more' && config.setting.laypage && data && data.length > 0 ? <div className={'mk-more' + (config.setting.pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
+        {config.wrap.pagestyle === 'page' && data ? <Pagination size="small" total={total} showTotal={(t, range) => total > 0 ? `${range[0]}-${range[1]} 鍏� ${total} 鏉 : `鍏� ${total} 鏉} pageSize={pageSize} showSizeChanger={true} pageSizeOptions={this.state.pageOptions} onChange={this.changePageIndex} onShowSizeChange={this.pageSizeChange} current={pageIndex}/> : null}
+        {config.wrap.pagestyle === 'more' && data && data.length > 0 ? <div className={'mk-more' + (pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
       </div>
     )
   }
diff --git a/src/tabviews/custom/components/card/data-card/index.scss b/src/tabviews/custom/components/card/data-card/index.scss
index 820b993..34a81cf 100644
--- a/src/tabviews/custom/components/card/data-card/index.scss
+++ b/src/tabviews/custom/components/card/data-card/index.scss
@@ -6,17 +6,6 @@
   min-height: 20px;
   overflow-y: auto;
 
-  >.button-list.toolbar-button {
-    padding: 0;
-    line-height: 45px;
-    button {
-      margin-right: 0px;
-      margin-bottom: 0px;
-      min-height: 28px;
-      height: auto;
-    }
-  }
-
   .data-zoom {
     display: flex;
     position: relative;
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 3599a92..33637fa 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.jsx
+++ b/src/tabviews/custom/components/card/double-data-card/index.jsx
@@ -7,14 +7,13 @@
 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'
 import MKEmitter from '@/utils/events.js'
 import TimerTask from '@/utils/timer-task.js'
 import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
 const CardItem = asyncComponent(() => import('../cardItem'))
+const TableHeader = asyncComponent(() => import('../tableHeader'))
 const MainAction = asyncComponent(() => import('@/tabviews/zshare/actionList'))
 const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
 
@@ -30,6 +29,9 @@
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     search: null,              // 鎼滅储鏉′欢
     pageIndex: 1,              // 椤电爜
+    pageSize: 10,
+    orderBy: '',
+    pageOptions: [],
     activeKey: '',             // 閫変腑鍗�
     selectKeys: [],            // 澶氶�夋椂閫変腑鍗$墖
     selectedData: [],          // 閫変腑鏁版嵁锛岀敤浜庡伐鍏锋爮鎸夐挳
@@ -76,6 +78,8 @@
       }
     }
 
+    _config.$extend = false
+
     _config.subcards.forEach(item => {
       if (item.setting.click === 'button' && !item.setting.linkbtn) {
         item.elements.forEach(ele => {
@@ -91,8 +95,10 @@
       if (item.$cardType !== 'extendCard') {
         _card = item
       } else if (!_card) {
+        _config.$extend = true
         precards.push(item)
       } else {
+        _config.$extend = true
         nextcards.push(item)
       }
     })
@@ -127,17 +133,45 @@
     subcard.setting = subcard.backSetting
 
     if (_card.setting.position === 'inner') {
-      wrapStyle = {}
+      wrapStyle = {backgroundColor: '#ffffff'}
       Object.keys(_card.style).forEach(key => {
-        if (!/^(margin|border|box)/.test(key)) return
+        if (!/^(margin|border|box|backgroundColor)/.test(key)) return
         wrapStyle[key] = _card.style[key]
         delete _card.style[key]
       })
     }
 
     _config.setting.sub_field = subconfig.columns.map(col => col.field).join(',')
+    let pageOptions = ['10', '25', '50', '100', '500', '1000']
+
+    if (!_config.setting.laypage) {
+      _config.wrap.pagestyle = 'none'
+    }
+
+    if (_config.wrap.pagestyle === 'page') {
+      let size = (_config.setting.pageSize || 10) + ''
+      if (!pageOptions.includes(size)) {
+        pageOptions.push(size)
+        pageOptions = pageOptions.sort((a, b) => a - b)
+      }
+    }
+
+    if (_config.wrap.zHeight) {
+      _config.wrap.zHeight = _config.wrap.zHeight <= 100 ? _config.wrap.zHeight + 'vh' : _config.wrap.zHeight
+    }
+
+    if (_config.wrap.zHeight || _config.wrap.minWidth) {
+      _config.wrap.zoomStyle = {
+        border: `1px solid ${_config.wrap.zBColor || 'transparent'}`,
+        height: _config.wrap.zHeight || 'auto'
+      }
+    } else {
+      _config.wrap.zoomStyle = null
+    }
 
     this.setState({
+      pageSize: _config.setting.pageSize || 10,
+      pageOptions,
       selected,
       precards,
       nextcards,
@@ -183,30 +217,35 @@
       Api.getLCacheConfig(config.uuid).then(res => {
         if (!res || this.loaded) return
         let _data = res.map((item, index) => {
+          let children = []
+
           if (item[config.setting.subdata]) {
             let _children = item[config.setting.subdata]
 
             delete item[config.setting.subdata]
 
-            item.children = _children.map((cell, i) => {
+            _children.forEach((cell, i) => {
               cell.key = i
               cell.$$uuid = cell[config.setting.subKey] || ''
+              cell.$$parentId = item[config.setting.primaryKey] || ''
               cell.$$BID = item[config.setting.primaryKey] || ''
               cell.$$BData = {...item}
               cell.$Index = i + 1 + ''
 
-              return cell
+              if (cell.$$uuid) {
+                children.push(cell)
+              }
             })
-          } else {
-            item.children = []
           }
+
+          item.children = children
 
           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])) {
+            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -260,7 +299,7 @@
 
     if (position === 'line') {
       if (lines && lines.length === 1) {
-        this.loadLinedata(lines[0].$$uuid)
+        this.loadLinedata(lines[0].$$parentId || lines[0].$$uuid)
       } else {
         this.loadData(id)
       }
@@ -366,6 +405,7 @@
   checkAll = () => {
     const { config, data, selectedData } = this.state
 
+    if (config.wrap.cardType !== 'checkbox') return
     if (!data || data.length === 0) return
     
     if (selectedData.length === 0 || selectedData.length < data.length) {
@@ -429,7 +469,7 @@
    */
   queryModuleParam = (menuId, callback) => {
     const { mainSearch } = this.props
-    const { arr_field, config, search } = this.state
+    const { arr_field, config, search, orderBy } = this.state
 
     if (config.uuid !== menuId) return
 
@@ -445,7 +485,7 @@
 
     callback({
       arr_field: arr_field,
-      orderBy: config.setting.order || '',
+      orderBy: orderBy || config.setting.order || '',
       search: searches,
       menuName: config.name
     })
@@ -453,7 +493,7 @@
 
   async loadData (id, type) {
     const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, search, BID, BData, selected, card } = this.state
+    const { config, arr_field, pageIndex, pageSize, search, BID, BData, selected, card, orderBy } = this.state
 
     if (config.setting.supModule && !BID && config.wrap.supKey !== 'false') { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.loaded = true
@@ -503,14 +543,14 @@
       })
     }
 
-    let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID)
+    let _orderBy = orderBy || config.setting.order || ''
+    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
       let start = 1
       if (config.setting.laypage) {
-        start = config.setting.pageSize * (pageIndex - 1) + 1
+        start = pageSize * (pageIndex - 1) + 1
       }
 
       this.loaded = true
@@ -536,20 +576,25 @@
         let _data = (this.state.data || []).concat(result.data || [])
         data = _data.map((item, index) => {
           if (item[config.setting.subdata]) {
+            let children = []
             let _children = item[config.setting.subdata]
 
             delete item[config.setting.subdata]
-
-            item.children = _children.map((cell, i) => {
+            
+            _children.forEach((cell, i) => {
               cell.key = i
               cell.$$uuid = cell[config.setting.subKey] || ''
+              cell.$$parentId = item[config.setting.primaryKey] || ''
               cell.$$BID = item[config.setting.primaryKey] || ''
               cell.$$BData = {...item}
               cell.$Index = i + 1 + ''
 
-              return cell
+              if (cell.$$uuid) {
+                children.push(cell)
+              }
             })
-          } else {
+            item.children = children
+          } else if (!item.children) {
             item.children = []
           }
 
@@ -560,7 +605,7 @@
           item.$Index = index + 1 + ''
 
           if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField])) {
+            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -569,23 +614,28 @@
         })
       } else {
         data = result.data.map((item, index) => {
+          let children = []
+
           if (item[config.setting.subdata]) {
             let _children = item[config.setting.subdata]
 
             delete item[config.setting.subdata]
 
-            item.children = _children.map((cell, i) => {
+            _children.forEach((cell, i) => {
               cell.key = i
               cell.$$uuid = cell[config.setting.subKey] || ''
+              cell.$$parentId = item[config.setting.primaryKey] || ''
               cell.$$BID = item[config.setting.primaryKey] || ''
               cell.$$BData = {...item}
               cell.$Index = i + 1 + ''
 
-              return cell
+              if (cell.$$uuid) {
+                children.push(cell)
+              }
             })
-          } else {
-            item.children = []
           }
+
+          item.children = children
 
           item.key = index
           item.$$uuid = item[config.setting.primaryKey] || ''
@@ -594,7 +644,7 @@
           item.$Index = index + start + ''
 
           if (config.wrap.controlField) {
-            if (config.wrap.controlVal.includes(item[config.wrap.controlField])) {
+            if (config.wrap.controlVal.includes(item[config.wrap.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -617,6 +667,13 @@
         total: result.total,
         loading: false
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
@@ -641,7 +698,7 @@
    */ 
   async loadLinedata (id) {
     const { mainSearch } = this.props
-    const { config, arr_field, pageIndex, search, BID, BData } = this.state
+    const { config, arr_field, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
 
     let searches = fromJS(search).toJS()
     if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
@@ -657,8 +714,8 @@
       loading: true
     })
 
-    let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID, id)
+    let _orderBy = orderBy || config.setting.order || ''
+    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, pageSize, BID, id)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
@@ -669,23 +726,28 @@
         try {
           data = data.map(item => {
             if (item[config.setting.primaryKey] === _data[config.setting.primaryKey]) {
+              let children = []
+
               if (_data[config.setting.subdata]) {
                 let _children = _data[config.setting.subdata]
 
                 delete _data[config.setting.subdata]
 
-                _data.children = _children.map((cell, i) => {
+                _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 + ''
 
-                  return cell
+                  if (cell.$$uuid) {
+                    children.push(cell)
+                  }
                 })
-              } else {
-                _data.children = []
               }
+
+              _data.children = children
 
               _data.key = item.key
               _data.$$uuid = _data[config.setting.primaryKey] || ''
@@ -721,9 +783,9 @@
   }
 
   loadMore = () => {
-    const { total, pageIndex, loading, config } = this.state
+    const { total, pageIndex, pageSize, loading } = this.state
 
-    if (loading || config.setting.pageSize * pageIndex >= total) {
+    if (loading || pageSize * pageIndex >= total) {
       return
     }
 
@@ -731,31 +793,6 @@
       pageIndex: pageIndex + 1
     }, () => {
       this.loadData('', 'plus')
-    })
-  }
-
-  prevPage = () => {
-    const { pageIndex } = this.state
-
-    if (pageIndex === 1) return
-
-    this.setState({
-      pageIndex: pageIndex - 1
-    }, () => {
-      this.loadData()
-    })
-  }
-
-  nextPage = () => {
-    const { config, pageIndex, total } = this.state
-    let _total = config.setting.pageSize * pageIndex
-
-    if (_total >= total) return
-
-    this.setState({
-      pageIndex: pageIndex + 1
-    }, () => {
-      this.loadData()
     })
   }
 
@@ -771,6 +808,15 @@
     this.setState({
       search: list,
       pageIndex: 1
+    }, () => {
+      this.loadData()
+    })
+  }
+
+  pageSizeChange = (current, size) => {
+    this.setState({
+      pageIndex: current,
+      pageSize: size
     }, () => {
       this.loadData()
     })
@@ -840,6 +886,43 @@
     }
   }
 
+  changeSubCard = (item) => {
+    const { subcard, card } = this.state
+
+    if (subcard.setting.click || card.setting.position !== 'inner' || card.setting.click !== 'menu') return
+    
+    let menuId = card.setting.MenuID || card.setting.menu.slice(-1)[0]
+    let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
+
+    if (!menu && card.setting.MenuName && card.setting.tabType) {
+      menu = {
+        MenuID: menuId,
+        MenuName: card.setting.MenuName,
+        MenuNo: card.setting.MenuNo || '',
+        type: card.setting.tabType
+      }
+    }
+
+    if (!menu) return
+
+    let newtab = {
+      ...menu,
+      param: {}
+    }
+
+    if (card.setting.joint === 'true') {
+      newtab.param.$BID = item.$$uuid || ''
+      
+      Object.keys(item).forEach(key => {
+        if (/^\$/.test(key)) return
+        if (key === 'children') return
+        newtab.param[key] = item[key]
+      })
+    }
+
+    MKEmitter.emit('modifyTabs', newtab, true)
+  }
+
   onDoubleClick = (i, subClass) => {
     const { opens, card } = this.state
 
@@ -852,22 +935,31 @@
     }
   }
 
+  refreshByHeader = (sorter) => {
+    this.setState({
+      orderBy: sorter || ''
+    }, () => {
+      this.loadData()
+    })
+  }
+
   render() {
-    const { config, precards, nextcards, loading, data, pageIndex, total, card, activeKey, BID, BData, selectedData, selectKeys, subcard, subconfig, wrapStyle, opens } = this.state
+    const { config, precards, nextcards, loading, data, pageIndex, pageSize, total, card, activeKey, BID, BData, selectedData, selectKeys, subcard, subconfig, wrapStyle, opens } = this.state
 
     if (config.wrap.empty === 'hidden' && (!data || data.length === 0)) return null
 
-    let _total = 0
-    let switchable = false
-    if (config.wrap.pagestyle === 'switch' && config.pageable && config.setting.laypage && total > config.setting.pageSize && data) {
-      _total = config.setting.pageSize * pageIndex
-      switchable = true
-    }
+    let extendData = null
 
-    let extendData = {$$BID: BID, $$BData: BData, $$selectedData: selectedData, $$type: 'extendCard'}
-
-    if (data && data[0]) {
-      extendData = {...extendData, ...data[0]}
+    if (config.$extend) {
+      extendData = {$$BID: BID, $$BData: BData, $$selectedData: selectedData, $$type: 'extendCard'}
+      
+      if (data && data[0]) {
+        if (selectedData[0]) {
+          extendData = {...extendData, ...selectedData[0]}
+        } else {
+          extendData = {...extendData, ...data[0]}
+        }
+      }
     }
 
     let checkAll = ''
@@ -902,69 +994,73 @@
             selectedData={selectedData}
           /> : null
         }
-        <div className={`data-zoom ${config.wrap.wrapClass}`}>
-          {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 '}>
-            {precards.map((item, index) => (
-              <Col key={'pre' + index} className="extend-card" span={item.setting.width || 6}>
-                <CardItem card={item} cards={config} data={extendData}>
-                  {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
-                </CardItem>
-              </Col>
-            ))}
-            {data && data.map((item, index) => {
-              let className = 'card-item-wrap mk-card ' + mainBox
-              let subClass = 'mk-unfold'
-              let unfold = true
-
-              if (item.$disabled) {
-                className = 'mk-disabled ' + mainBox
-              } else if (activeKey === index) {
-                className += 'active'
-              } else if (selectKeys.indexOf(index) > -1) {
-                className += 'selected'
-              }
-
-              if (card.setting.display !== 'default') {
-                if (item.children.length === 0) {
-                  subClass = 'mk-disabled'
-                  unfold = false
-                } else {
-                  subClass = opens.indexOf(index) > -1 ? 'mk-unfold' : 'mk-collapse'
-                  unfold = opens.indexOf(index) > -1
-                }
-              }
-
-              return (
-                <Col key={index} span={card.setting.width}>
-                  <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>
-                      {card.setting.controlIcon === 'left' ? (!unfold ? <PlusSquareOutlined className={subClass} onClick={(e) => this.changeUnfold(e, index, subClass)}/> : <MinusSquareOutlined className={subClass} onClick={(e) => this.changeUnfold(e, index, subClass)}/>) : null}
-                      {card.setting.controlIcon === 'right' ? <UpOutlined className={subClass} onClick={(e) => this.changeUnfold(e, index, subClass)}/> : null}
-                    </CardItem>
-                    <div className={'sub-card-wrap ' + subClass + (config.wrap.parity === 'true' ? ' mk-parity-bg' : '')}>
-                      {item.children.map((cell, index) => <Col key={'sub' + index} span={subcard.setting.width || 24}>
-                        <CardItem card={subcard} cards={subconfig} data={cell} />
-                      </Col>)}
-                    </div>
-                  </div>
+        <div className={config.wrap.zoomStyle ? 'data-zoom-box' : ''} style={config.wrap.zoomStyle}>
+          <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}>
+                  {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}>
+                    {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
+                  </CardItem>}
                 </Col>
-              )
-            })}
-            {nextcards.map((item, index) => (
-              <Col key={'next' + index} className="extend-card" span={item.setting.width || 6}>
-                <CardItem card={item} cards={config} data={extendData}>
-                  {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
-                </CardItem>
-              </Col>
-            ))}
-          </Row>
-          {switchable ? <div className={'prev-page ' + (total <= _total ? 'disabled' : '')} onClick={this.nextPage}><div><div><img src={nextImg} alt=""/></div></div></div> : null}
-          {precards.length === 0 && nextcards.length === 0 && (!data || data.length === 0) ? <Empty description={false}/> : null}
+              ))}
+              {data && data.map((item, index) => {
+                let className = 'card-item-wrap mk-card ' + mainBox
+                let subClass = 'mk-unfold'
+                let unfold = true
+
+                if (item.$disabled) {
+                  className = 'card-item-wrap mk-disabled ' + mainBox
+                } else if (activeKey === index) {
+                  className += 'active'
+                } else if (selectKeys.indexOf(index) > -1) {
+                  className += 'selected'
+                }
+
+                if (card.setting.display !== 'default') {
+                  if (item.children.length === 0) {
+                    subClass = 'mk-disabled'
+                    unfold = false
+                  } else {
+                    subClass = opens.indexOf(index) > -1 ? 'mk-unfold' : 'mk-collapse'
+                    unfold = opens.indexOf(index) > -1
+                  }
+                }
+
+                return (
+                  <Col key={index} span={card.setting.width}>
+                    <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>
+                        {card.setting.controlIcon === 'left' ? (!unfold ? <PlusSquareOutlined className={subClass} onClick={(e) => this.changeUnfold(e, index, subClass)}/> : <MinusSquareOutlined className={subClass} onClick={(e) => this.changeUnfold(e, index, subClass)}/>) : null}
+                        {card.setting.controlIcon === 'right' ? <UpOutlined className={subClass} onClick={(e) => this.changeUnfold(e, index, subClass)}/> : null}
+                      </CardItem>
+                      <div className={'sub-card-wrap ' + subClass + (config.wrap.parity === 'true' ? ' mk-parity-bg' : '')} onClick={() => this.changeSubCard(item)}>
+                        {item.children.map((cell, index) => <Col key={'sub' + index} span={subcard.setting.width || 24}>
+                          <CardItem card={subcard} cards={subconfig} data={cell} />
+                        </Col>)}
+                      </div>
+                    </div>
+                  </Col>
+                )
+              })}
+              {nextcards.map((item, index) => (
+                <Col key={'next' + index} className="extend-card" 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}>
+                    {item.setting.checkAll === 'show' ? <span onClick={this.checkAll} className={'circle-select' + checkAll}></span> : null}
+                  </CardItem>}
+                </Col>
+              ))}
+            </Row>
+            {!config.$extend && (!data || data.length === 0) ? <Empty description={false}/> : null}
+          </div>
         </div>
-        {config.wrap.pagestyle === 'page' && config.setting.laypage && data ? <Pagination size="small" total={total} showTotal={t => `鍏� ${t} 鏉} pageSize={config.setting.pageSize} onChange={this.changePageIndex} current={pageIndex}/> : null}
-        {config.wrap.pagestyle === 'more' && config.setting.laypage && data && data.length > 0 ? <div className={'mk-more' + (config.setting.pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
+        {config.wrap.pagestyle === 'page' && data ? <Pagination size="small" total={total} showTotal={(t, range) => total > 0 ? `${range[0]}-${range[1]} 鍏� ${total} 鏉 : `鍏� ${total} 鏉} pageSize={pageSize} showSizeChanger={true} pageSizeOptions={this.state.pageOptions} onChange={this.changePageIndex} onShowSizeChange={this.pageSizeChange} current={pageIndex}/> : null}
+        {config.wrap.pagestyle === 'more' && data && data.length > 0 ? <div className={'mk-more' + (pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
       </div>
     )
   }
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 f483742..b3a5b8a 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.scss
+++ b/src/tabviews/custom/components/card/double-data-card/index.scss
@@ -6,17 +6,6 @@
   min-height: 20px;
   overflow-y: auto;
 
-  >.button-list.toolbar-button {
-    padding: 0;
-    line-height: 45px;
-    button {
-      margin-right: 0px;
-      margin-bottom: 0px;
-      min-height: 28px;
-      height: auto;
-    }
-  }
-
   .data-zoom {
     display: flex;
     position: relative;
@@ -79,29 +68,6 @@
     background-position: center center;
     background-repeat: no-repeat;
     background-size: cover;
-  }
-  .prev-page {
-    width: 20px;
-    div {
-      height: 100%;
-      display: table;
-      div {
-        display: table-cell;
-        vertical-align: middle;
-      }
-    }
-    img {
-      width: 15px;
-      padding: 0 2px;
-      height: 70px;
-      cursor: pointer;
-    }
-  }
-  .prev-page.disabled {
-    img {
-      cursor: not-allowed;
-      opacity: 0.4;
-    }
   }
   .card-row-list::after {
     content: ' ';
@@ -320,6 +286,35 @@
       }
     }
   }
+  .data-zoom-box {
+    width: 100%;
+    overflow-x: auto;
+    overflow-y: auto;
+    padding-bottom: 10px;
+    border: 1px solid #e8e8e8;
+    border-radius: 4px;
+
+    .extend-card:first-child {
+      position: sticky;
+      top: 0px;
+      z-index: 2;
+    }
+  }
+  .data-zoom-box::-webkit-scrollbar {
+    height: 9px;
+    width: 9px;
+  }
+  .data-zoom-box::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+  }
+  .data-zoom-box::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0.07);
+    background: rgba(0, 0, 0, 0);
+  }
 }
 .double-data-card-box::-webkit-scrollbar {
   width: 7px;
diff --git a/src/tabviews/custom/components/card/prop-card/index.jsx b/src/tabviews/custom/components/card/prop-card/index.jsx
index aac9321..592322d 100644
--- a/src/tabviews/custom/components/card/prop-card/index.jsx
+++ b/src/tabviews/custom/components/card/prop-card/index.jsx
@@ -135,9 +135,15 @@
       }
 
       if (_config.wrap.datatype === 'dynamic' && this.loaded) {
-        this.autoExec()
+        if (_config.wrap.goback === 'true' && _data.$$empty) {
+          this.timer && this.timer.stop()
+
+          MKEmitter.emit('closeTabView', _config.$pageId)
+        } else {
+          this.autoExec()
+        }
       }
-      if (!_config.wrap.cardType && _data.$$uuid) {
+      if (_data.$$uuid) {
         setTimeout(() => {
           this.transferLine()
         }, 200)
@@ -213,12 +219,18 @@
       this.loaded = true
 
       this.setState({sync: false, data: _data}, () => {
-        if (selected !== 'false') {
-          this.checkTopLine()
-        } else if (!config.wrap.cardType && _data.$$uuid) {
-          this.transferLine()
+        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()
         }
-        this.autoExec()
       })
     } else if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
       this.setState({}, () => {
@@ -240,10 +252,17 @@
       this.loaded = true
 
       this.setState({data: _data}, () => {
-        if (selected !== 'false') {
-          this.checkTopLine()
+        if (config.wrap.goback === 'true' && _data.$$empty) {
+          this.timer && this.timer.stop()
+
+          MKEmitter.emit('closeTabView', config.$pageId)
         } else {
-          this.transferLine()
+          if (selected !== 'false') {
+            this.checkTopLine()
+          } else {
+            this.transferLine()
+          }
+          this.autoExec()
         }
       })
     }
@@ -421,9 +440,9 @@
         }
       })
 
-      if (config.timer && config.clearField) {
+      if (config.timer && config.clearField && result.data && result.data[0]) {
         let vals = (config.clearValue || '').split(',')
-        if (vals.includes(_data[config.clearField])) {
+        if (vals.includes(result.data[0][config.clearField])) {
           this.timer && this.timer.stop()
         }
       }
diff --git a/src/tabviews/custom/components/card/table-card/index.jsx b/src/tabviews/custom/components/card/table-card/index.jsx
index ed5623f..16fc44e 100644
--- a/src/tabviews/custom/components/card/table-card/index.jsx
+++ b/src/tabviews/custom/components/card/table-card/index.jsx
@@ -83,13 +83,14 @@
       showHeader = true
     }
 
+    _config.wrap.pagestyle = _config.wrap.pagestyle || 'page'
+
     if (_config.setting.laypage) {
       _config.wrap.contentHeight = showHeader ? 'calc(100% - 85px)' : 'calc(100% - 40px)'
     } else {
+      _config.wrap.pagestyle = 'none'
       _config.wrap.contentHeight = showHeader ? 'calc(100% - 45px)' : '100%'
     }
-
-    _config.wrap.pagestyle = _config.wrap.pagestyle || 'page'
 
     this.loaded = _data !== null
 
@@ -338,6 +339,13 @@
         total: result.total,
         loading: false
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
@@ -506,8 +514,8 @@
         {data && data.length === 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}>
           <Empty description={false}/>
         </div> : null}
-        {config.setting.laypage && config.wrap.pagestyle === 'page' ? <Pagination size="small" current={pageIndex} total={total} onChange={this.changePageIndex} /> : null}
-        {config.setting.laypage && config.wrap.pagestyle === 'more' && data && data.length > 0 ? <div className={'mk-more' + (config.setting.pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
+        {config.wrap.pagestyle === 'page' ? <Pagination size="small" current={pageIndex} total={total} onChange={this.changePageIndex} /> : null}
+        {config.wrap.pagestyle === 'more' && data && data.length > 0 ? <div className={'mk-more' + (config.setting.pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
       </div>
     )
   }
diff --git a/src/tabviews/custom/components/card/tableHeader/index.jsx b/src/tabviews/custom/components/card/tableHeader/index.jsx
new file mode 100644
index 0000000..c3e229f
--- /dev/null
+++ b/src/tabviews/custom/components/card/tableHeader/index.jsx
@@ -0,0 +1,160 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons'
+
+import './index.scss'
+
+class TableHeader extends Component {
+  static propTpyes = {
+    card: PropTypes.object,     // 鍗$墖閰嶇疆淇℃伅
+    data: PropTypes.object,
+    refresh: PropTypes.func
+  }
+
+  state = {
+    sortField: '',
+    order: ''
+  }
+
+  /**
+   * @description 鎼滅储鏉′欢鍒濆鍖�
+   */
+  UNSAFE_componentWillMount () {
+
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props), fromJS(nextProps))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  triggerHeader = (item) => {
+    const { sortField, order } = this.state
+
+    if (!item.sortField) return
+
+    if (item.sortField !== sortField) {
+      this.setState({sortField: item.sortField, order: 'asc'})
+
+      this.props.refresh(item.sortField + ' asc')
+    } else {
+      if (order === 'asc') {
+        this.setState({order: 'desc'})
+        this.props.refresh(item.sortField + ' desc')
+      } else if (order === 'desc') {
+        this.setState({sortField: '', order: ''})
+        this.props.refresh('')
+      }
+    }
+  }
+
+  getContent = () => {
+    const { data, card } = this.props
+    const { sortField, order } = this.state
+
+    let contents = []
+
+    card.elements.forEach(item => {
+      if (item.eleType !== 'text') return
+
+      let _style_ = null
+
+      if (item.style && item.style.clear === 'left') {
+        _style_ = {clear: 'left'}
+      }
+
+      let val = ''
+      let _style = item.style ? {...item.style} : {}
+
+      if (item.datatype === 'static') {
+        val = item.value || ''
+        if (/@username@|@fullName@|@mk_city@|@bid@/ig.test(val)) {
+          let userName = sessionStorage.getItem('User_Name') || ''
+          let fullName = sessionStorage.getItem('Full_Name') || ''
+          let city = sessionStorage.getItem('city') || ''
+          let bid = data.$$BID || ''
+          val = val.replace(/@username@/ig, userName).replace(/@fullName@/ig, fullName).replace(/@mk_city@/ig, city).replace(/@bid@/ig, bid)
+        } else if (/@month@/ig.test(val)) {
+          val = val.replace(/@month@/ig, new Date().toLocaleString('en-US', { month: 'long' }))
+        } else if (/@week@/ig.test(val)) {
+          val = val.replace(/@week@/ig, (() => {
+            let day = new Date().getDay()
+            let weeks = ['鏄熸湡鏃�', '鏄熸湡涓�', '鏄熸湡浜�', '鏄熸湡涓�', '鏄熸湡鍥�', '鏄熸湡浜�', '鏄熸湡鍏�']
+            return weeks[day]
+          })())
+        } else if (/@day@/ig.test(val)) {
+          val = val.replace(/@day@/ig, (() => {
+            let day = new Date().getDate()
+            return day < 10 ? '0' + day : day
+          })())
+        }
+      } else if (data.hasOwnProperty(item.field)) {
+        val = data[item.field]
+      }
+
+      if (val === '' && item.noValue === 'hide') { // 绌哄�奸殣钘�
+        return null
+      }
+
+      if (val !== '') {
+        if (item.sortField) {
+          val = <>
+            <span className="mk-content">{item.prefix || ''}{val}{item.postfix || ''}</span>
+            <span className="sort-wrap"><CaretUpOutlined /><CaretDownOutlined /></span>
+          </>
+        } else {
+          val = <span>{item.prefix || ''}{val}{item.postfix || ''}</span>
+        }
+      }
+
+      let lineStyle = {height: item.innerHeight || 'auto', display: 'flex', alignItems: 'center', justifyContent: _style.textAlign || 'left'}
+
+      let extra = ''
+      if (item.sortField) {
+        extra = ' sortable'
+
+        if (item.sortField === sortField) {
+          if (order === 'asc') {
+            extra += ' up-sort'
+          } else {
+            extra += ' down-sort'
+          }
+        }
+      }
+
+      contents.push(
+        <div className={'ant-col ant-col-' + item.width + extra} onClick={() => this.triggerHeader(item)} key={item.uuid} style={_style_} span={item.width}>
+          <div style={_style}>
+            <div className={'ant-mk-text mk-header-cell line' + (item.height || '')} style={lineStyle}>{val}</div>
+          </div>
+        </div>
+      )
+    })
+
+    return contents
+  }
+
+  render() {
+    const { card, children } = this.props
+
+    return (
+      <div className={'card-item-box mk-table-header'} style={card.style}>
+        {children}
+        <div className={'card-cell-list ' + (card.setting.layout === 'flex' ? 'mk-flex' : '')}>
+          {this.getContent()}
+        </div>
+      </div>
+    )
+  }
+}
+
+export default TableHeader
\ No newline at end of file
diff --git a/src/tabviews/custom/components/card/tableHeader/index.scss b/src/tabviews/custom/components/card/tableHeader/index.scss
new file mode 100644
index 0000000..5abc071
--- /dev/null
+++ b/src/tabviews/custom/components/card/tableHeader/index.scss
@@ -0,0 +1,45 @@
+.card-item-box.mk-table-header {
+  position: relative;
+  overflow: hidden;
+
+  .mk-content {
+    display: inline-block;
+    white-space: normal;
+    max-width: calc(100% - 20px);
+  }
+  .sort-wrap {
+    position: relative;
+    margin-left: 10px;
+    font-size: 12px;
+    color: #bfbfbf;
+    display: inline-block;
+
+    .anticon-caret-up {
+      position: relative;
+      top: -3px;
+    }
+    .anticon-caret-down {
+      position: absolute;
+      top: 7px;
+      left: 0px;
+    }
+  }
+  .sortable {
+    cursor: pointer;
+  }
+  .sortable.up-sort {
+    .anticon-caret-up {
+      color: var(--mk-sys-color);
+    }
+  }
+  .sortable.down-sort {
+    .anticon-caret-down {
+      color: var(--mk-sys-color);
+    }
+  }
+  .sortable:hover {
+    .mk-content {
+      color: var(--mk-sys-color);
+    }
+  }
+}
diff --git a/src/tabviews/custom/components/carousel/data-card/index.jsx b/src/tabviews/custom/components/carousel/data-card/index.jsx
index 4dbe6e2..590bc98 100644
--- a/src/tabviews/custom/components/carousel/data-card/index.jsx
+++ b/src/tabviews/custom/components/carousel/data-card/index.jsx
@@ -294,19 +294,28 @@
         Api.writeCacheConfig(config.uuid, result.data || '')
       }
 
+      let data = result.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.setState({
-        data: result.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
-        }),
+        data: data,
         loading: false
       }, () => {
         this.openModal(result.ErrCode)
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/carousel/prop-card/index.jsx b/src/tabviews/custom/components/carousel/prop-card/index.jsx
index 6698d56..bfeba28 100644
--- a/src/tabviews/custom/components/carousel/prop-card/index.jsx
+++ b/src/tabviews/custom/components/carousel/prop-card/index.jsx
@@ -330,6 +330,13 @@
           this.openModal(result.ErrCode)
         }
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/chart/antv-G6/index.jsx b/src/tabviews/custom/components/chart/antv-G6/index.jsx
index ac96d6b..8406f8d 100644
--- a/src/tabviews/custom/components/chart/antv-G6/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-G6/index.jsx
@@ -1293,7 +1293,7 @@
       this.setState({empty: false})
 
       if (plot.subtype === 'mindmap') {
-        this.ponitrender()
+        this.mindrender()
       } else if (plot.subtype === 'indentTree') {
         this.indentrender()
       } else if (plot.subtype === 'kapmap') {
@@ -1424,9 +1424,9 @@
   }
 
   /**
-   * @description 鏁g偣鍥�
+   * @description 鎬濈淮瀵煎浘
    */
-  ponitrender = () => {
+  mindrender = () => {
     const { config, plot, chartId } = this.state
     const data = this.getdata()
     const width = this.wrap.scrollWidth - 30
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 7e4180a..c76b83c 100644
--- a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -548,6 +548,13 @@
         this.data = result.data || []
         this.handleData()
       }
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
index 1544237..5a584b0 100644
--- a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
@@ -299,6 +299,13 @@
       this.setState({
         loading: false
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/chart/antv-pie/index.jsx b/src/tabviews/custom/components/chart/antv-pie/index.jsx
index 17e24f5..46e5ccf 100644
--- a/src/tabviews/custom/components/chart/antv-pie/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -259,6 +259,13 @@
         this.data = result.data || []
         this.handleData()
       }
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/chart/antv-scatter/index.jsx b/src/tabviews/custom/components/chart/antv-scatter/index.jsx
index b418e31..abc0f0c 100644
--- a/src/tabviews/custom/components/chart/antv-scatter/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-scatter/index.jsx
@@ -290,6 +290,13 @@
         this.data = result.data || []
         this.handleData()
       }
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/chart/custom-chart/index.jsx b/src/tabviews/custom/components/chart/custom-chart/index.jsx
index fb81260..f2b717e 100644
--- a/src/tabviews/custom/components/chart/custom-chart/index.jsx
+++ b/src/tabviews/custom/components/chart/custom-chart/index.jsx
@@ -280,6 +280,13 @@
         this.data = result.data || []
         this.handleData()
       }
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/code/sand-box/index.jsx b/src/tabviews/custom/components/code/sand-box/index.jsx
index 8ccc32b..dc1a995 100644
--- a/src/tabviews/custom/components/code/sand-box/index.jsx
+++ b/src/tabviews/custom/components/code/sand-box/index.jsx
@@ -20,8 +20,9 @@
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
     sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
-    data: {},                  // 鏁版嵁
+    data: [],                  // 鏁版嵁
     html: '',
+    result: {}
   }
 
   loaded = false
@@ -30,7 +31,7 @@
     const { data, initdata } = this.props
     let _config = fromJS(this.props.config).toJS()
 
-    let _data = {}
+    let _data = []
     let _sync = false
 
     let BID = ''
@@ -49,7 +50,7 @@
       _sync = _config.setting.sync === 'true'
 
       if (_sync && data) {
-        _data = data[_config.dataName] || {}
+        _data = data[_config.dataName] || []
         _sync = false
         this.loaded = true
       } else if (_sync && initdata) {
@@ -122,7 +123,7 @@
     const { sync, config } = this.state
 
     if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      let _data = {}
+      let _data = []
       if (nextProps.data && nextProps.data[config.dataName]) {
         _data = nextProps.data[config.dataName]
       }
@@ -157,13 +158,13 @@
 
     if (config.wrap.datatype === 'static') {
       this.setState({
-        data: {},
+        data: [],
         loading: false
       })
       return
     } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
-        data: {},
+        data: [],
         loading: false
       })
       this.loaded = true
@@ -186,7 +187,7 @@
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      let _data = result.data || {}
+      let _data = result.data || []
 
       this.loaded = true
       if (config.$cache && config.setting.onload !== 'false') {
@@ -199,8 +200,12 @@
         }, 10)
       }
 
+      let _result = {...result}
+      delete _result.data
+
       this.setState({
         data: _data,
+        result: _result,
         loading: false
       })
     } else {
@@ -216,36 +221,31 @@
   }
 
   renderView = () => {
-    const { data } = this.state
+    const { data, result } = this.state
     const { html, js, wrap, columns } = this.state.config
 
     let _html = html
-    if (_html && wrap.datatype !== 'static' && wrap.compileMode !== 'custom') {
-      let _data = data
-      if (Array.isArray(_data)) {
-        _data = _data[0] || {}
-      }
-      columns.forEach(col => {
-        if (col.field) {
-          let val = (_data[col.field] || _data[col.field] === 0) ? _data[col.field] : ''
-          let reg = new RegExp('@' + col.field + '@', 'ig')
+    if (_html && wrap.datatype !== 'static') {
+      if (/@[\u4E00-\u9FA50-9a-zA-Z_]+@/ig.test(_html)) {
+        let _data = data[0] || {}
 
-          _html = _html.replace(reg, val)
-        }
-      })
+        columns.forEach(col => {
+          if (col.field) {
+            let val = _data[col.field] !== undefined ? _data[col.field] : ''
+            let reg = new RegExp('@' + col.field + '@', 'ig')
+  
+            _html = _html.replace(reg, val)
+          }
+        })
+      }
     }
 
     this.setState({html: _html}, () => {
       if (js) {
         try {
-          if (wrap.compileMode !== 'custom') {
-            // eslint-disable-next-line no-eval
-            eval(js)
-          } else {
-            // eslint-disable-next-line
-            let evalfunc = eval('(true && function (data) {' + js + '})')
-            evalfunc(data)
-          }
+          // eslint-disable-next-line
+          let evalfunc = eval('(true && function (data, result) {' + js + '})')
+          evalfunc(data, result)
         } 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 434ed5d..a4084ac 100644
--- a/src/tabviews/custom/components/editor/braft-editor/index.jsx
+++ b/src/tabviews/custom/components/editor/braft-editor/index.jsx
@@ -222,7 +222,7 @@
     if (config.wrap.empty === 'hidden' && (!data || data.$$empty)) return null
 
     return (
-      <div className="custom-braft-editor-box" id={'anchor' + config.uuid} style={config.style}>
+      <div className={'custom-braft-editor-box ' + (config.wrap.firstTr || '')} id={'anchor' + config.uuid} style={config.style}>
         {loading ?
           <div className="loading-mask">
             <div className="ant-spin-blur"></div>
diff --git a/src/tabviews/custom/components/editor/braft-editor/index.scss b/src/tabviews/custom/components/editor/braft-editor/index.scss
index 5bbfc97..1829c88 100644
--- a/src/tabviews/custom/components/editor/braft-editor/index.scss
+++ b/src/tabviews/custom/components/editor/braft-editor/index.scss
@@ -28,6 +28,16 @@
   }
 }
 
+.custom-braft-editor-box.light {
+  .braft-content {
+    table {
+      tr:first-child {
+        background-color:#ffffff;
+      }
+    }
+  }
+}
+
 .custom-braft-editor-box::after {
   content: ' ';
   display: block;
diff --git a/src/tabviews/custom/components/form/step-form/index.jsx b/src/tabviews/custom/components/form/step-form/index.jsx
index 83349ad..561a5b7 100644
--- a/src/tabviews/custom/components/form/step-form/index.jsx
+++ b/src/tabviews/custom/components/form/step-form/index.jsx
@@ -98,8 +98,8 @@
 
     let _group = config.subcards[0]
 
-    if (_data && config.wrap.statusControl && _data[config.wrap.statusControl]) {
-      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]
       _group = _groups || _group
@@ -172,8 +172,8 @@
 
       _data.$$uuid = _data[config.setting.primaryKey] || ''
 
-      if (config.wrap.statusControl && _data[config.wrap.statusControl]) {
-        let _status = _data[config.wrap.statusControl]
+      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
       }
@@ -313,8 +313,8 @@
         _group = config.subcards[0]
       }
 
-      if (config.wrap.statusControl && _data[config.wrap.statusControl]) {
-        let _status = _data[config.wrap.statusControl]
+      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
       }
diff --git a/src/tabviews/custom/components/group/normal-group/index.jsx b/src/tabviews/custom/components/group/normal-group/index.jsx
index 631caf0..6cbc3cb 100644
--- a/src/tabviews/custom/components/group/normal-group/index.jsx
+++ b/src/tabviews/custom/components/group/normal-group/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Col, notification, Button, Row } from 'antd'
+import { Col, notification, Row } from 'antd'
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
@@ -44,7 +44,7 @@
 
   state = {
     mainSearch: [],
-    printing: false,
+    // printing: false,
     data: null
   }
 
@@ -296,101 +296,8 @@
     })
   }
 
-  canvasToImage(canvas) {
-    let image = new Image()
-    image.src = canvas.toDataURL('image/jpg')
-    image.style = 'width:100%;height:100%;position:absolute;z-index:1;left:0px;top:0px;'
-    return image
-  }
-
-  print = () => {
-    const { config } = this.props
-    const { printing } = this.state
-
-    if (printing) return
-    this.setState({printing: true})
-
-    let qrcodes = document.getElementsByClassName('qrcode-box')
-
-    for (let i = 0; i < qrcodes.length; i++) {
-      let canvas = qrcodes[i].getElementsByTagName('canvas')[0]
-
-      if (canvas) {
-        let img = this.canvasToImage(canvas)
-  
-        canvas.remove()
-        qrcodes[i].append(img)
-      }
-    }
-
-    let pageSize = ['A4', 'A3', 'A5'].includes(config.setting.pageSize) ? config.setting.pageSize : 'A4'
-    let pageLayout = config.setting.pageLayout !== 'horizontal' ? 'vertical' : 'horizontal'
-    let hides = config.setting.hide || []
-
-    let pageParam = {
-      A4: {
-        vertical: 980,
-        horizontal: 1200,
-      },
-      A3: {
-        vertical: 1200,
-        horizontal: 1600,
-      },
-      A5: {
-        vertical: 700,
-        horizontal: 1000,
-      }
-    }
-
-    let width = pageParam[pageSize][pageLayout]
-
-    try {
-      let jubuData =  document.getElementById(config.uuid).innerHTML
-
-      let iframe = document.createElement('IFRAME')
-      let linkList = document.getElementsByTagName('link')     // 鑾峰彇鐖剁獥鍙ink鏍囩瀵硅薄鍒楄〃
-      let styleList = document.getElementsByTagName('style')   // 鑾峰彇鐖剁獥鍙tyle鏍囩瀵硅薄鍒楄〃
-
-      document.body.appendChild(iframe)
-      let doc = iframe.contentWindow.document
-      
-      doc.open()
-      doc.write(`<!DOCTYPE html><html lang="en"><head>`)
-      for (let i = 0;i < linkList.length;i++) {
-        if (linkList[i].type === 'text/css') {
-          doc.write(`<LINK rel="stylesheet" type="text/css" href="${linkList[i].href}">`)
-        }
-      }
-      doc.write(`<style>body{width: ${width}px!important;} *{border-style: solid;border-width: 0;} .print-button{display: none!important;} ${hides.includes('search') ? '.top-search{display: none!important;}' : ''} ${hides.includes('button') ? '.ant-btn{opacity: 0!important;}' : ''}</style>`)
-      for (let i = 0;i < styleList.length;i++) {
-        doc.write('<style>' + styleList[i].innerHTML + '</style>')
-      }
-      doc.write(`</head><body>`)
-      doc.write(jubuData)
-      doc.write(`</body></html>`)
-      doc.close()
-
-      setTimeout(() => {
-        iframe.contentWindow.focus()
-        iframe.contentWindow.print()
-
-        document.body.removeChild(iframe)
-
-        this.setState({printing: false})
-      }, 500)
-    } catch (e) {
-      this.setState({printing: false})
-      notification.warning({
-        top: 92,
-        message: '鎵撳嵃寮傚父锛�',
-        duration: 5
-      })
-    }
-  }
-
   render() {
     const { config } = this.props
-    const { printing } = this.state
 
     if (!config.components || config.components.length === 0) return (<div style={config.style}></div>)
     
@@ -399,7 +306,6 @@
         {config.setting && config.setting.title ? <div className="group-header" style={config.headerStyle}>
           <span className="title">{config.setting.title}</span>
         </div> : null}
-        {config.setting && config.setting.print === 'true' ? <Button className="print-button" icon="printer" loading={printing} onClick={this.print}></Button> : null}
         <Row className="component-wrap">{this.getComponents()}</Row>
       </div>
     )
diff --git a/src/tabviews/custom/components/interfaces/interItem/index.jsx b/src/tabviews/custom/components/interfaces/interItem/index.jsx
index ab62d9b..3ba9519 100644
--- a/src/tabviews/custom/components/interfaces/interItem/index.jsx
+++ b/src/tabviews/custom/components/interfaces/interItem/index.jsx
@@ -39,9 +39,13 @@
       }
     }
 
-    setTimeout(() => {
-      this.loadData()
-    }, config.setting.delay)
+    if (config.setting.onload !== 'false') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay)
+    } else {
+      MKEmitter.addListener('initFinish', this.initFinish)
+    }
 
     MKEmitter.addListener('reloadData', this.reloadData)
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
@@ -57,8 +61,21 @@
       return
     }
     this.timer && this.timer.stop()
+    MKEmitter.removeListener('initFinish', this.initFinish)
     MKEmitter.removeListener('reloadData', this.reloadData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+  }
+
+  initFinish = (MenuID) => {
+    const { config } = this.props
+
+    if (config.MenuID !== MenuID) return
+
+    if (config.setting.onload === 'false') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay)
+    }
   }
 
   resetParentParam = (MenuID, id) => {
@@ -111,6 +128,10 @@
 
       MKEmitter.emit('mkPublicData', config.uuid, _data)
       MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
+
+      if (config.setting.loadlevel === 'init') {
+        MKEmitter.emit('interFinish', config.MenuID, config.uuid)
+      }
     } else {
       this.loading = false
       this.timer && this.timer.stop()
@@ -126,6 +147,10 @@
           duration: 10
         })
       }
+
+      if (config.setting.loadlevel === 'init') {
+        MKEmitter.emit('interFinish', config.MenuID, config.uuid)
+      }
     }
   }
 
diff --git a/src/tabviews/custom/components/module/account/index.jsx b/src/tabviews/custom/components/module/account/index.jsx
index 4996d2c..a4f2cb1 100644
--- a/src/tabviews/custom/components/module/account/index.jsx
+++ b/src/tabviews/custom/components/module/account/index.jsx
@@ -25,6 +25,7 @@
 
   componentDidMount () {
     this.loadData()
+    MKEmitter.addListener('reloadData', this.reloadData)
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -37,6 +38,20 @@
   componentWillUnmount () {
     this.setState = () => {
       return
+    }
+    MKEmitter.removeListener('reloadData', this.reloadData)
+  }
+
+  reloadData = (menuId) => {
+    const { config } = this.props
+    const { activeItem } = this.state
+    
+    if (config.uuid !== menuId) return
+
+    if (activeItem) {
+      MKEmitter.emit('resetSelectLine', config.uuid, activeItem.id, activeItem)
+    } else {
+      this.loadData()
     }
   }
 
@@ -171,7 +186,7 @@
 
     return (
       <div className="menu-account-wrap" style={config.style}>
-        {config.wrap.MenuID ? <Select value={activeItem ? activeItem.id : ''} placeholder="璇烽�夋嫨璐﹀" onChange={this.changeBook} dropdownRender={menu => (
+        {config.wrap.MenuID ? <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} value={activeItem ? activeItem.id : ''} placeholder="璇烽�夋嫨璐﹀" onChange={this.changeBook} dropdownRender={menu => (
           <div>
             {menu}
             <Divider style={{ margin: '4px 0' }} />
@@ -181,11 +196,11 @@
           </div>
         )}>
           {books.map(item => (
-            <Option disabled={!item.months} key={item.id}>{item.account_name}</Option>
+            <Option disabled={!item.months} title={item.account_name} key={item.id}>{item.account_name}</Option>
           ))}
-        </Select> : <Select value={activeItem ? activeItem.id : ''} disabled={config.wrap.readonly === 'true'} placeholder="璇烽�夋嫨璐﹀" onChange={this.changeBook}>
+        </Select> : <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} value={activeItem ? activeItem.id : ''} disabled={config.wrap.readonly === 'true'} placeholder="璇烽�夋嫨璐﹀" onChange={this.changeBook}>
           {books.map(item => (
-            <Option disabled={!item.months} key={item.id}>{item.account_name}</Option>
+            <Option disabled={!item.months} title={item.account_name} key={item.id}>{item.account_name}</Option>
           ))}
         </Select>}
         {activeItem ? <span className="date">{activeItem.date}</span> : null}
diff --git a/src/tabviews/custom/components/module/voucher/index.jsx b/src/tabviews/custom/components/module/voucher/index.jsx
index c230975..f11d8c0 100644
--- a/src/tabviews/custom/components/module/voucher/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/index.jsx
@@ -57,7 +57,7 @@
 
     let BID = ''
     let BData = ''
-
+    
     if (config.wrap.supModule) {
       BData = window.GLOB.CacheData.get(config.wrap.supModule)
     } else {
@@ -208,6 +208,8 @@
       let employee = []
       let cash_flow = []
       let others = []
+      let logistics = []
+      let lessor = []
 
       res.sup && res.sup.forEach(item => {
         names[item.sup_type_code] = item.sup_type_name
@@ -215,6 +217,14 @@
 
       res.supplier && res.supplier.forEach(item => {
         supplier.push({value: item.suppliercode, label: item.suppliername})
+      })
+
+      res.logistics && res.logistics.forEach(item => {
+        logistics.push({value: item.logistics_code, label: item.logistics_name})
+      })
+
+      res.lessor && res.lessor.forEach(item => {
+        lessor.push({value: item.lessor_code, label: item.lessor_name})
       })
 
       res.customer && res.customer.forEach(item => {
@@ -249,6 +259,8 @@
         subjects: res.subjects || [],
         names: names,
         supplier: supplier,
+        logistics: logistics,
+        lessor: lessor,
         customer: customer,
         department: department,
         project: project,
@@ -407,6 +419,14 @@
         line.supAccounts.forEach(item => {
           if (item.sup_acc_type === 'supplier') {
             if (!item.suppliercode || !item.suppliername) {
+              err = `绗�${_index}琛岋紝璇烽�夋嫨杈呭姪鏍哥畻銆俙
+            }
+          } else if (item.sup_acc_type === 'logistics') {
+            if (!item.logistics_code || !item.logistics_name) {
+              err = `绗�${_index}琛岋紝璇烽�夋嫨杈呭姪鏍哥畻銆俙
+            }
+          } else if (item.sup_acc_type === 'lessor') {
+            if (!item.lessor_code || !item.lessor_name) {
               err = `绗�${_index}琛岋紝璇烽�夋嫨杈呭姪鏍哥畻銆俙
             }
           } else if (item.sup_acc_type === 'customer') {
@@ -586,10 +606,10 @@
             supMap.delete(item.uuid + n.sup_acc_type)
           }
 
-          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`)
+          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' : ''}'`
+      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 || ''}'`
     })
 
     if (type === 'createVoucher') {
@@ -605,11 +625,11 @@
       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' : ''}'`)
+      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 || ''}'`)
     })
 
     supMap.forEach(n => {
-      sup_data.push(`'${n.uuid}','${n.sup_voucher_code}','${n.sup_voucher_lp}','${n.voucher_sup_lp || ''}','${n.sup_subject_code}','${n.sup_subject_name}','${n.sup_voucher_text || ''}','${n.sup_direct}',${n.sup_net_amount},'${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 || ''}','${n.sup_bid}',1`)
+      sup_data.push(`'${n.uuid}','${n.sup_voucher_code}','${n.sup_voucher_lp}','${n.voucher_sup_lp || ''}','${n.sup_subject_code}','${n.sup_subject_name}','${n.sup_voucher_text || ''}','${n.sup_direct}',${n.sup_net_amount},'${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 || ''}','${n.sup_bid}',1,'${n.lessor_code || ''}','${n.lessor_name || ''}','${n.logistics_code || ''}','${n.logistics_name || ''}'`)
     })
 
     let attachments_data = []
@@ -701,6 +721,14 @@
         line.supAccounts.forEach(item => {
           if (item.sup_acc_type === 'supplier') {
             if (!item.suppliercode || !item.suppliername) {
+              err = `绗�${_index}琛岋紝璇烽�夋嫨杈呭姪鏍哥畻銆俙
+            }
+          } else if (item.sup_acc_type === 'logistics') {
+            if (!item.logistics_code || !item.logistics_name) {
+              err = `绗�${_index}琛岋紝璇烽�夋嫨杈呭姪鏍哥畻銆俙
+            }
+          } else if (item.sup_acc_type === 'lessor') {
+            if (!item.lessor_code || !item.lessor_name) {
               err = `绗�${_index}琛岋紝璇烽�夋嫨杈呭姪鏍哥畻銆俙
             }
           } else if (item.sup_acc_type === 'customer') {
@@ -862,10 +890,10 @@
             supMap.delete(item.uuid + n.sup_acc_type)
           }
 
-          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`)
+          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' : ''}'`
+      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 || ''}'`
     })
 
     voucherMap.forEach(item => {
@@ -873,11 +901,11 @@
       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' : ''}'`)
+      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 || ''}'`)
     })
 
     supMap.forEach(n => {
-      sup_data.push(`'${n.uuid}','${n.sup_voucher_code}','${n.sup_voucher_lp}','${n.voucher_sup_lp || ''}','${n.sup_subject_code}','${n.sup_subject_name}','${n.sup_voucher_text || ''}','${n.sup_direct}',${n.sup_net_amount},'${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 || ''}','${n.sup_bid}',1`)
+      sup_data.push(`'${n.uuid}','${n.sup_voucher_code}','${n.sup_voucher_lp}','${n.voucher_sup_lp || ''}','${n.sup_subject_code}','${n.sup_subject_name}','${n.sup_voucher_text || ''}','${n.sup_direct}',${n.sup_net_amount},'${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 || ''}','${n.sup_bid}',1,'${n.lessor_code || ''}','${n.lessor_name || ''}','${n.logistics_code || ''}','${n.logistics_name || ''}'`)
     })
 
     param.subject_data = window.btoa(window.encodeURIComponent(subject_data.join(';un')))
@@ -1020,16 +1048,27 @@
   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')
+      }
     }
   }
 
@@ -1150,8 +1189,8 @@
               </Select>
             </div>
             <div className="temp-action">
-              <Button className="add-background header-btn" onClick={() => this.triggerTempsave()}>淇濆瓨</Button>
-              <Button className="out-background header-btn" onClick={this.triggerclose}>鍏抽棴</Button>
+              <Button className="save-temp header-btn" onClick={() => this.triggerTempsave()}>淇濆瓨</Button>
+              <Button className="close-temp header-btn" onClick={this.triggerclose}>鍏抽棴</Button>
             </div>
           </div> : null}
           <VoucherTable config={config} loading={loading} data={data} onChange={this.dataChange}/>
diff --git a/src/tabviews/custom/components/module/voucher/index.scss b/src/tabviews/custom/components/module/voucher/index.scss
index a2bae1b..4eec234 100644
--- a/src/tabviews/custom/components/module/voucher/index.scss
+++ b/src/tabviews/custom/components/module/voucher/index.scss
@@ -111,6 +111,17 @@
     color: #ffffff;
   }
 
+  .save-temp {
+    background-color: var(--mk-sys-color);
+    border-color: var(--mk-sys-color);
+    color: #ffffff;
+  }
+  .close-temp {
+    background-color: #ffffff;
+    border-color: #f5222d;
+    color: #f5222d;
+  }
+
   .system-background {
     background: var(--mk-sys-color);
     border-color: var(--mk-sys-color);
diff --git a/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx b/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx
index 2acf108..914d039 100644
--- a/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx
@@ -110,6 +110,10 @@
       subAccounts.forEach(item => {
         if (item.field === 'supplier') {
           account[item.field] = {suppliercode: item.value, suppliername: item.name}
+        } else if (item.field === 'logistics') {
+          account[item.field] = {logistics_code: item.value, logistics_name: item.name}
+        } else if (item.field === 'lessor') {
+          account[item.field] = {lessor_code: item.value, lessor_name: item.name}
         } else if (item.field === 'customer') {
           account[item.field] = {customercode: item.value, customername: item.name}
         } else if (item.field === 'department') {
@@ -764,6 +768,10 @@
               record.supAccounts.forEach(item => {
                 if (item.sup_acc_type === 'supplier') {
                   val += item.suppliercode ? '_' + item.suppliercode + ' ' + item.suppliername : ''
+                } else if (item.sup_acc_type === 'logistics') {
+                  val += item.logistics_code ? '_' + item.logistics_code + ' ' + item.logistics_name : ''
+                } else if (item.sup_acc_type === 'lessor') {
+                  val += item.lessor_code ? '_' + item.lessor_code + ' ' + item.lessor_name : ''
                 } else if (item.sup_acc_type === 'customer') {
                   val += item.customercode ? '_' + item.customercode + ' ' + item.customername : ''
                 } else if (item.sup_acc_type === 'department') {
diff --git a/src/tabviews/custom/components/module/voucher/voucherTable/index.scss b/src/tabviews/custom/components/module/voucher/voucherTable/index.scss
index fa2baa2..131b529 100644
--- a/src/tabviews/custom/components/module/voucher/voucherTable/index.scss
+++ b/src/tabviews/custom/components/module/voucher/voucherTable/index.scss
@@ -31,10 +31,10 @@
       border-right: 1px solid #e9e9e9;
     }
     span:nth-child(3), span:nth-child(6) {
-      border-color: #91d5ff;
+      border-color: #474069;
     }
     span:nth-child(9) {
-      border-color: #ffa39e;
+      border-color: #C48584;
     }
   }
 
@@ -45,11 +45,12 @@
       tr {
         th {
           position: relative;
-          background-color: transparent;
+          background-color: #E3E7F2;
           padding: 0;
           height: 60px;
           line-height: 60px;
           text-align: center;
+          border-right: 1px solid #d8d8d8;
 
           .ant-table-header-column {
             display: block;
@@ -82,12 +83,16 @@
       max-width: 60px;
     }
     .ant-table-tbody {
+      tr:last-child {
+        background-color: #FBF8EF;
+      }
       tr td {
         position: relative;
         background-color: transparent;
         padding: 0;
         height: 60px;
         vertical-align: top;
+        border-right: 1px solid #d8d8d8;
 
         .content-wrap {
           padding: 0px 5px;
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index 1926c23..83b7612 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -6,13 +6,13 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import { getMark } from '@/utils/utils.js'
-import MkIcon from '@/components/mk-icon'
 import MKEmitter from '@/utils/events.js'
 import Encrypts from '@/components/encrypts'
 import './index.scss'
 
 const { Paragraph } = Typography
 const Video = asyncComponent(() => import('@/components/video'))
+const MkIcon = asyncComponent(() => import('@/components/mk-icon'))
 const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
 const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList'))
 const PicRadio = {
@@ -340,7 +340,16 @@
           // eslint-disable-next-line
           content = eval(content)
         } catch (e) {
+          if (window.debugger) {
+            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)
         }
       }
 
@@ -348,11 +357,8 @@
 
       if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
-
-        if (col.eval === 'false') {
-          content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
-          content = <span dangerouslySetInnerHTML={{__html: content}}></span>
-        }
+        content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       }
 
       if (col.marks) {
@@ -378,14 +384,6 @@
         style = {...style, ...col.style}
       }
 
-      resProps.children = (
-        <CardCellComponent data={record} cards={config} elements={col.elements}/>
-      )
-    } else if (col.type === 'action') {
-      style.padding = '0px'
-      if (col.style) {
-        style = {...style, ...col.style}
-      }
       resProps.children = (
         <CardCellComponent data={record} cards={config} elements={col.elements}/>
       )
@@ -480,7 +478,7 @@
               onCell: record => ({
                 record,
                 col: item,
-                config: item.type === 'custom' || item.type === 'action' ? {setting, columns: fields} : null,
+                config: item.type === 'custom' ? {setting, columns: fields} : null,
                 triggerLink: this.triggerLink
               })
             }
@@ -504,6 +502,8 @@
           width: item.Width || 120
         })
       })
+
+      orderfields = null
     }
 
     if (rowspans.length === 0) {
@@ -816,7 +816,9 @@
       pickup: false
     })
 
-    sorter.field = orderfields[sorter.field] || ''
+    if (orderfields) {
+      sorter.field = orderfields[sorter.field] || ''
+    }
 
     this.props.refreshdata(pagination, filters, sorter)
   }
@@ -986,13 +988,26 @@
     }
 
     let height = setting.height || false
+    if (height && height <= 100) {
+      height = height + 'vh'
+    }
     let loading = this.props.loading
     if (setting.mask === 'hidden') {
       loading = false
     }
 
+    let fixed = ''
+    if (setting.colfixed && setting.colfixed.length) {
+      if (setting.colfixed.includes('first')) {
+        fixed = 'mk-fixed-first-col'
+      }
+      if (setting.colfixed.includes('last')) {
+        fixed += ' mk-fixed-last-col'
+      }
+    }
+
     return (
-      <div className={`normal-custom-table ${setting.tableHeader || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || 'middle'} table-col-${columns.length}`} id={tableId}>
+      <div className={`normal-custom-table ${setting.tableHeader || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || 'middle'} table-col-${columns.length} ${fixed}`} id={tableId}>
         {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 ?
           <Switch title="鏀惰捣" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /> : null
         }
@@ -1009,6 +1024,7 @@
             return {
               lineMarks: setting.tableMode !== 'fast' ? lineMarks : null,
               data: record,
+              title: setting.tipField ? record[setting.tipField] : '',
               className: index === activeIndex ? ' mk-row-active ' : '',
               onClick: () => {this.changeRow(record, index)},
               onDoubleClick: () => {this.doubleClickLine(record)}
diff --git a/src/tabviews/custom/components/share/normalTable/index.scss b/src/tabviews/custom/components/share/normalTable/index.scss
index 5a96fe8..12ad8fd 100644
--- a/src/tabviews/custom/components/share/normalTable/index.scss
+++ b/src/tabviews/custom/components/share/normalTable/index.scss
@@ -198,8 +198,11 @@
       display: block;
     }
   }
+  .ant-table-small.ant-table-bordered {
+    border-right: 1px solid #e8e8e8;
+  }
 
-  table, tr, th, td {
+  table, tr, th, td, .ant-table-small {
     border-color: var(--mk-table-border-color)!important;
   }
   table tr {
@@ -219,11 +222,11 @@
   table tbody tr {
     color: var(--mk-table-color);
   }
-  // table tbody {
-  //   tr:nth-child(even) {
-  //     background: #f5f5f5;
-  //   }
-  // }
+}
+.normal-custom-table:not(.ghost) {
+  .ant-table-small > .ant-table-content .ant-table-thead > tr > th {
+    background-color: #fafafa!important;
+  }
 }
 .normal-custom-table:not(.fixed-height) {
   .ant-table-body::-webkit-scrollbar {
@@ -255,6 +258,65 @@
     display: none;
   }
 }
+.normal-custom-table.mk-fixed-last-col {
+  table {
+    .ant-table-thead {
+      tr:first-child {
+        th:last-child {
+          position: sticky !important;
+          z-index: 2;
+          right: 0px;
+          box-shadow: 0 1px 1px #bcbcbc;
+        }
+      }
+    }
+    .ant-table-tbody {
+      tr {
+        td:last-child {
+          position: sticky !important;
+          z-index: 2;
+          right: 0px;
+          background: #ffffff;
+          box-shadow: 0 1px 1px #bcbcbc;
+        }
+      }
+    }
+  }
+}
+.normal-custom-table.mk-fixed-first-col {
+  table {
+    .ant-table-thead {
+      tr:first-child {
+        th:first-child {
+          position: sticky !important;
+          z-index: 2;
+          left: 0px;
+        }
+        th.ant-table-selection-column + th {
+          position: sticky !important;
+          z-index: 2;
+          left: 60px;
+        }
+      }
+    }
+    .ant-table-tbody {
+      tr {
+        td:first-child {
+          position: sticky !important;
+          z-index: 2;
+          left: 0px;
+          background: #ffffff;
+        }
+        td.ant-table-selection-column + td{
+          position: sticky !important;
+          z-index: 2;
+          left: 60px;
+          background: #ffffff;
+        }
+      }
+    }
+  }
+}
 .normal-custom-table.ghost {
   .main-pickup {
     display: none;
diff --git a/src/tabviews/custom/components/share/normalheader/index.scss b/src/tabviews/custom/components/share/normalheader/index.scss
index 8816fb1..8de5a23 100644
--- a/src/tabviews/custom/components/share/normalheader/index.scss
+++ b/src/tabviews/custom/components/share/normalheader/index.scss
@@ -18,7 +18,7 @@
     position: relative;
     z-index: 1;
   }
-  .top-search {
+  .mk-search-wrap {
     background: transparent;
     text-decoration: unset;
     font-weight: normal;
diff --git a/src/tabviews/custom/components/share/tabtransfer/index.jsx b/src/tabviews/custom/components/share/tabtransfer/index.jsx
index f7bbac1..79c6827 100644
--- a/src/tabviews/custom/components/share/tabtransfer/index.jsx
+++ b/src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -174,13 +174,10 @@
     })
   }
 
-  getComponents = () => {
-    const { config } = this.props
+  getComponents = (components) => {
     const { mainSearch, data } = this.state
 
-    if (!config || !config.components || config.components.length === 0) return (<Empty description={false} />)
-
-    return config.components.map(item => {
+    return components.map(item => {
       let style = null
 
       if (item.style && item.style.clear === 'left') {
@@ -355,8 +352,12 @@
   }
 
   render() {
+    const { config } = this.props
+
+    if (!config || !config.components || config.components.length === 0) return (<Empty description={false} />)
+
     return (
-      <Row className="component-wrap" gutter={8}>{this.getComponents()}</Row>
+      <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 80579fb..9658a04 100644
--- a/src/tabviews/custom/components/table/base-table/index.jsx
+++ b/src/tabviews/custom/components/table/base-table/index.jsx
@@ -200,7 +200,7 @@
             })
           }
           if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField])) {
+            if (setting.controlVal.includes(item[setting.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -396,26 +396,13 @@
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
   refreshbysearch = (searches) => {
-    const { setting } = this.state
-
-    if (setting.onload === 'false') {
-      this.setState({
-        pageIndex: 1,
-        search: searches,
-        setting: {...setting, onload: 'true'}
-      }, () => {
-        this.loadmaindata()
-        this.getStatFieldsValue()
-      })
-    } else {
-      this.setState({
-        pageIndex: 1,
-        search: searches
-      }, () => {
-        this.loadmaindata(true, 'true')
-        this.getStatFieldsValue()
-      })
-    }
+    this.setState({
+      pageIndex: 1,
+      search: searches
+    }, () => {
+      this.loadmaindata(true, 'true')
+      this.getStatFieldsValue()
+    })
   }
 
   /**
diff --git a/src/tabviews/custom/components/table/base-table/index.scss b/src/tabviews/custom/components/table/base-table/index.scss
index 34f97b7..724b889 100644
--- a/src/tabviews/custom/components/table/base-table/index.scss
+++ b/src/tabviews/custom/components/table/base-table/index.scss
@@ -5,32 +5,12 @@
   .normal-header {
     margin-bottom: 10px;
   }
-  .top-search {
+  .mk-search-wrap {
     border-bottom: 1px solid #efefef;
     padding-top: 10px;
   }
-  >.button-list.toolbar-button {
-    min-height: 60px;
+  .button-list.toolbar-button {
     padding-right: 60px;
-    button {
-      margin-right: 0px;
-      margin-bottom: 0px;
-      min-height: 28px;
-      height: auto;
-    }
-  }
-  .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);
-    }
   }
   .main-table-box {
     position: relative;
diff --git a/src/tabviews/custom/components/table/edit-table/index.jsx b/src/tabviews/custom/components/table/edit-table/index.jsx
index 3496def..d1281be 100644
--- a/src/tabviews/custom/components/table/edit-table/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/index.jsx
@@ -37,9 +37,7 @@
     pageIndex: 1,         // 椤电爜
     pageSize: 10,         // 姣忛〉鏁版嵁鏉℃暟
     orderBy: '',          // 鎺掑簭
-    search: '',           // 鎼滅储鏉′欢鏁扮粍锛屼娇鐢ㄦ椂闇�鍒嗗満鏅鐞�
-    statFValue: [],       // 鍚堣鍊�
-    lock: false
+    search: ''            // 鎼滅储鏉′欢鏁扮粍锛屼娇鐢ㄦ椂闇�鍒嗗満鏅鐞�
   }
 
   /**
@@ -65,69 +63,103 @@
 
     _config.submit.style = _config.submit.style || {}
     _config.submit.wrapStyle = {}
-    _config.submit.hasAction = _config.action.length > 0
-    if (!_config.submit.hasAction) {
-      if (_config.submit.style.marginTop) {
-        _config.submit.wrapStyle.paddingTop = _config.submit.style.marginTop
+    setting.hasAction = _config.action.length > 0
+
+    _config.action.forEach(btn => {
+      if (btn.funcType === 'addline') {
+        setting.addable = true
       }
-      if (_config.submit.style.marginBottom) {
-        _config.submit.wrapStyle.paddingBottom = _config.submit.style.marginBottom
+      btn.$tableId = setting.tableId
+      if (!btn.controlField) {
+        btn.controlField = '$lock'
+        btn.controlVals = []
       }
-    } else {
-      _config.submit.wrapStyle.paddingTop = '15px'
-    }
-
-    if (setting.height) {
-      setting.operType = 'btnMode'
-    }
-
-    let _columns = []
-    let signAdd = false
-    _config.cols.forEach(column => {
-      if (column.Hide === 'true') return
-      if (column.type === 'index') {
-        column.field = '$Index'
-        column.type = 'text'
-      }
-
-      if (setting.addable === 'true' && setting.operType === 'buoyMode' && column.type !== 'action' && !signAdd) {
-        column.addable = true
-        signAdd = true
-      }
-
-      if (column.marks && column.marks.length === 0) {
-        column.marks = ''
-      }
-
-      column.tableId = setting.tableId
-
-      if (column.type === 'text' && column.editable === 'true' && column.editType === 'select') {
-        column.options = column.options || []
-        column.options = column.options.filter(cell => {
-          cell.value = cell.Value
-          cell.label = cell.Text
-  
-          return !cell.Hide
-        })
-      }
-
-      _columns.push(column)
     })
 
-    if (setting.delable !== 'false' && setting.operType === 'buoyMode') {
-      if (_columns[_columns.length - 1] && _columns[_columns.length - 1].type !== 'action') {
-        _columns[_columns.length - 1].delable = true
-      } else if (_columns[_columns.length - 2] && _columns[_columns.length - 2].type !== 'action') {
-        _columns[_columns.length - 2].delable = true
-      }
+    let _columns = []
+    setting.initId = ''
+    let triMap = new Map()
+    setting.hasSubmit = false
+
+    let getColumns = (cols) => {
+      return cols.filter(item => {
+        if (item.Hide === 'true') return false
+
+        item.tableId = setting.tableId
+
+        if (item.type === 'colspan') {
+          item.subcols = getColumns(item.subcols)
+
+          if (item.subcols.length === 0) {
+            return false
+          }
+        } else if (item.type === 'custom') {
+          item.elements.forEach(btn => {
+            if (btn.eleType !== 'button') return
+            if (btn.funcType === 'addline') {
+              setting.addable = true
+            }
+            btn.$tableId = setting.tableId
+            if (!btn.controlField) {
+              btn.controlField = '$lock'
+              btn.controlVals = []
+            }
+          })
+        } else {
+          if (item.type === 'index') {
+            item.field = '$Index'
+            item.type = 'text'
+          }
+
+          if (item.marks && item.marks.length === 0) {
+            item.marks = ''
+          }
+
+          if (item.editable === 'true') {
+            setting.hasSubmit = true
+            if (!setting.initId) {
+              setting.initId = item.uuid
+            }
+            if (item.type === 'text' && (item.editType === 'switch' || item.editType === 'select')) {
+              triMap.set(item.uuid, item.editType)
+            }
+            if (item.type === 'text' && item.editType === 'select') {
+              item.options = item.options || []
+              item.options = item.options.filter(cell => {
+                cell.value = cell.Value
+                cell.label = cell.Text
+        
+                return !cell.Hide
+              })
+            }
+          }
+        }
+  
+        return true
+      })
     }
 
-    // if (setting.color) {
-    //   setting.style.color = setting.color
-    // }
-    // if (setting.fontSize) {
-    //   setting.style.fontSize = setting.fontSize
-    // }
+    _columns = getColumns(_config.cols)
+
+    if (triMap.size > 0) {
+      let setColumns = (cols) => {
+        return cols.map(item => {
+          if (item.type === 'colspan') {
+            item.subcols = setColumns(item.subcols)
+          } else if (item.editable === 'true' && triMap.has(item.enter)) {
+            item.triType = 'click'
+          }
+    
+          return item
+        })
+      }
+  
+      _columns = setColumns(_columns)
+
+      if (setting.initId && triMap.has(setting.initId)) {
+        setting.triType = 'click'
+      }
+    }
 
     if (!_config.lineMarks || _config.lineMarks.length === 0) {
       _config.lineMarks = null
@@ -148,7 +180,6 @@
       if (_config.setting.onload === 'true') {
         setTimeout(() => {
           this.loadmaindata()
-          this.getStatFieldsValue()
         }, _config.setting.delay || 0)
       }
     })
@@ -253,7 +284,7 @@
   /**
    * @description 鑾峰彇鍗曡鏁版嵁
    */ 
-  async loadmainLinedata (id, line) {
+  async loadmainLinedata (id) {
     const { mainSearch } = this.props
     const { setting, config, arr_field, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
@@ -276,10 +307,18 @@
 
     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] || {}
+      let _data = result.data[0]
       _data.$$uuid = _data[setting.primaryKey] || ''
       _data.$$BID = BID || ''
       _data.$$BData = BData || ''
@@ -294,34 +333,24 @@
         })
       }
 
-      try {
-        data = data.map(item => {
-          if (item.$$uuid === _data.$$uuid) {
-            _data.key = item.key
-            _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.$Index = item.$Index
+          return _data
+        } else {
           return item
-        })
-      } catch (e) {
-        console.warn('鏁版嵁鏌ヨ閿欒')
-      }
-
-      if (line) {
-        if (line.$type === 'del' && !result.data[0]) {
-          data = data.filter(m => m.$$uuid === line.$$uuid)
         }
-        MKEmitter.emit('transferData', config.uuid, _data, 'line')
-      } else {
-        MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
-      }
+      })
+      selectedData = selectedData.map(item => {
+        if (_data.$$uuid === item.$$uuid) {
+          return _data
+        }
+        return item
+      })
+
+      MKEmitter.emit('transferData', config.uuid, _data, 'line')
+      MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
 
       this.setState({
         data,
@@ -341,96 +370,16 @@
   }
 
   /**
-   * @description 鑾峰彇鍚堣瀛楁鍊�
-   */
-  getStatFieldsValue = () => {
-    const { mainSearch } = this.props
-    const { setting, config, search, BID, orderBy } = this.state
-
-    if (setting.supModule && !BID) { // 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 鎼滅储鏉′欢鏀瑰彉鏃讹紝閲嶇疆琛ㄦ牸鏁版嵁
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
   refreshbysearch = (searches) => {
-    const { setting } = this.state
-
-    if (setting.onload === 'false') {
-      this.setState({
-        pageIndex: 1,
-        search: searches,
-        setting: {...setting, onload: 'true'}
-      }, () => {
-        this.loadmaindata()
-        this.getStatFieldsValue()
-      })
-    } else {
-      this.setState({
-        pageIndex: 1,
-        search: searches
-      }, () => {
-        this.loadmaindata(true, 'true')
-        this.getStatFieldsValue()
-      })
-    }
+    this.setState({
+      pageIndex: 1,
+      search: searches
+    }, () => {
+      this.loadmaindata(true, 'true')
+    })
   }
 
   /**
@@ -463,11 +412,9 @@
         pageIndex: 1
       }, () => {
         this.loadmaindata(true, 'true')
-        this.getStatFieldsValue()
       })
     } else {
       this.loadmaindata(true, 'false')
-      this.getStatFieldsValue()
     }
   }
 
@@ -498,7 +445,7 @@
     })
   }
 
-  reloadData = (menuId, id, item) => {
+  reloadData = (menuId, id) => {
     const { config } = this.state
 
     if (config.uuid !== menuId) return
@@ -506,7 +453,7 @@
     if (!id) {
       this.reloadtable()
     } else {
-      this.loadmainLinedata(id, item)
+      this.loadmainLinedata(id)
     }
   }
 
@@ -520,8 +467,9 @@
         BID: id,
         BData: data
       }, () => {
-        this.loadmaindata(true, 'true')
-        this.getStatFieldsValue()
+        setTimeout(() => {
+          this.loadmaindata(true, 'true')
+        }, setting.delay || 0)
       })
     }
   }
@@ -589,23 +537,27 @@
   }
 
   render() {
-    const { BID, setting, actions, config, columns, BData, selectedData, lock } = this.state
+    const { BID, setting, actions, config, columns, BData, data, selectedData } = this.state
+
+    let style = {...config.style}
+    if (config.wrap.empty === 'hidden' && data.length === 0) {
+      style.display = 'none'
+    }
 
     return (
-      <div className="custom-edit-table" id={'anchor' + config.uuid} style={config.style}>
+      <div className={'custom-edit-table' + (setting.hasSubmit ? '' : ' withnot-submit')} id={'anchor' + config.uuid} style={style}>
         <NormalHeader config={config}/>
         {config.search && config.search.length ?
           <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
         }
-        <MainAction
+        {actions.length > 0 ? <MainAction
           BID={BID}
           setting={setting}
           actions={actions}
           BData={BData}
-          lock={lock}
           columns={config.columns}
           selectedData={selectedData}
-        />
+        /> : null}
         <MainTable
           BID={BID}
           setting={setting}
@@ -618,8 +570,6 @@
           loading={this.state.loading}
           refreshdata={this.refreshbytable}
           chgSelectData={(selects) => this.setState({selectedData: selects})}
-          changeLock={(lock) => this.setState({lock: lock})}
-          statFValue={this.state.statFValue}
         />
       </div>
     )
diff --git a/src/tabviews/custom/components/table/edit-table/index.scss b/src/tabviews/custom/components/table/edit-table/index.scss
index 16ea698..04c258f 100644
--- a/src/tabviews/custom/components/table/edit-table/index.scss
+++ b/src/tabviews/custom/components/table/edit-table/index.scss
@@ -5,64 +5,24 @@
   .normal-header {
     margin-bottom: 10px;
   }
-  .top-search {
+  .mk-search-wrap {
     border-bottom: 1px solid #efefef;
     padding-top: 10px;
   }
-  >.button-list.toolbar-button {
-    padding: 0;
-    line-height: 45px;
-    float: left;
+  .button-list.toolbar-button {
+    float: right;
+    margin-right: 80px;
     position: relative;
     z-index: 2;
-    button {
-      margin-right: 0px;
-      margin-bottom: 0px;
-      min-height: 28px;
-      height: auto;
-    }
   }
-  .ant-modal-mask {
+  .toolbar-button + .edit-custom-table-btn-wrap {
     position: absolute;
+    right: 0px;
+    margin-top: 15px;
   }
-  .ant-modal-wrap {
-    position: absolute;
-  }
-  .action-modal .ant-modal {
-    top: 40px;
-    max-width: 95%;
-    .ant-modal-body {
-      max-height: calc(100vh - 265px);
-    }
-  }
-  .ant-collapse {
-    background-color: transparent;
-    border-radius: 0px;
-    > .ant-collapse-item {
-      border: 0;
-      >.ant-collapse-header {
-        padding: 0;
-        .normal-header {
-          padding-right: 40px;
-        }
-      }
-    }
-    .ant-collapse-item:last-child > .ant-collapse-content {
-      border-radius: 0;
-      .ant-collapse-content-box {
-        padding: 0;
-        >.button-list.toolbar-button {
-          padding: 0;
-          line-height: 45px;
-          padding-right: 60px;
-          button {
-            margin-right: 0px;
-            margin-bottom: 0px;
-            min-height: 28px;
-            height: auto;
-          }
-        }
-      }
-    }
+}
+.custom-edit-table.withnot-submit {
+  .button-list.toolbar-button {
+    margin-right: 0px;
   }
 }
\ No newline at end of file
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 8c85c47..a38bb09 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -1,23 +1,20 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Table, Typography, Switch, Modal, Input, InputNumber, Tooltip, Button, notification, message, Select } from 'antd'
-import { ExclamationCircleOutlined, EditOutlined, PlusOutlined, PlusCircleOutlined, DeleteOutlined } from '@ant-design/icons'
+import { Table, Typography, Modal, Input, InputNumber, Button, notification, message, Select } from 'antd'
+import { EditOutlined, QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
 import Utils, { getEditTableSql, getMark } from '@/utils/utils.js'
-import MkIcon from '@/components/mk-icon'
 import MKEmitter from '@/utils/events.js'
-import zhCN from '@/locales/zh-CN/main.js'
-import enUS from '@/locales/en-US/main.js'
 import CusSwitch from './cusSwitch'
 import Encrypts from '@/components/encrypts'
 import './index.scss'
 
 const { Paragraph } = Typography
-const { confirm } = Modal
+const MkIcon = asyncComponent(() => import('@/components/mk-icon'))
 const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList'))
 
 class BodyRow extends React.Component {
@@ -99,17 +96,12 @@
 class BodyCell extends React.Component {
   state = {
     editing: false,
-    err: null
+    err: null,
+    value: ''
   }
 
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props.record), fromJS(nextProps.record)) ||
-      nextState.editing !== this.state.editing ||
-      nextState.err !== this.state.err
-  }
-
-  componentDidMount () {
-    MKEmitter.addListener('tdFocus', this.tdFocus)
+    return !is(fromJS(this.props.record), fromJS(nextProps.record)) || !is(fromJS(this.state), fromJS(nextState))
   }
 
   /**
@@ -119,14 +111,6 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('tdFocus', this.tdFocus)
-  }
-
-  tdFocus = (id) => {
-    const { col, record } = this.props
-
-    if (id !== col.uuid + record.$$uuid) return
-    this.focus()
   }
 
   enterPress = () => {
@@ -135,12 +119,13 @@
 
     this.setState({editing: false})
     setTimeout(() => {
-      if (col.enter === '$next') {
+      if (/\$next/.test(col.enter)) {
         MKEmitter.emit('nextLine', col, record.$$uuid)
       } else if (col.enter === '$sub') {
         MKEmitter.emit('subLine', col, record)
       } else if (col.enter !== '$noAct') {
-        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
+        let node = document.getElementById(col.enter + record.$$uuid)
+        node && node.click()
       }
     }, 50)
 
@@ -151,6 +136,8 @@
 
   focus = () => {
     const { col, record } = this.props
+
+    if (col.ctrlField && col.ctrlValue.includes(record[col.ctrlField])) return
 
     if (col.editType === 'switch' || col.editType === 'select') {
       this.setState({editing: true}, () => {
@@ -211,6 +198,7 @@
     } else if (col.required === 'true' && !val) {
       err = '璇峰~鍐�' + col.label
     }
+    
     this.setState({value: val, err})
   }
 
@@ -220,24 +208,17 @@
     this.setState({editing: false})
 
     setTimeout(() => {
-      if (col.enter === '$next') {
+      if (/\$next/.test(col.enter)) {
         MKEmitter.emit('nextLine', col, record.$$uuid)
       } else if (col.enter === '$sub') {
         MKEmitter.emit('subLine', col, record)
       } else if (col.enter !== '$noAct') {
-        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
+        let node = document.getElementById(col.enter + record.$$uuid)
+        node && node.click()
       }
     }, 50)
 
-    let values = {}
-    if (col.editField) {
-      values[col.field] = label
-      values[col.editField] = val
-    } else {
-      values[col.field] = val
-    }
-
-    MKEmitter.emit('changeRecord', col.tableId, {...record, ...values})
+    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
   }
 
   onSelectChange = (val, option) => {
@@ -253,23 +234,19 @@
         })
       }
 
-      if (col.editField) {
-        values[col.field] = _option.label
-        values[col.editField] = val
-      } else {
-        values[col.field] = val
-      }
+      values[col.field] = val
     }
 
     this.setState({editing: false})
 
     setTimeout(() => {
-      if (col.enter === '$next') {
+      if (/\$next/.test(col.enter)) {
         MKEmitter.emit('nextLine', col, record.$$uuid)
       } else if (col.enter === '$sub') {
         MKEmitter.emit('subLine', col, record)
       } else if (col.enter !== '$noAct') {
-        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
+        let node = document.getElementById(col.enter + record.$$uuid)
+        node && node.click()
       }
     }, 50)
 
@@ -288,11 +265,20 @@
 
     if (!col) return (<td {...resProps} className={className} style={style}/>)
 
+    let disabled = false
+    if (col.ctrlField) {
+      disabled = col.ctrlValue.includes(record[col.ctrlField])
+    }
+
     let children = null
     if (col.type === 'text') {
       let content = ''
       if (record[col.field] !== undefined) {
         content = `${record[col.field]}`
+      }
+
+      if (col.editType === 'select' && col.options.length > 0) {
+        content = col.map.get(content) || content
       }
 
       if (content !== '') {
@@ -325,30 +311,21 @@
         }
       }
 
-      if (col.editable === 'true') {
+      if (col.editable === 'true' && !disabled) {
         if (editing) {
           if (!col.editType || col.editType === 'text') {
             return (<td className="editing_table_cell">
-              <Input id={col.uuid + record.$$uuid} defaultValue={value} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
-              {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null}
+              <Input className={err ? 'has-error' : ''} title={err} id={col.uuid + record.$$uuid} defaultValue={value} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
             </td>)
           } else if (col.editType === 'switch') {
-            let _value = ''
-            if (col.editField) {
-              _value = record[col.editField] !== undefined ? record[col.editField] : ''
-            } else {
-              _value = record[col.field] !== undefined ? record[col.field] : ''
-            }
+            let _value = record[col.field] !== undefined ? record[col.field] : ''
+
             return (<td className="editing_table_cell">
               <CusSwitch config={col} defaultValue={_value} autoFocus={true} onChange={this.onSwitchChange} onBlur={this.switchBlur}/>
             </td>)
           } else {
-            let _value = ''
-            if (col.editField) {
-              _value = record[col.editField] !== undefined ? record[col.editField] : ''
-            } else {
-              _value = record[col.field] !== undefined ? record[col.field] : ''
-            }
+            let _value = record[col.field] !== undefined ? record[col.field] : ''
+
             return (<td className="editing_table_cell">
               <Select
                 showSearch
@@ -366,9 +343,7 @@
           }
         } else {
           return (<td className={className + ' pointer'} style={style}>
-            {col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}
-            <div className="mk-mask" onClick={this.focus}></div>{content}
-            {col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}
+            <div className="mk-mask" id={col.uuid + record.$$uuid} onClick={this.focus}></div>{content}
           </td>)
         }
       } else {
@@ -379,6 +354,9 @@
       try {
         content = parseFloat(record[col.field])
         if (isNaN(content)) {
+          content = ''
+        }
+        if (col.noValue === 'hide' && content === 0) {
           content = ''
         }
       } catch (e) {
@@ -421,17 +399,18 @@
         }
       }
 
-      if (col.editable === 'true') {
+      if (col.editable === 'true' && !disabled) {
         if (editing) {
+          let val = value
+          if (col.noValue === 'hide' && value === 0) {
+            val = ''
+          }
           return (<td className="editing_table_cell">
-            <InputNumber id={col.uuid + record.$$uuid} defaultValue={value} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
-            {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null}
+            <InputNumber className={err ? 'has-error' : ''} precision={col.decimal || 0} title={err} id={col.uuid + record.$$uuid} defaultValue={val} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
           </td>)
         } else {
           return (<td className={className + ' pointer'} style={style}>
-            {col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}
-            <div className="mk-mask" onClick={this.focus}></div>{content}
-            {col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}
+            <div className="mk-mask" id={col.uuid + record.$$uuid} onClick={this.focus}></div>{content}
           </td>)
         }
       } else {
@@ -464,19 +443,29 @@
           // eslint-disable-next-line
           content = eval(content)
         } catch (e) {
+          if (window.debugger) {
+            console.info(content)
+            console.warn(e)
+          }
           content = ''
         }
       }
 
       content = content === undefined ? '' : content
 
+      if (col.noValue === 'hide' && content === 0) {
+        content = ''
+      }
+
+      if (col.round && typeof(content) === 'number') {
+        content = Math.round(content * col.round) / col.round
+        content = content.toFixed(col.decimal)
+      }
+
       if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
-
-        if (col.eval === 'false') {
-          content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
-          content = <span dangerouslySetInnerHTML={{__html: content}}></span>
-        }
+        content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       }
 
       if (col.marks) {
@@ -505,38 +494,37 @@
       children = (
         <CardCellComponent data={record} cards={config} elements={col.elements}/>
       )
-    } else if (col.type === 'action') {
-      style.padding = '0px'
-      if (col.style) {
-        style = {...style, ...col.style}
-      }
-      children = (
-        <CardCellComponent data={record} cards={config} elements={col.elements}/>
-      )
-    } else if (col.type === 'operation') {
-      style.padding = '0px 5px'
-      children = (
-        <Button type="link" style={{color: 'rgb(255, 77, 79)', backgroundColor: 'transparent'}} onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})}>鍒犻櫎</Button>
-      )
     }
 
-    return (<td className={className} style={style}>{col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}{children}{col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}</td>)
-    // return (<td className={className} style={style}>{children}</td>)
+    return (<td className={className} style={style}>{children}</td>)
   }
 }
 
 class BodyAllCell extends React.Component {
   state = {
-    err: null
+    err: null,
+    value: ''
   }
 
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props.record), fromJS(nextProps.record)) ||
-      nextState.err !== this.state.err
+    return !is(fromJS(this.props.record), fromJS(nextProps.record)) || !is(fromJS(this.state), fromJS(nextState))
   }
 
-  componentDidMount () {
-    MKEmitter.addListener('tdFocus', this.tdFocus)
+  UNSAFE_componentWillMount() {
+    const { col } = this.props
+
+    if (col && col.editable === 'true') {
+      this.setState({value: this.props.record[col.field]})
+    }
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    const { col } = this.props
+    const { value } = this.state
+
+    if (col && col.editable === 'true' && nextProps.record[col.field] !== value) {
+      this.setState({value: nextProps.record[col.field]})
+    }
   }
 
   /**
@@ -546,65 +534,48 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('tdFocus', this.tdFocus)
-  }
-
-  tdFocus = (id) => {
-    const { col, record } = this.props
-
-    if (id !== col.uuid + record.$$uuid) return
-    this.focus()
   }
 
   enterPress = () => {
     const { col, record } = this.props
 
+    this.onBlur()
+
     setTimeout(() => {
-      if (col.enter === '$next') {
+      if (/\$next/.test(col.enter)) {
         MKEmitter.emit('nextLine', col, record.$$uuid)
       } else if (col.enter === '$sub') {
         MKEmitter.emit('subLine', col, record)
       } else if (col.enter !== '$noAct') {
-        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
+        let node = document.getElementById(col.enter + record.$$uuid)
+
+        if (node) {
+          if (col.triType === 'click') {
+            node.click()
+          } else {
+            node.select && node.select()
+          }
+        }
       }
     }, 50)
   }
-
-  focus = () => {
-    const { col, record } = this.props
-
-    if (col.editType === 'switch' || col.editType === 'select') {
-      let node = document.getElementById(col.uuid + record.$$uuid)
-      node && node.click()
-    } else {
-      let err = null
-      let val = record[col.field] !== undefined ? record[col.field] : ''
-  
-      if (col.type === 'number') {
-        val = +val
-        if (isNaN(val)) {
-          val = 0
-        }
-        if (typeof(col.max) === 'number' && val > col.max) {
-          err = col.label + '鏈�澶т负' + col.max
-        } else if (typeof(col.min) === 'number' && val < col.min) {
-          err = col.label + '鏈�灏忎负' + col.min
-        }
-      } else if (col.required === 'true' && !val) {
-        err = '璇峰~鍐�' + col.label
-      }
-  
-      this.setState({err}, () => {
-        let node = document.getElementById(col.uuid + record.$$uuid)
-        node && node.select()
-      })
-    }
-  }
   
   onChange = (val) => {
+    const { col } = this.props
+
+    if (col.noValue === 'hide' && val === null) {
+      this.setState({value: 0})
+    } else {
+      this.setState({value: val})
+    }
+  }
+
+  onBlur = () => {
     const { col, record } = this.props
+    const { value } = this.state
     
     let err = null
+    let val = value
 
     if (col.type === 'number') {
       val = +val
@@ -619,32 +590,35 @@
     } else if (col.required === 'true' && !val) {
       err = '璇峰~鍐�' + col.label
     }
+
     this.setState({err})
-    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
+
+    if (value !== record[col.field]) {
+      MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
+    }
   }
 
   onSwitchChange = (val, label) => {
     const { col, record } = this.props
 
     setTimeout(() => {
-      if (col.enter === '$next') {
+      if (/\$next/.test(col.enter)) {
         MKEmitter.emit('nextLine', col, record.$$uuid)
       } else if (col.enter === '$sub') {
         MKEmitter.emit('subLine', col, record)
       } else if (col.enter !== '$noAct') {
-        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
+        let node = document.getElementById(col.enter + record.$$uuid)
+        if (node) {
+          if (col.triType === 'click') {
+            node.click()
+          } else {
+            node.select && node.select()
+          }
+        }
       }
     }, 50)
 
-    let values = {}
-    if (col.editField) {
-      values[col.field] = label
-      values[col.editField] = val
-    } else {
-      values[col.field] = val
-    }
-
-    MKEmitter.emit('changeRecord', col.tableId, {...record, ...values})
+    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
   }
 
   onSelectChange = (val, option) => {
@@ -660,21 +634,23 @@
         })
       }
 
-      if (col.editField) {
-        values[col.field] = _option.label
-        values[col.editField] = val
-      } else {
-        values[col.field] = val
-      }
+      values[col.field] = val
     }
 
     setTimeout(() => {
-      if (col.enter === '$next') {
+      if (/\$next/.test(col.enter)) {
         MKEmitter.emit('nextLine', col, record.$$uuid)
       } else if (col.enter === '$sub') {
         MKEmitter.emit('subLine', col, record)
       } else if (col.enter !== '$noAct') {
-        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
+        let node = document.getElementById(col.enter + record.$$uuid)
+        if (node) {
+          if (col.triType === 'click') {
+            node.click()
+          } else {
+            node.select && node.select()
+          }
+        }
       }
     }, 50)
 
@@ -682,23 +658,24 @@
   }
 
   render() {
-    let { col, config, record, style, className } = this.props
+    let { col, config, record, style, className, ...resProps } = this.props
     const { err } = this.state
+
+    if (!col) return (<td {...resProps} className={className} style={style}/>)
+
+    let disabled = false
+    if (col.ctrlField) {
+      disabled = col.ctrlValue.includes(record[col.ctrlField])
+    }
 
     let children = null
     if (col.type === 'text') {
-      if (col.editable === 'true') {
-        let _value = ''
-        if (col.editField) {
-          _value = record[col.editField] !== undefined ? record[col.editField] : ''
-        } else {
-          _value = record[col.field] !== undefined ? record[col.field] : ''
-        }
+      if (col.editable === 'true' && !disabled) {
+        let _value = record[col.field] !== undefined ? record[col.field] : ''
         
         if (!col.editType || col.editType === 'text') {
           children = (<>
-            <Input id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
-            {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null}
+            <Input className={err ? 'has-error' : ''} title={err} id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
           </>)
         } else if (col.editType === 'switch') {
           children = (
@@ -723,6 +700,10 @@
         let content = ''
         if (record[col.field] !== undefined) {
           content = `${record[col.field]}`
+        }
+
+        if (col.editType === 'select' && col.options.length > 0) {
+          content = col.map.get(content) || content
         }
 
         if (content !== '') {
@@ -754,20 +735,32 @@
             content = <span style={mark.innerStyle}>{content}</span>
           }
         }
+
+        if (col.editable === 'true' && disabled) {
+          content = <span style={{display: 'inline-block', padding: '0 6px'}}>{content}</span>
+        }
+
         children = content
       }
     } else if (col.type === 'number') {
-      if (col.editable === 'true') {
+      if (col.editable === 'true' && !disabled) {
         let _value = record[col.field] !== undefined ? record[col.field] : ''
+
+        if (col.noValue === 'hide' && _value === 0) {
+          _value = ''
+        }
+
         children = (<>
-          <InputNumber id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress}/>
-          {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null}
+          <InputNumber className={err ? 'has-error' : ''} title={err} precision={col.decimal || 0} id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
         </>)
       } else {
         let content = ''
         try {
           content = parseFloat(record[col.field])
           if (isNaN(content)) {
+            content = ''
+          }
+          if (col.noValue === 'hide' && content === 0) {
             content = ''
           }
         } catch (e) {
@@ -809,6 +802,11 @@
             content = <span style={mark.innerStyle}>{content}</span>
           }
         }
+
+        if (col.editable === 'true' && disabled) {
+          content = <span style={{display: 'inline-block', padding: '0 6px'}}>{content}</span>
+        }
+
         children = content
       }
     } else if (col.type === 'textarea') {
@@ -838,19 +836,29 @@
           // eslint-disable-next-line
           content = eval(content)
         } catch (e) {
+          if (window.debugger) {
+            console.info(content)
+            console.warn(e)
+          }
           content = ''
         }
       }
 
       content = content === undefined ? '' : content
 
+      if (col.noValue === 'hide' && content === 0) {
+        content = ''
+      }
+
+      if (col.round && typeof(content) === 'number') {
+        content = Math.round(content * col.round) / col.round
+        content = content.toFixed(col.decimal)
+      }
+
       if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
-
-        if (col.eval === 'false') {
-          content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
-          content = <span dangerouslySetInnerHTML={{__html: content}}></span>
-        }
+        content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       }
 
       if (col.marks) {
@@ -879,20 +887,14 @@
       children = (
         <CardCellComponent data={record} cards={config} elements={col.elements}/>
       )
-    } else if (col.type === 'operation') {
-      style.padding = '0px 5px'
-      children = (
-        <Button type="link" style={{color: 'rgb(255, 77, 79)', backgroundColor: 'transparent'}} onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})}>鍒犻櫎</Button>
-      )
     }
 
-    return (<td className={'editing_all_table_cell ' + className} style={style}>{col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}{children}{col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}</td>)
+    return (<td className={'editing_all_table_cell ' + className} style={style}>{children}</td>)
   }
 }
 
 class NormalTable extends Component {
   static propTpyes = {
-    statFValue: PropTypes.any,       // 鍚堣瀛楁鏁版嵁
     MenuID: PropTypes.string,        // 鑿滃崟Id
     setting: PropTypes.object,       // 琛ㄦ牸鍏ㄥ眬璁剧疆锛歵ableType锛堣〃鏍兼槸鍚﹀彲閫夈�佸崟閫夈�佸閫夛級銆乤ctionfixed锛堟寜閽浐瀹氾級
     columns: PropTypes.array,        // 琛ㄦ牸鍒�
@@ -902,37 +904,33 @@
     total: PropTypes.any,            // 鎬绘暟
     loading: PropTypes.bool,         // 琛ㄦ牸鍔犺浇涓�
     refreshdata: PropTypes.func,     // 琛ㄦ牸涓帓搴忓垪銆侀〉鐮佺殑鍙樺寲鏃跺埛鏂�
-    changeLock: PropTypes.func,
     chgSelectData: PropTypes.func,
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    data: [],
     edData: [],
-    edColumns: [],
     selectedRowKeys: [],  // 琛ㄦ牸涓�変腑琛�
     tableId: '',          // 琛ㄦ牸ID
     pageIndex: 1,         // 鍒濆椤甸潰绱㈠紩
     pageSize: 10,         // 姣忛〉鏁版嵁鏉℃暟
     columns: null,        // 鏄剧ず鍒�
     forms: [],
-    pickup: false,        // 鏀惰捣鏈�夋嫨椤�
     orderfields: {},      // 鎺掑簭id涓巉ield杞崲
     loading: false,
-    editable: false,
-    pageOptions: []
+    pageOptions: [],
+    deForms: null,
+    visible: false,
+    midData: null
   }
 
   UNSAFE_componentWillMount () {
-    const { setting, fields, columns } = this.props
+    const { setting, fields, columns, BID } = this.props
     let orderfields = {}
-    let initEditLine = null
-    let edColumns = []
 
     let _columns = []
     let deForms = []
     let _forms = {}
+    let hasBid = false
 
     let getColumns = (cols) => {
       return cols.map(item => {
@@ -944,22 +942,30 @@
         } else {
           if (item.editable === 'true') {
             _forms[item.field] = item
-            if (!initEditLine) {
-              initEditLine = item
+
+            if (item.ctrlField) {
+              item.ctrlValue = item.ctrlValue.split(',')
             }
-          }
-    
-          if (item.type === 'text' && item.editable === 'true' && item.editType === 'select' && item.resourceType === '1') {
-            let _option = Utils.getSelectQueryOptions(item)
-    
-            if (window.GLOB.debugger === true || window.debugger === true) {
-              console.info(_option.sql)
+            
+            if (item.type === 'text' && item.editType === 'select') {
+              item.map = new Map()
+              if (item.resourceType === '1') {
+                let _option = Utils.getSelectQueryOptions(item)
+  
+                if (/@BID@/ig.test(_option.sql)) {
+                  hasBid = true
+                }
+        
+                item.base_sql = _option.sql
+                item.arr_field = _option.field
+        
+                deForms.push(item)
+              } else {
+                item.options.forEach(cell => {
+                  item.map.set(cell.value, cell.label)
+                })
+              }
             }
-    
-            item.base_sql = window.btoa(window.encodeURIComponent(_option.sql))
-            item.arr_field = _option.field
-    
-            deForms.push(item)
           }
     
           if (item.field) {
@@ -969,14 +975,14 @@
           cell = {
             align: item.Align,
             dataIndex: item.uuid,
-            title: item.label,
+            title: item.editable === 'true' ? <span>{item.label}<EditOutlined className="system-color mk-edit-sign"/></span> : item.label,
             sorter: !!(item.field && item.IsSort === 'true'),
             width: item.Width || 120,
             $type: item.type,
             onCell: record => ({
               record,
               col: item,
-              config: item.type === 'custom' || item.type === 'action' ? {setting, columns: fields} : null,
+              config: item.type === 'custom' ? {setting, columns: fields} : null,
             })
           }
         }
@@ -984,6 +990,7 @@
         return cell
       })
     }
+
     _columns = getColumns(columns)
 
     let forms = []
@@ -996,32 +1003,6 @@
         forms.push(item)
       }
     })
-
-    _columns.forEach(item => {
-      if (item.$type === 'action') return
-
-      let _copy = fromJS(item).toJS()
-      _copy.sorter = false
-
-      if (item.editable === 'true') {
-        _copy.title = <span>{item.label}<EditOutlined className="system-color mk-edit-sign"/></span>
-      }
-      edColumns.push(_copy)
-    })
-
-    if (setting.delable !== 'false' && setting.operType !== 'buoyMode') {
-      edColumns.push({
-        align: 'center',
-        dataIndex: 'mkoperation',
-        title: '鎿嶄綔',
-        sorter: false,
-        width: 100,
-        onCell: record => ({
-          record,
-          col: {type: 'operation', tableId: setting.tableId},
-        })
-      })
-    }
 
     let size = (setting.pageSize || 10) + ''
     let pageOptions = ['10', '25', '50', '100', '500', '1000']
@@ -1036,14 +1017,15 @@
       pageSize: setting.pageSize || 10,
       pageOptions,
       columns: _columns,
-      edColumns,
       tableId: setting.tableId,
-      orderfields,
-      initEditLine,
-      editable: setting.editable === 'true'
+      orderfields
     }, () => {
       if (deForms.length > 0) {
-        this.improveActionForm(deForms)
+        if (hasBid && setting.supModule && !BID) {
+          this.setState({ deForms })
+        } else {
+          this.improveActionForm(deForms, BID)
+        }
       }
 
       const element = document.getElementById(setting.tableId)
@@ -1058,10 +1040,19 @@
     return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
   }
 
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    const { BID } = this.props
+    const { deForms } = this.state
+
+    if (deForms && nextProps.BID !== BID) {
+      this.improveActionForm(deForms, nextProps.BID)
+    }
+  }
+
   componentDidMount () {
     MKEmitter.addListener('subLine', this.subLine)
     MKEmitter.addListener('nextLine', this.nextLine)
-    MKEmitter.addListener('addRecord', this.addLine)
+    MKEmitter.addListener('addRecord', this.addRecord)
     MKEmitter.addListener('delRecord', this.delRecord)
     MKEmitter.addListener('resetTable', this.resetTable)
     MKEmitter.addListener('transferData', this.transferData)
@@ -1077,7 +1068,7 @@
     }
     MKEmitter.removeListener('subLine', this.subLine)
     MKEmitter.removeListener('nextLine', this.nextLine)
-    MKEmitter.removeListener('addRecord', this.addLine)
+    MKEmitter.removeListener('addRecord', this.addRecord)
     MKEmitter.removeListener('delRecord', this.delRecord)
     MKEmitter.removeListener('resetTable', this.resetTable)
     MKEmitter.removeListener('transferData', this.transferData)
@@ -1085,24 +1076,20 @@
   }
 
   transferData = (menuid, data, type) => {
-    if (menuid !== this.props.MenuID) return
+    const { MenuID } = this.props
+    const { edData } = this.state
+
+    if (menuid !== MenuID) return
 
     if (type !== 'line') {
-      this.setState({data: data || []})
+      let index = edData.findIndex(item => !item.$origin && !item.$forbid)
 
-      if (this.state.editable && !this.state.pickup) {
-        setTimeout(() => {
-          this.pickupChange()
-        }, 200)
+      if (index > -1) {
+        this.setState({visible: true, midData: data})
+      } else {
+        this.updateMutil(data)
       }
-    } else if (type === 'line' && data.$$uuid) {
-      let _data = this.state.data.map(item => {
-        if (item.$$uuid === data.$$uuid) {
-          return data
-        } else {
-          return item
-        }
-      })
+    } else if (type === 'line') {
       let _edData = this.state.edData.map(item => {
         if (item.$$uuid === data.$$uuid) {
           return data
@@ -1111,24 +1098,66 @@
         }
       })
 
-      this.setState({edData: _edData, data: _data})
+      this.setState({edData: _edData})
     }
-    this.setState({editable: false})
   }
 
-  improveActionForm = (deForms) => {
-    const { BID, setting } = this.props
+  updateMutil = (data) => {
+    const { setting } = this.props
+
+    if (setting.editType === 'multi' && data.length > 0) {
+      this.setState({edData: []}, () => {
+        this.setState({edData: data, visible: false, midData: null})
+      })
+    } else {
+      this.setState({edData: data, visible: false, midData: null})
+    }
+
+    if (setting.addable && data.length === 0) {
+      setTimeout(() => {
+        this.plusLine(true)
+      }, 10)
+    }
+  }
+
+  improveActionForm = (deForms, BID) => {
+    const { setting } = this.props
 
     let deffers = []
     let mainItems = []  // 浜戠鎴栧崟鐐规暟鎹�
     let localItems = [] // 鏈湴鏁版嵁
     let cache = setting.cache !== 'false'
+    let debug = window.GLOB.debugger === true || window.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
 
     deForms.forEach(item => {
       if (item.database === 'sso') {
-        mainItems.push(`select '${item.uuid}' as obj_name,'${item.arr_field}' as arr_field,'${item.base_sql}' as LText`)
+        let sql = _sso + item.base_sql
+        _sso = ''
+
+        sql = sql.replace(/@BID@/ig, `'${BID}'`)
+
+        if (debug) {
+          console.info(sql)
+        }
+
+        sql = sql.replace(/%/ig, ' mpercent ')
+
+        mainItems.push(`select '${item.uuid}' as obj_name,'${item.arr_field}' as arr_field,'${window.btoa(window.encodeURIComponent(sql))}' as LText`)
       } else {
-        localItems.push(`select '${item.uuid}' as obj_name,'${item.arr_field}' as arr_field,'${item.base_sql}' as LText`)
+        let sql = _sql + item.base_sql
+        _sql = ''
+
+        sql = sql.replace(/@BID@/ig, `'${BID}'`)
+
+        if (debug) {
+          console.info(sql)
+        }
+
+        sql = sql.replace(/%/ig, ' mpercent ')
+        
+        localItems.push(`select '${item.uuid}' as obj_name,'${item.arr_field}' as arr_field,'${window.btoa(window.encodeURIComponent(sql))}' as LText`)
       }
     })
 
@@ -1211,16 +1240,14 @@
   }
 
   resetFormList = (result) => {
-    const { columns } = this.props
-    const { edColumns } = this.state
+    const { columns, edData } = this.state
 
     let _edColumns = []
 
     let reCols = {}
-    columns.forEach(item => {
+    this.props.columns.forEach(item => {
       if (item.resourceType === '1' && result[item.uuid] && result[item.uuid].length > 0) {
         let options = []
-        let _map = new Map()
         let all = false
         result[item.uuid].forEach(cell => {
           let _cell = {key: Utils.getuuid()}
@@ -1237,8 +1264,8 @@
             }
           }
 
-          if (_map.has(_cell.value)) return
-          _map.set(_cell.value, 0)
+          if (item.map.has(_cell.value)) return
+          item.map.set(_cell.value, _cell.label)
 
           if (item.linkSubField) {
             item.linkSubField.forEach(m => {
@@ -1255,11 +1282,11 @@
 
         item.options = options
 
-        reCols[item.uuid] = item
+        reCols[item.uuid] = fromJS(item).toJS()
       }
     })
 
-    _edColumns = edColumns.map(item => {
+    _edColumns = columns.map(item => {
       if (reCols[item.dataIndex]) {
         item.onCell = record => ({
           record,
@@ -1270,29 +1297,39 @@
       return item
     })
 
-    if (this.state.pickup) {
-      this.setState({
-        pickup: false
-      }, () => {
-        this.setState({pickup: true, edColumns: _edColumns})
-      })
-    } else {
-      this.setState({edColumns: _edColumns})
-    }
+    this.setState({columns: [], edData: []}, () => {
+      this.setState({columns: _edColumns, edData: edData})
+    })
   }
   
   nextLine = (col, uuid) => {
     const { setting } = this.props
-    const { edData, initEditLine, tableId } = this.state
+    const { edData, tableId } = this.state
 
     if (col.tableId !== tableId) return
 
     let index = edData.findIndex(item => item.$$uuid === uuid)
     let next = edData[index + 1] || null
-
-    if (next && initEditLine) {
-      MKEmitter.emit('tdFocus', initEditLine.uuid + next.$$uuid)
-    } else if (setting.addable === 'true') {
+    
+    if (next) {
+      let nextId = setting.initId + next.$$uuid
+      if (/^\$next_/.test(col.enter)) {
+        nextId = col.enter.split('_')[1] + next.$$uuid
+      }
+      
+      let node = document.getElementById(nextId)
+      if (node) {
+        if (setting.editType === 'multi') {
+          if (setting.triType === 'click') {
+            node.click()
+          } else {
+            node.select && node.select()
+          }
+        } else {
+          node.click()
+        }
+      }
+    } else if (setting.addable) {
       setTimeout(() => {
         this.plusLine()
       }, 10)
@@ -1304,83 +1341,31 @@
   }
 
   subLine = (col, record) => {
-    const { tableId, forms, edData } = this.state
+    const { tableId, edData } = this.state
 
     if (col && col.tableId !== tableId) return
 
-    if (edData.filter(item => !item.$origin).length > 1) {
-      setTimeout(() => {
-        this.submit(edData)
-      }, 10)
-      return
-    }
-
-    setTimeout(() => {
-      let item = fromJS(record).toJS()
-      let line = []
-      forms.forEach(col => {
-        if (col.editable !== 'true' || item.$deleted) {
-          if (col.type === 'number') {
-            item[col.field] = +item[col.field]
-            if (isNaN(item[col.field])) {
-              item[col.field] = 0
-            }
-          } else {
-            item[col.field] = item[col.field] !== undefined ? (item[col.field] + '') : ''
-          }
-          return
-        }
-        if (col.type === 'text') {
-          let val = item[col.field] !== undefined ? (item[col.field] + '') : ''
-          if (col.required === 'true' && !val) {
-            line.push(`${col.label}涓嶅彲涓虹┖`)
-          }
-          item[col.field] = val
-        } else if (col.type === 'number') {
-          let val = item[col.field]
-          if (!val && val !== 0) {
-            line.push(`${col.label}涓嶅彲涓虹┖`)
-            return
-          }
-          val = +val
-          if (isNaN(val)) {
-            line.push(`${col.label}鏁版嵁鏍煎紡閿欒`)
-            return
-          }
-
-          val = +val.toFixed(col.decimal || 0)
-          
-          if (typeof(col.max) === 'number' && val > col.max) {
-            line.push(`${col.label}涓嶅彲澶т簬${col.max}`)
-          } else if (typeof(col.min) === 'number' && val < col.min) {
-            line.push(`${col.label}涓嶅彲灏忎簬${col.min}`)
-          }
-
-          item[col.field] = val
-        }
-      })
-
-      let err = line.join('锛�')
-
-      if (err) {
-        notification.warning({
-          top: 92,
-          message: err,
-          duration: 5
-        })
-      } else {
-        this.submit([item], 'simple')
+    let _data = edData.map(item => {
+      if (item.$$uuid === record.$$uuid) {
+        item.$origin = false
       }
-    }, 10)
+      return item
+    })
+
+    this.setState({edData: _data}, () => {
+      this.submit()
+    })
   }
 
-  plusLine = () => {
-    const { edData, forms, initEditLine } = this.state
+  plusLine = (auto) => {
+    const { setting } = this.props
+    const { edData, forms } = this.state
 
-    let item = {...edData[edData.length - 1]}
+    let item = edData.length > 0 ? {...edData[edData.length - 1]} : {}
 
     item.$$uuid = Utils.getguid()
     item.$type = 'add'
+    item.$forbid = true
     item.$Index = ''
 
     forms.forEach(col => {
@@ -1399,7 +1384,18 @@
     })
 
     this.setState({edData: [...edData, item]}, () => {
-      MKEmitter.emit('tdFocus', initEditLine.uuid + item.$$uuid)
+      let node = document.getElementById(setting.initId + item.$$uuid)
+      if (node && !auto) {
+        if (setting.editType === 'multi') {
+          if (setting.triType === 'click') {
+            node.click()
+          } else {
+            node.select && node.select()
+          }
+        } else {
+          node.click()
+        }
+      }
     })
   }
 
@@ -1408,118 +1404,112 @@
     const { tableId, edData } = this.state
 
     if (id !== tableId) return
-
-    let _data = []
-
+    
     if (record.$type === 'add') {
-      _data = edData.filter(item => item.$$uuid !== record.$$uuid)
+      let _data = edData.filter(item => item.$$uuid !== record.$$uuid)
+      this.setState({edData: _data})
     } else {
-      _data = edData.map(item => {
+      let _data = fromJS(edData).toJS().map(item => {
         if (item.$$uuid === record.$$uuid) {
-          record.$deleted = true
-          record.$origin = false
-          record.$type = 'del'
-          return record
-        } else {
-          return item
+          item.$deleted = true
+          item.$origin = false
+          item.$type = 'del'
         }
+
+        return item
       })
 
-      if (setting.commit === 'simple' && record.$deleted) {
-        this.subLine(null, record)
-      }
+      this.setState({edData: _data}, () => {
+        if (setting.commit === 'simple') {
+          this.submit()
+        }
+      })
     }
-
-    this.setState({edData: _data})
   }
 
   changeRecord = (id, record) => {
+    const { setting } = this.props
     const { tableId } = this.state
 
     if (id !== tableId) return
 
+    let lock = record.$lock
+
     let _data = this.state.edData.map(item => {
       if (item.$$uuid === record.$$uuid) {
         record.$origin = false
+        record.$lock = true
+
+        delete record.$forbid
+
         return record
       } else {
         return item
       }
     })
 
-    this.setState({edData: _data})
+    this.setState({edData: _data}, () => {
+      if (setting.tableType && setting.hasAction && !lock && this.state.selectedRowKeys.includes(record.$$uuid)) {
+        this.selectdata(this.state.selectedRowKeys)
+      }
+    })
   }
 
-  addLine = (id, record) => {
+  addRecord = (id, record) => {
     const { BID } = this.props
     const { edData, forms, tableId } = this.state
 
-    if (id) {
-      if (id !== tableId) return
-      let _edData = fromJS(edData).toJS()
-      let index = _edData.findIndex(item => record.$$uuid === item.$$uuid)
+    if (id !== tableId) return
 
-      let item = {}
+    let _edData = fromJS(edData).toJS()
+    let item = {}
+    let index = null
+    let copy = edData.length > 0 ? {...edData[edData.length - 1]} : null
 
-      item.$$uuid = Utils.getguid()
-      item.$type = 'add'
-      item.$Index = ''
-      item.$$BID = BID || ''
-  
-      forms.forEach(col => {
-        if (col.initval !== '$copy') {
-          item[col.field] = col.initval
-        }
-        if (col.type === 'number') {
-          item[col.field] = +item[col.field]
-          if (isNaN(item[col.field])) {
-            item[col.field] = 0
-          }
-        }
-  
-        if (item[col.field] === undefined) {
-          item[col.field] = ''
-        }
-      })
+    if (record) {
+      index = _edData.findIndex(item => record.$$uuid === item.$$uuid)
+      index = index === -1 ? null : index
 
-      _edData.splice(index, 0, item)
-
-      this.setState({edData: _edData})
-    } else {
-      let item = {}
-      if (edData.length > 0) {
-        item = {...edData[edData.length - 1]}
-        item.$$uuid = Utils.getguid()
-        item.$type = 'add'
-        item.$Index = ''
-      } else {
-        item.$$uuid = Utils.getguid()
-        item.$type = 'add'
-        item.$Index = ''
-        item.$$BID = BID || ''
-      }
-  
-      forms.forEach(col => {
-        if (col.initval !== '$copy') {
-          item[col.field] = col.initval
-        }
-        if (col.type === 'number') {
-          item[col.field] = +item[col.field]
-          if (isNaN(item[col.field])) {
-            item[col.field] = 0
-          }
-        }
-  
-        if (item[col.field] === undefined) {
-          item[col.field] = ''
-        }
-      })
-  
-      this.setState({edData: [...edData, item]})
+      copy = {...record}
     }
+
+    if (copy) {
+      item = {...copy}
+    }
+
+    item.$$uuid = Utils.getguid()
+    item.$type = 'add'
+    item.$Index = ''
+    item.$forbid = true
+    item.$$BID = BID || ''
+
+    forms.forEach(col => {
+      if (col.initval !== '$copy') {
+        item[col.field] = col.initval
+      }
+      if (col.type === 'number') {
+        item[col.field] = +item[col.field]
+        if (isNaN(item[col.field])) {
+          item[col.field] = 0
+        }
+      }
+
+      if (item[col.field] === undefined) {
+        item[col.field] = ''
+      }
+    })
+
+    if (index === null) {
+      _edData.push(item)
+    } else {
+      _edData.splice(index, 0, item)
+    }
+
+    this.setState({edData: _edData})
   }
 
   checkData = () => {
+    const { setting } = this.props
     const { edData, forms } = this.state
 
     if (edData.length === 0) {
@@ -1528,11 +1518,28 @@
         message: '鎻愪氦鏁版嵁涓嶅彲涓虹┖锛�',
         duration: 5
       })
-      return
+      return null
     }
+
+    let data = fromJS(edData).toJS()
+
+    data = data.filter(item => !item.$forbid)
+    if (setting.commit === 'change' || setting.commit === 'simple') {
+      data = data.filter(item => !item.$origin)
+    }
+
+    if (data.length === 0) {
+      notification.warning({
+        top: 92,
+        message: '鏁版嵁鏈慨鏀癸紝涓嶅彲鎻愪氦锛�',
+        duration: 5
+      })
+      return null
+    }
+
     let err = ''
     let Index = 1
-    let data = fromJS(edData).toJS().map(item => {
+    data = data.map(item => {
       let line = []
       forms.forEach(col => {
         if (col.editable !== 'true' || item.$deleted) {
@@ -1554,7 +1561,9 @@
           item[col.field] = val
         } else if (col.type === 'number') {
           let val = item[col.field]
-          if (!val && val !== 0) {
+          if (col.noValue === 'hide' && !val) {
+            val = 0
+          } else if (!val && val !== 0) {
             line.push(`${col.label}涓嶅彲涓虹┖`)
             return
           }
@@ -1592,27 +1601,32 @@
         message: err,
         duration: 5
       })
-    } else {
-      this.submit(data)
+
+      return null
     }
+
+    return data
   }
 
-  submit = (data, type) => {
+  submit = () => {
     const { submit, BID, setting } = this.props
     const { forms } = this.state
 
-    if (type !== 'simple' && (setting.commit === 'change' || setting.commit === 'simple')) {
-      data = data.filter(item => !item.$origin)
-    }
+    this.setState({visible: false, midData: null})
 
-    if (data.length === 0) {
+    if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '鏁版嵁鏈慨鏀癸紝涓嶅彲鎻愪氦锛�',
+        message: '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
+
       return
     }
+
+    let data = this.checkData()
+
+    if (!data) return
 
     let result = getEditTableSql(submit, data, forms)
 
@@ -1653,12 +1667,7 @@
 
       Api.genericInterface(param).then((res) => {
         if (res.status) {
-          if (type === 'simple') {
-            this.updataLine(data[0])
-            this.execSuccess(res, type)
-          } else {
-            this.execSuccess(res)
-          }
+          this.execSuccess(res)
         } else {
           this.execError(res)
         }
@@ -1670,12 +1679,7 @@
 
       Api.genericInterface(param).then((res) => {
         if (res.status) {
-          if (type === 'simple') {
-            this.updataLine(data[0])
-            this.execSuccess(res, type)
-          } else {
-            this.execSuccess(res)
-          }
+          this.execSuccess(res)
         } else {
           this.execError(res)
         }
@@ -1685,55 +1689,47 @@
     }
   }
 
-  updataLine = (item) => {
-    if (item.$type === 'del') {
-      let _data = this.state.edData.filter(m => m.$$uuid !== item.$$uuid)
-
-      this.setState({edData: _data})
-    } else {
-      let _data = this.state.edData.map(m => {
-        if (m.$$uuid === item.$$uuid) {
-          item.$origin = true
-          return item
-        }
-        return m
-      })
-
-      this.setState({edData: _data})
-    }
-    MKEmitter.emit('reloadData', this.props.MenuID, item.$$uuid, item)
-  }
-
-  execSuccess = (res, type) => {
+  execSuccess = (res) => {
     const { submit } = this.props
+    const { edData } = this.state
 
     if (res && res.ErrCode === 'S') { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.ErrMesg || this.state.dict['main.action.confirm.success'],
+        message: res.ErrMesg || '鎵ц鎴愬姛',
         duration: submit.stime ? submit.stime : 2
       })
     } else if (res && res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.ErrMesg || this.state.dict['main.action.confirm.success']
+        title: res.ErrMesg || '鎵ц鎴愬姛'
       })
     } else if (res && res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
     }
 
-    this.setState({
-      loading: false
+    let _edData = fromJS(edData).toJS()
+
+    _edData = _edData.map(item => {
+      if (!item.$forbid) {
+        item.$origin = true
+      }
+      return item
     })
 
-    if (type === 'simple') return
+    this.setState({
+      loading: false,
+      edData: _edData
+    })
 
     if (submit.closetab === 'true') {
       MKEmitter.emit('popclose')
     }
+
     if (submit.execSuccess !== 'never') {
-      this.repick()
       MKEmitter.emit('refreshByButtonResult', submit.$menuId, submit.execSuccess, submit)
     }
+
+    submit.syncComponentId && MKEmitter.emit('reloadData', submit.syncComponentId)
   }
 
   execError = (res) => {
@@ -1765,33 +1761,12 @@
     })
 
     if (submit.execError !== 'never') {
-      this.repick()
       MKEmitter.emit('refreshByButtonResult', submit.$menuId, submit.execError, submit)
     }
   }
 
-  repick = () => {
-    const { setting } = this.props
-    const { data } = this.state
-
-    if (setting.submittal === 'true') {
-      this.setState({editable: true})
-    }
-
-    this.props.changeLock(false)
-    this.setState({
-      data: [],
-      edData: [],
-      pickup: false,
-    }, () => {
-      this.setState({
-        data: data,
-      })
-    })
-  }
-
   /**
-   * 
+   * @description 閫変腑琛�
    */
   onSelectChange = selectedRowKeys => {
     this.setState({ selectedRowKeys })
@@ -1807,28 +1782,28 @@
   /**
    * @description 鐐瑰嚮鏁磋锛岃Е鍙戝垏鎹紝 鍒ゆ柇鏄惁鍙�夛紝鍗曢�夋垨澶氶�夛紝杩涜瀵瑰簲鎿嶄綔
    */
-  changeRow = (index) => {
+  changeRow = (id) => {
     const { setting } = this.props
 
-    if (!setting.tableType || this.state.pickup) return
+    if (!setting.tableType) return
     
     let newkeys = fromJS(this.state.selectedRowKeys).toJS()
 
     let activeId = ''
     if (setting.tableType === 'radio') {
-      activeId = index
-      newkeys = [index]
+      activeId = id
+      newkeys = [id]
       this.setState({ selectedRowKeys: newkeys })
     } else {
-      if (newkeys.includes(index)) {
-        newkeys = newkeys.filter(item => item !== index)
+      if (newkeys.includes(id)) {
+        newkeys = newkeys.filter(item => item !== id)
 
         if (newkeys.length > 0) {
           activeId = newkeys.slice(-1)[0]
         }
       } else {
-        activeId = index
-        newkeys.push(index)
+        activeId = id
+        newkeys.push(id)
       }
 
       this.setState({ selectedRowKeys: newkeys })
@@ -1840,21 +1815,21 @@
 
   changedata = (id) => {
     const { MenuID } = this.props
-    const { data } = this.state
+    const { edData } = this.state
 
     let _data = ''
 
     if (id) {
-      _data = data.filter(item => item.$$uuid === id)[0] || ''
+      _data = edData.filter(item => item.$$uuid === id)[0] || ''
     }
 
     MKEmitter.emit('resetSelectLine', MenuID, id, _data)
   }
 
   selectdata = (keys) => {
-    const { data } = this.state
+    const { edData } = this.state
 
-    let _data = data.filter(item => keys.includes(item.$$uuid))
+    let _data = edData.filter(item => keys.includes(item.$$uuid))
 
     this.props.chgSelectData(_data)
   }
@@ -1890,96 +1865,22 @@
     }
   }
 
-  pickupChange = () => {
-    const { submit, MenuID, setting } = this.props
-    const { data } = this.state
-
-    let pickup = !this.state.pickup
-
-    if (!submit.sheet) {
-      notification.warning({
-        top: 92,
-        message: '鎻愪氦鎸夐挳灏氭湭璁剧疆锛屼笉鍙紪杈戯紒',
-        duration: 5
-      })
-      return
-    }
-
-    if (!pickup && this.state.edData.filter(item => !item.$origin).length > 0) {
-      const _this = this
-      confirm({
-        title: '鏁版嵁宸蹭慨鏀癸紝纭畾鏀惧純淇濆瓨鍚楋紵',
-        onOk() {
-          _this.setState({
-            data: [],
-            edData: [],
-            pickup
-          }, () => {
-            _this.setState({
-              data: data,
-              edData: pickup ? fromJS(data).toJS() : []
-            })
-          })
-        },
-        onCancel() {}
-      })
-    } else {
-      pickup && MKEmitter.emit('resetSelectLine', MenuID, '', '')
-      pickup && this.props.chgSelectData([])
-      let keys = this.state.selectedRowKeys
-      this.setState({
-        data: [],
-        edData: [],
-        selectedRowKeys: [],
-        pickup,
-        loading: false,
-        editable: false
-      }, () => {
-        if (pickup && setting.tableType === 'checkbox' && keys.length > 0) {
-          this.setState({
-            data: data,
-            edData: fromJS(data).toJS().filter(item => {
-              item.$origin = false
-              
-              return keys.includes(item.$$uuid)
-            })
-          })
-        } else {
-          this.setState({
-            data: data,
-            edData: pickup ? fromJS(data).toJS() : []
-          })
-        }
-      })
-
-    }
-    this.props.changeLock(pickup)
-  }
-
   render() {
-    const { setting, statFValue, lineMarks, submit } = this.props
-    const { pickup, tableId, data, edData, columns, edColumns, loading, pageOptions, selectedRowKeys } = this.state
+    const { setting, lineMarks, submit } = this.props
+    const { tableId, edData, columns, loading, pageOptions, selectedRowKeys, visible, midData } = this.state
 
     const components = {
       body: {
         row: BodyRow,
-        cell: setting.editType !== 'multi' || !pickup ? BodyCell : BodyAllCell
+        cell: setting.editType !== 'multi' ? BodyCell : BodyAllCell
       }
     }
 
-    // 鏁版嵁鏀惰捣鏃讹紝杩囨护宸查�夋暟鎹�
-    let _data = data
-    let _columns = columns
-
-    if (pickup) {
-      _data = edData
-      _data = _data.filter(item => !item.$deleted)
-      _columns = edColumns
-    }
+    let _data = edData.filter(item => !item.$deleted)
 
     // 璁剧疆琛ㄦ牸閫夋嫨灞炴�э細鍗曢�夈�佸閫夈�佷笉鍙��
     let rowSelection = null
-    if (setting.tableType && !pickup) {
+    if (setting.tableType) {
       rowSelection = {
         selectedRowKeys,
         type: (setting.tableType === 'radio') ? 'radio' : 'checkbox',
@@ -1988,49 +1889,42 @@
     }
 
     let _pagination = false
-    if (!pickup && setting.laypage !== 'false' && setting.laypage !== false) {
+    if (setting.laypage) {
       _pagination = {
         current: this.state.pageIndex,
         pageSize: this.state.pageSize,
         pageSizeOptions: pageOptions,
         showSizeChanger: true,
         total: this.props.total || 0,
-        showTotal: (total, range) => `${range[0]}-${range[1]} ${this.state.dict['main.pagination.of']} ${total} ${this.state.dict['main.pagination.items']}`
+        showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
       }
     }
 
-    let _footer = ''
-
-    if (!pickup && statFValue && statFValue.length > 0) {
-      _footer = statFValue.map(f => `${f.label}(鍚堣)锛�${f.value}`).join('锛�')
-    }
-
     let height = setting.height || false
+    if (height && height <= 100) {
+      height = height + 'vh'
+    }
 
     return (
       <>
-        {submit.hasAction && pickup ? <div className="edit-custom-table-leftbtn-wrap">
-          <Button style={submit.style} onClick={() => setTimeout(() => {this.checkData()}, 10)} loading={loading} className="submit-table" type="link">鎻愪氦</Button>
+        {setting.hasSubmit ? <div className="edit-custom-table-btn-wrap" style={submit.wrapStyle}>
+          <Button style={submit.style} onClick={() => setTimeout(() => {this.submit()}, 10)} loading={loading} className="submit-table" type="link">鎻愪氦</Button>
         </div> : null}
-        <div className="edit-custom-table-btn-wrap" style={submit.wrapStyle}>
-          {!submit.hasAction && pickup ? <Button style={submit.style} onClick={() => setTimeout(() => {this.checkData()}, 10)} loading={loading} className="submit-table" type="link">鎻愪氦</Button> : null}
-          {setting.switchable !== 'false' ? <Switch title="缂栬緫" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" disabled={loading || this.props.loading} checked={pickup} onChange={this.pickupChange} /> : null}
-        </div>
-        <div className={`edit-custom-table ${pickup ? 'editable' : ''} ${setting.tableHeader || ''} ${setting.operType || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || ''} mk-edit-${setting.editType || 'simple'}`} id={tableId}>
+        <div className={`edit-custom-table ${setting.tableHeader || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || ''} mk-edit-${setting.editType || 'simple'}`} id={tableId}>
           <Table
             rowKey="$$uuid"
             components={components}
-            // style={setting.style}
             size={setting.size || 'middle'}
             bordered={setting.bordered !== 'false'}
             rowSelection={rowSelection}
-            columns={_columns}
+            columns={columns}
             dataSource={_data}
             loading={this.props.loading}
             scroll={{ x: '100%', y: height }}
             onRow={(record, index) => {
               return {
                 lineMarks,
+                title: setting.tipField ? record[setting.tipField] : '',
                 data: record,
                 onClick: () => {this.changeRow(record.$$uuid)},
               }
@@ -2038,10 +1932,23 @@
             onChange={this.changeTable}
             pagination={_pagination}
           />
-          {_footer ? <div className={'normal-table-footer ' + (_pagination ? 'pagination' : '')}>{_footer}</div> : null}
-          {pickup && setting.addable === 'true' ? <Button className="mk-add-line" onClick={() => this.addLine()} disabled={this.props.loading} type="link"><PlusOutlined /></Button> : null}
-          {pickup && _data.length > 10 ? <Button style={submit.style} onClick={() => setTimeout(() => {this.checkData()}, 10)} loading={loading} className="submit-footer-table" type="link">鎻愪氦</Button> : null}
+          {setting.hasSubmit && _data.length > 10 ? <Button style={submit.style} onClick={() => setTimeout(() => {this.submit()}, 10)} loading={loading} className="submit-footer-table" type="link">鎻愪氦</Button> : null}
         </div>
+        <Modal
+          className="mk-user-confirm"
+          visible={visible}
+          width={450}
+          maskClosable={false}
+          closable={false}
+          footer={[
+            <Button key="cancel" onClick={() => { this.setState({ visible: false, midData: null }) }}>鍙栨秷</Button>,
+            <Button key="refresh" className="table-refresh" onClick={() => { midData && this.updateMutil(midData) }}>鍒锋柊琛ㄦ牸</Button>,
+            <Button key="confirm" type="primary" onClick={() => setTimeout(() => {this.submit()}, 10)}>鎻愪氦鏁版嵁</Button>
+          ]}
+          destroyOnClose
+        >
+          <div><QuestionCircleOutlined />琛ㄦ牸涓湁鏁版嵁灏氭湭鎻愪氦</div>
+        </Modal>
       </>
     )
   }
diff --git a/src/tabviews/custom/components/table/edit-table/normalTable/index.scss b/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
index 6d3798c..9fcaf63 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
@@ -7,14 +7,6 @@
   --mk-table-font-size: 14px;
   --mk-table-font-weight: normal;
 
-  .normal-table-footer {
-    padding: 10px 0px;
-    color: rgba(0, 0, 0, 0.65);
-  }
-  .normal-table-footer.pagination {
-    position: absolute;
-    bottom: 10px;
-  }
   >.ant-table-wrapper {
     position: relative;
     z-index: 1;
@@ -26,9 +18,9 @@
   .mk-edit-sign {
     position: absolute;
     bottom: 2px;
-    right: 5px;
-    opacity: 0.7;
-    font-size: 14px;
+    right: 3px;
+    opacity: 0.5;
+    font-size: 10px;
   }
 
   table {
@@ -151,6 +143,7 @@
       height: auto;
       border-radius: 0;
       box-shadow: none!important;
+      text-align: inherit;
     }
     .ant-select {
       padding: 0px;
@@ -174,15 +167,20 @@
       position: unset;
       border: none;
       box-shadow: none!important;
+      text-align: inherit;
       
       .ant-input-number-handler-wrap {
         display: none;
+      }
+      .ant-input-number-input-wrap {
+        text-align: inherit;
       }
       .ant-input-number-input {
         border-radius: 0;
         padding: 0;
         height: auto;
         position: absolute;
+        text-align: inherit;
         top: 0px;
         left: 0px;
         right: 0px;
@@ -190,17 +188,15 @@
         border: 1px solid var(--mk-sys-color);
       }
     }
-    .anticon-exclamation-circle {
-      color: #ff4d4f;
-      position: absolute;
-      right: 3px;
-      top: calc(50% - 8px);
+    .has-error, .has-error .ant-input-number-input {
+      border-color: #ff4d4f!important;
     }
   }
   .editing_all_table_cell {
     .ant-input {
       border-radius: 0;
       padding: 4px 5px;
+      text-align: inherit;
     }
     .ant-select {
       width: 100%;
@@ -210,28 +206,27 @@
     }
     .ant-input-number {
       border-radius: 0;
+      text-align: inherit;
       
       .ant-input-number-handler-wrap {
         display: none;
       }
+      .ant-input-number-input-wrap {
+        text-align: inherit;
+      }
       .ant-input-number-input {
         border-radius: 0;
         padding: 4px 5px;
+        text-align: inherit;
       }
     }
-    .anticon-exclamation-circle {
-      color: #ff4d4f;
-      position: absolute;
-      right: 13px;
-      top: calc(50% - 8px);
+    .has-error, .has-error .ant-input-number-input {
+      border-color: #ff4d4f!important;
     }
   }
   td.pointer {
     position: relative;
-  }
-  td.pointer {
     .mk-mask {
-      display: none;
       cursor: pointer;
       position: absolute;
       top: 0;
@@ -240,45 +235,11 @@
       right: 0;
     }
   }
-  .mk-editable {
-    position: absolute;
-    display: none;
-    top: calc(50% - 18px);
-    cursor: pointer;
-    padding: 10px 5px;
-    opacity: 0;
-  }
-  tr:hover {
-    .mk-editable {
-      opacity: 1;
-    }
-    .mk-plus {
-      left: -25px;
-    }
-    .mk-del {
-      right: -25px;
-    }
-  }
-  .mk-plus {
-    left: 0px;
-    color: rgb(38, 194, 129);
-    padding-right: 10px;
-  }
-  .mk-del {
-    right: 0px;
-    color: rgb(255, 77, 79);
-    padding-left: 10px;
-  }
-  .mk-add-line {
-    width: 100px;
-    color: #26C281;
-    border-radius: 0;
-    font-size: 25px;
-    height: 45px;
-  }
+
   .submit-footer-table {
     float: right;
-    min-height: 24px;
+    min-height: 28px;
+    min-width: 65px;
     height: auto;
     color: #ffffff;
     background-color: #1890ff;
@@ -286,8 +247,10 @@
     margin-top: 10px!important;
     margin-right: 10px!important;
   }
-
-  table, tr, th, td {
+  .ant-table-small.ant-table-bordered {
+    border-right: 1px solid #e8e8e8;
+  }
+  table, tr, th, td, .ant-table-small {
     border-color: var(--mk-table-border-color)!important;
   }
   table tr {
@@ -307,15 +270,22 @@
   table tbody tr {
     color: var(--mk-table-color);
   }
+  // .ant-table-bordered {
+  //   table {
+  //     tbody {
+  //       tr:last-child {
+  //         td {
+  //           border-bottom: none;
+  //         }
+  //       }
+  //     }
+  //   }
+  // }
 }
-.edit-custom-table.buoyMode {
-  .ant-table-scroll {
-    overflow: unset;
-    overflow-x: unset;
-
-    .ant-table-body {
-      overflow-x: unset!important;
-    }
+.edit-custom-table.mk-edit-simple {
+  table tbody tr td {
+    min-height: 32px;
+    height: 32px;
   }
 }
 .edit-custom-table.mk-edit-multi {
@@ -324,20 +294,13 @@
   }
 }
 .edit-custom-table.editable {
-  td {
-    background-color: #ffffff!important;
-  }
-  td.pointer .mk-mask {
-    display: block;
-  }
-  .mk-operation {
-    display: none;
-  }
   .ant-table-placeholder {
     display: none;
   }
-  .mk-editable {
-    display: inline-block;
+}
+.edit-custom-table:not(.ghost) {
+  .ant-table-small > .ant-table-content .ant-table-thead > tr > th {
+    background-color: #fafafa!important;
   }
 }
 .edit-custom-table:not(.fixed-height) {
@@ -422,36 +385,37 @@
 }
 .edit-custom-table-btn-wrap {
   float: right;
-  padding: 5px 0px;
-  .main-pickup {
-    position: relative;
-    z-index: 2;
-  }
   .submit-table {
     position: relative;
     z-index: 2;
+    min-width: 65px;
     margin-right: 15px;
-    min-height: 24px;
-    height: auto;
-    color: #ffffff;
-    background-color: #1890ff;
-    border-width: 0;
-    margin-top: 0px!important;
-    margin-bottom: 0px!important;
-  }
-}
-.edit-custom-table-leftbtn-wrap {
-  float: left;
-  line-height: 45px;
-  .submit-table {
-    position: relative;
-    z-index: 2;
     min-height: 28px;
     height: auto;
     color: #ffffff;
     background-color: #1890ff;
     border-width: 0;
-    margin-top: 0px;
-    margin-bottom: 0px;
+    margin-bottom: 10px!important;
+  }
+}
+.mk-user-confirm {
+  top: 30vh;
+
+  .ant-modal-body {
+    font-size: 16px;
+  }
+  .anticon-question-circle {
+    color: orange;
+    font-size: 16px;
+    margin-right: 5px;
+  }
+  .ant-modal-footer {
+    border-top: 0px;
+    padding: 10px 20px 25px 0px;
+    .table-refresh, .table-refresh:hover, .table-refresh:active, .table-refresh:focus {
+      color: #fff!important;
+      background-color: #ff4d4f!important;
+      border-color: #ff4d4f!important;
+    }
   }
 }
\ No newline at end of file
diff --git a/src/tabviews/custom/components/table/normal-table/index.jsx b/src/tabviews/custom/components/table/normal-table/index.jsx
index b4ec245..ca20ae8 100644
--- a/src/tabviews/custom/components/table/normal-table/index.jsx
+++ b/src/tabviews/custom/components/table/normal-table/index.jsx
@@ -112,7 +112,7 @@
         }
 
         if (setting.controlField) {
-          if (setting.controlVal.includes(item[setting.controlField])) {
+          if (setting.controlVal.includes(item[setting.controlField] + '')) {
             item.$disabled = true
           }
         }
@@ -256,35 +256,44 @@
         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
+      })
+
+      this.setState({
+        data: data,
         selectedData: [],
         total: result.total,
         loading: false
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
@@ -331,45 +340,52 @@
 
     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()
-      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])
-            }
-          })
-        }
+      let _data = result.data[0]
+      _data.$$uuid = _data[setting.primaryKey] || ''
+      _data.$$BID = BID || ''
+      _data.$$BData = BData || ''
 
-        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
-            }
-            return item
-          })
-        } catch (e) {
-          console.warn('鏁版嵁鏌ヨ閿欒')
-        }
-
-        MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
+      if (config.absFields) {
+        config.absFields.forEach(f => {
+          if (!isNaN(_data[f])) {
+            _data[f] = Math.abs(_data[f])
+          }
+        })
       }
+
+      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
+          }
+          return item
+        })
+      } catch (e) {
+        console.warn('鏁版嵁鏌ヨ閿欒')
+      }
+
+      MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid || '', _data)
 
       this.setState({
         data,
@@ -459,26 +475,13 @@
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
   refreshbysearch = (searches) => {
-    const { setting } = this.state
-
-    if (setting.onload === 'false') {
-      this.setState({
-        pageIndex: 1,
-        search: searches,
-        setting: {...setting, onload: 'true'}
-      }, () => {
-        this.loadmaindata()
-        this.getStatFieldsValue()
-      })
-    } else {
-      this.setState({
-        pageIndex: 1,
-        search: searches
-      }, () => {
-        this.loadmaindata(true, 'true')
-        this.getStatFieldsValue()
-      })
-    }
+    this.setState({
+      pageIndex: 1,
+      search: searches
+    }, () => {
+      this.loadmaindata(true, 'true')
+      this.getStatFieldsValue()
+    })
   }
 
   /**
@@ -627,7 +630,7 @@
           }
 
           if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField])) {
+            if (setting.controlVal.includes(item[setting.controlField] + '')) {
               item.$disabled = true
             }
           }
@@ -698,7 +701,7 @@
           }
 
           if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField])) {
+            if (setting.controlVal.includes(item[setting.controlField] + '')) {
               item.$disabled = true
             }
           }
diff --git a/src/tabviews/custom/components/table/normal-table/index.scss b/src/tabviews/custom/components/table/normal-table/index.scss
index 84e78f6..5a2828b 100644
--- a/src/tabviews/custom/components/table/normal-table/index.scss
+++ b/src/tabviews/custom/components/table/normal-table/index.scss
@@ -5,33 +5,12 @@
   .normal-header {
     margin-bottom: 10px;
   }
-  .top-search {
+  .mk-search-wrap {
     border-bottom: 1px solid #efefef;
     padding-top: 10px;
   }
-  >.button-list.toolbar-button {
-    min-height: 60px;
+  .button-list.toolbar-button {
     padding-right: 60px;
-    line-height: 40px;
-    button {
-      margin-right: 0px;
-      margin-bottom: 0px;
-      min-height: 28px;
-      height: auto;
-    }
-  }
-  .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);
-    }
   }
   .main-table-box {
     position: relative;
@@ -62,17 +41,6 @@
       border-radius: 0;
       .ant-collapse-content-box {
         padding: 0;
-        >.button-list.toolbar-button {
-          padding: 0;
-          line-height: 45px;
-          padding-right: 60px;
-          button {
-            margin-right: 0px;
-            margin-bottom: 0px;
-            min-height: 28px;
-            height: auto;
-          }
-        }
       }
     }
   }
diff --git a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
index 9b46381..69b47b4 100644
--- a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
+++ b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
@@ -144,7 +144,7 @@
     if (!tabs.subtabs.length) return null
 
     return (
-      <div className={'menu-antv-tabs-wrap ' + (tabs.setting.tabLabel || '')} style={tabs.style}>
+      <div className={'menu-antv-tabs-wrap ' + (tabs.setting.tabLabel || '')} id={'anchor' + tabs.uuid} style={tabs.style}>
         <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}>
diff --git a/src/tabviews/custom/components/timeline/normal-timeline/index.jsx b/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
index 463c865..1905369 100644
--- a/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
+++ b/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
@@ -83,6 +83,15 @@
 
     card = _config.subcards[0]
 
+    if (_config.wrap.dotSign === 'adaptive') {
+      try {
+        let cl = Math.floor(document.body.clientWidth * _config.width / 24 / 320)
+        _config.wrap.dotSign = ['', 'size16', 'size18', 'size20', 'size22', 'size24', 'size24', 'size24', 'size24'][cl]
+      } catch(e) {
+        _config.wrap.dotSign = 'size20'
+      }
+    }
+
     this.setState({
       card,
       sync: _sync,
@@ -294,17 +303,26 @@
         Api.writeCacheConfig(config.uuid, result.data || '')
       }
 
+      let data = result.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.setState({
-        data: result.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
-        }),
+        data: data,
         loading: false
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
@@ -445,7 +463,7 @@
         </div>
         <div className="mk-timeline-item-head">
           <div className="mk-timeline-item-tail" style={linebg}></div>
-          <div className={'mk-dot ' + (dot ? 'mk-dot-icon' : '')} style={{background: color}}>
+          <div className={'mk-dot ' + (dot ? 'mk-dot-icon' : '')} style={{background: color, color: color}}>
             {dot}
           </div>
         </div>
@@ -454,7 +472,7 @@
       return (<div className="mk-time-line-item" key={data.$Index}>
         <div className="mk-timeline-item-head">
           <div className="mk-timeline-item-tail" style={linebg}></div>
-          <div className={'mk-dot ' + (dot ? 'mk-dot-icon' : '')} style={{background: color}}>
+          <div className={'mk-dot ' + (dot ? 'mk-dot-icon' : '')} style={{background: color, color: color}}>
             {dot}
           </div>
         </div>
@@ -470,6 +488,8 @@
   render() {
     const { config, loading, data, description } = this.state
 
+    if (config.wrap.empty === 'hidden' && (!data || data.length === 0)) return null
+    
     return (
       <div className="normal-timeline-box" id={'anchor' + config.uuid} style={{...config.style}}>
         {loading ?
@@ -482,7 +502,7 @@
         {config.wrap.direction !== 'horizontal' && data && data.length > 0 ? <Timeline mode={config.wrap.mode} className={'card-row-list ' + (config.wrap.line || '')} style={{height: config.wrap.contentHeight}}>
           {data.map(item => this.getnodes(item))}
         </Timeline> : null}
-        {config.wrap.direction === 'horizontal' && data && data.length > 0 ? <div className={'mk-time-line-wrap card-row-list ' + (config.wrap.line || '')} style={{height: config.wrap.contentHeight}}>
+        {config.wrap.direction === 'horizontal' && data && data.length > 0 ? <div className={`mk-time-line-wrap card-row-list ${config.wrap.line || ''} ${config.wrap.iconSize || ''} ${config.wrap.dotSign || ''}`} style={{height: config.wrap.contentHeight}}>
           {data.map(item => this.getMknodes(item))}
         </div> : null}
         {data && data.length === 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}>
diff --git a/src/tabviews/custom/components/timeline/normal-timeline/index.scss b/src/tabviews/custom/components/timeline/normal-timeline/index.scss
index 38ef5b9..7e0945c 100644
--- a/src/tabviews/custom/components/timeline/normal-timeline/index.scss
+++ b/src/tabviews/custom/components/timeline/normal-timeline/index.scss
@@ -114,14 +114,15 @@
     }
     .mk-timeline-item-head {
       position: relative;
-      height: 20px;
+      height: 24px;
       text-align: center;
       .mk-dot {
         position: absolute;
         background: #e8e8e8;
-        padding: 5px;
-        display: inline-block;
-        border-radius: 20px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border-radius: 100%;
         z-index: 1;
         top: 50%;
         left: 50%;
@@ -130,26 +131,125 @@
         .anticon {
           font-size: 14px;
           color: #ffffff;
-          width: 16px;
-          height: 16px;
-          vertical-align: top;
         }
+      }
+      .mk-dot:not(.mk-dot-icon) {
+        padding: 5px;
       }
       .mk-dot-icon {
         width: 24px;
         height: 24px;
-        padding: 4px;
       }
     }
     .mk-timeline-item-tail {
       position: absolute;
-      top: 10px;
+      top: 50%;
       left: 0px;
       width: 100%;
       transform: translate(50%, -1px);
       border-top: 2px solid #e8e8e8;
     } 
   }
+
+  .mk-time-line-wrap.icon {
+    .mk-timeline-item-head {
+      .mk-dot {
+        background: #f8f8f8!important;
+      }
+      .mk-dot-icon {
+        color: inherit;
+        .anticon {
+          color: inherit;
+        }
+      }
+    }
+  }
+
+  .mk-time-line-wrap.size16 {
+    .mk-timeline-item-head {
+      height: 28px;
+      .mk-dot {
+        .anticon {
+          font-size: 16px;
+        }
+      }
+      .mk-dot-icon {
+        width: 28px;
+        height: 28px;
+      }
+    }
+  }
+
+  .mk-time-line-wrap.size18 {
+    .mk-timeline-item-head {
+      height: 32px;
+      .mk-dot {
+        .anticon {
+          font-size: 18px;
+        }
+      }
+      .mk-dot-icon {
+        width: 32px;
+        height: 32px;
+      }
+    }
+  }
+
+  .mk-time-line-wrap.size20 {
+    .mk-timeline-item-head {
+      height: 36px;
+      .mk-dot {
+        .anticon {
+          font-size: 20px;
+        }
+      }
+      .mk-dot-icon {
+        width: 36px;
+        height: 36px;
+      }
+    }
+  }
+
+  .mk-time-line-wrap.size22 {
+    .mk-timeline-item-head {
+      height: 40px;
+      .mk-dot {
+        .anticon {
+          font-size: 22px;
+        }
+      }
+      .mk-dot-icon {
+        width: 40px;
+        height: 40px;
+      }
+    }
+  }
+
+  .mk-time-line-wrap.size24 {
+    .mk-timeline-item-head {
+      height: 44px;
+      .mk-dot {
+        .anticon {
+          font-size: 24px;
+        }
+      }
+      .mk-dot-icon {
+        width: 44px;
+        height: 44px;
+      }
+    }
+  }
+  
+  .mk-time-line-wrap.system {
+    .mk-timeline-item-tail {
+      border-color: var(--mk-sys-color2);
+    }
+  }
+  .ant-timeline.system {
+    .ant-timeline-item-tail {
+      border-color: var(--mk-sys-color2);
+    }
+  }
 }
 
 .normal-timeline-box::after {
diff --git a/src/tabviews/custom/components/tree/antd-tree/index.jsx b/src/tabviews/custom/components/tree/antd-tree/index.jsx
index 6b287c2..922eba9 100644
--- a/src/tabviews/custom/components/tree/antd-tree/index.jsx
+++ b/src/tabviews/custom/components/tree/antd-tree/index.jsx
@@ -270,6 +270,13 @@
       }, () => {
         this.handleData()
       })
+
+      if (config.timer && config.clearField && result.data && result.data[0]) {
+        let vals = (config.clearValue || '').split(',')
+        if (vals.includes(result.data[0][config.clearField])) {
+          this.timer && this.timer.stop()
+        }
+      }
     } else {
       this.setState({
         loading: false
diff --git a/src/tabviews/custom/components/tree/antd-tree/index.scss b/src/tabviews/custom/components/tree/antd-tree/index.scss
index b384cef..eb5df34 100644
--- a/src/tabviews/custom/components/tree/antd-tree/index.scss
+++ b/src/tabviews/custom/components/tree/antd-tree/index.scss
@@ -120,18 +120,18 @@
   min-width: 85px;
   .button-list.toolbar-button {
     padding: 0px;
-  }
-  button {
-    display: block;
-    margin: 0!important;
-    width: 100%;
-    border-radius: 0px;
-    padding-left: 15px!important;
-    .anticon {
-      display: none;
-    }
-    .anticon + span {
-      margin-left: 0px;
+    button {
+      display: block;
+      margin: 0!important;
+      width: 100%;
+      border-radius: 0px;
+      padding-left: 15px!important;
+      .anticon {
+        display: none;
+      }
+      .anticon + span {
+        margin-left: 0px;
+      }
     }
   }
 }
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index cbf6415..3c6b9b3 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -70,8 +70,11 @@
     data: null,           // 鍒楄〃鏁版嵁闆�
     loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
     visible: false,       // 鏍囩椤垫帶鍒�
-    shortcuts: null       // 蹇嵎閿�
+    shortcuts: null,      // 蹇嵎閿�
+    loadinginter: false
   }
+
+  stepInter = null
 
   /**
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
@@ -93,6 +96,7 @@
         config = window.decodeURIComponent(window.atob(result.LongParam))
         config = config.replace(/@mywebsite@\//ig, window.GLOB.baseurl)
         config = JSON.parse(config)
+        config.MenuID = MenuID
       } catch (e) {
         console.warn('Parse Failure')
         config = ''
@@ -149,7 +153,7 @@
 
       // 鏁版嵁缂撳瓨璁剧疆
       if (config.cacheUseful === 'true') {
-        if (!['day', 'hour'].includes(config.timeUnit)) {
+        if (!['day', 'hour', 'minute'].includes(config.timeUnit)) {
           config.timeUnit = 'day'
         }
         config.cacheTime = config.cacheTime || 1
@@ -200,7 +204,9 @@
 
       config.$cache = config.cacheLocal === 'true'
 
-      config.interfaces = this.formatInterSetting(config.interfaces, regs)
+      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)
       
       // 鑾峰彇涓绘悳绱㈡潯浠�
@@ -236,8 +242,17 @@
         config.components = this.filterBalcony(config.components, balMap)
       }
 
+      if (initInters.length > 0) {
+        this.stepInter = {
+          MenuID: MenuID,
+          inters: initInters,
+          params: params
+        }
+      }
+
       this.setState({
         BID: BID,
+        loadinginter: this.stepInter !== null,
         shortcuts: shortcuts.length > 0 ? shortcuts : null,
         config,
         mainSearch
@@ -251,7 +266,10 @@
           ele.innerHTML = config.normalcss
           document.getElementsByTagName('head')[0].appendChild(ele)
         }
-        if (params.length === 0) {
+
+        if (this.stepInter) {
+
+        } else if (params.length === 0) {
           setTimeout(() => { // 寤舵椂鍔犺浇鐘舵��
             this.setState({
               loadingview: false
@@ -455,6 +473,40 @@
         item.search = Utils.initSearchVal(item.search)
       }
 
+      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
+        item.setting.supModule = item.supNodes[0].componentId
+      } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
+        let pid = item.setting.supModule.pop()
+        if (pid && pid !== 'empty') {
+          item.setting.supModule = pid
+        } else {
+          item.setting.supModule = ''
+        }
+      }
+
+      let pass = skip
+
+      if (item.wrap && item.wrap.permission === 'false') {
+        pass = true
+      }
+
+      // 鏉冮檺杩囨护
+      if (item.action && item.action.length > 0) {
+        item.action = item.action.filter(cell => {
+          if (cell.hidden === 'true') return false
+
+          cell = this.resetButton(item, cell, popview)
+
+          cell.$toolbtn = true
+
+          if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
+            cell = this.getPrinter(cell, item.uuid)
+          }
+
+          return pass || permAction[cell.uuid]
+        })
+      }
+
       if (item.type === 'table') {
         let statFields = []
         let getCols = (cols) => {
@@ -463,6 +515,8 @@
               return false
             } else if (col.Hide === 'true') {
               return false
+            } else if (col.type === 'action') {
+              col.type = 'custom'
             }
             
             if (col.type === 'number') {
@@ -475,26 +529,36 @@
                   col.decimal = col.decimal > 2 ? col.decimal - 2 : 0
                 }
               }
+            } else if (col.type === 'formula') {
+              if (typeof(col.decimal) === 'number') {
+                col.round = Math.pow(10, col.decimal)
+              }
             } else if (col.type === 'colspan') {
               col.subcols = getCols(col.subcols || [])
               if (col.subcols.length === 0) {
                 return false
               }
             } else if (col.type === 'custom') {
-              col.elements = col.elements.map(cell => {
-                if (['text', 'number', 'formula'].includes(cell.eleType)) {
-                  if (!cell.height) {
-                    cell.innerHeight = 'auto'
+              col.elements = col.elements.filter(cell => {
+                if (cell.eleType === 'button') {
+                  if (cell.hidden === 'true') return false
+
+                  cell = this.resetButton(item, cell, popview)
+
+                  if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
+                    cell = this.getPrinter(cell, item.uuid)
                   }
-                  if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-                    cell.round = Math.pow(10, cell.decimal)
-                    if (cell.format === 'percent') {
-                      cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-                    }
-                  }
+
+                  return pass || permAction[cell.uuid]
+                } else {
+                  cell = this.resetElement(cell)
                 }
-                return cell
+                return true
               })
+
+              if (col.elements.length === 0) {
+                return false
+              }
             }
       
             if (col.linkmenu && col.linkmenu.length > 0) {
@@ -510,63 +574,20 @@
         
         item.cols = getCols(item.cols)
         item.statFields = statFields
-      }
 
-      let mutil = false
-      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
-        mutil = true
-        item.setting.supModule = item.supNodes[0].componentId
-      } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
-        let pid = item.setting.supModule.pop()
-        if (pid && pid !== 'empty') {
-          item.setting.supModule = pid
-        } else {
-          item.setting.supModule = ''
+        if (item.subtype === 'editable') {
+          item.submit.logLabel = item.$menuname + '-鎻愪氦'
+          item.submit.$menuId = item.uuid
+          item.submit.syncComponentId = item.submit.syncComponent ? (item.submit.syncComponent.pop() || '') : ''
+
+          if (item.submit.syncComponentId && item.submit.syncComponentId === item.setting.supModule) {
+            item.submit.syncComponentId = ''
+            if (item.submit.execSuccess === 'grid') {
+              item.submit.execSuccess = 'mainline'
+            }
+          }
         }
-      }
-
-      // 鏉冮檺杩囨护
-      if (item.action && item.action.length > 0) {
-        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
-
-          if (!mutil && cell.syncComponentId === item.setting.supModule) {
-            cell.syncComponentId = ''
-            if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-              cell.execSuccess = 'mainline'
-            }
-          }
-
-          if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
-            cell = this.getPrinter(cell, item.uuid)
-          }
-
-          if (cell.btnstyle) { // 鍏煎
-            cell.style = cell.style || {}
-            cell.style = {...cell.style, ...cell.btnstyle}
-          }
-
-          if (cell.controlField) {
-            if (/,/ig.test(cell.controlVal)) {
-              cell.controlVals = cell.controlVal.split(',')
-            } else {
-              cell.controlVals = [(cell.controlVal || '')]
-            }
-          }
-
-          return skip || permAction[cell.uuid]
-        })
-      }
-
-      if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+      } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
         item.subcards && item.subcards.forEach(card => {
           if (card.style.boxShadow) {
             delete card.style.hShadow
@@ -579,45 +600,41 @@
             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 (!mutil && cell.syncComponentId === item.setting.supModule) {
-                cell.syncComponentId = ''
-                if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                  cell.execSuccess = 'mainline'
-                }
-              }
+              cell = this.resetButton(item, cell, popview)
 
               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 || '')]
-                }
-              }
-            } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
-              if (!cell.height) {
-                cell.innerHeight = 'auto'
-              }
-              if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-                cell.round = Math.pow(10, cell.decimal)
-                if (cell.format === 'percent') {
-                  cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-                }
-              }
+            } else {
+              cell = this.resetElement(cell)
             }
 
-            return cell.eleType !== 'button' || skip || permAction[cell.uuid]
+            return cell.eleType !== 'button' || pass || permAction[cell.uuid]
           })
+
+          if (card.setting.click === 'menus') {
+            if (card.menus) {
+              card.menus = card.menus.filter(m => !!m.MenuID)
+              if (card.menus.length === 0) {
+                card.menus = null
+              }
+            }
+            if (!card.menus || item.subtype !== 'datacard' || card.$cardType === 'extendCard') {
+              card.setting.click = ''
+            }
+          } else if (card.setting.click === 'menu') {
+            if (!Array.isArray(card.setting.menu)) {
+              card.setting.click = ''
+            }
+          }
+
+          if (item.subtype === 'dualdatacard' && card.$cardType !== 'extendCard') {
+            if (card.backSetting && card.backSetting.click === 'menu') {
+              if (!Array.isArray(card.backSetting.menu)) {
+                card.backSetting.click = ''
+              }
+            }
+          }
 
           if (!card.backElements || card.backElements.length === 0) return
 
@@ -625,44 +642,16 @@
             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 (!mutil && cell.syncComponentId === item.setting.supModule) {
-                cell.syncComponentId = ''
-                if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                  cell.execSuccess = 'mainline'
-                }
-              }
+              cell = this.resetButton(item, cell, popview)
 
               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 || '')]
-                }
-              }
-            } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
-              if (!cell.height) {
-                cell.innerHeight = 'auto'
-              }
-              if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-                cell.round = Math.pow(10, cell.decimal)
-                if (cell.format === 'percent') {
-                  cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-                }
-              }
+            } else {
+              cell = this.resetElement(cell)
             }
 
-            return cell.eleType !== 'button' || skip || permAction[cell.uuid]
+            return cell.eleType !== 'button' || pass || permAction[cell.uuid]
           })
         })
       } else if (item.type === 'balcony') {
@@ -677,91 +666,17 @@
           if (cell.eleType === 'button') {
             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
-
-            if (cell.syncComponentId === item.wrap.supModule) {
-              cell.syncComponentId = ''
-              if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                cell.execSuccess = 'mainline'
-              }
-            }
+            cell = this.resetButton(item, cell, popview)
 
             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 || '')]
-              }
-            }
-          } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
-            if (!cell.height) {
-              cell.innerHeight = 'auto'
-            }
-            if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-              cell.round = Math.pow(10, cell.decimal)
-              if (cell.format === 'percent') {
-                cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-              }
-            }
+          } else {
+            cell = this.resetElement(cell)
           }
 
-          return cell.eleType !== 'button' || skip || permAction[cell.uuid]
+          return cell.eleType !== 'button' || pass || permAction[cell.uuid]
         })
-      } else if (item.type === 'table') {
-        item.cols = item.cols.filter(col => {
-          if (col.type !== 'action') return true
-          col.elements = col.elements.filter(cell => {
-            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 === item.setting.supModule) {
-              cell.syncComponentId = ''
-              if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                cell.execSuccess = 'mainline'
-              }
-            }
-
-            if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) { // 鎵撳嵃鏈鸿缃�
-              cell = this.getPrinter(cell, item.uuid)
-            }
-
-            if (cell.btnstyle) { // 鍏煎
-              cell.style = cell.style || {}
-              cell.style = {...cell.style, ...cell.btnstyle}
-            }
-
-            if (cell.controlField) {
-              if (/,/ig.test(cell.controlVal)) {
-                cell.controlVals = cell.controlVal.split(',')
-              } else {
-                cell.controlVals = [(cell.controlVal || '')]
-              }
-            }
-
-            return skip || permAction[cell.uuid]
-          })
-          return col.elements.length !== 0
-        })
-
-        if (item.subtype === 'editable') {
-          item.submit.logLabel = item.$menuname + '-鎻愪氦'
-          item.submit.$menuId = item.uuid
-        }
       } else if (item.type === 'form') {
         item.subcards = item.subcards.map(group => {
           group.subButton.uuid = group.uuid
@@ -776,9 +691,9 @@
             group.subButton.Ot = item.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
           }
 
-          group.subButton.syncComponentId = group.subButton.syncComponent ? group.subButton.syncComponent.pop() : ''
+          group.subButton.syncComponentId = group.subButton.syncComponent ? (group.subButton.syncComponent.pop() || '') : ''
 
-          if (group.subButton.syncComponentId === item.setting.supModule) {
+          if (group.subButton.syncComponentId && group.subButton.syncComponentId === item.setting.supModule) {
             group.subButton.syncComponentId = ''
             if (group.subButton.execSuccess === 'grid') {
               group.subButton.execSuccess = 'mainline'
@@ -805,6 +720,12 @@
 
           return group
         })
+      } else if (item.subtype === 'voucher') {
+        if (item.wrap.supModule && item.wrap.supModule.length > 0) {
+          item.wrap.supModule = item.wrap.supModule.pop()
+        } else {
+          item.wrap.supModule = ''
+        }
       }
       
       return true
@@ -847,6 +768,94 @@
       
       return true
     })
+  }
+
+  resetButton = (item, cell, popview) => {
+    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.btnstyle) { // 鍏煎
+      cell.style = cell.style || {}
+      cell.style = {...cell.style, ...cell.btnstyle}
+    }
+
+    if (cell.controlField) {
+      if (/,/ig.test(cell.controlVal)) {
+        cell.controlVals = cell.controlVal.split(',')
+      } else {
+        cell.controlVals = [(cell.controlVal || '')]
+      }
+    }
+
+    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
+  }
+
+  resetElement = (cell) => {
+    cell.style = cell.style || {}
+    if (['text', 'number', 'formula'].includes(cell.eleType)) {
+      if (!cell.height) {
+        cell.innerHeight = 'auto'
+      }
+
+      cell.innerHeight = cell.innerHeight || 'auto'
+      cell.alignItems = cell.height > 1 ? cell.alignItems : ''
+
+      if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
+        cell.round = Math.pow(10, cell.decimal)
+        if (cell.format === 'percent') {
+          cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
+        }
+      } else if (cell.eleType === 'formula' && typeof(cell.decimal) === 'number') {
+        cell.round = Math.pow(10, cell.decimal)
+      }
+    } else if (cell.eleType === 'icon') {
+      if (!cell.innerHeight) { // 鍏煎
+        let fontSize = 14
+        let lineHeight = 1.5
+  
+        if (cell.style.fontSize) {
+          fontSize = parseInt(cell.style.fontSize)
+        }
+        if (cell.style.lineHeight) {
+          lineHeight = parseFloat(cell.style.lineHeight)
+        }
+  
+        cell.innerHeight = fontSize * lineHeight
+      }
+    }
+
+    return cell
   }
 
   getPrinter = (item, parentId) => {
@@ -989,13 +998,24 @@
   }
 
   // 鏍煎紡鍖栭粯璁よ缃�
-  formatInterSetting = (inters, regs) => {
+  formatInterSetting = (inters, regs, MenuID, initInters) => {
     if (!inters) return []
 
-    let interfaces = inters.filter(m => m.status === 'true')
+    let initlimit = false
+    let interfaces = inters.filter(m => {
+      if (m.status !== 'true') return false
+
+      if (m.setting.loadlevel === 'init') {
+        initlimit = true
+        initInters.push(m.uuid)
+      }
+
+      return true
+    })
 
     let delay = 15
     return interfaces.map(inter => {
+      inter.MenuID = MenuID
       inter.setting.delay = delay
       delay += 15
 
@@ -1006,6 +1026,10 @@
         } else {
           inter.setting.supModule = ''
         }
+      }
+
+      if (initlimit && inter.setting.loadlevel !== 'init') {
+        inter.setting.onload = 'false'
       }
 
       if (inter.setting.interType !== 'system') return inter
@@ -1122,6 +1146,7 @@
   }
 
   componentDidMount () {
+    MKEmitter.addListener('interFinish', this.interFinish)
     MKEmitter.addListener('debugChange', this.debugChange)
     MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
     MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu)
@@ -1134,6 +1159,7 @@
     this.setState = () => {
       return
     }
+    MKEmitter.removeListener('interFinish', this.interFinish)
     MKEmitter.removeListener('debugChange', this.debugChange)
     MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
     MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu)
@@ -1144,6 +1170,30 @@
       this.state.config.interfaces.forEach(m => {
         window.GLOB.CacheData.delete(m.uuid)
       })
+    }
+  }
+
+  interFinish = (MenuID, interId) => {
+    if (!this.stepInter || this.stepInter.MenuID !== MenuID) return
+
+    this.stepInter.inters = this.stepInter.inters.filter(item => item !== interId)
+
+    if (this.stepInter.inters.length === 0) {
+      this.setState({loadinginter: false})
+
+      if (this.stepInter.params.length === 0) {
+        setTimeout(() => { // 寤舵椂鍔犺浇鐘舵��
+          this.setState({
+            loadingview: false
+          })
+        }, 1000)
+      } else {
+        this.loadmaindata(this.stepInter.params)
+      }
+
+      MKEmitter.emit('initFinish', this.stepInter.MenuID)
+
+      this.stepInter = null
     }
   }
 
@@ -1175,6 +1225,8 @@
       })
     }
 
+    this.stepInter = null
+
     this.setState({
       BID: '',              // 椤甸潰璺宠浆鏃舵惡甯D
       loadingview: true,    // 椤甸潰鍔犺浇涓�
@@ -1195,9 +1247,9 @@
   }
 
   getComponents = () => {
-    const { config, BID, data, mainSearch } = this.state
+    const { config, BID, data, mainSearch, loadinginter } = this.state
 
-    if (!config || !config.components) return
+    if (!config || !config.components || loadinginter) return
 
     return config.components.map(item => {
       let style = null
@@ -1384,9 +1436,9 @@
     const { loadingview, viewlost, config, loading, shortcuts, BID } = this.state
 
     return (
-      <div className={'custom-page-wrap ' + (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' : ''}`} 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 : ''} className="component-wrap">{this.getComponents()}</Row>
+        <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}
diff --git a/src/tabviews/custom/index.scss b/src/tabviews/custom/index.scss
index 7d331eb..2c2a5fe 100644
--- a/src/tabviews/custom/index.scss
+++ b/src/tabviews/custom/index.scss
@@ -43,15 +43,14 @@
   .ant-btn-link:hover {
     opacity: 0.8;
   }
-  .button-list.toolbar-button {
-    button {
-      height: auto;
-      min-height: 28px;
-    }
-  }
 }
 .custom-page-wrap.loading {
   .ant-spin-spinning:not(.view-spin) {
     display: none;
   }
 }
+.custom-page-wrap.mk-scroll {
+  height: calc(100vh - 93px);
+  overflow: auto;
+  margin: 0!important;
+}
diff --git a/src/tabviews/custom/popview/index.jsx b/src/tabviews/custom/popview/index.jsx
index 6149fc0..0093459 100644
--- a/src/tabviews/custom/popview/index.jsx
+++ b/src/tabviews/custom/popview/index.jsx
@@ -97,7 +97,7 @@
 
     // 鏁版嵁缂撳瓨璁剧疆
     if (config.cacheUseful === 'true') {
-      if (!['day', 'hour'].includes(config.timeUnit)) {
+      if (!['day', 'hour', 'minute'].includes(config.timeUnit)) {
         config.timeUnit = 'day'
       }
       config.cacheTime = config.cacheTime || 1
@@ -302,6 +302,29 @@
         item.search = Utils.initSearchVal(item.search)
       }
 
+      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
+        item.setting.supModule = item.supNodes[0].componentId
+      } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
+        let pid = item.setting.supModule.pop()
+        if (pid && pid !== 'empty') {
+          item.setting.supModule = pid
+        } else {
+          item.setting.supModule = ''
+        }
+      }
+
+      // 鏉冮檺杩囨护
+      if (item.action && item.action.length > 0) {
+        item.action = item.action.filter(cell => {
+          if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
+
+          cell = this.resetButton(item, cell, Tab)
+          cell.$toolbtn = true
+
+          return true
+        })
+      }
+
       if (item.type === 'table') {
         let statFields = []
         let getCols = (cols) => {
@@ -310,6 +333,8 @@
               return false
             } else if (col.Hide === 'true') {
               return false
+            } else if (col.type === 'action') {
+              col.type = 'custom'
             }
             
             if (col.type === 'number') {
@@ -322,26 +347,31 @@
                   col.decimal = col.decimal > 2 ? col.decimal - 2 : 0
                 }
               }
+            } else if (col.type === 'formula') {
+              if (typeof(col.decimal) === 'number') {
+                col.round = Math.pow(10, col.decimal)
+              }
             } else if (col.type === 'colspan') {
               col.subcols = getCols(col.subcols || [])
               if (col.subcols.length === 0) {
                 return false
               }
             } else if (col.type === 'custom') {
-              col.elements = col.elements.map(cell => {
-                if (['text', 'number', 'formula'].includes(cell.eleType)) {
-                  if (!cell.height) {
-                    cell.innerHeight = 'auto'
-                  }
-                  if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-                    cell.round = Math.pow(10, cell.decimal)
-                    if (cell.format === 'percent') {
-                      cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-                    }
-                  }
+              col.elements = col.elements.filter(cell => {
+                if (cell.eleType === 'button') {
+                  if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
+            
+                  cell = this.resetButton(item, cell, Tab)
+                } else {
+                  cell = this.resetElement(cell)
                 }
-                return cell
+
+                return true
               })
+
+              if (col.elements.length === 0) {
+                return false
+              }
             }
       
             if (col.linkmenu && col.linkmenu.length > 0) {
@@ -357,57 +387,20 @@
         
         item.cols = getCols(item.cols)
         item.statFields = statFields
-      }
 
-      let mutil = false
-      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
-        mutil = true
-        item.setting.supModule = item.supNodes[0].componentId
-      } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
-        let pid = item.setting.supModule.pop()
-        if (pid && pid !== 'empty') {
-          item.setting.supModule = pid
-        } else {
-          item.setting.supModule = ''
+        if (item.subtype === 'editable') {
+          item.submit.logLabel = item.$menuname + '-鎻愪氦'
+          item.submit.$menuId = item.uuid
+          item.submit.syncComponentId = item.submit.syncComponent ? (item.submit.syncComponent.pop() || '') : ''
+
+          if (item.submit.syncComponentId && item.submit.syncComponentId === item.setting.supModule) {
+            item.submit.syncComponentId = ''
+            if (item.submit.execSuccess === 'grid') {
+              item.submit.execSuccess = 'mainline'
+            }
+          }
         }
-      }
-
-      // 鏉冮檺杩囨护
-      if (item.action && item.action.length > 0) {
-        item.action = item.action.filter(cell => {
-          if (cell.hidden === 'true' || ['popview', 'funcbutton'].includes(cell.OpenType)) return false
-
-          cell.logLabel = item.$menuname + '-' + cell.label
-          cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
-          cell.$menuId = item.uuid
-          cell.$tabId = Tab.uuid
-          cell.$toolbtn = true
-
-          if (!mutil && cell.syncComponentId === item.setting.supModule) {
-            cell.syncComponentId = ''
-            if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-              cell.execSuccess = 'mainline'
-            }
-          }
-
-          if (cell.btnstyle) { // 鍏煎
-            cell.style = cell.style || {}
-            cell.style = {...cell.style, ...cell.btnstyle}
-          }
-
-          if (cell.controlField) {
-            if (/,/ig.test(cell.controlVal)) {
-              cell.controlVals = cell.controlVal.split(',')
-            } else {
-              cell.controlVals = [(cell.controlVal || '')]
-            }
-          }
-
-          return true
-        })
-      }
-
-      if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+      } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
         item.subcards && item.subcards.forEach(card => {
           if (card.style.boxShadow) {
             delete card.style.hShadow
@@ -418,78 +411,49 @@
 
           card.elements = card.elements.filter(cell => {
             if (cell.eleType === 'button') {
-              if (cell.hidden === 'true' || ['popview', 'funcbutton'].includes(cell.OpenType)) return false
+              if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
 
-              cell.logLabel = item.$menuname + '-' + cell.label
-              cell.Ot = cell.Ot || 'requiredSgl'
-              cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
-              cell.$menuId = item.uuid
-              cell.$tabId = Tab.uuid
-
-              if (!mutil && cell.syncComponentId === item.setting.supModule) {
-                cell.syncComponentId = ''
-                if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                  cell.execSuccess = 'mainline'
-                }
-              }
-              if (cell.controlField) {
-                if (/,/ig.test(cell.controlVal)) {
-                  cell.controlVals = cell.controlVal.split(',')
-                } else {
-                  cell.controlVals = [(cell.controlVal || '')]
-                }
-              }
-            } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
-              if (!cell.height) {
-                cell.innerHeight = 'auto'
-              }
-              if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-                cell.round = Math.pow(10, cell.decimal)
-                if (cell.format === 'percent') {
-                  cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-                }
-              }
+              cell = this.resetButton(item, cell, Tab)
+            } else {
+              cell = this.resetElement(cell)
             }
 
             return true
           })
 
+          if (card.setting.click === 'menus') {
+            if (card.menus) {
+              card.menus = card.menus.filter(m => !!m.MenuID)
+              if (card.menus.length === 0) {
+                card.menus = null
+              }
+            }
+            if (!card.menus || item.subtype !== 'datacard' || card.$cardType === 'extendCard') {
+              card.setting.click = ''
+            }
+          } else if (card.setting.click === 'menu') {
+            if (!Array.isArray(card.setting.menu)) {
+              card.setting.click = ''
+            }
+          }
+
+          if (item.subtype === 'dualdatacard' && card.$cardType !== 'extendCard') {
+            if (card.backSetting && card.backSetting.click === 'menu') {
+              if (!Array.isArray(card.backSetting.menu)) {
+                card.backSetting.click = ''
+              }
+            }
+          }
+
           if (!card.backElements || card.backElements.length === 0) return
 
           card.backElements = card.backElements.filter(cell => {
             if (cell.eleType === 'button') {
-              if (cell.hidden === 'true' || ['popview', 'funcbutton'].includes(cell.OpenType)) return false
+              if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
 
-              cell.logLabel = item.$menuname + '-' + cell.label
-              cell.Ot = cell.Ot || 'requiredSgl'
-              cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
-              cell.$menuId = item.uuid
-              cell.$tabId = Tab.uuid
-
-              if (!mutil && cell.syncComponentId === item.setting.supModule) {
-                cell.syncComponentId = ''
-                if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                  cell.execSuccess = 'mainline'
-                }
-              }
-
-              if (cell.controlField) {
-                if (/,/ig.test(cell.controlVal)) {
-                  cell.controlVals = cell.controlVal.split(',')
-                } else {
-                  cell.controlVals = [(cell.controlVal || '')]
-                }
-              }
-            } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
-              if (!cell.height) {
-                cell.innerHeight = 'auto'
-              }
-              if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-                cell.round = Math.pow(10, cell.decimal)
-                if (cell.format === 'percent') {
-                  cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-                }
-              }
+              cell = this.resetButton(item, cell, Tab)
+            } else {
+              cell = this.resetElement(cell)
             }
 
             return true
@@ -505,81 +469,15 @@
         }
         item.elements = item.elements.filter(cell => {
           if (cell.eleType === 'button') {
-            if (cell.hidden === 'true' || ['popview', 'funcbutton'].includes(cell.OpenType)) return false
+            if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
 
-            cell.logLabel = item.$menuname + '-' + cell.label
-            cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
-            cell.$menuId = item.uuid
-            cell.$tabId = Tab.uuid
-
-            if (cell.syncComponentId === item.wrap.supModule) {
-              cell.syncComponentId = ''
-              if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                cell.execSuccess = 'mainline'
-              }
-            }
-            if (cell.controlField) {
-              if (/,/ig.test(cell.controlVal)) {
-                cell.controlVals = cell.controlVal.split(',')
-              } else {
-                cell.controlVals = [(cell.controlVal || '')]
-              }
-            }
-          } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
-            if (!cell.height) {
-              cell.innerHeight = 'auto'
-            }
-            if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
-              cell.round = Math.pow(10, cell.decimal)
-              if (cell.format === 'percent') {
-                cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
-              }
-            }
+            cell = this.resetButton(item, cell, Tab)
+          } else {
+            cell = this.resetElement(cell)
           }
 
           return true
         })
-      } else if (item.type === 'table') {
-        item.cols = item.cols.filter(col => {
-          if (col.type !== 'action') return true
-          col.elements = col.elements.filter(cell => {
-            if (cell.hidden === 'true' || ['popview', 'funcbutton'].includes(cell.OpenType)) return false
-            
-            cell.logLabel = item.$menuname + '-' + cell.label
-            cell.Ot = cell.Ot || 'requiredSgl'
-            cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
-            cell.$menuId = item.uuid
-            cell.$tabId = Tab.uuid
-
-            if (cell.syncComponentId === item.setting.supModule) {
-              cell.syncComponentId = ''
-              if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
-                cell.execSuccess = 'mainline'
-              }
-            }
-
-            if (cell.btnstyle) { // 鍏煎
-              cell.style = cell.style || {}
-              cell.style = {...cell.style, ...cell.btnstyle}
-            }
-
-            if (cell.controlField) {
-              if (/,/ig.test(cell.controlVal)) {
-                cell.controlVals = cell.controlVal.split(',')
-              } else {
-                cell.controlVals = [(cell.controlVal || '')]
-              }
-            }
-
-            return true
-          })
-          return col.elements.length !== 0
-        })
-
-        if (item.subtype === 'editable') {
-          item.submit.logLabel = item.$menuname + '-鎻愪氦'
-          item.submit.$menuId = item.uuid
-        }
       } else if (item.type === 'form') {
         item.subcards = item.subcards.map(group => {
           group.subButton.uuid = group.uuid
@@ -593,9 +491,9 @@
             group.subButton.Ot = item.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
           }
 
-          group.subButton.syncComponentId = group.subButton.syncComponent ? group.subButton.syncComponent.pop() : ''
+          group.subButton.syncComponentId = group.subButton.syncComponent ? (group.subButton.syncComponent.pop() || '') : ''
 
-          if (group.subButton.syncComponentId === item.setting.supModule) {
+          if (group.subButton.syncComponentId && group.subButton.syncComponentId === item.setting.supModule) {
             group.subButton.syncComponentId = ''
             if (group.subButton.execSuccess === 'grid') {
               group.subButton.execSuccess = 'mainline'
@@ -666,6 +564,93 @@
     })
   }
 
+  resetButton = (item, cell, Tab) => {
+    cell.logLabel = item.$menuname + '-' + cell.label
+    cell.Ot = cell.Ot || 'requiredSgl'
+    cell.syncComponentId = cell.syncComponent ? (cell.syncComponent.pop() || '') : ''
+    cell.$menuId = item.uuid
+    cell.$MenuID = Tab.$MenuID
+    cell.$tabId = Tab.uuid
+
+    if (cell.btnstyle) { // 鍏煎
+      cell.style = cell.style || {}
+      cell.style = {...cell.style, ...cell.btnstyle}
+    }
+
+    if (cell.controlField) {
+      if (/,/ig.test(cell.controlVal)) {
+        cell.controlVals = cell.controlVal.split(',')
+      } else {
+        cell.controlVals = [(cell.controlVal || '')]
+      }
+    }
+
+    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
+  }
+
+  resetElement = (cell) => {
+    cell.style = cell.style || {}
+    if (['text', 'number', 'formula'].includes(cell.eleType)) {
+      if (!cell.height) {
+        cell.innerHeight = 'auto'
+      }
+
+      cell.innerHeight = cell.innerHeight || 'auto'
+      cell.alignItems = cell.height > 1 ? cell.alignItems : ''
+
+      if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
+        cell.round = Math.pow(10, cell.decimal)
+        if (cell.format === 'percent') {
+          cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
+        }
+      } else if (cell.type === 'formula' && typeof(cell.decimal) === 'number') {
+        cell.round = Math.pow(10, cell.decimal)
+      }
+    } else if (cell.eleType === 'icon') {
+      if (!cell.innerHeight) { // 鍏煎
+        let fontSize = 14
+        let lineHeight = 1.5
+  
+        if (cell.style.fontSize) {
+          fontSize = parseInt(cell.style.fontSize)
+        }
+        if (cell.style.lineHeight) {
+          lineHeight = parseFloat(cell.style.lineHeight)
+        }
+  
+        cell.innerHeight = fontSize * lineHeight
+      }
+    }
+
+    return cell
+  }
+
   getPrinter = (item, parentId) => {
     let _item = window.GLOB.UserCacheMap.get(parentId + item.uuid)
 
diff --git a/src/tabviews/custom/popview/index.scss b/src/tabviews/custom/popview/index.scss
index b69e65d..c3e4b31 100644
--- a/src/tabviews/custom/popview/index.scss
+++ b/src/tabviews/custom/popview/index.scss
@@ -43,12 +43,6 @@
   .ant-btn-link:hover {
     opacity: 0.8;
   }
-  .button-list.toolbar-button {
-    button {
-      height: auto;
-      min-height: 28px;
-    }
-  }
 }
 .pop-page-wrap.loading {
   .ant-spin-spinning:not(.view-spin) {
diff --git a/src/tabviews/formtab/actionList/index.jsx b/src/tabviews/formtab/actionList/index.jsx
index 87e516a..9b97235 100644
--- a/src/tabviews/formtab/actionList/index.jsx
+++ b/src/tabviews/formtab/actionList/index.jsx
@@ -327,7 +327,7 @@
   actionSettingError = () => {
     notification.warning({
       top: 92,
-      message: this.props.dict['main.action.settingerror'],
+      message: '鎸夐挳璁剧疆閿欒锛�',
       duration: 5
     })
   }
diff --git a/src/tabviews/formtab/index.jsx b/src/tabviews/formtab/index.jsx
index 98691d1..dcc0d1d 100644
--- a/src/tabviews/formtab/index.jsx
+++ b/src/tabviews/formtab/index.jsx
@@ -224,7 +224,7 @@
         } else if (item.resourceType === '1' && !item.dataSource) {
           notification.warning({
             top: 92,
-            message: item.label + ': ' + this.state.dict['main.datasource.settingerror'],
+            message: item.label + ': 鏁版嵁婧愰厤缃敊璇紒',
             duration: 5
           })
         }
diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx
index ac80f8f..694a47d 100644
--- a/src/tabviews/subtable/index.jsx
+++ b/src/tabviews/subtable/index.jsx
@@ -657,7 +657,7 @@
           item.$Index = start + index + ''
 
           if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField])) {
+            if (setting.controlVal.includes(item[setting.controlField] + '')) {
               item.$disabled = true
             }
           }
diff --git a/src/tabviews/subtable/index.scss b/src/tabviews/subtable/index.scss
index 9f855e4..3e12f6f 100644
--- a/src/tabviews/subtable/index.scss
+++ b/src/tabviews/subtable/index.scss
@@ -2,7 +2,7 @@
   position: relative;
   min-height: 200px;
 
-  >.top-search {
+  >.mk-search-wrap {
     padding: 0px 0px 5px;
     border-bottom: 1px solid #efefef;
   }
@@ -71,19 +71,6 @@
   }
   .box404 {
     padding-top: 30px;
-  }
-  .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;
diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx
index ef20200..8be474a 100644
--- a/src/tabviews/subtabtable/index.jsx
+++ b/src/tabviews/subtabtable/index.jsx
@@ -591,7 +591,7 @@
           item.$Index = start + index + ''
 
           if (setting.controlField) {
-            if (setting.controlVal.includes(item[setting.controlField])) {
+            if (setting.controlVal.includes(item[setting.controlField] + '')) {
               item.$disabled = true
             }
           }
diff --git a/src/tabviews/subtabtable/index.scss b/src/tabviews/subtabtable/index.scss
index 85d52e8..534296f 100644
--- a/src/tabviews/subtabtable/index.scss
+++ b/src/tabviews/subtabtable/index.scss
@@ -2,25 +2,12 @@
   position: relative;
   min-height: 200px;
   padding-top: 16px;
-  >.top-search {
+  >.mk-search-wrap {
     padding: 0px 0px 5px;
     border-bottom: 1px solid #efefef;
   }
   .box404 {
     padding-top: 30px;
-  }
-  .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;
diff --git a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
index fc411f4..9311874 100644
--- a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
@@ -190,7 +190,6 @@
               // sessionStorage.setItem('debug', res.debug || '')
               // sessionStorage.setItem('role_id', res.role_id || '')
               // sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
-              // sessionStorage.setItem('localRole_id', res.role_id || '')
 
               localStorage.setItem('UserID', res.UserID)
               localStorage.setItem('LoginUID', res.LoginUID)
@@ -204,7 +203,6 @@
               localStorage.setItem('departmentcode', res.departmentcode || '')
               localStorage.setItem('organization', res.organization || '')
               localStorage.setItem('mk_user_type', res.mk_user_type || '')
-              localStorage.setItem('localRole_id', res.role_id || '')
               
               sessionStorage.removeItem('CloudAvatar')
               sessionStorage.removeItem('cloudDataM')
diff --git a/src/tabviews/zshare/actionList/editLine/index.jsx b/src/tabviews/zshare/actionList/editLine/index.jsx
new file mode 100644
index 0000000..7d29501
--- /dev/null
+++ b/src/tabviews/zshare/actionList/editLine/index.jsx
@@ -0,0 +1,149 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Button } from 'antd'
+
+import MkIcon from '@/components/mk-icon'
+import MKEmitter from '@/utils/events.js'
+// import './index.scss'
+
+class EditLine extends Component {
+  static propTpyes = {
+    btn: PropTypes.object,            // 鎸夐挳
+    disabled: PropTypes.any,          // 琛屾寜閽鐢�
+  }
+
+  state = {
+    disabled: false,
+    hidden: false
+  }
+
+  UNSAFE_componentWillMount () {
+    const { btn, selectedData, BData, disabled } = this.props
+
+    if (btn.controlField) {
+      this.setStatus(btn, selectedData || [], BData, disabled)
+    } else if (disabled) {
+      this.setState({disabled: true})
+    }
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    const { btn } = this.props
+
+    if (btn.controlField) {
+      this.setStatus(btn, nextProps.selectedData || [], nextProps.BData, nextProps.disabled)
+    } else {
+      this.setState({disabled: nextProps.disabled === true})
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  setStatus = (btn, data, BData, disprop) => {
+    let disabled = false
+    let hidden = false
+
+    if (btn.control !== 'parent') {
+      if (data.length > 0) {
+        data.forEach(item => {
+          let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
+          if (btn.controlVals.includes(s)) {
+            disabled = true
+          }
+        })
+      } else if (btn.controlVals.includes('')) {
+        disabled = true
+      }
+    } else {
+      if (!BData || !BData.hasOwnProperty(btn.controlField)) {
+        hidden = true
+      } else {
+        let s = BData[btn.controlField] + ''
+        if (btn.controlVals.includes(s)) {
+          hidden = true
+        }
+      }
+    }
+
+    if (disabled && btn.control === 'hidden') {
+      hidden = true
+    }
+
+    if (disprop) {
+      disabled = true
+    }
+
+    this.setState({hidden, disabled})
+  }
+
+  /**
+   * @description 瑙﹀彂鎸夐挳鎿嶄綔
+   */
+  actionTrigger = () => {
+    const { btn, selectedData } = this.props
+
+    if (this.state.disabled) return
+
+    let data = selectedData || []
+    
+    if (btn.funcType === 'addline') {
+      MKEmitter.emit('addRecord', btn.$tableId, data[0] || null)
+    } else {
+      MKEmitter.emit('delRecord', btn.$tableId, data[0] || null)
+    }
+  }
+
+  render() {
+    const { btn } = this.props
+    const { disabled, hidden } = this.state
+
+    if (hidden) return null
+
+    let label = ''
+    let icon = ''
+    let type = 'link'
+    let className = ''
+
+    if (btn.show === 'button') {
+      label = btn.label
+      icon = btn.icon || ''
+    } else if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
+      icon = ''
+    } else if (btn.show === 'icon') {
+      icon = btn.icon || ''
+    } else if (!btn.$toolbtn) {
+      icon = btn.icon || ''
+      label = btn.label
+      className = 'mk-btn mk-' + btn.class
+    } else {
+      type = ''
+      icon = btn.icon || ''
+      label = btn.label
+      className = 'mk-btn mk-' + btn.class
+    }
+
+    return (
+      <Button
+        type={type}
+        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
+        disabled={disabled}
+        style={btn.style}
+        icon={icon}
+        className={className}
+        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
+      >{label}</Button>
+    )
+  }
+}
+
+export default EditLine
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/editLine/index.scss b/src/tabviews/zshare/actionList/editLine/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tabviews/zshare/actionList/editLine/index.scss
diff --git a/src/tabviews/zshare/actionList/excelInbutton/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
index b632588..2abe56f 100644
--- a/src/tabviews/zshare/actionList/excelInbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -78,7 +78,7 @@
       if (data.length > 0) {
         data.forEach(item => {
           let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
-          if (btn.controlVals.includes(s)) {
+          if (btn.controlVals.includes(s) || item.$lock) {
             disabled = true
           }
         })
@@ -199,8 +199,18 @@
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn, '', this.state.selines)
     }
     
-    btn.syncComponentId && MKEmitter.emit('reloadData', btn.syncComponentId)
-    
+    if (btn.syncComponentId) {
+      if (btn.syncComponentId === 'multiComponent') {
+        btn.syncComponentIds.forEach((id, i) => {
+          setTimeout(() => {
+            MKEmitter.emit('reloadData', id)
+          }, 20 * i)
+        })
+      } else {
+        MKEmitter.emit('reloadData', btn.syncComponentId)
+      }
+    }
+
     if (btn.switchTab && btn.switchTab.length > 0) {
       let id = btn.switchTab[btn.switchTab.length - 1]
       let node = document.getElementById('tab' + id)
@@ -296,7 +306,7 @@
       })
     }
 
-    let result = getExcelInSql(btn, data, this.state.dict, (this.props.BID || ''), this.state.primaryId)
+    let result = getExcelInSql(btn, data, (this.props.BID || ''), this.state.primaryId)
 
     if (result.errors) {
       notification.warning({
@@ -426,6 +436,7 @@
       })
     } else if (btn.intertype === 'outer') { // 澶栭儴鎺ュ彛
       let _outParam = null
+      let ver_token = false
 
       new Promise(resolve => {
         // 鍐呴儴璇锋眰
@@ -483,6 +494,7 @@
             } else {
               param.$token = btn.exInterface || ''
             }
+            ver_token = true
           } else {
             if (window.GLOB.systemType === 'production' && btn.proInterface) {
               param.rduri = btn.proInterface
@@ -511,7 +523,9 @@
       }).then(response => {
         if (!response) return
         // 鍥炶皟璇锋眰
-        if (btn.callbackFunc) {
+        if (ver_token && response.ErrMesg === 'token_error') {
+          this.execError(response)
+        } else if (btn.callbackFunc ) {
           // 瀛樺湪鍥炶皟鍑芥暟鏃讹紝璋冪敤
           delete response.message
           delete response.status
diff --git a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
index be05ea6..78fc739 100644
--- a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -713,6 +713,21 @@
           })
         }
 
+        if (btn.verify.wrapText === 'true' && data) {
+          let lines = data.length + 1
+          let start = 2
+          if (btn.verify.merge === 'true') {
+            lines = data.length + 2
+          }
+          for (let n = 0; n < cols.length; n++) {
+            for (let m = start; m <= lines; m++) {
+              if (ws[cols[n] + m] && !ws[cols[n] + m].s) {
+                ws[cols[n] + m].s = {alignment: { wrapText: true }}
+              }
+            }
+          }
+        }
+
         // ws["A1"].s = {fill: { bgColor: { rgb: "FFFFAA"  }}, font: { color: { rgb: "1890FF" } }}
 
         const wb = XLSX.utils.book_new()
@@ -884,7 +899,7 @@
       defaultSql = btn.verify.defaultSql || 'true'
       _dataresource = btn.verify.dataresource || ''
       queryType = btn.verify.queryType
-      primaryKey = btn.verify.primaryKey || 'ID'
+      // primaryKey = btn.verify.primaryKey || 'ID'
 
       if (/\s/.test(_dataresource)) {
         _dataresource = '(' + _dataresource + ') tb'
@@ -920,6 +935,11 @@
       custom_script: customScript,
       default_sql: defaultSql,
       menuname: btn.logLabel
+    }
+
+    if (btn.verify.dataType !== 'custom' && setting.sub_field) {
+      arr_field = arr_field + ',' + setting.sub_field
+      param.arr_field = arr_field
     }
 
     // 鏁版嵁绠$悊鏉冮檺
@@ -988,9 +1008,9 @@
     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}'))`
+        _search += ` and ${primaryKey} in (select ID from dbo.SplitComma('${primaryId}'))`
       } else if (primaryId) {
-        _search = `where ${primaryKey} in (select ID from  dbo.SplitComma('${primaryId}'))`
+        _search = `where ${primaryKey} in (select ID from dbo.SplitComma('${primaryId}'))`
       }
     }
 
@@ -1098,7 +1118,17 @@
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn, '', [])
     }
     
-    btn.syncComponentId && MKEmitter.emit('reloadData', btn.syncComponentId)
+    if (btn.syncComponentId) {
+      if (btn.syncComponentId === 'multiComponent') {
+        btn.syncComponentIds.forEach((id, i) => {
+          setTimeout(() => {
+            MKEmitter.emit('reloadData', id)
+          }, 20 * i)
+        })
+      } else {
+        MKEmitter.emit('reloadData', btn.syncComponentId)
+      }
+    }
     
     if (btn.switchTab && btn.switchTab.length > 0) {
       let id = btn.switchTab[btn.switchTab.length - 1]
diff --git a/src/tabviews/zshare/actionList/index.jsx b/src/tabviews/zshare/actionList/index.jsx
index 10871f6..8723fa0 100644
--- a/src/tabviews/zshare/actionList/index.jsx
+++ b/src/tabviews/zshare/actionList/index.jsx
@@ -17,11 +17,11 @@
 const PrintButton = asyncComponent(() => import('./printbutton'))
 const FuncMegvii = asyncComponent(() => import('./funcMegvii'))
 const FuncZip = asyncComponent(() => import('./funczip'))
+const EditLine = asyncComponent(() => import('./editLine'))
 
 class ActionList extends Component {
   static propTpyes = {
     BID: PropTypes.any,               // 涓昏〃ID
-    lock: PropTypes.any,              // 鍙紪杈戣〃涓寜閽攣瀹�
     BData: PropTypes.any,             // 涓昏〃鏁版嵁
     selectedData: PropTypes.any,      // 瀛愯〃涓�夋嫨鏁版嵁
     MenuID: PropTypes.string,         // 鑿滃崟ID
@@ -55,14 +55,14 @@
   }
 
   getButtonList = (actions) => {
-    const { BID, BData, MenuID, columns, setting, selectedData, lock } = this.props
+    const { BID, BData, MenuID, columns, setting, selectedData } = this.props
     return actions.map(item => {
       if (['exec', 'prompt', 'pop'].includes(item.OpenType)) {
         return (
           <NormalButton
             key={item.uuid}
             show={item.show || 'actionList'}
-            disabled={lock || false}
+            disabled={false}
             BID={BID}
             btn={item}
             BData={BData}
@@ -76,7 +76,7 @@
           <ExcelInButton
             key={item.uuid}
             show={item.show || 'actionList'}
-            disabled={lock || false}
+            disabled={false}
             BID={BID}
             btn={item}
             BData={BData}
@@ -89,7 +89,7 @@
           <ExcelOutButton
             key={item.uuid}
             show={item.show || 'actionList'}
-            disabled={lock || false}
+            disabled={false}
             BID={BID}
             btn={item}
             BData={BData}
@@ -102,7 +102,7 @@
           <PopupButton
             key={item.uuid}
             show={item.show || 'actionList'}
-            disabled={lock || false}
+            disabled={false}
             BID={BID}
             btn={item}
             BData={BData}
@@ -115,7 +115,7 @@
           <TabButton
             key={item.uuid}
             show={item.show || 'actionList'}
-            disabled={lock || false}
+            disabled={false}
             btn={item}
             BID={BID}
             BData={BData}
@@ -128,7 +128,7 @@
           <NewPageButton
             key={item.uuid}
             show={item.show || 'actionList'}
-            disabled={lock || false}
+            disabled={false}
             btn={item}
             BData={BData}
             selectedData={selectedData}
@@ -140,7 +140,7 @@
             <ChangeUserButton
               key={item.uuid}
               show={item.show || 'actionList'}
-              disabled={lock || false}
+              disabled={false}
               BID={BID}
               btn={item}
               BData={BData}
@@ -154,7 +154,7 @@
             <PrintButton
               key={item.uuid}
               show={item.show || 'actionList'}
-              disabled={lock || false}
+              disabled={false}
               BID={BID}
               btn={item}
               BData={BData}
@@ -168,7 +168,7 @@
             <FuncMegvii
               key={item.uuid}
               show={item.show || 'actionList'}
-              disabled={lock || false}
+              disabled={false}
               BID={BID}
               btn={item}
               setting={setting}
@@ -180,10 +180,19 @@
             <FuncZip
               key={item.uuid}
               show={item.show || 'actionList'}
-              disabled={lock || false}
+              disabled={false}
               BID={BID}
               btn={item}
               setting={setting}
+              selectedData={selectedData}
+            />
+          )
+        } else if (item.funcType === 'addline' || item.funcType === 'delline') {
+          return (
+            <EditLine
+              key={item.uuid}
+              disabled={false}
+              btn={item}
               selectedData={selectedData}
             />
           )
@@ -194,14 +203,13 @@
   }
 
   render() {
-    const { setting, MenuID } = this.props
+    const { setting } = this.props
     const { actions, mores } = this.state
-    let fixed = setting.actionfixed && setting.tabType === 'main' // 鎸夐挳鏄惁鍥哄畾鍦ㄥご閮�
 
-    if (fixed && MenuID) {
+    if (setting.actionfixed === 'true') {
       return (
         <Affix offsetTop={48}>
-          <div className="button-list toolbar-button" id={fixed ? MenuID + 'mainaction' : ''}>
+          <div className="button-list toolbar-button">
             {this.getButtonList(actions)}
             {mores ? <Dropdown overlay={<div className="mk-button-dropdown-wrap">{this.getButtonList(mores)}</div>} trigger={['hover']}>
               <div className="mk-button-more">鏇村<DownOutlined/></div>
@@ -211,7 +219,7 @@
       )
     } else {
       return (
-        <div className="button-list toolbar-button" id={fixed ? MenuID + 'mainaction' : ''}>
+        <div className="button-list toolbar-button">
           {this.getButtonList(actions)}
           {mores ? <Dropdown overlay={<div className="mk-button-dropdown-wrap">{this.getButtonList(mores)}</div>} trigger={['hover']}>
             <div className="mk-button-more">鏇村<DownOutlined/></div>
diff --git a/src/tabviews/zshare/actionList/index.scss b/src/tabviews/zshare/actionList/index.scss
index 99ac35f..42c8bcc 100644
--- a/src/tabviews/zshare/actionList/index.scss
+++ b/src/tabviews/zshare/actionList/index.scss
@@ -1,11 +1,13 @@
 .button-list.toolbar-button {
   position: relative;
-  padding: 15px 0px 5px;
+  padding: 15px 0px 0px;
   background: #ffffff;
+  min-height: 55px;
+
   button {
     min-width: 65px;
     margin-right: 15px;
-    margin-bottom: 10px;
+    margin-bottom: 10px!important;
     overflow: hidden;
     min-height: 28px;
     height: auto;
@@ -26,6 +28,7 @@
     display: none;
   }
 }
+
 .mk-button-more {
   display: inline-block;
   height: 28px;
diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
index 33f3232..94b50d8 100644
--- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx
+++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -69,7 +69,7 @@
       if (data.length > 0) {
         data.forEach(item => {
           let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
-          if (btn.controlVals.includes(s)) {
+          if (btn.controlVals.includes(s) || item.$lock) {
             disabled = true
           }
         })
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index 4b9f777..07a4c6c 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -144,7 +144,7 @@
       if (data.length > 0) {
         data.forEach(item => {
           let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
-          if (btn.controlVals.includes(s)) {
+          if (btn.controlVals.includes(s) || item.$lock) {
             disabled = true
           }
         })
@@ -601,7 +601,7 @@
             param.LText = sql
             param.$callbacksql = callbacksql
           } else {
-            param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, false, this.moduleParams, Utils.getAllSearchOptions, Utils.getAllSearchOptions) // 鏁版嵁婧�
+            param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧�
             if (btn.output) {
               param.key_back_type = 'Y'
             }
@@ -838,7 +838,7 @@
   getSysDeclareSql = (btn, formdata, data, columns, primaryId, BID = '') => {
     let datavars = {}                 // 澹版槑鐨勫彉閲忥紝琛ㄥ崟鍙婃樉绀哄垪
     // 闇�瑕佸0鏄庣殑鍙橀噺闆�
-    let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
+    let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'mk_deleted', 'bid']
   
     // sql璇彞
     let _sql = ''
@@ -855,17 +855,24 @@
   
       if (!_initvars.includes(_key)) {
         _initvars.push(_key)
+        let val = form.value
   
         if (form.type === 'number' || form.type === 'rate') {
-          let val = form.value
           if (isNaN(val)) {
             val = 0
           }
           _initFormfields.push(`@${_key}=${val}`)
         } else if (['date', 'datemonth'].includes(form.type)) {
-          _initFormfields.push(`@${_key}='${form.value || '1949-10-01'}'`)
+          _initFormfields.push(`@${_key}='${val || '1949-10-01'}'`)
         } else {
-          _initFormfields.push(`@${_key}='${form.value}'`)
+          if (/'/.test(val)) {
+            val = val.replace(/'/ig, '"')
+          }
+          if (form.isconst) {
+            _initFormfields.push(`@${_key}=N'${val}'`)
+          } else {
+            _initFormfields.push(`@${_key}='${val}'`)
+          }
         }
       }
       
@@ -890,15 +897,16 @@
       }
     })
   
+    let _data = {}
     if (data) {
       Object.keys(data).forEach(key => {
-        data[key.toLowerCase()] = data[key]
+        _data[key.toLowerCase()] = data[key]
       })
     }
   
     // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
     if (data && btn.Ot !== 'notRequired' && columns && columns.length > 0) {
-      datavars = {...data, ...datavars}
+      datavars = {..._data, ...datavars}
   
       const setField = (col) => {
         if (!col.field) return
@@ -909,6 +917,10 @@
   
           if (col.datatype && /^date/ig.test(col.datatype) && !_val) {
             _val = '1949-10-01'
+          }
+
+          if (/'/.test(_val)) {
+            _val = _val.replace(/'/ig, '"')
           }
   
           _initvars.push(_key)
@@ -956,7 +968,7 @@
       _declarefields = ',' + _declarefields
     }
     _sql = `/* 绯荤粺鐢熸垚 */
-        Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @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),@bid nvarchar(50)${_declarefields}
+        Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @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),@mk_deleted int,@bid nvarchar(50)${_declarefields}
       `
   
     let userName = sessionStorage.getItem('User_Name') || ''
@@ -979,7 +991,7 @@
     // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
     _sql += `
         /* 鍑瘉鍙婄敤鎴蜂俊鎭垵濮嬪寲璧嬪�� */
-        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@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}', @bid='${BID}', @BillCode='', @ModularDetailCode=''
+        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@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}', @mk_deleted=1, @bid='${BID}', @BillCode='', @ModularDetailCode=''
         `
   
     // 琛ㄥ崟鍙橀噺璧嬪��
@@ -1053,37 +1065,49 @@
 
       if (params[0].$unCheckParam) {
         this.checkLoopRequest(params, _resolve)
+      } else if (btn.preFunc && params.length === 1) {
+        let param = params[0]
+        let _param = fromJS(param).toJS()
+        _param.func = btn.preFunc
+
+        Api.genericInterface(_param).then(res => {
+          if (res.status) {
+            if (res.ErrCode !== '-1') {
+              param = {...param, ...res}
+
+              delete param.status
+              delete param.ErrCode
+              delete param.ErrMesg
+              delete param.message
+  
+              setTimeout(() => {
+                Api.genericInterface(param).then(result => {
+                  if (!result.status) {
+                    notification.warning({
+                      top: 92,
+                      message: result.message,
+                      duration: 5
+                    })
+                  }
+                })
+              }, 600)
+            }
+
+            this.triggerNote(res) // 娑堟伅
+            this.execSuccess(res)
+          } else {
+            this.execError(res)
+          }
+          _resolve()
+        }, () => {
+          this.updateStatus()
+          _resolve()
+        })
       } else if (params.length <= 20 && btn.execType !== 'single') {
         let deffers = params.map((param, i) => {
           return new Promise(resolve => {
             setTimeout(() => {
-              let _param = null
-              if (btn.preFunc) {
-                _param = fromJS(param).toJS()
-                param.func = btn.preFunc
-              }
               Api.genericInterface(param).then(res => {
-                if (btn.preFunc && res.status && res.ErrCode !== '-1') {
-                  _param = {..._param, ...res}
-
-                  delete _param.status
-                  delete _param.ErrCode
-                  delete _param.ErrMesg
-                  delete _param.message
-
-                  setTimeout(() => {
-                    Api.genericInterface(_param).then(result => {
-                      if (!result.status) {
-                        notification.warning({
-                          top: 92,
-                          message: result.message,
-                          duration: 5
-                        })
-                      }
-                    })
-                  }, 600)
-                }
-
                 if (res.status) {
                   this.triggerNote(res) // 娑堟伅
                 }
@@ -1558,36 +1582,8 @@
       loadingNumber: params.length
     })
 
-    let _param = null
-
-    if (btn.preFunc) {
-      _param = fromJS(param).toJS()
-      param.func = btn.preFunc
-    }
-
     Api.genericInterface(param).then(res => {
       if (res.status) {
-        if (btn.preFunc && res.ErrCode !== '-1') {
-          _param = {..._param, ...res}
-  
-          delete _param.status
-          delete _param.ErrCode
-          delete _param.ErrMesg
-          delete _param.message
-  
-          setTimeout(() => {
-            Api.genericInterface(_param).then(result => {
-              if (!result.status) {
-                notification.warning({
-                  top: 92,
-                  message: result.message,
-                  duration: 5
-                })
-              }
-            })
-          }, 600)
-        }
-
         this.triggerNote(res) // 娑堟伅
 
         if (params.length === 0) {
@@ -1734,6 +1730,7 @@
   outerOuterRequest = (params, result, record, _resolve) => {
     const { btn } = this.props
     let outParam = JSON.parse(JSON.stringify(result))
+    let ver_token = false
 
     if (btn.outerFunc) {
       result.func = btn.outerFunc
@@ -1772,6 +1769,7 @@
         } else {
           result.$token = btn.exInterface || ''
         }
+        ver_token = true
       } else {
         if (window.GLOB.systemType === 'production' && btn.proInterface) {
           result.rduri = btn.proInterface
@@ -1788,6 +1786,10 @@
 
     Api.genericInterface(result).then(res => {
       if (!res) return // LoginError鏃朵腑鏂姹�
+      if (ver_token && res.ErrMesg === 'token_error') {
+        this.execError(res)
+        return
+      }
       this.outerCallbackRequest(params, res, record, outParam, _resolve)
     }, () => {
       this.outerCallbackRequest(params, {status: false, message: 500, ErrCode: 'E', ErrMesg: 500}, record, outParam, _resolve)
@@ -1962,8 +1964,9 @@
     const { btn } = this.props
     const { btnconfig, autoMatic } = this.state
 
-    if (res.message && /^@speak@/.test(res.message)) {
-      res.message = res.message.replace('@speak@', '')
+    let sign = ''
+    if (/^@speak@/i.test(res.message)) {
+      res.message = res.message.replace(/^@speak@/i, '')
       let val = res.message.match(/<<.*>>/)
       res.message = res.message.replace(/\s*<<.*>>\s*/g, '')
       val = val ? val[0].replace(/<<|>>/g, '') : ''
@@ -1977,6 +1980,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) { // 鎵ц鎴愬姛
@@ -2032,9 +2038,9 @@
       return
     }
 
-    if (btn.execSuccess === 'closetab') {
+    if (btn.execSuccess === 'closetab' || sign === '@close_tab@') {
       MKEmitter.emit('closeTabView', btn.$MenuID)
-    } else if (btn.execSuccess === 'closepoptab') {
+    } else if (btn.execSuccess === 'closepoptab' || sign === '@close_popup@') {
       MKEmitter.emit('popclose')
     } else if (btn.execSuccess !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn, id, this.state.selines)
@@ -2044,7 +2050,17 @@
       MKEmitter.emit('refreshDebugTable')
     }
     
-    btn.syncComponentId && MKEmitter.emit('reloadData', btn.syncComponentId)
+    if (btn.syncComponentId) {
+      if (btn.syncComponentId === 'multiComponent') {
+        btn.syncComponentIds.forEach((id, i) => {
+          setTimeout(() => {
+            MKEmitter.emit('reloadData', id)
+          }, 20 * i)
+        })
+      } else {
+        MKEmitter.emit('reloadData', btn.syncComponentId)
+      }
+    }
 
     if (tabId) {
       MKEmitter.emit('reloadMenuView', tabId, 'table')
@@ -2099,7 +2115,18 @@
       this.sendMessage(btn.verify, id)
     }
     if (btn.verify.wxNote === 'true') {
-      this.sendWxMessage(btn.verify, id)
+      if (btn.verify.wxTemplateId === 'mk_category_temp') {
+        let verify = fromJS(btn.verify).toJS()
+        verify.wxTemplateId = verify.wxCustomTempId
+
+        verify.wxNoteKeys = verify.wxNoteKeys.filter(item => item.key)
+
+        if (!verify.wxTemplateId || verify.wxNoteKeys.length === 0) return
+
+        this.sendWxMessage(verify, id)
+      } else {
+        this.sendWxMessage(btn.verify, id)
+      }
     }
   }
 
@@ -2122,8 +2149,15 @@
     param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     param.secretkey = Utils.encrypt(param.LText, param.timestamp)
 
+    let domain1 = ''
+    let domain2 = ''
+    if (['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok'].includes(verify.wxTemplateId) && options.sysType !== 'cloud') {
+      domain1 = 'https://cloud.mk9h.cn/'
+      domain2 = 'https://cloud.mk9h.cn:8443/'
+    }
+
     Api.genericInterface(param).then(res => {
-      // res.data = [{openid: 'o2E7gvoSFvQRG7I8_gZxf4y3ONkQ', send_id: '2223333', first: '鎮ㄧ殑缂磋垂淇℃伅濡備笅', keyword1: '010000000001', keyword2: '2022骞�07鏈�03鏃�', keyword3: '渚涙殩缂磋垂', keyword4: '20鍏�', keyword5: '鎴愬姛', remark: '鎰熻阿鎮ㄧ殑浣跨敤锛�'}]
+      // res.send_data = [{openid: 'o2E7gvoSFvQRG7I8_gZxf4y3ONkQ', send_id: Utils.getuuid(), p1: '010000000001', p2: '鏄庣', p3: 'dddd', p4: '椤洪', p5: '鎴愬姛'}]
       if (!res.status) {
         notification.warning({
           top: 92,
@@ -2131,7 +2165,12 @@
           duration: 5
         })
         return
-      } else if (!res.send_data || res.send_data.length === 0) {
+      }
+
+      let sends = res.send_data || []
+      sends = sends.filter(item => !!item.openid)
+
+      if (sends.length === 0) {
         return
       }
 
@@ -2155,13 +2194,13 @@
       }
       
       verify.wxNoteKeys.forEach(item => {
-        _param.data[item.key] = {value: '', color: item.color}
+        _param.data[item.key] = {value: ''}
       })
 
-      let params = res.send_data.map(item => {
+      let params = sends.map(item => {
         let m = fromJS(_param).toJS()
 
-        m.touser = item.openid || ''
+        m.touser = item.openid
         if (item.bid && m.miniprogram && m.miniprogram.pagepath.indexOf('MenuId') > -1) {
           m.miniprogram.pagepath = m.miniprogram.pagepath + `&BID=${item.bid}`
         }
@@ -2179,21 +2218,25 @@
         return m
       })
 
-      Api.wxAccessToken().then(res => {
+      Api.wxAccessToken(domain1).then(res => {
         if (!res.oa_access_token) return
   
         params.forEach(n => {
-          if (!n.touser) return
-
-          Api.wxNginxRequest(`cgi-bin/message/template/send?access_token=${res.oa_access_token}`, 'post', n).then(re => {
+          Api.wxNginxRequest(`${domain2}cgi-bin/message/template/send?access_token=${res.oa_access_token}`, 'post', n).then(re => {
             if (verify.wxNoteCallback === 'true') {
+              let msg = re.errmsg || ''
+
+              if (msg.length > 50) {
+                msg = msg.substr(0, 50)
+              }
+
               let _p = {
                 func: 's_get_sms_weixin_local_suc_err',
                 upid: id,
                 send_id: n.client_msg_id || '',
                 status_result: re.errcode === 0 ? 'S' : 'E',
                 errcode: re.errcode,
-                msg_result: re.errmsg
+                msg_result: msg
               }
 
               _p.LText = Utils.formatOptions(Utils.getuuid())
@@ -2350,12 +2393,13 @@
    * 2銆乪xcel瀵煎嚭锛屽け璐ュ悗鍙栨秷瀵煎嚭鎸夐挳鍔犺浇涓姸鎬�
    * 3銆侀�氱煡涓诲垪琛ㄥ埛鏂�
    */
-  execError = (res) => {
+  execError = (res = {}) => {
     const { btn } = this.props
     const { btnconfig, autoMatic } = this.state
 
-    if (res.message && /^@speak@/.test(res.message)) {
-      res.message = res.message.replace('@speak@', '')
+    let sign = ''
+    if (/^@speak@/i.test(res.message)) {
+      res.message = res.message.replace(/^@speak@/i, '')
       let val = res.message.match(/<<.*>>/)
       res.message = res.message.replace(/\s*<<.*>>\s*/g, '')
       val = val ? val[0].replace(/<<|>>/g, '') : ''
@@ -2369,6 +2413,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 === 'E' && !autoMatic) {
@@ -2416,13 +2463,29 @@
       MKEmitter.emit('mkFC', 'focus', btnconfig.setting.errFocus)
     }
 
-    if (btn.execError === 'closepoptab') {
+    if (sign === '@close_tab@') {
+      MKEmitter.emit('closeTabView', btn.$MenuID)
+    } else if (btn.execError === 'closepoptab' || sign === '@close_popup@') {
       MKEmitter.emit('popclose')
     } else if (btn.execError !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', this.state.selines)
-    } else if (btn.OpenType === 'form' && btn.formType !== 'counter') {
+    }
+    if (btn.OpenType === 'form') {
       let data = this.props.selectedData && this.props.selectedData[0] ? this.props.selectedData[0] : null
-      this.setState({check: data && data[btn.field] === btn.openVal})
+
+      if (btn.formType === 'counter') {
+        let count = 0
+        if (data && data[btn.field]) {
+          count = +data[btn.field]
+          if (isNaN(count)) {
+            count = 0
+          }
+        }
+
+        this.setState({count: count })
+      } else {
+        this.setState({check: data && data[btn.field] === btn.openVal})
+      }
     }
 
     if (window.GLOB.breakpoint) {
@@ -2576,49 +2639,51 @@
 
     btnconfig.fields.forEach(item => {
       if (!item.field) return
+      
       let _item = {
         key: item.field,
         readin: item.readin !== 'false' && item.readin !== 'top',
         fieldlen: item.fieldlength || 50,
         writein: item.writein !== 'false',
-        type: item.type
-      }
-
-      let _initval = item.initval
-      let _readin = item.readin !== 'false'
-      let _format = item.precision || 'day' // 鏃堕棿鏍煎紡鍖�
-
-      if (item.type === 'funcvar') {
-        _initval = ''
-        _readin = false
-        _item.readin = false
-      } else if (item.type === 'linkMain') {
-        _readin = false
-        _item.readin = false
-      } else if (item.type === 'date') {
-        if (_format !== 'day') {
-          _format = 'YYYY-MM-DD HH:mm:ss'
-        } else {
-          _format = 'YYYY-MM-DD'
-        }
-      } else if (item.type === 'datetime') {
-        _item.type = 'date'
-        _format = 'YYYY-MM-DD HH:mm:ss'
+        type: item.type,
+        value: item.initval,
+        isconst: item.constant === 'true'
       }
 
       let key = item.field.toLowerCase()
+      let _readin = item.readin !== 'false'
 
-      if (_item.type === 'linkMain' && BData.hasOwnProperty(key)) {
-        _initval = BData[key]
-      } else if (_readin && _data.hasOwnProperty(key)) {
-        _initval = _data[key]
-      } else if (_item.type === 'date' && _initval) {
-        _initval = moment().subtract(_initval, 'days').format(_format)
-      } else if (_item.type === 'datemonth' && _initval) {
-        _initval = moment().subtract(_initval, 'month').format('YYYY-MM')
+      if (_item.type === 'date') { // 鏃堕棿鍏煎
+        _item.precision = item.precision || 'day'
+      } else if (_item.type === 'datetime') {
+        _item.type = 'date'
+        _item.precision = 'second'
+      } else if (['funcvar', 'linkMain'].includes(_item.type)) {
+        _readin = false
+        _item.readin = false
+      } else if (['select', 'link', 'radio'].includes(_item.type)) { // 閫変腑绗竴椤�
+        if (/^\s*\$first\s*$/.test(_item.value)) {
+          _item.value = ''
+
+          if (item.resourceType === '0' && item.options[0] && item.options[0].Value) {
+            _item.value = item.options[0].Value
+          }
+        }
       }
 
-      _item.value = _initval === undefined ? '' : _initval
+      if (_item.type === 'funcvar') {
+        _item.value = ''
+      } else if (_item.type === 'linkMain' && BData.hasOwnProperty(key)) {
+        _item.value = BData[key]
+      } else if (_readin && _data.hasOwnProperty(key)) {
+        _item.value = _data[key]
+      } else if (_item.type === 'date' && _item.value) {
+        _item.value = moment().subtract(_item.value, 'days').format(_item.precision === 'day' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss')
+      } else if (_item.type === 'datemonth' && _item.value) {
+        _item.value = moment().subtract(_item.value, 'month').format('YYYY-MM')
+      }
+
+      _item.value = _item.value === undefined ? '' : _item.value
 
       if (_item.type === 'number' || item.declare === 'decimal') {
         _item.type = 'number'
@@ -2640,9 +2705,19 @@
             _item.value = _item.value.slice(-item.fieldlength)
           }
         }
-      } else if (_item.type.indexOf('date') > -1) {
-        if (item.declareType === 'nvarchar(50)') {
-          _item.type = 'text'
+      } else if (_item.type === 'datemonth') {
+        _item.type = 'text'
+      } else  if (_item.type === 'date') {
+        _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
+      } else if (_item.type === 'switch' || _item.type === 'check') {
+        if (_readin) {
+          _item.value = _item.value === item.openVal ? item.openVal : item.closeVal
+        } else {
+          if (item.initval === true) {
+            _item.value = item.openVal
+          } else {
+            _item.value = item.closeVal
+          }
         }
       } else if (_item.type === 'rate') {
         let count = item.rateCount || 5
diff --git a/src/tabviews/zshare/actionList/popupbutton/index.jsx b/src/tabviews/zshare/actionList/popupbutton/index.jsx
index c07cf91..f61eadf 100644
--- a/src/tabviews/zshare/actionList/popupbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/popupbutton/index.jsx
@@ -84,7 +84,7 @@
       if (data.length > 0) {
         data.forEach(item => {
           let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
-          if (btn.controlVals.includes(s)) {
+          if (btn.controlVals.includes(s) || item.$lock) {
             disabled = true
           }
         })
@@ -222,7 +222,17 @@
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn)
     }
 
-    btn.syncComponentId && MKEmitter.emit('reloadData', btn.syncComponentId)
+    if (btn.syncComponentId) {
+      if (btn.syncComponentId === 'multiComponent') {
+        btn.syncComponentIds.forEach((id, i) => {
+          setTimeout(() => {
+            MKEmitter.emit('reloadData', id)
+          }, 20 * i)
+        })
+      } else {
+        MKEmitter.emit('reloadData', btn.syncComponentId)
+      }
+    }
   }
 
   getPop = () => {
diff --git a/src/tabviews/zshare/actionList/printbutton/index.jsx b/src/tabviews/zshare/actionList/printbutton/index.jsx
index c8302d8..2bbfe85 100644
--- a/src/tabviews/zshare/actionList/printbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -94,7 +94,7 @@
       if (data.length > 0) {
         data.forEach(item => {
           let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
-          if (btn.controlVals.includes(s)) {
+          if (btn.controlVals.includes(s) || item.$lock) {
             disabled = true
           }
         })
@@ -1183,6 +1183,7 @@
   printOuterLoopRequest = (params, btn, _list, _resolve) => {
     let param = params.shift()
     let _outParam = null
+    let ver_token = false
 
     new Promise(resolve => {
       // 鍐呴儴璇锋眰
@@ -1240,6 +1241,7 @@
           } else {
             res.$token = btn.exInterface || ''
           }
+          ver_token = true
         } else {
           if (window.GLOB.systemType === 'production' && btn.proInterface) {
             res.rduri = btn.proInterface
@@ -1262,7 +1264,10 @@
     }).then(response => {
       if (!response) return
 
-      if (btn.callbackFunc) {
+      if (ver_token && response.ErrMesg === 'token_error') {
+        this.execError(response)
+        _resolve({next: false, list: []})
+      } else if (btn.callbackFunc) {
         // 瀛樺湪鍥炶皟鍑芥暟鏃讹紝璋冪敤
         delete response.message
         delete response.status
@@ -1967,7 +1972,7 @@
   actionSettingError = () => {
     notification.warning({
       top: 92,
-      message: this.state.dict['main.action.settingerror'],
+      message: '鎸夐挳璁剧疆閿欒锛�',
       duration: 5
     })
   }
@@ -2115,62 +2120,98 @@
     
     btnconfig.fields.forEach(item => {
       if (!item.field) return
-      let _readin = item.readin !== 'false'
-      let _initval = item.initval
 
-      if (item.type === 'linkMain' || item.type === 'funcvar') {
-        _readin = false
-      }
-
-      if (item.type === 'linkMain' && BData.hasOwnProperty(item.field.toLowerCase())) {
-        _initval = BData[item.field.toLowerCase()]
-      } else if (_readin && _data.hasOwnProperty(item.field.toLowerCase())) {
-        _initval = _data[item.field.toLowerCase()]
-      } else if (item.type === 'date' && _initval) {
-        _initval = moment().subtract(_initval, 'days').format('YYYY-MM-DD')
-      } else if (item.type === 'datemonth' && _initval) {
-        _initval = moment().subtract(_initval, 'month').format('YYYY-MM')
-      } else if (item.type === 'datetime' && _initval) {
-        _initval = moment().subtract(_initval, 'days').format('YYYY-MM-DD HH:mm:ss')
-      }
-
-      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
-      } else if (item.type === 'rate') {
-        item.rateCount = item.rateCount || 5
-        let allowHalf = item.allowHalf === 'true'
-
-        if (allowHalf) {
-          _initval = parseFloat(_initval)
-          if (_initval % 0.5 !== 0) {
-            _initval = parseInt(_initval)
-          }
-        } else {
-          _initval = parseInt(_initval)
-        }
-
-        if (isNaN(_initval) || _initval < 0) {
-          _initval = 0
-        } else if (_initval > item.rateCount) {
-          _initval = item.rateCount
-        }
-      }
-
-      if (_initval === undefined) {
-        _initval = ''
-      }
-
-      result.push({
+      let _item = {
         key: item.field,
-        readonly: item.readonly === 'true',
         readin: item.readin !== 'false' && item.readin !== 'top',
-        fieldlen: _fieldlen,
+        fieldlen: item.fieldlength || 50,
+        writein: item.writein !== 'false',
         type: item.type,
-        value: _initval
-      })
+        value: item.initval,
+        isconst: item.constant === 'true'
+      }
+
+      let key = item.field.toLowerCase()
+      let _readin = item.readin !== 'false'
+
+      if (_item.type === 'date') { // 鏃堕棿鍏煎
+        _item.precision = item.precision || 'day'
+      } else if (_item.type === 'datetime') {
+        _item.type = 'date'
+        _item.precision = 'second'
+      } else if (['funcvar', 'linkMain'].includes(_item.type)) {
+        _readin = false
+        _item.readin = false
+      } else if (['select', 'link', 'radio'].includes(_item.type)) { // 閫変腑绗竴椤�
+        if (/^\s*\$first\s*$/.test(_item.value)) {
+          _item.value = ''
+
+          if (item.resourceType === '0' && item.options[0] && item.options[0].Value) {
+            _item.value = item.options[0].Value
+          }
+        }
+      }
+
+      if (_item.type === 'funcvar') {
+        _item.value = ''
+      } else if (_item.type === 'linkMain' && BData.hasOwnProperty(key)) {
+        _item.value = BData[key]
+      } else if (_readin && _data.hasOwnProperty(key)) {
+        _item.value = _data[key]
+      } else if (_item.type === 'date' && _item.value) {
+        _item.value = moment().subtract(_item.value, 'days').format(_item.precision === 'day' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss')
+      } else if (_item.type === 'datemonth' && _item.value) {
+        _item.value = moment().subtract(_item.value, 'month').format('YYYY-MM')
+      }
+
+      _item.value = _item.value === undefined ? '' : _item.value
+
+      if (_item.type === 'number' || item.declare === 'decimal') {
+        _item.type = 'number'
+        _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, '')       // 鍘婚櫎鍒惰〃绗�
+
+        if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
+          _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+        }
+        if (_item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 鐗规畩瀛楁鏇挎崲
+          _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
+        }
+        if (_item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
+          if (item.lenControl === 'left') {
+            _item.value = _item.value.substr(0, item.fieldlength)
+          } else {
+            _item.value = _item.value.slice(-item.fieldlength)
+          }
+        }
+      } else if (_item.type === 'datemonth') {
+        _item.type = 'text'
+      } else  if (_item.type === 'date') {
+        _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
+      } else if (_item.type === 'switch' || _item.type === 'check') {
+        if (_readin) {
+          _item.value = _item.value === item.openVal ? item.openVal : item.closeVal
+        } else {
+          if (item.initval === true) {
+            _item.value = item.openVal
+          } else {
+            _item.value = item.closeVal
+          }
+        }
+      } else if (_item.type === 'rate') {
+        let count = item.rateCount || 5
+        _item.value = parseInt(_item.value)
+
+        if (isNaN(_item.value) || _item.value < 0) {
+          _item.value = 0
+        } else if (_item.value > count) {
+          _item.value = count
+        }
+      }
+
+      result.push(_item)
     })
 
     if (btnconfig.setting.display === 'exec') {
diff --git a/src/tabviews/zshare/actionList/tabbutton/index.jsx b/src/tabviews/zshare/actionList/tabbutton/index.jsx
index fbdfe15..9a7662a 100644
--- a/src/tabviews/zshare/actionList/tabbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -69,7 +69,7 @@
       if (data.length > 0) {
         data.forEach(item => {
           let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
-          if (btn.controlVals.includes(s)) {
+          if (btn.controlVals.includes(s) || item.$lock) {
             disabled = true
           }
         })
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index a1ea659..067bfd2 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -19,6 +19,7 @@
 
 const MKCheckCard = asyncComponent(() => import('./mkCheckCard'))
 const MKSwitch = asyncComponent(() => import('./mkSwitch'))
+const MKCheck = asyncComponent(() => import('./mkCheck'))
 const MKCheckbox = asyncComponent(() => import('./mkCheckbox'))
 const MKRadio = asyncComponent(() => import('./mkRadio'))
 const MKDatePicker = asyncComponent(() => import('./mkDatePicker'))
@@ -117,18 +118,20 @@
         }
         delete item.field
         return true
-      } else if (item.type === 'date') { // 鏃堕棿鎼滅储
+      } else if (item.type === 'date') {
         item.precision = item.precision || 'day'
       } else if (item.type === 'datetime') {
         item.type = 'date'
         item.precision = 'second'
       }
 
-      if (!item.field || !['text', 'number', 'switch', 'rate', 'select', 'link', 'cascader', 'linkMain', 'funcvar', 'date', 'datemonth', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color', 'vercode'].includes(item.type)) return false
+      if (!item.field || !['text', 'number', 'switch', 'check', 'rate', 'select', 'link', 'cascader', 'linkMain', 'funcvar', 'date', 'datemonth', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color', 'vercode'].includes(item.type)) return false
 
       if (/^\s+$/.test(item.label)) {
         item.style = item.style || {}
-        item.style.color = 'transparent'
+        item.style.opacity = 0
+        item.style.width = 1
+        item.style.display = 'inline-block'
       }
 
       // 鏁版嵁鑷姩濉厖
@@ -175,6 +178,19 @@
         if (item.empty === 'hidden' && item.oriOptions.length === 0) {
           item.hidden = true
         }
+        if (item.type === 'checkcard' && item.readonly && item.unchecked === 'hidden') {
+          let selectKeys = item.initval
+          if (item.multiple === 'true') {
+            selectKeys = selectKeys ? selectKeys.split(',') : []
+            item.options = item.options.filter(item => selectKeys.includes(item.$value))
+          } else {
+            item.options = item.options.filter(item => selectKeys === item.$value)
+          }
+          item.oriOptions = fromJS(item.options).toJS()
+          if (item.options.length === 0) {
+            item.hidden = true
+          }
+        }
       }
 
       let newval = '$empty'
@@ -205,7 +221,7 @@
         if (newval === '$empty' && item.initval) {
           newval = moment().subtract(item.initval, 'month').format('YYYY-MM')
         }
-      } else if (item.type === 'switch') { // 寮�鍏冲彧鎺ユ敹鍥哄畾鍊�
+      } else if (item.type === 'switch' || item.type === 'check') { // 寮�鍏冲嬀閫夋鍙帴鏀跺浐瀹氬��
         if (newval !== '$empty' && (newval === item.closeVal || newval === item.openVal)) {
 
         } else if (item.initval === true) {
@@ -397,10 +413,13 @@
 
         let cell = fieldMap.get(item.field)
 
-        if (cell.hidden) return
-
+        // if (cell.hidden) return
+        
         if (supItem.hidden || !item.values.includes(supItem.initval)) {
           cell.hidden = true
+          if (cell.empty === 'hidden') {
+            cell.$hidden = true
+          }
           fieldMap.set(item.field, cell)
         }
 
@@ -464,7 +483,7 @@
       }
 
       if (['select', 'link', 'radio'].includes(item.type)) { // 閫変腑绗竴椤�
-        if (typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) {
+        if (/^\s*\$first\s*$/.test(item.initval)) {
           item.$first = true
           item.initval = ''
         }
@@ -527,9 +546,17 @@
       if (unload) return
       
       if (action.setting && action.setting.focus && fieldMap.has(action.setting.focus)) {
-        setTimeout(() => {
-          MKEmitter.emit('mkFC', 'focus', fieldMap.get(action.setting.focus).uuid)
-        }, 500)
+        let focusItem = fieldMap.get(action.setting.focus)
+
+        if (focusItem.type === 'text' || focusItem.type === 'number') {
+          setTimeout(() => {
+            MKEmitter.emit('mkFC', 'focus', focusItem.uuid)
+          }, 50)
+        } else {
+          setTimeout(() => {
+            MKEmitter.emit('mkFC', 'focus', focusItem.uuid)
+          }, 500)
+        }
       }
 
       if (deForms.length > 0) {
@@ -568,6 +595,9 @@
         if (debug) {
           console.info(sql)
         }
+
+        sql = sql.replace(/%/ig, ' mpercent ')
+        
         mainItems.push(`select '${item.field}' as obj_name,'${item.arr_field}' as arr_field,'${window.btoa(window.encodeURIComponent(sql))}' as LText`)
       } else {
         let sql = _sql + item.base_sql
@@ -579,6 +609,9 @@
         if (debug) {
           console.info(sql)
         }
+
+        sql = sql.replace(/%/ig, ' mpercent ')
+
         localItems.push(`select '${item.field}' as obj_name,'${item.arr_field}' as arr_field,'${window.btoa(window.encodeURIComponent(sql))}' as LText`)
       }
     })
@@ -821,8 +854,23 @@
           }
         }
 
-        if (item.empty === 'hidden' && item.oriOptions.length > 0) {
+        if (item.empty === 'hidden' && item.oriOptions.length > 0 && !item.$hidden) {
           item.hidden = false
+        }
+        if (item.type === 'checkcard' && item.readonly && item.unchecked === 'hidden') {
+          let selectKeys = item.initval
+          if (item.multiple === 'true') {
+            selectKeys = selectKeys ? selectKeys.split(',') : []
+            item.options = item.options.filter(item => selectKeys.includes(item.$value))
+          } else {
+            item.options = item.options.filter(item => selectKeys === item.$value)
+          }
+          item.oriOptions = fromJS(item.options).toJS()
+          if (item.options.length === 0) {
+            item.hidden = true
+          } else {
+            item.hidden = false
+          }
         }
       }
       
@@ -882,6 +930,10 @@
       current.controlFields.forEach(cell => {
         let m = map.get(cell.field)
         m.hidden = current.hidden || !cell.values.includes(val)
+
+        if (m.empty === 'hidden' && m.oriOptions.length === 0) {
+          m.hidden = true
+        }
 
         if (m.hidden) {
           m.initval = this.record[m.field]
@@ -960,6 +1012,8 @@
           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)}/>)
+        } else if (item.type === 'check') {
+          content = (<MKCheck config={item} onChange={(val) => this.recordChange({[item.field]: val}, item)}/>)
         } else if (item.type === 'checkbox') {
           content = (<MKCheckbox config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
         } else if (item.type === 'radio') {
@@ -1027,7 +1081,8 @@
             readin: item.readin,
             writein: item.writein,
             fieldlen: item.fieldlength,
-            key: item.field
+            key: item.field,
+            isconst: item.constant === 'true'
           }
     
           _item.value = record[item.field] !== undefined ? record[item.field] : ''
@@ -1054,10 +1109,10 @@
                 _item.value = _item.value.slice(-item.fieldlength)
               }
             }
-          } else if (item.type.indexOf('date') > -1) {
-            if (item.declareType === 'nvarchar(50)') {
-              _item.type = 'text'
-            }
+          } else if (item.type === 'datemonth') {
+            _item.type = 'text'
+          } else  if (item.type === 'date') {
+            _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
           } else if (item.type === 'vercode') {
             _item.type = 'text'
             forms.push({
diff --git a/src/tabviews/zshare/mutilform/mkCheck/index.jsx b/src/tabviews/zshare/mutilform/mkCheck/index.jsx
new file mode 100644
index 0000000..aea3f25
--- /dev/null
+++ b/src/tabviews/zshare/mutilform/mkCheck/index.jsx
@@ -0,0 +1,41 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Checkbox } from 'antd'
+
+class MKCheck extends Component {
+  static propTpyes = {
+    config: PropTypes.object,
+    onChange: PropTypes.func
+  }
+
+  state = {
+    defaultChecked: this.props.config.initval === this.props.config.openVal
+  }
+
+  onChange = (e) => {
+    const { config } = this.props
+
+    if (e.target.checked) {
+      this.props.onChange(config.openVal)
+    } else {
+      this.props.onChange(config.closeVal)
+    }
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { config } = this.props
+    const { defaultChecked } = this.state
+
+    return (
+      <Checkbox disabled={config.readonly} defaultChecked={defaultChecked} onChange={this.onChange}>{config.checkTip}</Checkbox>
+    )
+  }
+}
+
+export default MKCheck
\ No newline at end of file
diff --git a/src/tabviews/zshare/mutilform/mkCheck/index.scss b/src/tabviews/zshare/mutilform/mkCheck/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tabviews/zshare/mutilform/mkCheck/index.scss
diff --git a/src/tabviews/zshare/mutilform/mkVercode/index.jsx b/src/tabviews/zshare/mutilform/mkVercode/index.jsx
index ae8fb99..dfa614b 100644
--- a/src/tabviews/zshare/mutilform/mkVercode/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkVercode/index.jsx
@@ -77,7 +77,7 @@
     let n_id = (() => {
       let uuid = []
       let timestamp = new Date().getTime()
-      let _options = '0123456789abcdefghigklmnopqrstuv'
+      let _options = '01234567890123456789012345678901'
       for (let i = 0; i < 19; i++) {
         uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
       }
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index e08b2cb..2f6d9ab 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -42,7 +42,6 @@
     tableId: PropTypes.string,       // 鍒楄〃Id
     statFValue: PropTypes.any,       // 鍚堣瀛楁鏁版嵁
     pageSize: PropTypes.any,         // 姣忛〉鏁版嵁
-    dict: PropTypes.object,          // 瀛楀吀椤�
     MenuID: PropTypes.string,        // 鑿滃崟Id
     setting: PropTypes.object,       // 琛ㄦ牸鍏ㄥ眬璁剧疆锛歵ableType锛堣〃鏍兼槸鍚﹀彲閫夈�佸崟閫夈�佸閫夛級銆乧olumnfixed锛堝垪鍥哄畾锛夈�乤ctionfixed锛堟寜閽浐瀹氾級
     pickup: PropTypes.any,           // 鏁版嵁鏀惰捣
@@ -1251,7 +1250,7 @@
         pageSizeOptions: pageOptions,
         showSizeChanger: true,
         total: this.props.total || 0,
-        showTotal: (total, range) => `${range[0]}-${range[1]} ${this.props.dict['main.pagination.of']} ${total} ${this.props.dict['main.pagination.items']}`
+        showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
       }
     }
 
diff --git a/src/tabviews/zshare/normalTable/index.scss b/src/tabviews/zshare/normalTable/index.scss
index 931fee4..75c4770 100644
--- a/src/tabviews/zshare/normalTable/index.scss
+++ b/src/tabviews/zshare/normalTable/index.scss
@@ -232,11 +232,6 @@
       display: block;
     }
   }
-  // table tbody {
-  //   tr:nth-child(even) {
-  //     background: #f9f9f9;
-  //   }
-  // }
 }
 .image-scale-modal {
   width: 70vw;
diff --git a/src/tabviews/zshare/pageMessage/index.jsx b/src/tabviews/zshare/pageMessage/index.jsx
index 60db458..4ca2a3b 100644
--- a/src/tabviews/zshare/pageMessage/index.jsx
+++ b/src/tabviews/zshare/pageMessage/index.jsx
@@ -15,7 +15,6 @@
 class PageMessage extends Component {
   static propTpyes = {
     BID: PropTypes.any,          // 鐖剁骇Id锛岀敤浜庢煡璇笅鎷夐�夋嫨椤�
-    dict: PropTypes.object,      // 瀛楀吀
   }
 
   state = {
@@ -314,7 +313,7 @@
 
 
   render() {
-    const { menu, dict } = this.props
+    const { menu } = this.props
     const { debug, visible, data } = this.state
 
     return (
@@ -333,7 +332,7 @@
           visible={visible}
           onCancel={() => this.setState({visible: false})}
           footer={[
-            <Button key="close" onClick={() => this.setState({visible: false})}>{dict['main.close']}</Button>
+            <Button key="close" onClick={() => this.setState({visible: false})}>鍏抽棴</Button>
           ]}
           destroyOnClose
         >
diff --git a/src/tabviews/zshare/settingcomponent/index.jsx b/src/tabviews/zshare/settingcomponent/index.jsx
index 2f137ee..c3c366a 100644
--- a/src/tabviews/zshare/settingcomponent/index.jsx
+++ b/src/tabviews/zshare/settingcomponent/index.jsx
@@ -14,7 +14,6 @@
 
 class CustomSetting extends Component {
   static propTpyes = {
-    dict: PropTypes.object,           // 瀛楀吀琛�
     config: PropTypes.object,         // 椤甸潰閰嶇疆淇℃伅
     shortcuts: PropTypes.any,         // 鑷畾涔夎缃�
   }
@@ -144,29 +143,36 @@
             })
           })
         } else if (item.type === 'table') {
-          item.cols && item.cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements && col.elements.forEach(cell => {
-              cell.$expanded = false
-              if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType !== 'button') return
+                  cell.$expanded = false
+                  if (cell.OpenType === 'funcbutton' && cell.funcType === 'print') {
 
-                cell.$port = cell.verify ? cell.verify.linkUrl : ''
-                if (cell.verify && cell.verify.printerTypeList && cell.verify.printerTypeList.length > 0) {
-                  cell.verify.printerTypeList = cell.verify.printerTypeList.map(_cell => {
-                    _cell.uuid = _cell.uuid || _cell.key
-                    _cell.parentId = cell.uuid
-                    _cell.$port = cell.$port
+                    cell.$port = cell.verify ? cell.verify.linkUrl : ''
+                    if (cell.verify && cell.verify.printerTypeList && cell.verify.printerTypeList.length > 0) {
+                      cell.verify.printerTypeList = cell.verify.printerTypeList.map(_cell => {
+                        _cell.uuid = _cell.uuid || _cell.key
+                        _cell.parentId = cell.uuid
+                        _cell.$port = cell.$port
 
-                    return _cell
-                  })
-                  cell.$expanded = true
-                }
-                printbtns.push(cell)
+                        return _cell
+                      })
+                      cell.$expanded = true
+                    }
+                    printbtns.push(cell)
+                  }
+
+                  _comp.action.push({...cell, $line: true, ...(userConfig[cell.uuid] || {})})
+                })
               }
-
-              _comp.action.push({...cell, $line: true, ...(userConfig[cell.uuid] || {})})
             })
-          })
+          }
+          loopCol(item.cols)
         } 
         
         if (_comp.action.length > 0) {
@@ -525,9 +531,9 @@
           visible={visible}
           onCancel={() => { this.setState({ visible: false }) }}
           footer={[
-            <Button key="revert" type="danger" loading={this.state.revertLoading} onClick={this.settingRevert}>{this.props.dict['main.revert.default']}</Button>,
-            <Button key="cancel" onClick={() => { this.setState({ visible: false }) }}>{this.props.dict['main.cancel']}</Button>,
-            <Button key="confirm" type="primary" loading={this.state.confirmLoading} onClick={this.settingSubmit}>{this.props.dict['main.submit']}</Button>
+            <Button key="revert" type="danger" loading={this.state.revertLoading} onClick={this.settingRevert}>鎭㈠榛樿璁剧疆</Button>,
+            <Button key="cancel" onClick={() => { this.setState({ visible: false }) }}>鍙栨秷</Button>,
+            <Button key="confirm" type="primary" loading={this.state.confirmLoading} onClick={this.settingSubmit}>鎻愪氦</Button>
           ]}
           destroyOnClose
         >
diff --git a/src/tabviews/zshare/topSearch/index.jsx b/src/tabviews/zshare/topSearch/index.jsx
index 8f1b7d4..2ee1aaa 100644
--- a/src/tabviews/zshare/topSearch/index.jsx
+++ b/src/tabviews/zshare/topSearch/index.jsx
@@ -16,6 +16,8 @@
 
 const MutilForm = asyncSpinComponent(() => import('./advanceform'))
 const MKCheckCard = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkCheckCard'))
+const MKCheck = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkCheck'))
+const MKSwitch = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkSwitch'))
 const MKSelect = asyncComponent(() => import('./mkSelect'))
 const DateGroup = asyncComponent(() => import('./dategroup'))
 const MKDatePicker = asyncComponent(() => import('./mkDatePicker'))
@@ -189,9 +191,9 @@
             })
           } else { // 鍚堝苟璇锋眰锛屽尯鍒嗘湰鍦板強绯荤粺
             if (item.database === 'sso') {
-              mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql))}' as LText`)
+              mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
             } else {
-              localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql))}' as LText`)
+              localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
             }
           }
         }
@@ -532,6 +534,10 @@
         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 === 'check') {
+        content = <MKCheck config={item} onChange={(val) => this.recordChange(val, false, item)} />
+      } else if (item.type === 'switch') {
+        content = <MKSwitch config={item} onChange={(val) => this.recordChange(val, false, item)} />
       }
 
       if (content) {
@@ -836,7 +842,7 @@
 
     return (
       <>
-        <Form {...formItemLayout} className={`top-search mk-float-${setting.float}`} style={setting.style}>
+        <Form {...formItemLayout} className={`mk-search-wrap mk-float-${setting.float}`} style={setting.style}>
           <Row gutter={24}>{this.getFields()}</Row>
           {advanceValues.length && (setting.advanceType !== 'pulldown' || (setting.advanceType === 'pulldown' && !visible)) ? <Row gutter={24}>
             <div className="advanced-list">
diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss
index 1d7e1bc..6ac744d 100644
--- a/src/tabviews/zshare/topSearch/index.scss
+++ b/src/tabviews/zshare/topSearch/index.scss
@@ -1,4 +1,4 @@
-.top-search {
+.mk-search-wrap {
   background: #ffffff;
 
   .mk-search-col {
@@ -114,7 +114,7 @@
     margin-top: 3px;
   }
 }
-.top-search.mk-float-right {
+.mk-search-wrap.mk-float-right {
   >.ant-row {
     text-align: right;
   }
diff --git a/src/templates/calendarconfig/index.jsx b/src/templates/calendarconfig/index.jsx
index 2bb9117..34f957a 100644
--- a/src/templates/calendarconfig/index.jsx
+++ b/src/templates/calendarconfig/index.jsx
@@ -8,7 +8,6 @@
 import moment from 'moment'
 
 import Api from '@/api'
-import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -399,8 +398,6 @@
       // }
       resolve()
     }).then(() => {
-      let reload = _config.isAdd
-
       // 淇濆瓨鏃跺垹闄ら厤缃被鍨嬶紝system 銆乽ser
       delete _config.type
       delete _config.isAdd
@@ -481,8 +478,6 @@
             originMenu: fromJS(_config).toJS(),
             menuloading: false,
             menucloseloading: false
-          }, () => {
-            reload && MKEmitter.emit('revert')
           })
 
           this.props.reloadmenu()
diff --git a/src/templates/calendarconfig/source.jsx b/src/templates/calendarconfig/source.jsx
index 8e500d9..9638d63 100644
--- a/src/templates/calendarconfig/source.jsx
+++ b/src/templates/calendarconfig/source.jsx
@@ -31,42 +31,7 @@
       remarkfield: '',
       refresh: 'false'
     },
-    search: [
-      {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'text',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: 'like',
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'select',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: '=',
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'date',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: 'greater',
-      }
-    ]
+    search: []
   }
 
   searchItems = [
diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx
index 62ac181..e55643e 100644
--- a/src/templates/comtableconfig/index.jsx
+++ b/src/templates/comtableconfig/index.jsx
@@ -9,7 +9,6 @@
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-import MKEmitter from '@/utils/events.js'
 import { updateCommonTable } from '@/utils/utils-update.js'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -27,7 +26,7 @@
 
 const Versions = asyncComponent(() => import('@/menu/versions'))
 const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent'))
-const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
+// const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
 const UpdateTable = asyncComponent(() => import('./updatetable'))
 const Unattended = asyncComponent(() => import('@/templates/zshare/unattended'))
 const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent'))
@@ -357,7 +356,6 @@
     }
 
     let _LongParam = ''
-    let reload = _config.isAdd
 
     // 淇濆瓨鏃跺垹闄ら厤缃被鍨嬶紝system 銆乽ser
     delete _config.type
@@ -561,8 +559,6 @@
               config: _config,
               openEdition: response.open_edition || '',
               originMenu: fromJS(_config).toJS()
-            }, () => {
-              reload && MKEmitter.emit('revert')
             })
 
             localParam.func = 'sPC_TrdMenu_AddUpt_For_Local'
@@ -1202,7 +1198,7 @@
               <div>
                 <Unattended config={config} updateConfig={this.updateconfig}/>
                 <Versions MenuId={menu.MenuID} open_edition={openEdition} updateConfig={this.refreshConfig}/>
-                <ReplaceField type="table" config={config} updateConfig={this.updateconfig}/>
+                {/* <ReplaceField type="table" config={config} updateConfig={this.updateconfig}/> */}
                 <EditComponent type="table" options={['search', 'form', 'action', 'columns']} config={this.state.config} refresh={this.editConfig}/>
                 <UpdateTable config={config}/>
                 <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={this.state.config.enabled} onChange={this.onEnabledChange} />
diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx
index 1b7d5de..f21ac4b 100644
--- a/src/templates/comtableconfig/source.jsx
+++ b/src/templates/comtableconfig/source.jsx
@@ -24,125 +24,125 @@
     },
     tables: [],
     search: [
-      {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'text',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: 'like',
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'select',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: '=',
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'date',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: 'greater',
-      }
+      // {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   label: 'label',
+      //   field: '',
+      //   initval: '',
+      //   type: 'text',
+      //   resourceType: '0',
+      //   options: [],
+      //   orderType: 'asc',
+      //   match: 'like',
+      // }, {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   label: 'label',
+      //   field: '',
+      //   initval: '',
+      //   type: 'select',
+      //   resourceType: '0',
+      //   options: [],
+      //   orderType: 'asc',
+      //   match: '=',
+      // }, {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   label: 'label',
+      //   field: '',
+      //   initval: '',
+      //   type: 'date',
+      //   resourceType: '0',
+      //   options: [],
+      //   orderType: 'asc',
+      //   match: 'greater',
+      // }
     ],
     action: [
-      {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'add',
-        intertype: 'system',
-        Ot: 'notRequired',
-        position: 'toolbar',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'pop',
-        icon: 'plus',
-        class: 'green',
-        verify: null
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'update',
-        intertype: 'system',
-        Ot: 'requiredSgl',
-        position: 'toolbar',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'pop',
-        icon: 'form',
-        class: 'purple',
-        verify: null
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'delete',
-        intertype: 'system',
-        Ot: 'required',
-        position: 'toolbar',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'prompt',
-        icon: 'delete',
-        class: 'red',
-        verify: null
-      }
+      // {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   label: 'add',
+      //   intertype: 'system',
+      //   Ot: 'notRequired',
+      //   position: 'toolbar',
+      //   execSuccess: 'grid',
+      //   execError: 'never',
+      //   OpenType: 'pop',
+      //   icon: 'plus',
+      //   class: 'green',
+      //   verify: null
+      // }, {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   label: 'update',
+      //   intertype: 'system',
+      //   Ot: 'requiredSgl',
+      //   position: 'toolbar',
+      //   execSuccess: 'grid',
+      //   execError: 'never',
+      //   OpenType: 'pop',
+      //   icon: 'form',
+      //   class: 'purple',
+      //   verify: null
+      // }, {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   label: 'delete',
+      //   intertype: 'system',
+      //   Ot: 'required',
+      //   position: 'toolbar',
+      //   execSuccess: 'grid',
+      //   execError: 'never',
+      //   OpenType: 'prompt',
+      //   icon: 'delete',
+      //   class: 'red',
+      //   verify: null
+      // }
     ],
     columns: [
-      {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }
+      // {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   Align: 'left',
+      //   label: 'label',
+      //   field: '',
+      //   Hide: 'false',
+      //   IsSort: 'true',
+      //   type: 'text',
+      //   Width: 120
+      // }, {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   Align: 'left',
+      //   label: 'label',
+      //   field: '',
+      //   Hide: 'false',
+      //   IsSort: 'true',
+      //   type: 'text',
+      //   Width: 120
+      // }, {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   Align: 'left',
+      //   label: 'label',
+      //   field: '',
+      //   Hide: 'false',
+      //   IsSort: 'true',
+      //   type: 'text',
+      //   Width: 120
+      // }, {
+      //   origin: true,
+      //   uuid: Utils.getuuid(),
+      //   Align: 'left',
+      //   label: 'label',
+      //   field: '',
+      //   Hide: 'false',
+      //   IsSort: 'true',
+      //   type: 'text',
+      //   Width: 120
+      // }
     ],
     gridBtn: {
       display: false,
diff --git a/src/templates/comtableconfig/updatetable/index.jsx b/src/templates/comtableconfig/updatetable/index.jsx
index ffe2380..e2a7d87 100644
--- a/src/templates/comtableconfig/updatetable/index.jsx
+++ b/src/templates/comtableconfig/updatetable/index.jsx
@@ -21,6 +21,7 @@
 
   state = {}
   delButtons = []
+  baseMsg = {}
 
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
@@ -52,8 +53,14 @@
   }
 
   execUpdate = (_resolve) => {
-    const { config } = this.props
+    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,
@@ -80,13 +87,14 @@
     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, popActions, oldtabs)
+    let tbl = this.getTable(config, mainTb, errors, formActions, formTabs, 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) {
@@ -183,7 +191,7 @@
         _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)
+              tab.components[0] = this.getTable(menus[tab.components[0].linkTab], tab.components[0], errors, formActions, formTabs, popActions, oldtabs)
 
               return tab
             })
@@ -191,14 +199,14 @@
           return item
         })
 
-        this.setPopView(_resolve, _config, formActions, popActions, errors)
+        this.setPopView(_resolve, _config, formActions, formTabs, popActions, errors)
       })
     } else {
-      this.setPopView(_resolve, _config, formActions, popActions, errors)
+      this.setPopView(_resolve, _config, formActions, formTabs, popActions, errors)
     }
   }
 
-  setPopView = (_resolve, _config, formActions, popActions, errors) => {
+  setPopView = (_resolve, _config, formActions, formTabs, popActions, errors) => {
     if (popActions.length > 0) {
       let defers = popActions.map((item, i) => {
         return new Promise((resolve) => {
@@ -256,22 +264,24 @@
                       uuid: btn.uuid,
                       MenuID: btn.uuid,
                       ParentId: tab.components[0].uuid,
-                      enabled: false,
                       MenuName: btn.label,
                       tables: _config.tables || [],
                       Template: 'BaseTable',
-                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
                       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 !== 'action') return
+                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'}
@@ -280,14 +290,15 @@
                         uuid: btn.uuid,
                         MenuID: btn.uuid,
                         ParentId: tab.components[0].uuid,
-                        enabled: false,
                         MenuName: btn.label,
                         tables: _config.tables || [],
                         Template: 'BaseTable',
-                        components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                        components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
                         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 + '銆嬮厤缃俊鎭涪澶�')
                     }
@@ -305,22 +316,24 @@
                     uuid: btn.uuid,
                     MenuID: btn.uuid,
                     ParentId: item.uuid,
-                    enabled: false,
                     MenuName: btn.label,
                     tables: _config.tables || [],
                     Template: 'BaseTable',
-                    components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                    components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
                     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 !== 'action') return
+              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'}
@@ -329,14 +342,15 @@
                       uuid: btn.uuid,
                       MenuID: btn.uuid,
                       ParentId: item.uuid,
-                      enabled: false,
                       MenuName: btn.label,
                       tables: _config.tables || [],
                       Template: 'BaseTable',
-                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions)],
+                      components: [this.getTable(menus[btn.uuid], mainTb, errors, formActions, formTabs)],
                       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 + '銆嬮厤缃俊鎭涪澶�')
                   }
@@ -346,14 +360,33 @@
           }
         })
 
-        this.setPopForm(_resolve, _config, formActions, errors)
+        this.setPopForm(_resolve, _config, formActions, formTabs, errors)
       })
     } else {
-      this.setPopForm(_resolve, _config, formActions, errors)
+      this.setPopForm(_resolve, _config, formActions, formTabs, errors)
     }
   }
 
-  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, formTabs, errors) => {
     if (formActions.length > 0) {
       let defers = formActions.map((item, i) => {
         return new Promise((resolve) => {
@@ -419,8 +452,9 @@
                 }
               })
               tab.components[0].cols.forEach(col => {
-                if (col.type !== 'action') return
+                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')) {
@@ -456,8 +490,9 @@
               }
             })
             item.cols.forEach(col => {
-              if (col.type !== 'action') return
+              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')) {
@@ -477,10 +512,10 @@
           }
         })
 
-        this.saveConfig(_resolve, _config, errors)
+        this.saveConfig(_resolve, _config, errors, formTabs)
       })
     } else {
-      this.saveConfig(_resolve, _config, errors)
+      this.saveConfig(_resolve, _config, errors, formTabs)
     }
   }
 
@@ -500,8 +535,9 @@
       }
     })
     item.cols.forEach(col => {
-      if (col.type !== 'action') return
+      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 = {
@@ -518,7 +554,7 @@
     })
   }
 
-  saveConfig = (_resolve, _config, errors) => {
+  saveConfig = (_resolve, _config, errors, formTabs) => {
     let err = errors.join('锛�')
     let _this = this
 
@@ -529,17 +565,17 @@
         content: '',
         onOk() {
           return new Promise(resolve => {
-            _this.saveNewMenu(resolve, _config)
+            _this.saveNewMenu(resolve, _config, formTabs)
           })
         },
         onCancel() {}
       })
     } else {
-      this.saveNewMenu(_resolve, _config)
+      this.saveNewMenu(_resolve, _config, formTabs)
     }
   }
 
-  saveNewMenu = (_resolve, _config) => {
+  saveNewMenu = (_resolve, _config, formTabs) => {
     _config.components.forEach(item => {
       if (item.type === 'tabs') {
         item.subtabs.forEach(tab => {
@@ -549,8 +585,9 @@
             }
           })
           tab.components[0].cols.forEach(col => {
-            if (col.type !== 'action') return
+            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])
               }
@@ -566,8 +603,9 @@
           }
         })
         item.cols.forEach(col => {
-          if (col.type !== 'action') return
+          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])
             }
@@ -578,53 +616,100 @@
       }
     })
 
+    // 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()
+      }
+    })
+  }
+
+  submitConfig = (_resolve, config) => {
     let tbs = []
-    _config.components.forEach(item => {
+    config.components.forEach(item => {
       if (item.type === 'tabs') {
         item.subtabs.forEach(tab => {
           if (tab.components[0].$tables) {
             tbs.push(...tab.components[0].$tables)
-          }
-
-          tab.components[0].errors = []
-          let columns = tab.components[0].columns.map(c => c.field)
-          if (tab.components[0].setting.interType === 'system' && tab.components[0].setting.execute !== 'false' && !tab.components[0].setting.dataresource) {
-            tab.components[0].errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
-          } else if (tab.components[0].setting.interType === 'system' && tab.components[0].setting.execute === 'false' && tab.components[0].scripts.filter(script => script.status !== 'false').length === 0) {
-            tab.components[0].errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
-          } else if (!tab.components[0].setting.primaryKey) {
-            tab.components[0].errors.push({ level: 0, detail: '鏈缃富閿紒'})
-          } else if (!columns.includes(tab.components[0].setting.primaryKey)) {
-            tab.components[0].errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
-          } else if (!tab.components[0].setting.supModule) {
-            tab.components[0].errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
           }
         })
       } else {
         if (item.$tables) {
           tbs.push(...item.$tables)
         }
-
-        item.errors = []
-        let columns = item.columns.map(c => c.field)
-        if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
-          item.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
-        } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.filter(script => script.status !== 'false').length === 0) {
-          item.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
-        } else if (!item.setting.primaryKey) {
-          item.errors.push({ level: 0, detail: '鏈缃富閿紒'})
-        } else if (!columns.includes(item.setting.primaryKey)) {
-          item.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
-        } else if (!item.setting.supModule) {
-          item.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
-        }
       }
     })
 
-    this.submitConfig(_resolve, _config, tbs)
-  }
-
-  submitConfig = (_resolve, config, tbs) => {
     let arr = []
     tbs = tbs.filter(tb => {
       let _tb = tb.toLowerCase()
@@ -734,7 +819,7 @@
     })
   }
 
-  getTable = (config, newCon, errors, formActions, popActions, oldtabs) => { 
+  getTable = (config, newCon, errors, formActions, formTabs, popActions, oldtabs) => { 
     let _card = {
       uuid: newCon.uuid,
       type: 'table',
@@ -759,7 +844,7 @@
       return _card
     }
 
-    if (newCon.supModule && oldtabs[newCon.supModule]) {
+    if (oldtabs && newCon.supModule && oldtabs[newCon.supModule]) {
       _card.setting.supModule = [oldtabs[newCon.supModule]]
     } else {
       _card.setting.supModule = ['empty']
@@ -969,7 +1054,7 @@
     }
 
     let colbtns = []
-    let colors = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#666666', default: 'rgba(0, 0, 0, 0.65)' }
+    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 => {
@@ -982,6 +1067,9 @@
 
       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'
@@ -1029,7 +1117,29 @@
 
         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' || !btn.linkmenu || btn.linkmenu.length !== 3) {
+        if (btn.tabTemplate === 'FormTab') {
+          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 + '銆嬩笉鍦ㄦ敮鎸�')
           return
@@ -1053,7 +1163,7 @@
         } else if (btn.class.indexOf('border') > -1) {
           _btn.style = {color: color, backgroundColor: '#fff', borderColor: color, marginRight: '15px'}
         } else {
-          _btn.style = {color: '#fff', backgroundColor: color, borderColor: color, marginRight: '15px'}
+          _btn.style = {color: btn.class === 'gray' ? 'rgba(0, 0, 0, 0.65)' : '#fff', backgroundColor: color, borderColor: color, marginRight: '15px'}
         }
         _card.action.push(_btn)
       }
@@ -1066,7 +1176,7 @@
         marks: [],
         isSub: false,
         uuid: Utils.getuuid(),
-        type: 'action',
+        type: 'custom',
         Width: 120,
         elements: colbtns,
         style: {paddingTop: '12px', paddingLeft: '8px', paddingBottom: '12px', paddingRight: '8px'}
@@ -1106,6 +1216,50 @@
       _card.wrap.doubleClick = ''
     }
 
+    _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: '鏈缃笂绾х粍浠讹紒'})
+    }
+
+    _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}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+        }
+      })
+    })
+
     return _card
   }
 
diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx
index a3e43f0..d9b92c4 100644
--- a/src/templates/formtabconfig/index.jsx
+++ b/src/templates/formtabconfig/index.jsx
@@ -362,18 +362,23 @@
       _formfields = [..._formfields, ...group.sublist]
     })
 
-    _inputfields = _formfields.filter(item => ['text', 'number', 'textarea', 'color'].includes(item.type) && card.field !== item.field)
-    _tabfields = _formfields.filter(item => card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type))
-    
-    if (card.linkSubField && card.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      card.linkSubField = card.linkSubField.filter(item => fields.includes(item))
-    }
-
     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)
@@ -388,6 +393,11 @@
         })
       }
     })
+
+    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 => {
@@ -1564,9 +1574,6 @@
               </div>
             } style={{ width: '100%' }}>
               <SettingOutlined onClick={this.changeSetting} />
-              {/* <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��">
-                <QuestionCircleOutlined style={{position: 'relative', color: '#c49f47', left: '5px', top: '20px'}} />
-              </Tooltip> */}
               <Collapse
                 activeKey={config.groups.map(group => group.uuid)}
                 expandIconPosition={'right'}
@@ -1597,9 +1604,6 @@
                 ))}
               </Collapse>
               <div className="action-list">
-                {/* <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�">
-                  <QuestionCircleOutlined style={{position: 'absolute', color: '#c49f47', left: '5px', top: '5px'}} />
-                </Tooltip> */}
                 <DragElement
                   type="action"
                   list={this.state.config.action}
diff --git a/src/templates/formtabconfig/index.scss b/src/templates/formtabconfig/index.scss
index d555524..cb73f81 100644
--- a/src/templates/formtabconfig/index.scss
+++ b/src/templates/formtabconfig/index.scss
@@ -124,7 +124,7 @@
       >.ant-collapse {
         border-radius: 0;
         border: 0;
-        margin-top: 30px;
+        margin-top: 45px;
         .ant-collapse-header {
           cursor: default;
           border-radius: 0;
diff --git a/src/templates/modalconfig/dragelement/card.jsx b/src/templates/modalconfig/dragelement/card.jsx
index dad19c1..063f651 100644
--- a/src/templates/modalconfig/dragelement/card.jsx
+++ b/src/templates/modalconfig/dragelement/card.jsx
@@ -129,6 +129,8 @@
       <Checkbox value="C">C</Checkbox>
       <Checkbox value="D">D</Checkbox>
     </Checkbox.Group>)
+  } else if (card.type === 'check') {
+    formItem = <Checkbox checked={card.initval}>{card.checkTip || ''}</Checkbox>
   } else if (card.type === 'hint') {
     formItem = <div style={{marginTop: '8px', color: 'rgba(0, 0, 0, 0.85)', lineHeight: '1.5', ...card.style}}>{card.message}</div>
   } else if (card.type === 'formula') {
@@ -146,7 +148,7 @@
     formItem = <CheckCard config={card} />
   }
 
-  let _label = <span className="mk-form-label" style={card.style}>{card.label}</span>
+  let _label = <span className={'mk-form-label ' + (/^\s+$/.test(card.label) ? 'no-colon' : '')} style={card.style}>{card.label}</span>
 
   if (card.tooltip) {
     _label = <><QuestionCircleOutlined className="mk-form-tip" /><span className="mk-form-label" style={card.style}>{card.label}</span></>
@@ -156,6 +158,10 @@
   } else if (card.type === 'hint' && !card.label) {
     className += ' no-label'
     _label = ' '
+  }
+
+  if (window.GLOB.formId === card.uuid) {
+    className += ' actived'
   }
 
   return (
@@ -181,7 +187,7 @@
             {formItem}
             <div></div>
             {showField ? <div className="field-name" style={card.writein === 'false' ? {color: 'orange'} : {}}>
-              {card.field}{card.hidden === 'true' || card.type === 'funcvar' ? '锛堥殣钘忥級' : ''}{card.readonly === 'true' ? '锛堝彧璇伙級' : ''}{card.linkField ? <span style={{color: '#1890ff'}}>{`锛堝叧鑱�${card.linkField}锛塦}</span> : ''}{card.supField ? <span style={{color: '#8E44AD'}}>{`锛堜笂绾�${card.supField}锛塦}</span> : ''}
+              {card.field}{card.hidden === 'true' || card.type === 'funcvar' ? '锛堥殣钘忥級' : ''}{card.readonly === 'true' ? '锛堝彧璇伙級' : ''}{card.readin === 'false' ? '锛堟湭濉厖锛�' : ''}{card.linkField ? <span style={{color: '#1890ff'}}>{`锛堝叧鑱�${card.linkField}锛塦}</span> : ''}{card.supField ? <span style={{color: '#8E44AD'}}>{`锛堜笂绾�${card.supField}锛塦}</span> : ''}
             </div> : ''}
           </Form.Item>}
         </div>
diff --git a/src/templates/modalconfig/dragelement/index.jsx b/src/templates/modalconfig/dragelement/index.jsx
index 3cd1b5a..4798f28 100644
--- a/src/templates/modalconfig/dragelement/index.jsx
+++ b/src/templates/modalconfig/dragelement/index.jsx
@@ -62,6 +62,8 @@
     let val = JSON.parse(JSON.stringify(_card))
     val.copyType = 'form'
 
+    _card.$copy = true
+
     delete val.$srcId
     
     let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
diff --git a/src/templates/modalconfig/dragelement/index.scss b/src/templates/modalconfig/dragelement/index.scss
index df834a2..c99318b 100644
--- a/src/templates/modalconfig/dragelement/index.scss
+++ b/src/templates/modalconfig/dragelement/index.scss
@@ -33,12 +33,22 @@
       line-height: 1;
     }
   }
-  .mk-form-label::after {
+  .ant-form-item.actived {
+    .mk-form-label {
+      color: #1890ff;
+    }
+  }
+  .mk-form-label:after {
     content: ':';
     position: relative;
     top: -0.5px;
     margin: 0 8px 0 2px;
     text-decoration: none;
+  }
+  .mk-form-label.no-colon {
+    opacity: 0;
+    width: 1px;
+    display: inline-block;
   }
   .ant-form-item-no-colon::after {
     content: none!important;
@@ -130,12 +140,12 @@
 }
 .modal-fields-row.up_down {
   .ant-form-item {
-    display: block;
+    display: block!important;
     .ant-form-item-label {
       width: 100%!important;
       text-align: left;
-      height: 24px;
-      line-height: 28px;
+      height: 24px!important;
+      line-height: 28px!important;
     }
     .ant-form-item-control-wrapper {
       width: 100%!important;
@@ -161,4 +171,18 @@
   .page-card {
     margin-bottom: 5px;
   }
-}
\ No newline at end of file
+}
+// .modal-fields-row.copy {
+//   z-index: 3;
+// }
+// .modal-fields-row.copy::before {
+//   content: ' ';
+//   display: block;
+//   position: fixed;
+//   left: 0;
+//   right: 0;
+//   top: 0;
+//   bottom: 0;
+//   background: rgba(0,0,0,0.2);
+//   z-index: 2;
+// }
\ No newline at end of file
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index b4d6d8b..5291743 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -126,6 +126,7 @@
   }
 
   componentDidMount() {
+    window.GLOB.formId = ''
     MKEmitter.addListener('submitStyle', this.getStyle)
     document.onkeydown = (event) => {
       let e = event || window.event
@@ -267,7 +268,7 @@
         })
       }
 
-      if (item.type === 'switch') {
+      if (item.type === 'switch' || item.type === 'check') {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -391,6 +392,8 @@
 
       _config.fields = _config.fields.filter(item => !item.origin)
 
+      window.GLOB.formId = res.uuid
+
       if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
         this.setState({
           sqlVerifing: true
diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
index f599ffb..d3d1ea1 100644
--- a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -186,14 +186,8 @@
           reReadonly.interface = true
           reRequired.interface = false
         }
-      } else if (intertype === 'inner') { // preFunc 鍓嶇疆鍑芥暟
+      } else if (intertype === 'inner') {
         shows.push('innerFunc', 'output')
-
-        // positecgroup
-        if (window.GLOB.appkey === '20201102081641237BDDE0D5F2E98420BA7EC') {
-          shows.push('preFunc')
-        }
-
         reRequired.innerFunc = true
       } else {
         shows.push('sql', 'sqlType', 'output')
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index 06d1cf2..b871c62 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -56,15 +56,15 @@
 
   componentDidMount () {
     this.getBillPrintTemp()
-    MKEmitter.addListener('revert', this.revert)
+    // MKEmitter.addListener('revert', this.revert)
     MKEmitter.addListener('pasteButton', this.pasteButton)
   }
 
-  revert = () => {
-    this.setState({
-      actionlist: fromJS(this.props.config.action).toJS()
-    })
-  }
+  // revert = () => {
+  //   this.setState({
+  //     actionlist: fromJS(this.props.config.action).toJS()
+  //   })
+  // }
 
   pasteButton = (MenuId, btn) => {
     const { config } = this.props
@@ -847,7 +847,7 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('revert', this.revert)
+    // MKEmitter.removeListener('revert', this.revert)
     MKEmitter.removeListener('pasteButton', this.pasteButton)
   }
 
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx
index a83f4a9..7724f6c 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx
@@ -87,7 +87,7 @@
                     message: '璇疯緭鍏ュ瓧娈�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" />)}
+              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleConfirm}/>)}
             </Form.Item>
           </Col>
           <Col span={6}>
@@ -100,7 +100,7 @@
                     message: '璇疯緭鍏ュ悕绉�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" />)}
+              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleConfirm}/>)}
             </Form.Item>
           </Col>
           <Col span={6}>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
index a4e6142..837dd40 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -61,19 +61,39 @@
   }
 
   edit = (record) => {
+    const { type } = this.props
+
     this.setState({
       editItem: record
     })
 
-    this.props.form.setFieldsValue({
-      sql: record.sql,
-      position: record.position || 'back'
-    })
+    if (type === 'fullscreen') {
+      this.props.form.setFieldsValue({
+        sql: record.sql
+      })
+    } else {
+      this.props.form.setFieldsValue({
+        sql: record.sql,
+        position: record.position || 'back'
+      })
+    }
   }
 
   handleConfirm = () => {
+    const { type } = this.props
+    const { editItem } = this.state
+
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
+      if (type === 'fullscreen' && err) {
+        notification.warning({
+          top: 92,
+          message: '璇疯緭鍏ql!',
+          duration: 5
+        })
+        return
+      }
+
       if (!err) {
         if (/^[\s\n]+$/.test(values.sql)) {
           notification.warning({
@@ -84,7 +104,12 @@
           return
         }
         
-        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+        values.uuid = editItem ? editItem.uuid : ''
+        values.position = values.position || (editItem ? editItem.position : 'front')
+
+        if (type === 'fullscreen' && editItem) {
+          values.status = editItem.status || 'true'
+        }
 
         let _quot = values.sql.match(/'{1}/g)
         let _lparen = values.sql.match(/\({1}/g)
@@ -112,6 +137,13 @@
           notification.warning({
             top: 92,
             message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 5
+          })
+          return
+        } else if (/,,/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇杩炵画鐨勮嫳鏂囬�楀彿锛�,,锛�',
             duration: 5
           })
           return
@@ -204,7 +236,7 @@
               this.props.scriptsChange(values)
             })
             this.props.form.setFieldsValue({
-              sql: ''
+              sql: ' '
             })
           } else {
             this.setState({loading: false})
@@ -224,7 +256,7 @@
     })
     
     this.props.form.setFieldsValue({
-      sql: ''
+      sql: ' '
     })
   }
 
@@ -251,6 +283,9 @@
     }
 
     let _sql = this.props.form.getFieldValue('sql')
+    if (/^\s+$/.test(_sql)) {
+      _sql = ''
+    }
     if (_sql) {
       _sql = _sql + ` 
 
@@ -269,8 +304,8 @@
   }
 
   render() {
-    const { systemScripts, btn } = this.props
-    const { usefulfields } = this.state
+    const { systemScripts, btn, type } = this.props
+    const { usefulfields, editItem } = this.state
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
       labelCol: {
@@ -286,24 +321,24 @@
     return (
       <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
         <Row gutter={24}>
-          {btn.sheet ? <Col span={8}>
+          {!type && btn.sheet ? <Col span={8}>
             <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
               {btn.sheet}
             </Form.Item>
           </Col> : null}
-          <Col span={10}>
+          {!type ? <Col span={10}>
             <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
               ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
             </Form.Item>
-          </Col>
-          <Col span={24} className="sqlfield">
+          </Col> : null}
+          {!type ? <Col span={24} className="sqlfield">
             <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}
             </Form.Item>
-          </Col>
-          <Col span={8} style={{whiteSpace: 'nowrap'}}>
+          </Col> : null}
+          {!type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
             <Form.Item style={{marginBottom: 0}} label={
               <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}>
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -320,8 +355,8 @@
                 </Radio.Group>
               )}
             </Form.Item>
-          </Col>
-          <Col span={10}>
+          </Col> : null}
+          {!type ? <Col span={10}>
             <Form.Item style={{marginBottom: 0}} label={'蹇嵎娣诲姞'}>
               <Select
                 showSearch
@@ -342,10 +377,10 @@
                 )}
               </Select>
             </Form.Item>
-          </Col>
+          </Col> : null}
           <Col span={6} className="add">
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
-              淇濆瓨
+            {type === 'fullscreen' && !editItem ? '娣诲姞' : '淇濆瓨'}
             </Button>
             <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
               鍙栨秷
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
index 249c732..a3460ed 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -19,6 +19,7 @@
 const { confirm } = Modal
 const { Paragraph } = Typography
 const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
+const FullScripts = asyncComponent(() => import('@/templates/zshare/verifycard/fullScripts'))
 
 class VerifyCard extends Component {
   static propTpyes = {
@@ -122,7 +123,7 @@
       {
         title: '鎶ラ敊缂栫爜',
         dataIndex: 'errorCode',
-        width: '12%',
+        width: '10%',
         editable: true,
         inputType: 'select',
         options: [
@@ -135,13 +136,24 @@
       {
         title: '楠岃瘉绫诲瀷',
         dataIndex: 'verifyType',
-        width: '12%',
-        render: (text, record) => record.verifyType === 'logic' ? '閫昏緫楠岃瘉' : '鐗╃悊楠岃瘉',
+        width: '14%',
+        render: (text, record) => {
+          let names = {
+            physical: '鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級',
+            logic: '閫昏緫楠岃瘉锛堝叏閲忛獙璇侊級',
+            physical_temp: '鐗╃悊楠岃瘉锛堜粎涓存椂琛級',
+            logic_temp: '閫昏緫楠岃瘉锛堜粎涓存椂琛級',
+          }
+
+          return names[text] || '鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級'
+        },
         inputType: 'select',
         editable: true,
         options: [
-          { value: 'physical', text: '鐗╃悊楠岃瘉' },
-          { value: 'logic', text: '閫昏緫楠岃瘉' }
+          { value: 'physical', text: '鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級' },
+          { value: 'logic', text: '閫昏緫楠岃瘉锛堝叏閲忛獙璇侊級' },
+          { value: 'physical_temp', text: '鐗╃悊楠岃瘉锛堜粎涓存椂琛級' },
+          { value: 'logic_temp', text: '閫昏緫楠岃瘉锛堜粎涓存椂琛級' }
         ]
       },
       {
@@ -453,6 +465,7 @@
   changeColumns = (columns) => {
     const { verify } = this.state
 
+    let reset = false
     columns = columns.map(col => {
       col.type = col.type || 'Nvarchar(50)'
       if (col.type === 'text' || col.type === 'image') {
@@ -465,8 +478,14 @@
         col.limit = col.type.match(/\d+/) ? col.type.match(/\d+/)[0] : '20000'
       } else if (/^Decimal/ig.test(col.type)) {
         col.limit = col.type.match(/\d+/ig)[1]
+        if (col.required === 'false') {
+          reset = true
+        }
         col.required = 'true'
       } else if (/^int/ig.test(col.type)) {
+        if (col.required === 'false') {
+          reset = true
+        }
         col.required = 'true'
       } else {
         col.limit = ''
@@ -477,6 +496,10 @@
 
       return col
     })
+
+    if (reset) {
+      message.warning('鏁板�肩被鍨嬪潎涓哄繀濉��')
+    }
 
     this.setState({verify: {...verify, columns}}, () => {
       this.resetUniqueColumns()
@@ -833,6 +856,23 @@
               {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
             </span>
           } key="scripts" id="mk-exin-script">
+            <FullScripts
+              verify={verify}
+              getScriptsFullForm={() => this.scriptsFullForm}
+              getScriptsForm={() => this.scriptsForm}
+              handleStatus={this.handleStatus}
+              handleDelete={this.handleDelete}
+            >
+              <CustomScript
+                type="fullscreen"
+                btn={this.props.card}
+                usefulfields={verify.columns}
+                scripts={verify.scripts}
+                systemScripts={this.state.systemScripts}
+                scriptsChange={this.scriptsChange}
+                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
+              />
+            </FullScripts>
             <CustomScript
               btn={this.props.card}
               usefulfields={verify.columns}
@@ -847,7 +887,7 @@
             <Form {...formItemLayout}>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> S </span>
                     <Button onClick={() => {this.showError('S')}} type="primary" size="small">
                       鏌ョ湅
@@ -855,14 +895,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> Y </span>
                     <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
                       鏌ョ湅
@@ -872,7 +912,15 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -1 </span>
+                    鎵ц鎴愬姛鏃犳彁绀恒��
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> N </span>
                     <Button onClick={() => {this.showError('N')}} type="primary" size="small">
                       鏌ョ湅
@@ -880,14 +928,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> F </span>
                     <Button onClick={() => {this.showError('F')}} type="primary" size="small">
                       鏌ョ湅
@@ -895,14 +943,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> E </span>
                     <Button onClick={() => {this.showError('E')}} type="primary" size="small">
                       鏌ョ湅
@@ -912,7 +960,7 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> NM </span>
                     <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
                       鏌ョ湅
@@ -922,9 +970,9 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
-                    <span className="errorval"> -1 </span>
-                    涓嶆彁绀�
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -2 </span>
+                    鎵ц澶辫触鏃犳彁绀�
                   </Form.Item>
                 </Col>
               </Row>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
index 604f0a8..a9f4ffa 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
@@ -77,4 +77,12 @@
       z-index: 1;
     }
   }
+  .full-scripts {
+    position: absolute;
+    right: 24px;
+    top: 0px;
+    font-size: 16px;
+    color: #1890ff;
+    z-index: 1;
+  }
 }
\ No newline at end of file
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx
index a6e9bf2..365f6b0 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx
@@ -108,8 +108,10 @@
                 ]
               })(
                 <Select>
-                  <Select.Option value="physical"> 鐗╃悊楠岃瘉 </Select.Option>
-                  <Select.Option value="logic"> 閫昏緫楠岃瘉 </Select.Option>
+                  <Select.Option value="physical"> 鐗╃悊楠岃瘉锛堝叏閲忛獙璇侊級 </Select.Option>
+                  <Select.Option value="logic"> 閫昏緫楠岃瘉锛堝叏閲忛獙璇侊級 </Select.Option>
+                  <Select.Option value="physical_temp"> 鐗╃悊楠岃瘉锛堜粎涓存椂琛級 </Select.Option>
+                  <Select.Option value="logic_temp"> 閫昏緫楠岃瘉锛堜粎涓存椂琛級  </Select.Option>
                 </Select>
               )}
             </Form.Item>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx
index e3159f8..76d36ee 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx
@@ -48,7 +48,7 @@
                     message: '璇疯緭鍏ュ瓧娈�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" />)}
+              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleConfirm}/>)}
             </Form.Item>
           </Col>
           <Col span={5}>
@@ -61,7 +61,7 @@
                     message: '璇疯緭鍏ュ悕绉�!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" />)}
+              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleConfirm}/>)}
             </Form.Item>
           </Col>
           <Col span={5}>
@@ -74,7 +74,7 @@
                     message: '璇疯緭鍏ュ垪瀹�!'
                   }
                 ]
-              })(<InputNumber min={5} max={200} precision={0} />)}
+              })(<InputNumber min={5} max={200} precision={0} onPressEnter={this.handleConfirm}/>)}
             </Form.Item>
           </Col>
           <Col span={6}>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
index 09adfd9..bf43e2c 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
@@ -114,8 +114,7 @@
     })
 
     this.props.form.setFieldsValue({
-      sql: record.sql,
-      position: record.position || 'back'
+      sql: record.sql
     })
   }
 
@@ -163,6 +162,13 @@
             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')
@@ -187,7 +193,7 @@
               editItem: null
             })
             this.props.form.setFieldsValue({
-              sql: ''
+              sql: ' '
             })
           } else {
             this.setState({
@@ -205,7 +211,7 @@
     })
     
     this.props.form.setFieldsValue({
-      sql: ''
+      sql: ' '
     })
   }
 
@@ -225,6 +231,9 @@
     }
 
     let _sql = this.props.form.getFieldValue('sql')
+    if (/^\s+$/.test(_sql)) {
+      _sql = ''
+    }
     if (_sql) {
       _sql = _sql + ` 
 
@@ -261,43 +270,25 @@
       <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
         <Row gutter={24}>
           <Col span={8}>
-            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
+            <Form.Item label="琛ㄥ悕" style={{whiteSpace: 'nowrap', margin: 0}}>
               {sheet}
             </Form.Item>
           </Col>
           <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>
           <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>
               {usefulfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎼滅储鏉′欢锛岃鎸夌収@xxx@鏍煎紡浣跨敤銆�'}>,&nbsp;{usefulfields}</Tooltip> : null}
               {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={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鎵ц浣嶇疆
-              </Tooltip>
-            }>
-              {getFieldDecorator('position', {
-                initialValue: 'front'
-              })(
-                <Radio.Group>
-                  <Radio value="init">鍒濆鍖�</Radio>
-                  <Radio value="front">sql鍓�</Radio>
-                  <Radio value="back">sql鍚�</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> */}
           <Col span={8}>
-            <Form.Item style={{marginBottom: 0}} label={'蹇嵎娣诲姞'}>
+            <Form.Item style={{marginBottom: 0}} label="蹇嵎娣诲姞">
               <Select
                 showSearch
                 filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
@@ -327,7 +318,7 @@
             </Button>
           </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/verifyexcelout/datasource/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
index 0159b4e..04fa4a8 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
@@ -76,6 +76,14 @@
               })
               reject()
               return
+            } else if (/,,/ig.test(values.dataresource)) {
+              notification.warning({
+                top: 92,
+                message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜拌繛缁殑鑻辨枃閫楀彿锛�,,锛�',
+                duration: 5
+              })
+              reject()
+              return
             }
 
             let error = Utils.verifySql(values.dataresource)
@@ -100,8 +108,18 @@
   }
 
   updateDataType = (e) => {
-    this.setState({dataType: e.target.value})
     this.props.updateDataType(e.target.value)
+
+    if (e.target.value === 'custom') {
+      setTimeout(() => {
+        this.setState({
+          dataType: e.target.value,
+          defaultSql: this.props.setting.defaultSql || 'true'
+        })
+      }, 10)
+    } else {
+      this.setState({dataType: e.target.value})
+    }
   }
 
   render() {
@@ -198,13 +216,13 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            {dataType === 'custom' && defaultSql === 'true' ? <Col className="short-label" span={8}>
+            {/* {dataType === 'custom' && defaultSql === 'true' ? <Col className="short-label" span={8}>
               <Form.Item label="涓婚敭">
                 {getFieldDecorator('primaryKey', {
                   initialValue: setting.primaryKey || 'ID',
                 })(<Input placeholder={''} autoComplete="off" />)}
               </Form.Item>
-            </Col> : null}
+            </Col> : null} */}
             {dataType === 'custom' && defaultSql === 'true' ? <Col className="short-label" span={8}>
               <Form.Item label="鎺掑簭鏂瑰紡">
                 {getFieldDecorator('order', {
@@ -274,6 +292,22 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
+            {btnType !== 'print' ? <Col span={8}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="Excel鍐呭鍖烘槸鍚﹁嚜鍔ㄦ崲琛屻��">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鑷姩鎹㈣
+                </Tooltip>
+              }>
+                {getFieldDecorator('wrapText', {
+                  initialValue: setting.wrapText || 'false'
+                })(
+                <Radio.Group>
+                  <Radio value="false">鍚�</Radio>
+                  <Radio value="true">鏄�</Radio>
+                </Radio.Group>)}
+              </Form.Item>
+            </Col> : null}
           </Row>
         </Form>
       </div>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
index 76e6878..86d94de 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -4,6 +4,7 @@
 import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Radio, Spin, Typography, Popconfirm } from 'antd'
 import { EditOutlined, StopOutlined, CheckCircleOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
 import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -28,6 +29,7 @@
 
   state = {
     verify: {},
+    debugId: '',
     activeKey: 'setting',
     defaultscript: '', // 鑷畾涔夎剼鏈�
     excelColumns: [
@@ -158,20 +160,20 @@
           )
         }
       },
-      {
-        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 === '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: 'status',
@@ -585,6 +587,17 @@
       } else if (activeKey === 'setting') {
         this.settingForm.handleConfirm().then(res => {
           let _verify = {...verify, ...res}
+
+          if (res.dataType !== 'custom') {
+            delete _verify.tableName
+            delete _verify.dataresource
+            delete _verify.queryType
+            delete _verify.defaultSql
+            delete _verify.order
+
+            _verify.scripts = []
+          }
+          
           this.setState({
             verify: _verify
           }, () => {
@@ -688,6 +701,13 @@
           notification.warning({
             top: 92,
             message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 5
+          })
+          return
+        } else if (/,,/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇杩炵画鐨勮嫳鏂囬�楀彿锛�,,锛�',
             duration: 5
           })
           return
@@ -988,7 +1008,7 @@
   }
 
   sqlverify = (_resolve, _reject, scripts) => {
-    const { searches, verify } = this.state
+    const { searches, verify, debugId } = this.state
 
     if (verify.dataType !== 'custom') {
       _resolve()
@@ -996,7 +1016,15 @@
     }
 
     let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    let sql = SettingUtils.getDebugSql(verify, scripts, (verify.useSearch === 'true' ? searches : []), Utils, timestamp)
+    let sql = SettingUtils.getDebugSql(verify, scripts, (verify.useSearch === 'true' ? searches : []), Utils, '2023-04-20 15:29:37')
+
+    let _debugId = md5(sql)
+
+    if (debugId === _debugId) {
+      _resolve()
+      return
+    }
+
     let param = {
       func: 's_debug_sql',
       exec_type: 'y',
@@ -1008,6 +1036,7 @@
 
     Api.genericInterface(param).then(result => {
       if (result.status) {
+        this.setState({debugId: _debugId})
         _resolve()
       } else {
         _reject()
@@ -1019,7 +1048,22 @@
   }
 
   updateDataType = (val) => {
-    this.setState({verify: {...this.state.verify, dataType: val}})
+    const { config } = this.props
+
+    let verify = {...this.state.verify, dataType: val}
+    if (val === 'custom' && config.setting) {
+      verify.tableName = verify.tableName || config.setting.tableName || ''
+      verify.dataresource = verify.dataresource || config.setting.dataresource || ''
+      verify.queryType = verify.queryType || config.setting.queryType || ''
+      verify.defaultSql = verify.defaultSql || config.setting.execute || ''
+      verify.order = verify.order || config.setting.order || ''
+
+      if (verify.scripts.length === 0 && config.scripts && config.scripts.length > 0) {
+        verify.scripts = fromJS(config.scripts).toJS()
+      }
+    }
+
+    this.setState({verify: verify})
   }
 
   render() {
@@ -1113,7 +1157,7 @@
             <Form {...formItemLayout}>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> S </span>
                     <Button onClick={() => {this.showError('S')}} type="primary" size="small">
                       鏌ョ湅
@@ -1121,14 +1165,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> Y </span>
                     <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
                       鏌ョ湅
@@ -1138,7 +1182,15 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -1 </span>
+                    鎵ц鎴愬姛鏃犳彁绀恒��
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> N </span>
                     <Button onClick={() => {this.showError('N')}} type="primary" size="small">
                       鏌ョ湅
@@ -1146,14 +1198,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> F </span>
                     <Button onClick={() => {this.showError('F')}} type="primary" size="small">
                       鏌ョ湅
@@ -1161,14 +1213,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> E </span>
                     <Button onClick={() => {this.showError('E')}} type="primary" size="small">
                       鏌ョ湅
@@ -1178,7 +1230,7 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> NM </span>
                     <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
                       鏌ョ湅
@@ -1188,9 +1240,9 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
-                    <span className="errorval"> -1 </span>
-                    涓嶆彁绀�
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -2 </span>
+                    鎵ц澶辫触鏃犳彁绀�
                   </Form.Item>
                 </Col>
               </Row>
diff --git a/src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx
index bc04f46..e238cf8 100644
--- a/src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx
@@ -156,7 +156,7 @@
             <Form {...formItemLayout}>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> S </span>
                     <Button onClick={() => {this.showError('S')}} type="primary" size="small">
                       鏌ョ湅
@@ -164,14 +164,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> Y </span>
                     <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
                       鏌ョ湅
@@ -181,7 +181,15 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -1 </span>
+                    鎵ц鎴愬姛鏃犳彁绀恒��
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> N </span>
                     <Button onClick={() => {this.showError('N')}} type="primary" size="small">
                       鏌ョ湅
@@ -189,14 +197,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> F </span>
                     <Button onClick={() => {this.showError('F')}} type="primary" size="small">
                       鏌ョ湅
@@ -204,14 +212,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> E </span>
                     <Button onClick={() => {this.showError('E')}} type="primary" size="small">
                       鏌ョ湅
@@ -221,7 +229,7 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> NM </span>
                     <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
                       鏌ョ湅
@@ -231,9 +239,9 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
-                    <span className="errorval"> -1 </span>
-                    涓嶆彁绀�
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -2 </span>
+                    鎵ц澶辫触鏃犳彁绀�
                   </Form.Item>
                 </Col>
               </Row>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
index 832945f..90ff096 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -4,6 +4,7 @@
 import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Input, Select, Radio, Tooltip, Typography, Popconfirm, Spin } from 'antd'
 import { QuestionCircleOutlined, EditOutlined, StopOutlined, CheckCircleOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
 import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -33,6 +34,7 @@
 
   state = {
     verify: {},
+    debugId: '',
     templates: [],
     loading: false,
     activeKey: 'base',
@@ -611,10 +613,18 @@
   }
 
   sqlverify = (_resolve, _reject, scripts) => {
-    const { verify, declareSql } = this.state
+    const { verify, declareSql, debugId } = this.state
 
     let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    let sql = SettingUtils.getDebugSql(verify.setting || {}, verify.columns, scripts, declareSql, timestamp)
+    let sql = SettingUtils.getDebugSql(verify.setting || {}, verify.columns, scripts, declareSql, '2023-04-20 15:29:37')
+
+    let _debugId = md5(sql)
+
+    if (debugId === _debugId) {
+      _resolve()
+      return
+    }
+
     let param = {
       func: 's_debug_sql',
       exec_type: 'y',
@@ -626,6 +636,7 @@
 
     Api.genericInterface(param).then(result => {
       if (result.status) {
+        this.setState({debugId: _debugId})
         _resolve()
       } else {
         _reject()
@@ -921,7 +932,7 @@
             <Form {...formItemLayout}>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> S </span>
                     <Button onClick={() => {this.showError('S')}} type="primary" size="small">
                       鏌ョ湅
@@ -929,14 +940,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> Y </span>
                     <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
                       鏌ョ湅
@@ -946,7 +957,15 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -1 </span>
+                    鎵ц鎴愬姛鏃犳彁绀恒��
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> N </span>
                     <Button onClick={() => {this.showError('N')}} type="primary" size="small">
                       鏌ョ湅
@@ -954,14 +973,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> F </span>
                     <Button onClick={() => {this.showError('F')}} type="primary" size="small">
                       鏌ョ湅
@@ -969,14 +988,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> E </span>
                     <Button onClick={() => {this.showError('E')}} type="primary" size="small">
                       鏌ョ湅
@@ -986,7 +1005,7 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> NM </span>
                     <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
                       鏌ョ湅
@@ -996,9 +1015,9 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
-                    <span className="errorval"> -1 </span>
-                    涓嶆彁绀�
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -2 </span>
+                    鎵ц澶辫触鏃犳彁绀�
                   </Form.Item>
                 </Col>
               </Row>
diff --git a/src/templates/sharecomponent/columncomponent/columnform/index.scss b/src/templates/sharecomponent/columncomponent/columnform/index.scss
index 0b02ab2..aabfa36 100644
--- a/src/templates/sharecomponent/columncomponent/columnform/index.scss
+++ b/src/templates/sharecomponent/columncomponent/columnform/index.scss
@@ -15,4 +15,9 @@
       width: 88%;
     }
   }
+  >.ant-row >.ant-col {
+    display: inline-block;
+    vertical-align: top;
+    float: none;
+  }
 }
diff --git a/src/templates/sharecomponent/columncomponent/index.jsx b/src/templates/sharecomponent/columncomponent/index.jsx
index 71179be..e8172e2 100644
--- a/src/templates/sharecomponent/columncomponent/index.jsx
+++ b/src/templates/sharecomponent/columncomponent/index.jsx
@@ -470,18 +470,18 @@
     })
   }
 
-  revert = () => {
-    this.setState({
-      columnlist: fromJS(this.props.config.columns).toJS()
-    })
-  }
+  // revert = () => {
+  //   this.setState({
+  //     columnlist: fromJS(this.props.config.columns).toJS()
+  //   })
+  // }
 
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
   }
 
   componentDidMount () {
-    MKEmitter.addListener('revert', this.revert)
+    // MKEmitter.addListener('revert', this.revert)
     MKEmitter.addListener('plusColumns', this.plusColumns)
   }
 
@@ -492,7 +492,7 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('revert', this.revert)
+    // MKEmitter.removeListener('revert', this.revert)
     MKEmitter.removeListener('plusColumns', this.plusColumns)
   }
 
diff --git a/src/templates/sharecomponent/fieldscomponent/editcard/index.jsx b/src/templates/sharecomponent/fieldscomponent/editcard/index.jsx
index d4eb344..4387911 100644
--- a/src/templates/sharecomponent/fieldscomponent/editcard/index.jsx
+++ b/src/templates/sharecomponent/fieldscomponent/editcard/index.jsx
@@ -18,7 +18,9 @@
           _type = 'text'
         }
       } else if (props.type === 'search') {
-        if (_type !== 'select') {
+        if (_type === 'date' || _type === 'datetime') {
+          _type = 'date'
+        } else if (_type !== 'select') {
           _type = 'text'
         }
       } else if (props.type === 'form') {
@@ -83,6 +85,7 @@
           <Radio.Group onChange={this.changeType} value={card.type} disabled={!card.selected || card.origin}>
             <Radio value="text">text</Radio>
             <Radio value="select">select</Radio>
+            <Radio value="date">date</Radio>
           </Radio.Group> : null
         }
         {type === 'columns' ?
diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx
index 0aa6042..c493ccd 100644
--- a/src/templates/sharecomponent/fieldscomponent/index.jsx
+++ b/src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -106,10 +106,13 @@
       selectCards.forEach(item => {
         let _match = ''
         let initval = ''
-        if (item.type === 'select') {
+        let _type = item.type
+        if (item.type === 'date') {
+          _type = 'daterange'
+        } else if (item.type === 'select') {
           _match = '='
         } else {
-          item.type = 'text'
+          _type = 'text'
           _match = 'like'
         }
 
@@ -118,7 +121,7 @@
           label: item.label,
           field: item.field,
           initval: initval,
-          type: item.type,
+          type: _type,
           resourceType: '0',
           options: [],
           orderType: 'asc',
@@ -163,7 +166,7 @@
           field: item.field,
           datatype: _t
         }
-        items.push(newcard)
+        items.unshift(newcard)
         keys.push(item.field.toLowerCase())
       })
 
@@ -194,7 +197,13 @@
           required: 'true'
         }
 
-        if (item.type === 'text' && item.length >= 256) {
+        if (/^icon|images?$/ig.test(item.field)) {
+          newcard.type = 'fileupload'
+          newcard.fileType = 'picture-card'
+          newcard.fieldlength = item.length || 512
+          newcard.maxSize = 1
+          newcard.maxfile = 1
+        } else if (item.type === 'text' && item.length >= 256) {
           newcard.type = 'textarea'
           newcard.required = 'false'
           newcard.fieldlength = item.length
@@ -263,9 +272,16 @@
     const { type } = this.props
     const { fields } = this.state
 
+    let label = '鎵归噺娣诲姞'
+    if (type === 'search') {
+      label = '娣诲姞鎼滅储'
+    } else if (type === 'columns') {
+      label = '娣诲姞鏄剧ず鍒�'
+    }
+
     return (
       <div className="quickly-add">
-        <Button type="primary" block onClick={this.queryField}>鎵归噺娣诲姞</Button>
+        <Button type="primary" block onClick={this.queryField}>{label}</Button>
         {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */}
         <Modal
           wrapClassName="model-table-fieldmanage-modal"
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index 2951024..6d282da 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -44,12 +44,12 @@
 
   componentDidMount () {
     MKEmitter.addListener('plusSearch', this.plusSearch)
-    MKEmitter.addListener('revert', this.revert)
+    // MKEmitter.addListener('revert', this.revert)
   }
 
-  revert = () => {
-    this.setState({searchlist: fromJS(this.props.config.search).toJS()})
-  }
+  // revert = () => {
+  //   this.setState({searchlist: fromJS(this.props.config.search).toJS()})
+  // }
 
   plusSearch = (MenuId, item, type) => {
     const { config } = this.props
@@ -321,7 +321,7 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('revert', this.revert)
+    // MKEmitter.removeListener('revert', this.revert)
     MKEmitter.removeListener('plusSearch', this.plusSearch)
   }
 
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
index 6588635..95350b6 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -87,6 +87,8 @@
       {value: '[7, -7]', label: '鍓嶅悗涓冨ぉ'},
       {value: '[30, -30]', label: '鍓嶅悗30澶�'},
       {value: '[90, -90]', label: '鍓嶅悗90澶�'},
+      {value: '[180, -180]', label: '鍓嶅悗180澶�'},
+      {value: '[365, -365]', label: '鍓嶅悗365澶�'},
       {value: '[-1, -1]', label: '鏄庡ぉ'},
       {value: '[-2, -2]', label: '鍚庡ぉ'}
     ]
@@ -104,6 +106,8 @@
   datemonth: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'query', 'labelwidth'],
   daterange: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required', 'Hide', 'labelShow', 'advanced', 'query', 'precision', 'labelwidth'],
   group: ['label', 'type', 'field', 'datefield', 'initval', 'blacklist', 'ratio', 'items', 'required', 'labelShow', 'query', 'labelwidth'],
+  switch: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'openVal', 'closeVal', 'openText', 'closeText', 'Hide', 'labelShow', 'advanced', 'query', 'labelwidth'],
+  check: ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'openVal', 'closeVal', 'checkTip', 'Hide', 'labelShow', 'advanced', 'query', 'labelwidth'],
   range: ['label', 'type', 'field', 'initval', 'match', 'blacklist', 'Hide', 'required', 'maxValue', 'minValue', 'step', 'labelShow', 'query', 'labelwidth']
 }
 
@@ -226,22 +230,24 @@
     }
 
     if (type === 'text') {
-      reOptions.match = matchReg.text
+      reOptions.match = matchReg.class1
     } else if (type === 'multiselect') {
-      reOptions.match = matchReg.multiselect
+      reOptions.match = matchReg.class3
     } else if (type === 'select' || type === 'link') {
-      reOptions.match = matchReg.select
+      reOptions.match = matchReg.class1
+    } else if (type === 'switch' || type === 'check') {
+      reOptions.match = matchReg.class2
     } else if (type === 'date') {
-      reOptions.match = matchReg.date
+      reOptions.match = matchReg.class4
     } else if (type === 'datemonth') {
-      reOptions.match = matchReg.datemonth
+      reOptions.match = matchReg.class5
     } else if (type === 'dateweek' || type === 'daterange' || type === 'range') {
-      reOptions.match = matchReg.daterange
+      reOptions.match = matchReg.class5
     } else if (type === 'checkcard') {
       if (this.record.multiple === 'false') {
-        reOptions.match = matchReg.select
+        reOptions.match = matchReg.class1
       } else if (this.record.multiple === 'true') {
-        reOptions.match = matchReg.multiselect
+        reOptions.match = matchReg.class3
       }
     }
 
@@ -738,6 +744,8 @@
               })
               return
             }
+          } else if (values.type === 'switch' || values.type === 'check') {
+            values.initval = values.initval === values.openVal ? values.openVal : values.closeVal
           }
 
           ['linkField', 'valueField', 'valueText', 'orderBy'].forEach(item => {
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx
index 1a6de21..6b8f830 100644
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx
+++ b/src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx
@@ -90,6 +90,14 @@
               })
               reject()
               return
+            } else if (/,,/ig.test(values.dataresource)) {
+              notification.warning({
+                top: 92,
+                message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜拌繛缁殑鑻辨枃閫楀彿锛�,,锛�',
+                duration: 5
+              })
+              reject()
+              return
             }
 
             let error = Utils.verifySql(values.dataresource)
diff --git a/src/templates/sharecomponent/settingcomponent/index.jsx b/src/templates/sharecomponent/settingcomponent/index.jsx
index 4886a07..3f9e0ce 100644
--- a/src/templates/sharecomponent/settingcomponent/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/index.jsx
@@ -64,7 +64,6 @@
         visible: false,
         loading: false
       })
-      res.actionfixed = res.actionfixed === 'true'
 
       this.props.updatesetting({...config, setting: res})
     }, () => {
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
index 323f052..29f51db 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
@@ -119,6 +119,14 @@
               })
               reject()
               return
+            } else if (/,,/ig.test(values.dataresource)) {
+              notification.warning({
+                top: 92,
+                message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜拌繛缁殑鑻辨枃閫楀彿锛�,,锛�',
+                duration: 5
+              })
+              reject()
+              return
             }
 
             let error = Utils.verifySql(values.dataresource)
@@ -442,7 +450,7 @@
           {config.Template === 'CommonTable' ? <Col span={8}>
             <Form.Item label="鎸夐挳鍥哄畾">
               {getFieldDecorator('actionfixed', {
-                initialValue: setting.actionfixed === 'true' || setting.actionfixed === true ? 'true' : 'false'
+                initialValue: setting.actionfixed === 'true' ? 'true' : 'false'
               })(
               <Radio.Group>
                 <Radio value="true">鏄�</Radio>
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
index 2f679b7..fbfb050 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
@@ -265,6 +265,13 @@
         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')
diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx
index 540dee1..15954e3 100644
--- a/src/templates/sharecomponent/tablecomponent/index.jsx
+++ b/src/templates/sharecomponent/tablecomponent/index.jsx
@@ -8,6 +8,7 @@
 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'
 
 import './index.scss'
@@ -33,15 +34,28 @@
   UNSAFE_componentWillMount () {
     const { config } = this.props
 
+    let tables = config.tables ? fromJS(config.tables).toJS() : []
+
+    window.GLOB.publicTables = tables
+
     this.setState({
-      selectedTables: config.tables ? fromJS(config.tables).toJS() : []
+      selectedTables: tables
     }, () => {
       this.gettableFields()
     })
   }
 
   componentDidMount () {
+    MKEmitter.addListener('publicTableChange', this.publicTableChange)
     this.gettables()
+  }
+
+  publicTableChange = (table, type) => {
+    if (type === 'plus') {
+      this.onTableChange(table)
+    } else if (type === 'del') {
+      this.deleteTable(table)
+    }
   }
 
   /**
@@ -170,11 +184,15 @@
     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
+
       this.setState({
-        selectedTables: [...selectedTables, _table]
+        selectedTables: _tables
       })
 
-      let _config = {...config, tables: [...selectedTables, _table]}
+      let _config = {...config, tables: _tables}
       
       Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
         if (res.status) {
@@ -248,6 +266,8 @@
     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
@@ -265,6 +285,7 @@
     this.setState = () => {
       return
     }
+    MKEmitter.removeListener('publicTableChange', this.publicTableChange)
   }
 
   render() {
@@ -276,7 +297,7 @@
         {/* 琛ㄥ悕娣诲姞 */}
         <div className="ant-col ant-form-item-label">
           <label>
-            <Tooltip placement="topLeft" title="姝ゅ鍙互娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽彲閫氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鍙壒閲忔坊鍔犺〃鏍肩浉鍏冲瓧娈点��">
+            <Tooltip placement="topLeft" title="姝ゅ鍙互娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃銆�">
               <QuestionCircleOutlined className="mk-form-tip" />
               琛ㄥ悕
             </Tooltip>
diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
index ab38ac2..0a21e7d 100644
--- a/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
+++ b/src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
@@ -108,6 +108,14 @@
               })
               reject()
               return
+            } else if (/,,/ig.test(values.dataresource)) {
+              notification.warning({
+                top: 92,
+                message: '鏁版嵁婧愪腑锛屼笉鍙嚭鐜拌繛缁殑鑻辨枃閫楀彿锛�,,锛�',
+                duration: 5
+              })
+              reject()
+              return
             }
 
             let error = Utils.verifySql(values.dataresource)
diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx
index c47ca6d..524b4f1 100644
--- a/src/templates/subtableconfig/index.jsx
+++ b/src/templates/subtableconfig/index.jsx
@@ -9,7 +9,6 @@
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-import MKEmitter from '@/utils/events.js'
 import { updateSubTable } from '@/utils/utils-update.js'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -26,7 +25,7 @@
 const { confirm } = Modal
 
 const Versions = asyncComponent(() => import('@/menu/versions'))
-const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
+// const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
 const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent'))
 const SettingComponent = asyncComponent(() => import('@/templates/sharecomponent/settingcomponent'))
 const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
@@ -342,7 +341,6 @@
     }
 
     let _LongParam = ''
-    let reload = _config.isAdd
 
     // 淇濆瓨鏃跺垹闄ら厤缃被鍨嬶紝system 銆乽ser
     delete _config.type
@@ -502,7 +500,6 @@
             config: _config,
             originConfig: fromJS(_config).toJS()
           }, () => {
-            reload && MKEmitter.emit('revert')
             this.setState({
               menuloading: false,
               menucloseloading: false
@@ -998,7 +995,7 @@
             } bordered={false} extra={
               <div>
                 <Versions MenuId={config.uuid} open_edition={openEdition} updateConfig={this.refreshConfig}/>
-                <ReplaceField type="table" config={config} updateConfig={this.updateconfig}/>
+                {/* <ReplaceField type="table" config={config} updateConfig={this.updateconfig}/> */}
                 <EditComponent type="table" options={['search', 'form', 'action', 'columns']} config={config} refresh={this.updateConfig}/>
                 <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} />
                 <Button type="primary" id="save-config" onClick={this.submitConfig} loading={this.state.menuloading}>淇濆瓨</Button>
diff --git a/src/templates/subtableconfig/source.jsx b/src/templates/subtableconfig/source.jsx
index ef337b5..58b2581 100644
--- a/src/templates/subtableconfig/source.jsx
+++ b/src/templates/subtableconfig/source.jsx
@@ -22,127 +22,9 @@
       outerFunc: ''
     },
     tables: [],
-    search: [
-      {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'text',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: 'like',
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'select',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: '=',
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'label',
-        field: '',
-        initval: '',
-        type: 'date',
-        resourceType: '0',
-        options: [],
-        orderType: 'asc',
-        match: 'greater',
-      }
-    ],
-    action: [
-      {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'add',
-        intertype: 'system',
-        Ot: 'notRequired',
-        position: 'toolbar',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'pop',
-        icon: 'plus',
-        class: 'green',
-        verify: null
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'update',
-        intertype: 'system',
-        Ot: 'requiredSgl',
-        position: 'grid',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'pop',
-        icon: 'form',
-        class: 'purple',
-        verify: null
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        label: 'delete',
-        intertype: 'system',
-        Ot: 'required',
-        position: 'toolbar',
-        execSuccess: 'grid',
-        execError: 'never',
-        OpenType: 'prompt',
-        icon: 'delete',
-        class: 'red',
-        verify: null
-      }
-    ],
-    columns: [
-      {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }, {
-        origin: true,
-        uuid: Utils.getuuid(),
-        Align: 'left',
-        label: 'label',
-        field: '',
-        Hide: 'false',
-        IsSort: 'true',
-        type: 'text',
-        Width: 120
-      }
-    ],
+    search: [],
+    action: [],
+    columns: [],
     gridBtn: {
       display: false,
       Align: 'center',
diff --git a/src/templates/zshare/codemirror/index.jsx b/src/templates/zshare/codemirror/index.jsx
index aa4698f..729bb1a 100644
--- a/src/templates/zshare/codemirror/index.jsx
+++ b/src/templates/zshare/codemirror/index.jsx
@@ -1,11 +1,12 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Dropdown, Menu } from 'antd'
-import { FullscreenOutlined, FullscreenExitOutlined, FontSizeOutlined, FormatPainterOutlined } from '@ant-design/icons'
+import { Dropdown, Menu, Modal, notification } from 'antd'
+import { FullscreenOutlined, FullscreenExitOutlined, FontSizeOutlined, FormatPainterOutlined, SwapOutlined } from '@ant-design/icons'
 
 import {UnControlled as CodeMirror} from 'react-codemirror2'
 import sqlFormatter from '@/utils/sqlFormatter.js'
+import ReplaceForm from './replaceform'
 import 'codemirror/mode/javascript/javascript'
 import 'codemirror/mode/sql/sql'
 import 'codemirror/mode/xml/xml'
@@ -33,7 +34,8 @@
     options: null,  // mode : text/xml, text/css, text/javascript銆乼ext/x-mysql ; theme : cobalt - 榛戝簳
     fullScreen: false,
     style: {fontSize: '18px', lineHeight: '32px'},
-    display: true
+    display: true,
+    visible: false
   }
 
   editor = null
@@ -149,9 +151,45 @@
     this.props.onChange(_sql)
   }
 
+  submit = () => {
+    let _sql = this.state.value
+
+    this.ReplaceRef.handleConfirm().then(res => {
+      let reg = new RegExp(res.origin, 'ig')
+      let times = _sql.match(reg)
+
+      if (!times) {
+        notification.warning({
+          top: 92,
+          message: '鏈煡璇㈠埌瀛楃銆�' + res.origin + '銆嬨��',
+          duration: 5
+        })
+        return
+      }
+
+      let _href = window.location.href.split('#')[0]
+      localStorage.setItem(_href + 'sql_char', JSON.stringify([res.origin, res.value]))
+
+      _sql = _sql.replace(reg, res.value)
+
+      this.setState({display: false, defaultVal: _sql}, () => {
+        this.setState({display: true})
+      })
+      
+      this.props.onChange(_sql)
+
+      notification.success({
+        top: 92,
+        message: `鍏辨浛鎹�${times.length}澶勫瓧绗︺��${res.origin}銆嬨�俙,
+        duration: 5
+      })
+      this.setState({ visible: false })
+    })
+  }
+
   render() {
     const { mode, func } = this.props
-    const { defaultVal, options, fullScreen, style, display } = this.state
+    const { defaultVal, options, fullScreen, style, display, visible } = this.state
     const menu = (
       <Menu>
         <Menu.Item
@@ -194,24 +232,39 @@
     )
 
     return (
-      <div className="code-mirror-wrap" style={fullScreen || func ? style : null}>
-        {!mode && !fullScreen ? <FormatPainterOutlined onClick={this.handleFormat}/> : null}
-        {!fullScreen ? <FullscreenOutlined onClick={this.fullScreenChange}/> : null}
-        {fullScreen ? <FullscreenExitOutlined onClick={this.fullScreenChange}/> : null}
-        {fullScreen || func ? <Dropdown overlayClassName="mk-mirror-font" overlay={menu} placement="bottomRight">
-          <FontSizeOutlined />
-        </Dropdown> : null}
-        {display ? <CodeMirror
-          className="code-mirror-area"
-          value={defaultVal}
-          options={options}
-          editorDidMount={editor => { this.editor = editor }}
-          onChange={(editor, data, value) => {
-            this.setState({value})
-            this.props.onChange(value)
-          }}
-        /> : null}
-      </div>
+      <>
+        <div className={'code-mirror-wrap ' + (fullScreen ? 'mk-fullscreen' : '')} style={fullScreen || func ? style : null}>
+          {!mode ? <FormatPainterOutlined title="鏍煎紡鍖�" onClick={this.handleFormat}/> : null}
+          <FullscreenOutlined title="鏈�澶у寲" onClick={this.fullScreenChange}/>
+          <FullscreenExitOutlined title="鍚戜笅杩樺師" onClick={this.fullScreenChange}/>
+          {fullScreen || func ? <Dropdown overlayClassName="mk-mirror-font" overlay={menu} placement="bottomRight">
+            <FontSizeOutlined />
+          </Dropdown> : null}
+          <SwapOutlined title="瀛楃鏇挎崲" onClick={() => this.setState({visible: true})}/>
+          {display ? <CodeMirror
+            className="code-mirror-area"
+            value={defaultVal}
+            options={options}
+            editorDidMount={editor => { this.editor = editor }}
+            onChange={(editor, data, value) => {
+              this.setState({value})
+              this.props.onChange(value)
+            }}
+          /> : null}
+        </div>
+        <Modal
+          title="瀛楃鏇挎崲"
+          visible={visible}
+          width={500}
+          maskClosable={false}
+          okText="鏇挎崲"
+          onOk={this.submit}
+          onCancel={() => {this.setState({ visible: false })}}
+          destroyOnClose
+        >
+          <ReplaceForm inputSubmit={this.submit} wrappedComponentRef={(inst) => this.ReplaceRef = inst}/>
+        </Modal>
+      </>
     )
   }
 }
diff --git a/src/templates/zshare/codemirror/index.scss b/src/templates/zshare/codemirror/index.scss
index 2ee7018..bcd1d5a 100644
--- a/src/templates/zshare/codemirror/index.scss
+++ b/src/templates/zshare/codemirror/index.scss
@@ -37,6 +37,7 @@
     color: #1890ff;
     cursor: pointer;
     transition: opacity 0.3s;
+    display: none;
   }
   .anticon-fullscreen-exit:hover {
     opacity: 1;
@@ -45,7 +46,7 @@
     position: fixed;
     z-index: 11;
     right: 10px;
-    top: 40px;
+    top: 65px;
     font-size: 20px;
     opacity: 0.7;
     color: #1890ff;
@@ -87,6 +88,44 @@
       background: #f5f5f5;
     }
   }
+  .anticon-swap {
+    position: absolute;
+    left: -25px;
+    top: 40px;
+    color: #13c2c2;
+    font-size: 16px;
+  }
+}
+.code-mirror-wrap.mk-fullscreen {
+  .anticon-format-painter {
+    position: fixed;
+    z-index: 11;
+  }
+  .anticon-fullscreen-exit {
+    display: inline-block;
+  }
+  .anticon-fullscreen {
+    display: none;
+  }
+
+  .anticon-swap {
+    position: fixed;
+    z-index: 11;
+    left: auto;
+    right: 10px;
+    top: auto;
+    bottom: 20px;
+  }
+}
+.model-custom-scripts-modal .code-mirror-wrap:not(.mk-fullscreen), .model-custom-view-scripts-modal .code-mirror-wrap:not(.mk-fullscreen) {
+  .anticon-swap {
+    position: absolute;
+    z-index: 11;
+    left: auto;
+    right: 10px;
+    top: auto;
+    bottom: 20px;
+  }
 }
 .mk-mirror-font {
   z-index: 1200!important;
diff --git a/src/templates/zshare/codemirror/replaceform/index.jsx b/src/templates/zshare/codemirror/replaceform/index.jsx
new file mode 100644
index 0000000..2cf2646
--- /dev/null
+++ b/src/templates/zshare/codemirror/replaceform/index.jsx
@@ -0,0 +1,102 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input } from 'antd'
+// import './index.scss'
+
+class ReplaceForm extends Component {
+  static propTpyes = {
+    inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢
+  }
+
+  state = {
+    orivalue: '',
+    value: ''
+  }
+
+  UNSAFE_componentWillMount() {
+    let _href = window.location.href.split('#')[0]
+    let res = localStorage.getItem(_href + 'sql_char')
+
+    if (res) {
+      res = JSON.parse(res)
+
+      this.setState({
+        orivalue: res[0] || '',
+        value: res[1] || ''
+      })
+    }
+  }
+
+  componentDidMount () {
+    try {
+      let _form = document.getElementById('origin')
+      if (_form && _form.select) {
+        _form.select()
+      }
+    } catch (e) {
+      console.warn('Form focusing error锛�')
+    }
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        }
+      })
+    })
+  }
+
+  enterPress = (e) => {
+    e.stopPropagation()
+
+    setTimeout(() => {
+      this.props.inputSubmit()
+    }, 200)
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const { orivalue, value } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 14 }
+      }
+    }
+    return (
+      <Form {...formItemLayout}>
+        <Row gutter={24}>
+          <Col span={24}>
+            <Form.Item label="鍘熷瓧绗�">
+              {getFieldDecorator('origin', {
+                initialValue: orivalue,
+                rules: [
+                  {
+                    required: true,
+                    message: '璇疯緭鍏ュ師瀛楃!'
+                  }
+                ]
+              })(<Input autoComplete="off" onPressEnter={this.enterPress}/>)}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label="鏇挎崲涓�">
+              {getFieldDecorator('value', {
+                initialValue: value
+              })(<Input autoComplete="off" onPressEnter={this.enterPress}/>)}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(ReplaceForm)
\ No newline at end of file
diff --git a/src/templates/zshare/codemirror/replaceform/index.scss b/src/templates/zshare/codemirror/replaceform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/templates/zshare/codemirror/replaceform/index.scss
diff --git a/src/templates/zshare/customscript/index.jsx b/src/templates/zshare/customscript/index.jsx
index bdd9c1d..2cc6298 100644
--- a/src/templates/zshare/customscript/index.jsx
+++ b/src/templates/zshare/customscript/index.jsx
@@ -231,6 +231,13 @@
         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')
diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx
index ff2c97f..ad29e43 100644
--- a/src/templates/zshare/editTable/index.jsx
+++ b/src/templates/zshare/editTable/index.jsx
@@ -3,17 +3,17 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider, DragSource, DropTarget } from 'react-dnd'
 import { Table, Input, InputNumber, Popconfirm, Form, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd'
-import { CopyOutlined, EditOutlined, DeleteOutlined, SnippetsOutlined, SwapOutlined } from '@ant-design/icons'
+import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined } from '@ant-design/icons'
 
 import Utils from '@/utils/utils.js'
 import ColorSketch from '@/mob/colorsketch'
-import PasteForm from '@/templates/zshare/pasteform'
 import asyncComponent from '@/utils/asyncComponent'
 import CusSwitch from './cusSwitch'
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
+const PasteBoard = asyncComponent(() => import('@/components/pasteboard'))
 const EditableContext = React.createContext()
 const { confirm } = Modal
 let dragingIndex = -1
@@ -163,6 +163,7 @@
 class EditTable extends Component {
   static propTpyes = {
     actions: PropTypes.any,         // 鎿嶄綔椤�
+    searchKey: PropTypes.any,       // 鎼滅储鏉′欢
     data: PropTypes.any,            // 鏁版嵁鍒楄〃
     columns: PropTypes.array,       // 鏄剧ず鍒�
     onChange: PropTypes.func        // 鏁版嵁鍙樺寲
@@ -171,7 +172,6 @@
   state = {
     data: [],
     editingKey: '',
-    visible: false,
     editLineId: '',
     columns: []
   }
@@ -195,7 +195,7 @@
           鎿嶄綔
           <span className="copy-control">
             {actions.includes('copy') ? <CopyOutlined title="澶嶅埗" onClick={() => this.copy()} /> : null}
-            {actions.includes('copy') ? <SnippetsOutlined title="绮樿创" onClick={this.paste} /> : null}
+            {actions.includes('copy') ? <PasteBoard getPasteValue={this.pasteSubmit}/> : null}
             {actions.includes('clear') ? <DeleteOutlined title="娓呯┖" onClick={this.clear} /> : null}
           </span>
         </div>),
@@ -351,66 +351,74 @@
     }
   }
   
-  paste = () => {
-    this.setState({visible: true})
-  }
-  
-  pasteSubmit = () => {
+  pasteSubmit = (res, callback) => {
     const { type } = this.props
     const { columns } = this.state
     let data = fromJS(this.state.data).toJS()
 
-    this.pasteFormRef.handleConfirm().then(res => {
-      if (res.copyType === 'columns' && type === 'datasourcefield') {
-        res.type = 'array'
-        res.data = []
-        res.columns.forEach(col => {
-          if (!col.field) return
-          if (col.type === 'number') {
-            let datatype = 'Int'
-            if (col.decimal) {
-              datatype = `Decimal(18,${col.decimal})`
-            }
-
-            res.data.push({
-              $index: res.data.length + 1,
-              datatype: datatype,
-              field: col.field,
-              decimal: col.decimal,
-              label: col.label,
-              type: 'number',
-              uuid: Utils.getuuid()
-            })
-          } else {
-            let datatype = 'Nvarchar(50)'
-            let fieldlength = 50
-            if (col.fieldlength && [10, 20, 50, 100, 256, 512, 1024, 2048].includes(col.fieldlength)) {
-              fieldlength = col.fieldlength
-              datatype = `Nvarchar(${fieldlength})`
-            }
-
-            res.data.push({
-              $index: res.data.length + 1,
-              datatype: datatype,
-              field: col.field,
-              fieldlength: fieldlength,
-              label: col.label,
-              type: 'text',
-              uuid: Utils.getuuid()
-            })
+    if (res.copyType === 'columns' && type === 'datasourcefield') {
+      res.type = 'array'
+      res.data = []
+      res.columns.forEach(col => {
+        if (!col.field) return
+        if (col.type === 'number') {
+          let datatype = 'Int'
+          if (col.decimal) {
+            datatype = `Decimal(18,${col.decimal})`
           }
-        })
-      } else if (res.key !== type) {
-        message.warning('閰嶇疆淇℃伅鏍煎紡閿欒锛�')
-        return
-      }
 
-      if (res.type === 'line') {
-        let unique = true
-        res.data.uuid = Utils.getuuid()
-        columns.forEach(col => {
-          if (col.unique !== true || !unique) return
+          res.data.push({
+            $index: res.data.length + 1,
+            datatype: datatype,
+            field: col.field,
+            decimal: col.decimal,
+            label: col.label,
+            type: 'number',
+            uuid: Utils.getuuid()
+          })
+        } else {
+          let datatype = 'Nvarchar(50)'
+          let fieldlength = 50
+          if (col.fieldlength && [10, 20, 50, 100, 256, 512, 1024, 2048].includes(col.fieldlength)) {
+            fieldlength = col.fieldlength
+            datatype = `Nvarchar(${fieldlength})`
+          }
 
+          res.data.push({
+            $index: res.data.length + 1,
+            datatype: datatype,
+            field: col.field,
+            fieldlength: fieldlength,
+            label: col.label,
+            type: 'text',
+            uuid: Utils.getuuid()
+          })
+        }
+      })
+    } else if (res.key !== type) {
+      message.warning('閰嶇疆淇℃伅鏍煎紡閿欒锛�')
+      return
+    }
+
+    if (res.type === 'line') {
+      let unique = true
+      res.data.uuid = Utils.getuuid()
+      columns.forEach(col => {
+        if (col.unique !== true || !unique) return
+
+        if (col.strict) {
+          let key = res.data[col.dataIndex].toLowerCase()
+          let _index = data.findIndex(item => key === item[col.dataIndex].toLowerCase())
+
+          if (_index > -1) {
+            notification.warning({
+              top: 92,
+              message: col.title + '涓嶅彲閲嶅锛�',
+              duration: 5
+            })
+            unique = false
+          }
+        } else {
           let _index = data.findIndex(item => res.data[col.dataIndex] === item[col.dataIndex])
 
           if (_index > -1) {
@@ -421,38 +429,49 @@
             })
             unique = false
           }
-        })
+        }
+      })
 
-        if (!unique) return
+      if (!unique) return
 
-        data.unshift(res.data)
-        this.setState({ data, editingKey: '', visible: false }, () => {
-          this.props.onChange(data)
-        })
-      } else if (res.type === 'array') {
-        res.data.forEach(cell => {
-          let unique = true
-          cell.uuid = Utils.getuuid()
-          columns.forEach(col => {
-            if (col.unique !== true || !unique) return
+      data.unshift(res.data)
+      this.setState({ data, editingKey: '', editLineId: res.data.uuid || '' }, () => {
+        this.props.onChange(data)
+      })
+    } else if (res.type === 'array') {
+      res.data.forEach(cell => {
+        let unique = true
+        cell.uuid = Utils.getuuid()
+        columns.forEach(col => {
+          if (col.unique !== true || !unique) return
+
+          if (col.strict) {
+            let _index = data.findIndex(item => cell[col.dataIndex].toLowerCase() === item[col.dataIndex].toLowerCase())
+  
+            if (_index > -1) {
+              unique = false
+            }
+          } else {
             let _index = data.findIndex(item => cell[col.dataIndex] === item[col.dataIndex])
   
             if (_index > -1) {
               unique = false
             }
-          })
-  
-          if (!unique) return
-  
-          data.push(cell)
+          }
         })
 
-        this.setState({ data, editingKey: '', visible: false }, () => {
-          this.props.onChange(data)
-        })
-      }
-      message.success('绮樿创鎴愬姛銆�')
-    })
+        if (!unique) return
+
+        data.push(cell)
+      })
+
+      this.setState({ data, editingKey: '' }, () => {
+        this.props.onChange(data)
+      })
+    }
+
+    callback()
+    message.success('绮樿创鎴愬姛銆�')
   }
 
   handleStatus = (record) => {
@@ -585,7 +604,7 @@
   }
 
   render() {
-    const { actions, indexShow } = this.props
+    const { actions, indexShow, searchKey } = this.props
     const { editLineId } = this.state
 
     let components = {
@@ -595,7 +614,7 @@
     }
 
     let moveprops = {}
-    if (actions.includes('move')) {
+    if (actions.includes('move') && !searchKey) {
       components.body.row = DragableBodyRow
       moveprops.moveAble = !this.state.editingKey
       moveprops.moveRow = this.moveRow
@@ -641,6 +660,8 @@
       return item
     })
 
+    let reg = searchKey ? new RegExp(searchKey, 'ig') : null
+
     return (
       <EditableContext.Provider value={this.props.form}>
         <div className="modal-edit-table">
@@ -651,7 +672,18 @@
               components={components}
               dataSource={data}
               columns={columns}
-              rowClassName={record => !editLineId || editLineId !== record.uuid ? 'editable-row' : 'editable-row active'}
+              rowClassName={record => {
+                let className = 'editable-row'
+                if (editLineId && editLineId === record.uuid) {
+                  className += ' active'
+                }
+                if (searchKey) {
+                  if (!reg.test(record.field) && !reg.test(record.label)) {
+                    className += ' hidden'
+                  }
+                }
+                return className
+              }}
               pagination={false}
               onRow={(record, index) => ({
                 index,
@@ -659,18 +691,6 @@
               })}
             />
           </DndProvider>
-          {/* 淇℃伅绮樿创 */}
-          <Modal
-            title="绮樿创"
-            visible={this.state.visible}
-            width={600}
-            maskClosable={false}
-            onOk={this.pasteSubmit}
-            onCancel={() => {this.setState({visible: false})}}
-            destroyOnClose
-          >
-            <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/>
-          </Modal>
         </div>
       </EditableContext.Provider>
     )
diff --git a/src/templates/zshare/editTable/index.scss b/src/templates/zshare/editTable/index.scss
index a2f12ad..cac8205 100644
--- a/src/templates/zshare/editTable/index.scss
+++ b/src/templates/zshare/editTable/index.scss
@@ -31,6 +31,9 @@
       background-color: #bae7ff!important;
     }
   }
+  .editable-row.hidden {
+    display: none;
+  }
   .mk-index {
     text-align: center;
     white-space: nowrap;
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 635f5a6..9512ea7 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -355,6 +355,12 @@
     }, {
       value: 'group',
       text: '鏃ユ湡锛堢粍鍚堬級'
+    }, {
+      value: 'switch',
+      text: '寮�鍏�'
+    }, {
+      value: 'check',
+      text: '鍕鹃�夋'
     }]
   }
 
@@ -834,6 +840,42 @@
         value: 'custom',
         text: '鑷畾涔�'
       }]
+    },
+    {
+      type: 'text',
+      key: 'openVal',
+      label: '寮�鍚��',
+      initVal: card.openVal || '',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'closeVal',
+      label: '鍏抽棴鍊�',
+      initVal: card.closeVal || '',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'openText',
+      label: '寮�鍚彁绀�',
+      initVal: card.openText || '',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'closeText',
+      label: '鍏抽棴鎻愮ず',
+      initVal: card.closeText || '',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'checkTip',
+      label: '鎻愮ず',
+      initVal: card.checkTip || '',
+      tooltip: '鍕鹃�夋鍚庣殑鎻愮ず鏂囧瓧',
+      required: false
     },
     {
       type: 'color',
@@ -1477,16 +1519,6 @@
         value: 'close',
         text: '鍏抽棴'
       }]
-    },
-    {
-      type: 'text',
-      key: 'preFunc',
-      label: '鍓嶇疆鍑芥暟',
-      initVal: card.preFunc || '',
-      tooltip: usefulFields.length ? `鍑芥暟鍚嶇О闇�浠�${usefulFields.join(', ')}绛夊瓧绗﹀紑濮嬶紱鍓嶇疆鍑芥暟鎵ц瀹屾垚鍚庯紝缁撴灉浼氫紶鍏ュ唴閮ㄥ嚱鏁颁腑锛屾鏃跺唴閮ㄥ嚱鏁颁細寮傛鎵ц锛涘綋鍓嶇疆鍑芥暟杩斿洖涓璄rrCode绛変簬-1鏃讹紝灏嗕笉鍐嶆墽琛屽唴閮ㄥ嚱鏁般�俙 : '',
-      fields: usefulFields,
-      required: false,
-      readonly: false
     },
     {
       type: 'radio',
@@ -2468,6 +2500,9 @@
     value: 'switch',
     text: '寮�鍏�'
   }, {
+    value: 'check',
+    text: '鍕鹃�夋'
+  }, {
     value: 'checkbox',
     text: '澶氶�夋'
   }, {
@@ -2542,6 +2577,9 @@
       value: 'switch',
       text: '寮�鍏�'
     }, {
+      value: 'check',
+      text: '鍕鹃�夋'
+    }, {
       value: 'checkbox',
       text: '澶氶�夋'
     }, {
@@ -2595,6 +2633,10 @@
     card.precision = 'second'
   }
 
+  if (!card.place && appType === 'mob') {
+    card.place = ['checkbox', 'radio', 'checkcard', 'textarea'].includes(card.type) ? 'up_down' : 'left_right'
+  }
+
   let options = card.options || []
   if (['select', 'radio', 'link'].includes(card.type) && card.setAll === 'true') { // 鍏煎
     options.unshift({
@@ -2606,7 +2648,7 @@
   }
 
   let initval = card.initval || ''
-  if (card.type === 'switch') {
+  if (card.type === 'switch' || card.type === 'check') {
     initval = card.initval === true
   } else if (card.type === 'number') {
     initval = card.initval || 0
@@ -2683,6 +2725,14 @@
       key: 'closeText',
       label: '鍏抽棴鎻愮ず',
       initVal: card.closeText || '',
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'checkTip',
+      label: '鎻愮ず',
+      initVal: card.checkTip || '',
+      tooltip: '鍕鹃�夋鍚庣殑鎻愮ず鏂囧瓧',
       required: false
     },
     {
@@ -2804,6 +2854,7 @@
       key: 'dataSource',
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆�',
       required: true,
       readonly: false
     },
@@ -3369,6 +3420,20 @@
       }]
     },
     {
+      type: 'radio',
+      key: 'unchecked',
+      label: '鏈�変腑椤�',
+      initVal: card.unchecked || 'show',
+      tooltip: '濡傛灉娌℃湁閫変腑椤癸紝璇ヨ〃鍗曞皢琚殣钘忋��',
+      options: [{
+        value: 'show',
+        text: '鏄剧ず'
+      }, {
+        value: 'hidden',
+        text: '闅愯棌'
+      }]
+    },
+    {
       type: 'color',
       key: 'backgroundColor',
       label: '鑳屾櫙鑹�',
@@ -3448,7 +3513,7 @@
       type: 'radio',
       key: 'eval',
       label: '瑙f瀽',
-      initVal: card.eval || 'true',
+      initVal: card.eval || 'false',
       tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
       required: false,
       options: [{
@@ -3494,7 +3559,7 @@
       key: 'place',
       label: '鎺掑垪',
       initVal: card.place || 'left_right',
-      tooltip: '鎻愮ず鏂囧瓧涓庤緭鍏ユ鐨勪綅缃叧绯汇�傛敞锛氶�夋嫨鍣ㄣ�佹棩鏈熻〃鍗曞湪琛ㄥ崟鏍峰紡涓洪槾褰辨椂鏈夋晥',
+      tooltip: '鎻愮ず鏂囧瓧涓庤緭鍏ユ鐨勪綅缃叧绯汇��',
       forbid: appType !== 'mob',
       options: [{
         value: 'left_right',
@@ -3661,6 +3726,20 @@
       }, {
         value: 'right',
         text: '鍙虫埅'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'constant',
+      label: 'Unicode甯搁噺',
+      tooltip: '浣跨敤鏃跺皢鍦ㄦ彁浜ゅ唴瀹瑰墠鍔犱笂 N锛屼唬琛ㄥ瓨鍏ユ暟鎹簱鏃朵互 Unicode 鏍煎紡瀛樺偍銆�',
+      initVal: card.constant || 'false',
+      options: [{
+        value: 'true',
+        text: '浣跨敤'
+      }, {
+        value: 'false',
+        text: '涓嶄娇鐢�'
       }]
     },
     {
@@ -3917,6 +3996,20 @@
     // },
     {
       type: 'radio',
+      key: 'pickerMode',
+      label: '寮圭獥鏍峰紡',
+      initVal: card.pickerMode || 'default',
+      required: false,
+      options: [
+        {value: 'default', text: '榛樿'},
+        {value: 'board', text: '闈㈡澘'},
+        {value: 'board-block', text: '闈㈡澘2'},
+        {value: 'dropdown', text: '涓嬫媺妗�'},
+      ],
+      forbid: appType !== 'mob'
+    },
+    {
+      type: 'radio',
       key: 'empty',
       label: '绌哄�奸殣钘�',
       initVal: card.empty || 'show',
diff --git a/src/templates/zshare/menuform/index.jsx b/src/templates/zshare/menuform/index.jsx
index b3ce1f3..f70d08e 100644
--- a/src/templates/zshare/menuform/index.jsx
+++ b/src/templates/zshare/menuform/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { Form, Row, Col, Input, Select } from 'antd'
 import { formRule } from '@/utils/option.js'
-import './index.scss'
+// import './index.scss'
 
 class MainSearch extends Component {
   static propTpyes = {
diff --git a/src/templates/zshare/modalform/datatable/index.jsx b/src/templates/zshare/modalform/datatable/index.jsx
index 7f13956..75a9a67 100644
--- a/src/templates/zshare/modalform/datatable/index.jsx
+++ b/src/templates/zshare/modalform/datatable/index.jsx
@@ -431,6 +431,8 @@
   }
 
   render() {
+    const { display, fields } = this.props
+
     const components = {
       body: {
         row: DragableBodyRow,
@@ -456,9 +458,9 @@
     })
 
     let addable = false
-    if (this.props.display === 'picture' || this.props.display === 'color') {
+    if (display === 'picture' || display === 'color') {
       addable = true
-    } else if (this.props.fields && this.props.fields.length > 0) {
+    } else if (fields && fields.length > 0) {
       addable = true
     }
 
diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx
index 84fd387..e766b8b 100644
--- a/src/templates/zshare/modalform/index.jsx
+++ b/src/templates/zshare/modalform/index.jsx
@@ -19,20 +19,21 @@
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
 
 const modalTypeOptions = {
-  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType'],
+  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant'],
   number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom'],
-  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom'],
-  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
-  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'setAll', 'emptyText', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
-  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'width', 'multiple', 'splitline', 'marginTop', 'marginBottom'],
+  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
+  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
+  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'setAll', 'emptyText', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
+  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'place', 'width', 'multiple', 'splitline', 'marginTop', 'marginBottom'],
   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'],
+  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'],
+  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', 'declareType', 'splitline', 'place', 'marginTop', 'marginBottom'],
+  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'],
-  textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'span', 'labelwidth', 'maxRows', 'encryption', 'interception', 'tooltip', 'extra', 'count', 'placeholder', 'marginTop', 'marginBottom'],
+  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'],
   rate: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'splitline', 'tooltip', 'extra', 'marginTop', 'marginBottom', 'allowHalf', 'color', 'rateCount', 'character', 'place'],
@@ -230,10 +231,13 @@
       if (sessionStorage.getItem('appType') === 'mob') {
         shows.push('hidelabel')
       }
+      if (this.record.readonly === 'true' && this.record.hidden !== 'true') {
+        shows.push('unchecked')
+      }
     } else if (['date', 'datemonth', 'datetime'].includes(type)) {
       reOptions.initval = dateOptions[type]
       reTypes.initval = 'select'
-    } else if (type === 'switch') {
+    } else if (type === 'switch' || type === 'check') {
       reOptions.initval = [
         {value: true, text: '寮�'},
         {value: false, text: '鍏�'}
@@ -335,6 +339,10 @@
       shows.push('supvalue')
     }
 
+    if (this.record.hidden === 'true') {
+      shows = shows.filter(s => !['supField', 'supvalue', 'tooltip', 'extra', 'enter', 'tabField'].includes(s))
+    }
+
     return {
       shows,
       reOptions,
@@ -363,7 +371,7 @@
       if (value === 'number' || value === 'rate') {
         this.record.initval = 0
         _fieldval.initval = 0
-      } else if (value === 'switch') {
+      } else if (value === 'switch' || value === 'check') {
         this.record.initval = false
         _fieldval.initval = false
       }
@@ -719,6 +727,9 @@
         if (this.record.type === 'select' || this.record.type === 'link') {
           extra = <span className="add-resource-empty" onClick={this.handleEmpty}>绌�</span>
         }
+        if (item.placeholder) {
+          extra = <><span className="resource-public-var">{item.placeholder}</span>{extra}</>
+        }
 
         content = <CodeMirror />
       } else if (item.type === 'textarea') {
@@ -801,6 +812,52 @@
     return fields
   }
 
+  transfer = (options) => {
+    if (options.length === 0) return options
+
+    let isNumber = true
+    options.forEach(item => {
+      if (!/^([0-9]|[1-9]\d{0,2})$/.test(item.Value)) {
+        isNumber = false
+      }
+    })
+
+    if (isNumber) {
+      return options.map(item => {
+        item.Value = +item.Value
+        return item
+      })
+    } else {
+      return options.map(item => {
+        item.Value = item.Value + ''
+        return item
+      })
+    }
+  }
+
+  transferCard = (options) => {
+    if (options.length === 0) return options
+
+    let isNumber = true
+    options.forEach(item => {
+      if (!/^([0-9]|[1-9]\d{0,2})$/.test(item.$value)) {
+        isNumber = false
+      }
+    })
+
+    if (isNumber) {
+      return options.map(item => {
+        item.$value = +item.$value
+        return item
+      })
+    } else {
+      return options.map(item => {
+        item.$value = item.$value + ''
+        return item
+      })
+    }
+  }
+
   handleConfirm = () => {
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
@@ -816,6 +873,8 @@
               if (values.type === 'radio' && values.linkField) {
                 type = 'link'
               }
+
+              values.options = this.transfer(values.options)
 
               if (values.options.filter(op => op.Text === '').length > 0) {
                 notification.warning({
@@ -870,6 +929,8 @@
                 return m
               })
 
+              values.options = this.transferCard(values.options)
+
               let type = values.type
               if (values.linkField) {
                 type = 'link'
diff --git a/src/templates/zshare/modalform/index.scss b/src/templates/zshare/modalform/index.scss
index ee25254..23d5929 100644
--- a/src/templates/zshare/modalform/index.scss
+++ b/src/templates/zshare/modalform/index.scss
@@ -47,6 +47,12 @@
     cursor: pointer;
     font-size: 14px;
   }
+  .resource-public-var {
+    position: absolute;
+    left: 0px;
+    top: -25px;
+    font-size: 14px;
+  }
   >.ant-row >.ant-col {
     display: inline-block;
     vertical-align: top;
diff --git a/src/templates/zshare/modalform/modaleditable/index.jsx b/src/templates/zshare/modalform/modaleditable/index.jsx
index 5e84435..053e370 100644
--- a/src/templates/zshare/modalform/modaleditable/index.jsx
+++ b/src/templates/zshare/modalform/modaleditable/index.jsx
@@ -140,51 +140,51 @@
     })
   }
 
-  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
-      }
+  // 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
+  //     item[column.dataIndex] = val
 
-      return item
-    })
+  //     return item
+  //   })
 
-    this.setState({
-      dataSource: _data,
-      columns: columns.map(col => {
-        if (col.dataIndex === column.dataIndex) {
-          col.datatype = value
-        }
+  //   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>
-        }
+  //       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)
-    })
-  }
+  //       return col
+  //     })
+  //   }, () => {
+  //     this.props.onChange(_data)
+  //   })
+  // }
 
   handleUpDown = (record, direction) => {
     const { dataSource } = this.state
@@ -373,13 +373,13 @@
         if (col.dataIndex !== 'operation') {
           col.title = <div>
             {col.$title}
-            <Popconfirm
+            {/* <Popconfirm
               title={`纭畾鍒囨崲涓�${col.datatype === 'number' ? '鏂囨湰' : '鏁板��'}鍚楋紵`}
               overlayClassName="popover-confirm"
               onConfirm={() => this.changeDatatype(col)
             }>
               <SwapOutlined style={{ color: col.datatype === 'number' ? '#1890ff' : ''}} />
-            </Popconfirm>
+            </Popconfirm> */}
           </div>
         }
         return col
diff --git a/src/templates/zshare/pasteform/index.jsx b/src/templates/zshare/pasteform/index.jsx
index 2facaa2..3067ef0 100644
--- a/src/templates/zshare/pasteform/index.jsx
+++ b/src/templates/zshare/pasteform/index.jsx
@@ -55,12 +55,31 @@
               }
             }
           } catch (e) {
-            notification.warning({
-              top: 92,
-              message: '瑙f瀽閿欒',
-              duration: 5
-            })
-            _config = ''
+            // 閫氳繃sql璇彞娣诲姞瀛楁闆�
+            if (/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int)/ig.test(values.config)) {
+              _config = {
+                key: 'datasourcefield',
+                type: 'array',
+                data: []
+              }
+
+              let list = values.config.match(/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int)/ig)
+
+              list.forEach(item => {
+                _config.data.unshift({
+                  datatype: item.split(/\s+/)[1],
+                  field: item.split(/\s+/)[0],
+                  label: item.split(/\s+/)[0],
+                })
+              })
+            } else {
+              notification.warning({
+                top: 92,
+                message: '瑙f瀽閿欒',
+                duration: 5
+              })
+              _config = ''
+            }
           }
 
           if (_config) {
diff --git a/src/templates/zshare/verifycard/baseform/index.jsx b/src/templates/zshare/verifycard/baseform/index.jsx
index a0f5892..00171d3 100644
--- a/src/templates/zshare/verifycard/baseform/index.jsx
+++ b/src/templates/zshare/verifycard/baseform/index.jsx
@@ -5,10 +5,9 @@
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
-import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
-const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
+const sysTempsIds = ['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok']
 
 class BillCodeForm extends Component {
   static propTpyes = {
@@ -26,7 +25,6 @@
   }
 
   componentDidMount() {
-    const { verify } = this.props
     let wxTemps = sessionStorage.getItem('wxTemplates')
 
     if (window.GLOB.WXAppID && window.GLOB.nginx && !wxTemps) {
@@ -38,21 +36,22 @@
           Api.wxNginxRequest(`cgi-bin/template/get_all_private_template?access_token=${wxtoken}`, 'get').then(res => {
             let temps = []
             if (res.template_list) {
-              temps = res.template_list.filter(item => item.primary_industry)
-              let selectTemp = temps.filter(item => item.template_id === verify.wxTemplateId)[0]
+              temps = res.template_list.filter(item => {
+                if (!item.primary_industry || sysTempsIds.includes(item.template_id)) return false
+                if (item.content) {
+                  item.content = item.content.replace('{{first.DATA}}\n', '').replace('\n{{remark.DATA}}', '')
+                }
 
-              if (selectTemp) {
-                selectTemp.content = selectTemp.content.replace(/\r\n|\n/g, '<br/>')
-                selectTemp.example = selectTemp.example.replace(/\r\n|\n/g, '<br/>')
-              }
-
-              this.setState({wxTemps: temps, selectTemp})
+                return true
+              })
             }
-
+            
             sessionStorage.setItem('wxTemplates', JSON.stringify(temps))
             localStorage.setItem('wxTemplates', JSON.stringify(temps))
 
             localStorage.removeItem('wxTemplates')
+
+            this.resetTemps(temps)
           })
         } else {
           sessionStorage.setItem('wxTemplates', JSON.stringify([]))
@@ -75,15 +74,50 @@
     } else if (wxTemps) {
       wxTemps = JSON.parse(wxTemps)
 
-      let selectTemp = wxTemps.filter(item => item.template_id === verify.wxTemplateId)[0]
-
-      if (selectTemp) {
-        selectTemp.content = selectTemp.content.replace(/\r\n|\n/g, '<br/>')
-        selectTemp.example = selectTemp.example.replace(/\r\n|\n/g, '<br/>')
-      }
-  
-      this.setState({wxTemps, selectTemp})
+      this.resetTemps(wxTemps)
     }
+  }
+
+  resetTemps = (wxTemps) => {
+    const { verify } = this.props
+
+    let sysTemps = [
+      {
+        template_id: '8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo',
+        title: '璁㈠崟鍙楃悊閫氱煡锛堟槑绉戜簯锛�',
+        primary_industry: 'IT绉戞妧',
+        deputy_industry: 'IT杞欢涓庢湇鍔�',
+        content: '璁㈠崟鍙凤細{{keyword1.DATA}}\n璁㈠崟绫诲瀷锛歿{keyword2.DATA}}\n璁㈠崟鐘舵�侊細{{keyword3.DATA}}\n閫氱煡鏃堕棿锛歿{keyword4.DATA}}',
+        example: '璁㈠崟鍙凤細20190101001\r\n璁㈠崟绫诲瀷锛氳。鏌淺r\n璁㈠崟鐘舵�侊細璁捐瀹屾垚\r\n閫氱煡鏃堕棿锛�2019骞�1鏈�1鏃�12:30'
+      },
+      {
+        template_id: 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok',
+        title: '璁㈠崟杩涘害鎻愰啋锛堟槑绉戜簯锛�',
+        primary_industry: 'IT绉戞妧',
+        deputy_industry: 'IT杞欢涓庢湇鍔�',
+        content: '璁㈠崟绫诲瀷锛歿{keyword1.DATA}}\n璁㈠崟鍙凤細{{keyword2.DATA}}\n璁㈠崟鐘舵�侊細{{keyword3.DATA}}',
+        example: '璁㈠崟绫诲瀷锛氶��绉熺敵璇穃r\n璁㈠崟鍙凤細TZ16101909\r\n璁㈠崟鐘舵�侊細寰呭彇璐�'
+      },
+      {
+        template_id: 'mk_category_temp',
+        title: '绫荤洰妯℃澘',
+        primary_industry: '',
+        deputy_industry: '',
+        content: '',
+        example: ''
+      }
+    ]
+    
+    let _wxTemps = [...wxTemps, ...sysTemps]
+
+    let selectTemp = _wxTemps.filter(item => item.template_id === verify.wxTemplateId)[0]
+
+    if (selectTemp) {
+      selectTemp.content = selectTemp.content.replace(/\r\n|\n/g, '<br/>')
+      selectTemp.example = selectTemp.example.replace(/\r\n|\n/g, '<br/>')
+    }
+
+    this.setState({wxTemps: _wxTemps, selectTemp})
   }
 
   handleConfirm = () => {
@@ -97,10 +131,11 @@
     } else if (verify.wxNote === 'true') {
       if (!verify.wxTemplateId) {
         error = '寮�鍚叕浼楀彿娑堟伅鎺ㄩ�佹椂锛岄渶瑕侀�夋嫨娑堟伅妯℃澘锛�'
+      } else if (verify.wxTemplateId === 'mk_category_temp' && !verify.wxCustomTempId) {
+        error = '寮�鍚叕浼楀彿娑堟伅鎺ㄩ�佹椂锛岄渶瑕佸~鍐欐秷鎭ā鏉縄D锛�'
       } else if (verify.wxNoteLink === 'url' && !verify.wxNoteLinkUrl) {
         error = '璇峰~鍐欑綉鍧�锛�'
       }
-
     }
 
     return error
@@ -125,6 +160,8 @@
       _verify.wxNoteLinkMenuId = ''
       _verify.wxNoteCallback = 'false'
       _verify.wxNoteKeys = null
+
+      delete _verify.wxCustomTempId
 
       if (this.state.selectTemp) {
         this.setState({selectTemp: null})
@@ -155,7 +192,7 @@
     const { verify } = this.props
 
     let _verify = {...verify, wxTemplateId: val}
-    let selectTemp = {content: option.props.content.replace(/\r\n|\n/g, '<br/>'), example: option.props.example.replace(/\r\n|\n/g, '<br/>')}
+    let selectTemp = {template_id: val, content: option.props.content.replace(/\r\n|\n/g, '<br/>'), example: option.props.example.replace(/\r\n|\n/g, '<br/>')}
 
     let keys = []
     if (option.props.content) {
@@ -163,26 +200,27 @@
       keys = keys.map(key => key.replace(/{{|\.DATA}}/g, ''))
     }
 
-    let index = 1
-    _verify.wxNoteKeys = keys.map(key => {
-      let item = {
-        key: key,
-        color: '#000000',
-        readonly: false
+    delete _verify.wxCustomTempId
+
+    if (selectTemp.template_id === 'mk_category_temp') {
+      _verify.wxNoteKeys = []
+      for (let i = 1; i <= 10; i++) {
+        _verify.wxNoteKeys.push({
+          key: '',
+          value: 'p' + i
+        })
       }
-      if (key === 'first') {
-        item.value = 'first'
-        item.readonly = true
-      } else if (key === 'remark') {
-        item.value = 'remark'
-        item.readonly = true
-      } else {
+    } else {
+      let index = 1
+      _verify.wxNoteKeys = keys.map(key => {
+        let item = { key: key }
+        
         item.value = 'p' + index
         index++
-      }
-
-      return item
-    })
+  
+        return item
+      })
+    }
 
     this.setState({selectTemp})
 
@@ -203,16 +241,24 @@
     this.props.onChange(_verify)
   }
 
-  onWxNoteColorChange = (key, val) => {
+  onWxNoteValueChange = (value, val) => {
     let _verify = fromJS(this.props.verify).toJS()
 
     _verify.wxNoteKeys = _verify.wxNoteKeys.map(m => {
-      if (m.key === key) {
-        m.color = val
+      if (m.value === value) {
+        m.key = val.replace(/\s+/ig, '')
       }
 
       return m
     })
+
+    this.props.onChange(_verify)
+  }
+
+  onWxNoteTempIdChange = (value) => {
+    let _verify = fromJS(this.props.verify).toJS()
+
+    _verify.wxCustomTempId = value.replace(/\s+/ig, '')
 
     this.props.onChange(_verify)
   }
@@ -413,9 +459,9 @@
               <Input placeholder="" autoComplete="off" value={verify.wxNoteLinkMenuId || ''} onChange={(e) => {this.onOptionChange(e.target.value, 'wxNoteLinkMenuId')}}/>
             </Form.Item>
           </Col> : null}
-          {verify.wxNote === 'true' && verify.wxNoteKeys ? verify.wxNoteKeys.map(item => <Col span={8} key={item.key}>
-            <Form.Item className="mk-note-keyword" label={item.key} required>
-              <Select value={item.value} disabled={item.readonly} onSelect={(val) => this.onWxNoteKeyChange(item.key, val)}>
+          {verify.wxNote === 'true' && verify.wxNoteKeys && (!selectTemp || selectTemp.template_id !== 'mk_category_temp') ? verify.wxNoteKeys.map((item, index) => <Col span={8} key={'mk' + index}>
+            <Form.Item label={item.key} required>
+              <Select value={item.value} onSelect={(val) => this.onWxNoteKeyChange(item.key, val)}>
                 <Select.Option value="p1">p1</Select.Option>
                 <Select.Option value="p2">p2</Select.Option>
                 <Select.Option value="p3">p3</Select.Option>
@@ -427,10 +473,19 @@
                 <Select.Option value="p9">p9</Select.Option>
                 <Select.Option value="p10">p10</Select.Option>
               </Select>
-              <ColorSketch value={item.color || '#ffffff'} onChange={(val, hex) => {this.onWxNoteColorChange(item.key, hex)}} />
             </Form.Item>
           </Col>) : null}
-          {selectTemp && verify.wxNoteKeys ? <Col span={24} className="wx-note">
+          {verify.wxNote === 'true' && verify.wxNoteKeys && (selectTemp && selectTemp.template_id === 'mk_category_temp') ? <Col span={8}>
+            <Form.Item label="妯℃澘ID" required>
+              <Input placeholder="" defaultValue={verify.wxCustomTempId} autoComplete="off" onChange={(e) => {this.onWxNoteTempIdChange(e.target.value)}}/>
+            </Form.Item>
+          </Col> : null}
+          {verify.wxNote === 'true' && verify.wxNoteKeys && (selectTemp && selectTemp.template_id === 'mk_category_temp') ? verify.wxNoteKeys.map((item, index) => <Col span={8} key={'mk' + index}>
+            <Form.Item label={item.value}>
+              <Input placeholder="" defaultValue={item.key} autoComplete="off" onChange={(e) => {this.onWxNoteValueChange(item.value, e.target.value)}}/>
+            </Form.Item>
+          </Col>) : null}
+          {selectTemp && selectTemp.template_id !== 'mk_category_temp' && verify.wxNoteKeys ? <Col span={24} className="wx-note">
             <div className="note-wrap">
               <div className="note">
                 <p>鍐呭绀轰緥</p>
@@ -449,12 +504,25 @@
                 <div>
                   <p>openid:&nbsp;&nbsp;"鎺ユ敹鑰卭penid",</p>
                   <p>send_id:&nbsp;&nbsp;"闃查噸鍏d",</p>
-                  {verify.wxNoteKeys.map(item => <p>{item.value}:&nbsp;&nbsp;"=&gt; {item.key}",</p>)}
+                  {verify.wxNoteKeys.map((item, i) => <p key={'index' + i}>{item.value}:&nbsp;&nbsp;"=&gt; {item.key}",</p>)}
                   <p>bid:&nbsp;&nbsp;"璺宠浆灏忕▼搴忔椂锛屽彲浣滀负BID銆�"</p>
                 </div>
               </div>
             </div>
           </Col> : null}
+          {selectTemp && selectTemp.template_id === 'mk_category_temp' && verify.wxNoteKeys ? <Col span={24} className="wx-note">
+            <div className="note-wrap">
+              <div className="note">
+                <p>娑堟伅浣�</p>
+                <div>
+                  <p>openid:&nbsp;&nbsp;"鎺ユ敹鑰卭penid",</p>
+                  <p>send_id:&nbsp;&nbsp;"闃查噸鍏d",</p>
+                  <p>bid:&nbsp;&nbsp;"璺宠浆灏忕▼搴忔椂锛屽彲浣滀负BID銆�"</p>
+                  <p style={{color: '#1890ff'}}>璇峰湪閫氱敤瀛楁涓紙p1~p10锛夊~鍏ユā鏉夸腑瀵瑰簲鐨勫瓧娈靛悕锛屽 time1.DATA 鍒欏~鍐� time1銆�</p>
+                </div>
+              </div>
+            </div>
+          </Col> : null}
         </Row>
       </Form>
     )
diff --git a/src/templates/zshare/verifycard/baseform/index.scss b/src/templates/zshare/verifycard/baseform/index.scss
index 4cd6283..8625b9f 100644
--- a/src/templates/zshare/verifycard/baseform/index.scss
+++ b/src/templates/zshare/verifycard/baseform/index.scss
@@ -1,29 +1,3 @@
-.mk-note-keyword {
-  .ant-select {
-    width: 50%;
-    .ant-select-selection {
-      border-radius: 4px 0px 0px 4px;
-    }
-  }
-  .color-sketch-block {
-    width: 50%;
-    display: inline-block;
-    vertical-align: top;
-    position: relative;
-    top: 4px;
-    .color-sketch-block-box {
-      width: calc(100% - 75px);
-      height: 32px;
-      border-radius: 0px 4px 4px 0px;
-      .color-sketch-block-inner {
-        border-radius: 0px 4px 4px 0px;
-      }
-    }
-    .color-sketch-value {
-      width: 75px;
-    }
-  }
-}
 .wx-note {
   display: flex;
   .note-wrap {
diff --git a/src/templates/zshare/verifycard/billcodeform/index.jsx b/src/templates/zshare/verifycard/billcodeform/index.jsx
index 6aed692..235a1fe 100644
--- a/src/templates/zshare/verifycard/billcodeform/index.jsx
+++ b/src/templates/zshare/verifycard/billcodeform/index.jsx
@@ -4,7 +4,7 @@
 import { Form, Row, Col, Select, Button, InputNumber, Input, Tooltip } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
-import './index.scss'
+// import './index.scss'
 
 class BillCodeForm extends Component {
   static propTpyes = {
diff --git a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
index 4fe7e4e..ce0b0fd 100644
--- a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
+++ b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
@@ -71,6 +71,13 @@
             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')
@@ -240,7 +247,7 @@
           <Col span={24} className="sqlfield">
             <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;
+              <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, mk_deleted</span></Tooltip>,&nbsp;
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞跺湪鍗曞彿鐢熸垚鎴栧垱寤哄嚟璇佹椂浣跨敤銆�'}><span style={{color: '#13c2c2'}}>BillCode, BVoucher, FIBVoucherDate, FiYear, ModularDetailCode</span></Tooltip>
               {usefulfields ? <span>, {usefulfields}</span> : ''}
             </Form.Item>
diff --git a/src/templates/zshare/verifycard/contrastform/index.jsx b/src/templates/zshare/verifycard/contrastform/index.jsx
index 19f4de9..1de6e45 100644
--- a/src/templates/zshare/verifycard/contrastform/index.jsx
+++ b/src/templates/zshare/verifycard/contrastform/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { Form, Row, Col, Select, Button, Input } from 'antd'
-import './index.scss'
+// import './index.scss'
 
 class UniqueForm extends Component {
   static propTpyes = {
diff --git a/src/templates/zshare/verifycard/customform/index.jsx b/src/templates/zshare/verifycard/customform/index.jsx
index 32a9516..2af2b05 100644
--- a/src/templates/zshare/verifycard/customform/index.jsx
+++ b/src/templates/zshare/verifycard/customform/index.jsx
@@ -6,7 +6,7 @@
 import Utils from '@/utils/utils.js'
 import Api from '@/api'
 import CodeMirror from '@/templates/zshare/codemirror'
-import './index.scss'
+// import './index.scss'
 
 class CustomForm extends Component {
   static propTpyes = {
@@ -87,6 +87,13 @@
           notification.warning({
             top: 92,
             message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 5
+          })
+          return
+        } else if (/,,/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇杩炵画鐨勮嫳鏂囬�楀彿锛�,,锛�',
             duration: 5
           })
           return
@@ -190,7 +197,7 @@
           <Col span={21} className="sqlfield">
             <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;
+              <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, mk_deleted</span></Tooltip>,&nbsp;
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞跺湪鍗曞彿鐢熸垚鎴栧垱寤哄嚟璇佹椂浣跨敤銆�'}><span style={{color: '#13c2c2'}}>BillCode, BVoucher, FIBVoucherDate, FiYear, ModularDetailCode</span></Tooltip>
               {usefulfields ? <span>, {usefulfields}</span> : ''}
             </Form.Item>
diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx
index 4c4a094..fd2f022 100644
--- a/src/templates/zshare/verifycard/customscript/index.jsx
+++ b/src/templates/zshare/verifycard/customscript/index.jsx
@@ -101,6 +101,13 @@
             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')
@@ -286,7 +293,7 @@
           {!_type ? <Col span={24} className="sqlfield">
             <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;
+              <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, mk_deleted</span></Tooltip>,&nbsp;
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞跺湪鍗曞彿鐢熸垚鎴栧垱寤哄嚟璇佹椂浣跨敤銆�'}><span style={{color: '#13c2c2'}}>BillCode, BVoucher, FIBVoucherDate, FiYear, ModularDetailCode</span></Tooltip>
               {usefulfields ? <span>, {usefulfields}</span> : ''}
             </Form.Item>
diff --git a/src/templates/zshare/verifycard/fullScripts/index.jsx b/src/templates/zshare/verifycard/fullScripts/index.jsx
new file mode 100644
index 0000000..116fdbb
--- /dev/null
+++ b/src/templates/zshare/verifycard/fullScripts/index.jsx
@@ -0,0 +1,130 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Modal, notification, Typography, Popconfirm } from 'antd'
+import { CheckCircleOutlined, StopOutlined, SwapOutlined, DeleteOutlined, BorderOutlined } from '@ant-design/icons'
+
+import MinView from '@/assets/img/minview.png'
+import './index.scss'
+
+const { Paragraph } = Typography
+
+class fullScripts extends Component {
+  static propTpyes = {
+    verify: PropTypes.object,
+    getScriptsForm: PropTypes.func
+  }
+
+  state = {
+    visible: false,
+    scriptId: '',
+    columns: []
+  }
+
+  trigger = () => {
+    const { getScriptsForm } = this.props
+
+    let scriptsForm = getScriptsForm()
+
+    if (scriptsForm) {
+      let sql = scriptsForm.props.form.getFieldValue('sql') || ''
+      if (scriptsForm.state.editItem || (sql && !/^\s+$/.test(sql))) {
+        notification.warning({
+          top: 92,
+          message: '璇蜂繚瀛樿嚜瀹氫箟鑴氭湰锛�',
+          duration: 5
+        })
+        return
+      }
+    }
+
+    this.setState({visible: true, scriptId: ''})
+  }
+
+  render() {
+    const { verify, children } = this.props
+    const { visible, scriptId } = this.state
+
+    return (
+      <>
+        <BorderOutlined className="full-scripts" onClick={this.trigger}/>
+        <Modal
+          wrapClassName="model-custom-scripts-modal"
+          title="鑷畾涔夎剼鏈�"
+          visible={visible}
+          width={'95vw'}
+          maskClosable={false}
+          destroyOnClose
+        >
+          <img className="unfull-scripts" src={MinView} onClick={() => this.setState({visible: false, scriptId: ''})} alt=""/>
+          <div className="script-table-wrap">
+            {verify.scripts.map(item => {
+              let title = item.sql.match(/^\s*\/\*.+\*\//)
+              title = title && title[0] ? title[0] : ''
+              let _text = title ? item.sql.replace(title, '') : item.sql
+
+              let position = null
+              if (item.position === 'init') {
+                position = <span style={{color: 'orange'}}>鍒濆鍖�</span>
+              } else if (item.position === 'front') {
+                position = <span style={{color: '#26C281'}}>sql鍓�</span>
+              } else {
+                position = <span style={{color: '#1890ff'}}>sql鍚�</span>
+              }
+
+              if (item.status === 'false') {
+                return (
+                  <div className="script-item" key={item.uuid}>
+                    <div style={{cursor: 'not-allowed'}}>
+                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
+                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
+                      <div>{position}
+                        <span style={{color: '#ff4d4f', marginLeft: '20px'}}>
+                          绂佺敤
+                          <StopOutlined style={{marginLeft: '5px'}} />
+                        </span>
+                      </div>
+                    </div>
+                    <div style={{height: '24px'}}></div>
+                  </div>
+                )
+              } else {
+                return (
+                  <div className={'script-item ' + (scriptId === item.uuid ? 'active' : '') } key={item.uuid}>
+                    <div style={{cursor: 'pointer'}} onClick={() => {
+                      let scriptsFullForm = this.props.getScriptsFullForm()
+                      scriptsFullForm && scriptsFullForm.edit(item)
+
+                      this.setState({scriptId: item.uuid})
+                    }}>
+                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
+                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
+                      <div>{position}
+                        <span style={{color: '#26C281', marginLeft: '20px'}}>
+                          鍚敤
+                          <CheckCircleOutlined style={{marginLeft: '5px'}}/>
+                        </span>
+                      </div>
+                    </div>
+                    <div style={{textAlign: 'right'}}>
+                      <span className="operation-btn" onClick={() => this.props.handleStatus(item, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
+                      <Popconfirm
+                        overlayClassName="popover-confirm"
+                        title="纭畾鍒犻櫎鍚�?"
+                        onConfirm={() => this.props.handleDelete(item, 'scripts')
+                      }>
+                        <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
+                      </Popconfirm>
+                    </div>
+                  </div>
+                )
+              }
+            })}
+          </div>
+          {visible ? children : null}
+        </Modal>
+      </>
+    )
+  }
+}
+
+export default fullScripts
\ No newline at end of file
diff --git a/src/templates/zshare/verifycard/fullScripts/index.scss b/src/templates/zshare/verifycard/fullScripts/index.scss
new file mode 100644
index 0000000..4cdba1c
--- /dev/null
+++ b/src/templates/zshare/verifycard/fullScripts/index.scss
@@ -0,0 +1,130 @@
+.model-custom-scripts-modal {
+  .ant-modal {
+    top: 30px;
+    .ant-modal-header {
+      padding: 10px 24px;
+    }
+    .ant-modal-footer {
+      display: none;
+    }
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal-body {
+      padding: 0;
+      height: calc(100vh - 100px);
+      overflow: hidden;
+      display: flex;
+
+      .script-table-wrap {
+        width: 240px;
+        overflow-y: auto;
+        overflow-x: hidden;
+        height: calc(100vh - 100px);
+
+        .operation-btn {
+          display: inline-block;
+          font-size: 16px;
+          padding: 0 5px;
+          cursor: pointer;
+          margin-left: 5px;
+        }
+
+        .script-item {
+          border-bottom: 1px solid #eeeeee;
+          padding: 15px 10px 5px;
+        }
+        .script-item.active {
+          background-color: #bae7ff;
+        }
+        .ant-typography {
+          margin-bottom: 5px;
+        }
+      }
+
+      .script-table-wrap::-webkit-scrollbar {
+        width: 7px;
+      }
+      .script-table-wrap::-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);
+      }
+      .script-table-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);
+      }
+
+      .unfull-scripts {
+        position: absolute;
+        right: 20px;
+        z-index: 2;
+        top: 10px;
+        color: #1890ff;
+        width: 26px;
+        cursor: pointer;
+        padding: 5px;
+    
+      }
+
+      .verify-form {
+        flex: 1;
+        >.ant-row {
+          margin: 0!important;
+          position: unset;
+        }
+        .sql {
+          padding: 0!important;
+          .ant-form-item-label {
+            display: none;
+          }
+          .ant-form-item-control-wrapper {
+            width: 100%;
+          }
+          .CodeMirror {
+            height: calc(100vh - 100px);
+            border-radius: 0;
+          }
+          .code-mirror-area {
+            border-radius: 0;
+            width: calc(95vw - 240px);
+          }
+        }
+        .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 {
+          position: absolute;
+          top: 10px;
+          z-index: 1;
+          .ant-btn {
+            height: 28px;
+          }
+          .mk-green {
+            margin-left: 0!important;
+            margin-right: 10px;
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index b2be305..ade0e92 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Form, Tabs, Row, Col, Button, Popconfirm, notification, Modal, message, InputNumber, Typography } from 'antd'
-import { CheckCircleOutlined, StopOutlined, EditOutlined, SwapOutlined, DeleteOutlined, ExclamationOutlined, BorderOutlined } from '@ant-design/icons'
+import { CheckCircleOutlined, StopOutlined, EditOutlined, SwapOutlined, DeleteOutlined, ExclamationOutlined } from '@ant-design/icons'
 import Toast from 'antd-mobile/es/components/toast'
 import Dialog from 'antd-mobile/es/components/dialog'
 import moment from 'moment'
@@ -21,13 +21,13 @@
 import asyncComponent from '@/utils/asyncComponent'
 import { updateForm } from '@/utils/utils-update.js'
 import MKEmitter from '@/utils/events.js'
-import MinView from '@/assets/img/minview.png'
 import './index.scss'
 
 const { TabPane } = Tabs
 const { confirm } = Modal
 const { Paragraph } = Typography
 const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
+const FullScripts = asyncComponent(() => import('./fullScripts'))
 
 class VerifyCard extends Component {
   static propTpyes = {
@@ -44,8 +44,6 @@
     appType: sessionStorage.getItem('appType'),
     notes: [],              // 鐭俊妯℃澘
     setting: null,
-    visible: false,
-    scriptId: '',
     verify: {},
     fields: [],
     usefulfields: '',
@@ -545,7 +543,11 @@
     let _invalid = _verify.invalid
 
     if (!_invalid) { // 閫夋嫨琛屾椂锛屽け鏁堥獙璇侀粯璁ゅ紑鍚�
-      _invalid = card.Ot !== 'notRequired' ? 'true' : 'false'
+      if (config.setting && config.setting.maxScript && config.setting.maxScript >= 300) {
+        _invalid = 'false'
+      } else {
+        _invalid = card.Ot !== 'notRequired' ? 'true' : 'false'
+      }
     }
     if (card.sqlType === 'custom') { // 鑷畾涔夐獙璇佹椂锛屼笉浣跨敤榛樿sql
       _verify.default = 'false'
@@ -664,15 +666,36 @@
         resolve(_fields)
       }
     }).then(_fields => {
-      let _usefulfields = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode', 'tbid']
-      let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@RoleID nvarchar(512)', '@mk_departmentcode nvarchar(512)', '@mk_organization nvarchar(512)', '@mk_user_type nvarchar(20)', '@mk_nation nvarchar(50)', '@mk_province nvarchar(50)', '@mk_city nvarchar(50)', '@mk_district nvarchar(50)', '@mk_address nvarchar(100)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)', '@bid nvarchar(50)', '@tbid nvarchar(50)']
-      let _select = ['@UserName=\'\'', '@FullName=\'\'', '@RoleID=\'\'', '@mk_departmentcode=\'\'', '@mk_organization=\'\'', '@mk_user_type=\'\'', '@mk_nation=\'\'', '@mk_province=\'\'', '@mk_city=\'\'', '@mk_district=\'\'', '@mk_address=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'', '@bid=\'\'']
+      let _usefulfields = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode', 'tbid', 'mk_deleted']
+      let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@RoleID nvarchar(512)', '@mk_departmentcode nvarchar(512)', '@mk_organization nvarchar(512)', '@mk_user_type nvarchar(20)', '@mk_nation nvarchar(50)', '@mk_province nvarchar(50)', '@mk_city nvarchar(50)', '@mk_district nvarchar(50)', '@mk_address nvarchar(100)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)', '@bid nvarchar(50)', '@tbid nvarchar(50)', '@mk_deleted int']
+      let _select = ['@UserName=\'\'', '@FullName=\'\'', '@RoleID=\'\'', '@mk_departmentcode=\'\'', '@mk_organization=\'\'', '@mk_user_type=\'\'', '@mk_nation=\'\'', '@mk_province=\'\'', '@mk_city=\'\'', '@mk_district=\'\'', '@mk_address=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'', '@bid=\'\'', '@mk_deleted=1']
       let fieldArr = _usefulfields.map(_f => _f.toLowerCase())
       let hasBid = false
 
       _usefulfields = []
       
       fieldArr.push('bid')
+
+      let verIndex = _fields.findIndex(item => item.type === 'vercode')
+      if (verIndex > -1) {
+        _fields = fromJS(_fields).toJS()
+        _fields.splice(verIndex, 0, {
+          type: 'text',
+          fieldlength: 50,
+          writein: 'false',
+          field: 'mk_timestamp'
+        }, {
+          type: 'text',
+          fieldlength: 50,
+          writein: 'false',
+          field: 'mk_send_type'
+        }, {
+          type: 'text',
+          fieldlength: 50,
+          writein: 'false',
+          field: 'mk_n_id'
+        })
+      }
 
       _fields = _fields.filter(_f => _f.field)
       _fields.forEach(_f => {
@@ -788,6 +811,10 @@
       let _insertsql = ''
       let _updatesql = ''
       let _primaryKey = config.setting.primaryKey || 'id'
+
+      if (this.props.side === 'sub') {
+        _primaryKey = config.setting.subKey || 'id'
+      }
 
       if (card.sqlType === 'insert' || card.sqlType === 'insertOrUpdate') {
         let keys = []
@@ -921,7 +948,7 @@
         if (_verify.voucher && _verify.voucher.enabled) {
           _voucher = ',BVoucher=@BVoucher,FIBVoucherDate=@FIBVoucherDate,FiYear=@FiYear'
         }
-        _defaultsql = `update ${card.sql} set deleted=1,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@${_voucher} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
+        _defaultsql = `update ${card.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@${_voucher} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
       } else if (card.sqlType === 'delete') {
         let _msg = ''
         if (columns && columns.length > 0 && card.Ot !== 'notRequired') {
@@ -1511,7 +1538,7 @@
 
   render() {
     const { card } = this.props
-    const { activeKey, verifyInter, setting, verify, fields, visible, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes, appType } = this.state
+    const { activeKey, verifyInter, setting, verify, fields, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes, appType } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -1611,17 +1638,25 @@
               {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
             </span>
           } key="scripts" id="mk-normal-script">
-            <BorderOutlined className="full-scripts" onClick={() => {
-              if (this.scriptsForm && (this.scriptsForm.state.editItem || (this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))))) {
-                notification.warning({
-                  top: 92,
-                  message: '璇蜂繚瀛樿嚜瀹氫箟鑴氭湰锛�',
-                  duration: 5
-                })
-                return
-              }
-              this.setState({visible: true, scriptId: ''})
-            }}/>
+            <FullScripts
+              verify={verify}
+              getScriptsFullForm={() => this.scriptsFullForm}
+              getScriptsForm={() => this.scriptsForm}
+              handleStatus={this.handleStatus}
+              handleDelete={this.handleDelete}
+            >
+              <CustomScript
+                type="fullscreen"
+                btn={this.props.card}
+                initsql={this.state.initsql}
+                customScripts={verify.scripts}
+                defaultsql={this.state.defaultsql}
+                usefulfields={this.state.usefulfields}
+                systemScripts={this.state.systemScripts}
+                scriptsChange={this.scriptsChange}
+                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
+              />
+            </FullScripts>
             <CustomScript
               btn={this.props.card}
               initsql={this.state.initsql}
@@ -1655,7 +1690,7 @@
             <Form {...formItemLayout}>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> S </span>
                     <Button onClick={() => {this.showError('S')}} type="primary" size="small">
                       鏌ョ湅
@@ -1663,14 +1698,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> Y </span>
                     <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
                       鏌ョ湅
@@ -1680,7 +1715,15 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -1 </span>
+                    鎵ц鎴愬姛鏃犳彁绀恒��
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> N </span>
                     <Button onClick={() => {this.showError('N')}} type="primary" size="small">
                       鏌ョ湅
@@ -1688,14 +1731,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ntime || (appType === 'mob' ? 3 : 10)} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> F </span>
                     <Button onClick={() => {this.showError('F')}} type="primary" size="small">
                       鏌ョ湅
@@ -1703,14 +1746,14 @@
                   </Form.Item>
                 </Col>
                 <Col span={8}>
-                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                  <Form.Item label="鍋滅暀鏃堕棿">
                     <InputNumber defaultValue={verify.ftime || (appType === 'mob' ? 3 : 10)} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
                   </Form.Item>
                 </Col>
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> E </span>
                     <Button onClick={() => {this.showError('E')}} type="primary" size="small">
                       鏌ョ湅
@@ -1720,7 +1763,7 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                  <Form.Item label="鎻愮ず缂栫爜">
                     <span className="errorval"> NM </span>
                     <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
                       鏌ョ湅
@@ -1730,98 +1773,15 @@
               </Row>
               <Row gutter={24}>
                 <Col offset={6} span={6}>
-                  <Form.Item label={'鎻愮ず缂栫爜'}>
-                    <span className="errorval"> -1 </span>
-                    涓嶆彁绀�
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -2 </span>
+                    鎵ц澶辫触鏃犳彁绀�
                   </Form.Item>
                 </Col>
               </Row>
             </Form>
           </TabPane>
         </Tabs>
-        <Modal
-          wrapClassName="model-custom-scripts-modal"
-          title="鑷畾涔夎剼鏈�"
-          visible={visible}
-          width={'95vw'}
-          maskClosable={false}
-          destroyOnClose
-        >
-          <img className="unfull-scripts" src={MinView} onClick={() => this.setState({visible: false, scriptId: ''})} alt=""/>
-          <div className="script-table-wrap">
-            {verify.scripts.map(item => {
-              let title = item.sql.match(/^\s*\/\*.+\*\//)
-              title = title && title[0] ? title[0] : ''
-              let _text = title ? item.sql.replace(title, '') : item.sql
-
-              let position = null
-              if (item.position === 'init') {
-                position = <span style={{color: 'orange'}}>鍒濆鍖�</span>
-              } else if (item.position === 'front') {
-                position = <span style={{color: '#26C281'}}>sql鍓�</span>
-              } else {
-                position = <span style={{color: '#1890ff'}}>sql鍚�</span>
-              }
-
-              if (item.status === 'false') {
-                return (
-                  <div className="script-item" key={item.uuid}>
-                    <div style={{cursor: 'not-allowed'}}>
-                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
-                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
-                      <div>{position}
-                        <span style={{color: '#ff4d4f', marginLeft: '20px'}}>
-                          绂佺敤
-                          <StopOutlined style={{marginLeft: '5px'}} />
-                        </span>
-                      </div>
-                    </div>
-                    <div style={{height: '24px'}}></div>
-                  </div>
-                )
-              } else {
-                return (
-                  <div className={'script-item ' + (this.state.scriptId === item.uuid ? 'active' : '') } key={item.uuid}>
-                    <div style={{cursor: 'pointer'}} onClick={() => {
-                      this.scriptsFullForm.edit(item)
-                      this.setState({scriptId: item.uuid})
-                    }}>
-                      {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null}
-                      <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph>
-                      <div>{position}
-                        <span style={{color: '#26C281', marginLeft: '20px'}}>
-                          鍚敤
-                          <CheckCircleOutlined style={{marginLeft: '5px'}}/>
-                        </span>
-                      </div>
-                    </div>
-                    <div style={{textAlign: 'right'}}>
-                      <span className="operation-btn" onClick={() => this.handleStatus(item, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
-                      <Popconfirm
-                        overlayClassName="popover-confirm"
-                        title="纭畾鍒犻櫎鍚�?"
-                        onConfirm={() => this.handleDelete(item, 'scripts')
-                      }>
-                        <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
-                      </Popconfirm>
-                    </div>
-                  </div>
-                )
-              }
-            })}
-          </div>
-          <CustomScript
-            type="fullscreen"
-            btn={this.props.card}
-            initsql={this.state.initsql}
-            customScripts={verify.scripts}
-            defaultsql={this.state.defaultsql}
-            usefulfields={this.state.usefulfields}
-            systemScripts={this.state.systemScripts}
-            scriptsChange={this.scriptsChange}
-            wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
-          />
-        </Modal>
       </div>
     )
   }
diff --git a/src/templates/zshare/verifycard/index.scss b/src/templates/zshare/verifycard/index.scss
index 055f770..6ee9eb2 100644
--- a/src/templates/zshare/verifycard/index.scss
+++ b/src/templates/zshare/verifycard/index.scss
@@ -89,136 +89,6 @@
     z-index: 1;
   }
 }
-.model-custom-scripts-modal {
-  .ant-modal {
-    top: 30px;
-    .ant-modal-header {
-      padding: 10px 24px;
-    }
-    .ant-modal-footer {
-      display: none;
-    }
-    .ant-modal-close {
-      display: none;
-    }
-    .ant-modal-body {
-      padding: 0;
-      height: calc(100vh - 100px);
-      overflow: hidden;
-      display: flex;
-
-      .script-table-wrap {
-        width: 240px;
-        overflow-y: auto;
-        overflow-x: hidden;
-        height: calc(100vh - 100px);
-
-        .operation-btn {
-          display: inline-block;
-          font-size: 16px;
-          padding: 0 5px;
-          cursor: pointer;
-          margin-left: 5px;
-        }
-
-        .script-item {
-          border-bottom: 1px solid #eeeeee;
-          padding: 15px 10px 5px;
-        }
-        .script-item.active {
-          background-color: #bae7ff;
-        }
-        .ant-typography {
-          margin-bottom: 5px;
-        }
-      }
-
-      .script-table-wrap::-webkit-scrollbar {
-        width: 7px;
-      }
-      .script-table-wrap::-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);
-      }
-      .script-table-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);
-      }
-
-      .unfull-scripts {
-        position: absolute;
-        right: 20px;
-        z-index: 2;
-        top: 10px;
-        color: #1890ff;
-        width: 26px;
-        cursor: pointer;
-        padding: 5px;
-    
-      }
-
-      .verify-form {
-        flex: 1;
-        >.ant-row {
-          margin: 0!important;
-          position: unset;
-        }
-        .sql {
-          padding: 0!important;
-          .ant-form-item-label {
-            display: none;
-          }
-          .ant-form-item-control-wrapper {
-            width: 100%;
-          }
-          .CodeMirror {
-            height: calc(100vh - 100px);
-            border-radius: 0;
-          }
-          .code-mirror-area {
-            border-radius: 0;
-            width: calc(95vw - 240px);
-          }
-        }
-        .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 {
-          position: absolute;
-          top: 10px;
-          z-index: 1;
-          .ant-btn {
-            height: 28px;
-          }
-          .mk-green {
-            margin-left: 0!important;
-            margin-right: 10px;
-          }
-        }
-      }
-    }
-  }
-}
 .adm-mask {
   z-index: 2000!important;
 }
diff --git a/src/templates/zshare/verifycard/uniqueform/index.jsx b/src/templates/zshare/verifycard/uniqueform/index.jsx
index 556e2d4..2c1e3d2 100644
--- a/src/templates/zshare/verifycard/uniqueform/index.jsx
+++ b/src/templates/zshare/verifycard/uniqueform/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { Form, Row, Col, Select, Button } from 'antd'
-import './index.scss'
+// import './index.scss'
 
 class UniqueForm extends Component {
   static propTpyes = {
diff --git a/src/templates/zshare/verifycard/voucherform/index.jsx b/src/templates/zshare/verifycard/voucherform/index.jsx
index 7dd3ba2..e0ea747 100644
--- a/src/templates/zshare/verifycard/voucherform/index.jsx
+++ b/src/templates/zshare/verifycard/voucherform/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Form, Row, Col, Select, Switch, notification } from 'antd'
-import './index.scss'
+// import './index.scss'
 
 class UniqueForm extends Component {
   static propTpyes = {
diff --git a/src/utils/option.js b/src/utils/option.js
index ca6a857..e771dfe 100644
--- a/src/utils/option.js
+++ b/src/utils/option.js
@@ -157,6 +157,8 @@
     {value: '[7, -7]', text: '鍓嶅悗涓冨ぉ'},
     {value: '[30, -30]', text: '鍓嶅悗30澶�'},
     {value: '[90, -90]', text: '鍓嶅悗90澶�'},
+    {value: '[180, -180]', label: '鍓嶅悗180澶�'},
+    {value: '[365, -365]', label: '鍓嶅悗365澶�'},
     {value: '[-1, -1]', text: '鏄庡ぉ'},
     {value: '[-2, -2]', text: '鍚庡ぉ'},
     {value: 'week', text: '鏈懆'},
@@ -188,7 +190,7 @@
 
 // 鍖归厤瑙勫垯
 export const matchReg = {
-  text: [{
+  class1: [{
     value: 'like',
     text: 'like'
   }, {
@@ -210,20 +212,7 @@
     value: '<=',
     text: '<='
   }],
-  multiselect: [{
-    value: 'like',
-    text: 'like'
-  }, {
-    value: 'not like',
-    text: 'not like'
-  }],
-  select: [{
-    value: 'like',
-    text: 'like'
-  }, {
-    value: 'not like',
-    text: 'not like'
-  }, {
+  class2: [{
     value: '=',
     text: '='
   }, {
@@ -239,7 +228,14 @@
     value: '<=',
     text: '<='
   }],
-  date: [{
+  class3: [{
+    value: 'like',
+    text: 'like'
+  }, {
+    value: 'not like',
+    text: 'not like'
+  }],
+  class4: [{
     value: '>=',
     text: '>='
   }, {
@@ -249,11 +245,7 @@
     value: '=',
     text: '='
   }],
-  datemonth: [{
-    value: 'between',
-    text: 'between'
-  }],
-  daterange: [{
+  class5: [{
     value: 'between',
     text: 'between'
   }]
@@ -389,36 +381,6 @@
 }, {
   value: 'border-purple',
   text: '鐧藉簳绱'
-}]
-
-// 鎸夐挳棰滆壊闆�
-export const btnCustomClasses = [{
-  value: 'primary',
-  text: '钃濊壊'
-}, {
-  value: 'yellow',
-  text: '榛勮壊'
-}, {
-  value: 'orange',
-  text: '姗欒壊'
-}, {
-  value: 'danger',
-  text: '绾㈣壊'
-}, {
-  value: 'green',
-  text: '缁胯壊'
-}, {
-  value: 'dgreen',
-  text: '娣辩豢鑹�'
-}, {
-  value: 'purple',
-  text: '绱壊'
-}, {
-  value: 'cyan',
-  text: '闈掕壊'
-}, {
-  value: 'gray',
-  text: '鐏拌壊'
 }]
 
 export const calendarColors = [
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index c07d64c..be4f888 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -19,6 +19,8 @@
       } else if (item.type === 'tabs') {
         if (item.subtype === 'tabletabs') {
           item.subtabs.forEach(tab => {
+            if (tab.components[0].uuid === selfId) return
+            
             modules.push({
               value: tab.components[0].uuid,
               label: tab.label,
@@ -517,73 +519,44 @@
           })
         }
       } else if (item.type === 'table' && item.cols) {
-        let loopCol = (col) => {
-          col.subcols = col.subcols.map(c => {
-            c.uuid = md5(commonId + c.uuid)
-  
-            if (c.type === 'colspan' && c.subcols) {
-              c = loopCol(c)
-            } else if (c.type === 'custom' && c.elements) {
-              c.elements = c.elements.map(cell => {
-                cell.uuid = this.getuuid()
+        let loopCol = (cols) => {
+          return cols.map(col => {
+            if (col.type === 'action') {
+              col.type = 'custom'
+            }
 
-                return cell
-              })
-            } else if (c.type === 'action' && c.elements) {
-              c.elements = c.elements.map(cell => {
+            col.uuid = md5(commonId + col.uuid)
+  
+            if (col.type === 'colspan' && col.subcols) {
+              col.subcols = loopCol(col.subcols)
+            } else if (col.type === 'custom' && col.elements) {
+              col.elements = col.elements.map(cell => {
                 cell.uuid = md5(commonId + cell.uuid)
 
-                if (clear && cell.pageTemplate === 'linkpage' && cell.linkmenu) {
-                  cell.pageTemplate = ''
-                  cell.linkmenu = ''
-                }
+                if (cell.eleType === 'button') {
+                  if (clear && cell.pageTemplate === 'linkpage' && cell.linkmenu) {
+                    cell.pageTemplate = ''
+                    cell.linkmenu = ''
+                  }
 
-                this.resetBtn(cell, commonId)
+                  this.resetBtn(cell, commonId)
+                }
 
                 return cell
               })
+            } else if (col.editable === 'true' && col.enter && col.enter !== '$next' && col.enter !== '$sub') {
+              if (/\$next_/.test(col.enter)) {
+                col.enter = '$next_' + md5(commonId + col.enter.split('_')[1])
+              } else {
+                col.enter = md5(commonId + col.enter)
+              }
             }
-            return c
-          })
-  
-          return col
-        }
 
-        item.cols = item.cols.map(col => {
-          col.uuid = md5(commonId + col.uuid)
-  
-          if (col.type === 'colspan' && col.subcols) {
-            col = loopCol(col)
-          } else if (col.type === 'custom' && col.elements) {
-            col.elements = col.elements.map(cell => {
-              cell.uuid = this.getuuid()
-              return cell
-            })
-          } else if (col.type === 'action' && col.elements) {
-            col.elements = col.elements.map(cell => {
-              cell.uuid = md5(commonId + cell.uuid)
-              this.resetBtn(cell, commonId)
-              return cell
-            })
-          }
-          return col
-        })
-
-        if (item.subtype === 'editable') {
-          item.cols = item.cols.map(col => {
-            if (col.editable === 'true' && col.enter) {
-              col.enter = md5(commonId + col.enter)
-            } else if (col.type === 'colspan' && col.subcols) {
-              col.subcols = col.subcols.map(c => {
-                if (c.editable === 'true' && c.enter) {
-                  c.enter = md5(commonId + c.enter)
-                }
-                return c
-              })
-            }
             return col
           })
         }
+
+        item.cols = loopCol(item.cols)
       } else if (item.type === 'form') {
         item.subcards = item.subcards.map(cell => {
           cell.uuid = this.getuuid()
@@ -688,7 +661,12 @@
     if (btn.anchors && btn.anchors.length > 0) {
       btn.anchors = btn.anchors.map(m => md5(commonId + m))
     }
-    if (btn.syncComponent && btn.syncComponent.length > 0) {
+    if (btn.syncComponent && btn.syncComponent[0] === 'multiComponent' && btn.syncComponents) {
+      btn.syncComponents = btn.syncComponents.map(m => {
+        m.syncComId = m.syncComId.map(n => md5(commonId + n))
+        return m
+      })
+    } else if (btn.syncComponent && btn.syncComponent.length > 0) {
       btn.syncComponent = btn.syncComponent.map(m => md5(commonId + m))
     }
   }
@@ -709,7 +687,7 @@
   * @description 閲嶇疆缁勪欢閰嶇疆
   * @return {String}  item 缁勪欢淇℃伅
   */
-  static resetComponentConfig = (item) => {
+  static resetComponentConfig = (item, appType) => {
     if (item.type === 'navbar') {
       return item
     }
@@ -742,6 +720,16 @@
     } else if (['card', 'carousel', 'timeline'].includes(item.type)) {
       if (item.wrap.autoExec) {
         item.wrap.autoExec = md5(commonId + item.wrap.autoExec)
+      }
+
+      if (appType !== 'mob') {
+        if (item.wrap.pagestyle === 'slide') {
+          item.wrap.pagestyle = 'page'
+        }
+      } else {
+        if (item.wrap.pagestyle === 'switch') {
+          item.wrap.pagestyle = 'page'
+        }
       }
       
       item.subcards.forEach(card => {
@@ -821,63 +809,47 @@
         })
       }
     } else if (item.type === 'table' && item.cols) {
-      let loopCol = (col) => {
-        col.subcols = col.subcols.map(c => {
-          c.uuid = this.getuuid()
+      let loopCol = (cols) => {
+        return cols.map(col => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
 
-          if (c.type === 'colspan' && c.subcols) {
-            c = loopCol(c)
-          } else if (c.type === 'custom' && c.elements) {
-            c.elements = c.elements.map(cell => {
-              cell.uuid = this.getuuid()
+          col.uuid = md5(commonId + col.uuid)
+
+          if (col.type === 'colspan' && col.subcols) {
+            col.subcols = loopCol(col.subcols)
+          } else if (col.type === 'custom' && col.elements) {
+            if (sessionStorage.getItem('editMenuType') === 'popview') {
+              col.elements = col.elements.filter(c => c.eleType !== 'button' || (c.OpenType !== 'popview' && c.OpenType !== 'funcbutton'))
+            }
+            col.elements = col.elements.map(cell => {
+              cell.uuid = md5(commonId + cell.uuid)
+              if (cell.eleType === 'button') {
+                if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+                  if (cell.modal && cell.modal.fields.length > 0) {
+                    cell.modal.fields = cell.modal.fields.map(m => {
+                      m.uuid = this.getuuid()
+                      return m
+                    })
+                  }
+                }
+              }
               return cell
             })
-          }
-          return c
-        })
-
-        return col
-      }
-
-      item.cols = item.cols.map(col => {
-        col.uuid = md5(commonId + col.uuid)
-
-        if (col.type === 'colspan' && col.subcols) {
-          col = loopCol(col)
-        } else if (col.type === 'custom' && col.elements) {
-          col.elements = col.elements.map(cell => {
-            cell.uuid = this.getuuid()
-            return cell
-          })
-        } else if (col.type === 'action' && col.elements) {
-          if (sessionStorage.getItem('editMenuType') === 'popview') {
-            col.elements = col.elements.filter(c => c.OpenType !== 'popview' && c.OpenType !== 'funcbutton')
-          }
-          col.elements = col.elements.map(cell => {
-            cell.uuid = md5(commonId + cell.uuid)
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (cell.modal && cell.modal.fields.length > 0) {
-                cell.modal.fields = cell.modal.fields.map(m => {
-                  m.uuid = this.getuuid()
-                  return m
-                })
-              }
+          } else if (col.editable === 'true' && col.enter && col.enter !== '$next' && col.enter !== '$sub') { // 鍙紪杈戣〃
+            if (/\$next_/.test(col.enter)) {
+              col.enter = '$next_' + md5(commonId + col.enter.split('_')[1])
+            } else {
+              col.enter = md5(commonId + col.enter)
             }
-
-            return cell
-          })
-        }
-        return col
-      })
-
-      if (item.subtype === 'editable') {
-        item.cols = item.cols.map(col => {
-          if (col.editable === 'true' && col.enter) {
-            col.enter = md5(commonId + col.enter)
           }
+
           return col
         })
       }
+
+      item.cols = loopCol(item.cols)
     } else if (item.type === 'form') {
       item.subcards = item.subcards.map(cell => {
         cell.uuid = this.getuuid()
@@ -1084,23 +1056,31 @@
     })
   }
 
-  config.cols && config.cols.forEach(col => {
-    if (col.type === 'action') {
-      col.elements.forEach(cell => {
-        if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
-          action.push(cell)
-        } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
-          action.push(cell)
-        } else if (cell.OpenType === 'popview') {
-          if (pops) {
-            pops.push({...cell, parentId: config.uuid})
-          } else if (cell.config && cell.config.$tables) {
-            tables.push(...cell.config.$tables)
-          }
+  if (config.cols) {
+    let loopCol = (cols) => {
+      cols.forEach(col => {
+        if (col.type === 'colspan') {
+          loopCol(col.subcols)
+        } else if (col.type === 'custom') {
+          col.elements.forEach(cell => {
+            if (cell.eleType !== 'button') return
+            if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
+              action.push(cell)
+            } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
+              action.push(cell)
+            } else if (cell.OpenType === 'popview') {
+              if (pops) {
+                pops.push({...cell, parentId: config.uuid})
+              } else if (cell.config && cell.config.$tables) {
+                tables.push(...cell.config.$tables)
+              }
+            }
+          })
         }
       })
     }
-  })
+    loopCol(config.cols)
+  }
 
   config.elements && config.elements.forEach(cell => {
     if (cell.eleType !== 'button') return
@@ -1240,4 +1220,182 @@
   tables = Array.from(new Set(tables))
 
   return tables
+}
+
+/**
+ * @description 妫�娴嬬粍浠跺唴瀹�
+ */
+export function checkComponent (card) {
+  let errors = []
+  let columns = []
+
+  if (card.$c_ds) {
+    columns = card.columns.map(c => c.field)
+    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
+      errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
+    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
+      errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+    } else if (!card.setting.primaryKey) {
+      errors.push({ level: 0, detail: '鏈缃富閿紒'})
+    } else if (!columns.includes(card.setting.primaryKey)) {
+      errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
+    } else if (card.subtype === 'dualdatacard') {                     // 鍙岄噸鍗�
+      if (!card.setting.subKey) {
+        errors.push({ level: 0, detail: '鏈缃瓙琛ㄤ富閿紒'})
+      } else if (!card.setting.subBID) {
+        errors.push({ level: 0, detail: '鏈缃瓙琛˙ID锛�'})
+      } else if (!card.setting.supModule) {
+        errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+      }
+    } else if (card.type === 'card' && card.subtype === 'datacard') { // 鏁版嵁鍗★紝鍙兘鏈夊涓婄骇
+      if (card.wrap.supType !== 'multi' && !card.setting.supModule) {
+        errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+      }
+    } else if (card.type !== 'balcony' && !card.setting.supModule) {  // 鎮诞妗嗕笂绾х粍浠堕渶鍗曠嫭璁剧疆
+      errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+    }
+  } else if ((card.type === 'balcony' || card.type === 'card') && card.wrap.datatype === 'public') {
+    columns = card.columns.map(c => c.field)
+  }
+
+  let doubleClick = ''
+  if (card.type === 'table') {
+    doubleClick = card.wrap.doubleClick || ''
+  }
+
+  if (card.$c_ac) {
+    card.action.forEach(cell => {
+      if (cell.hidden === 'true' || cell.origin) return
+      // if (cell.OpenType === 'popview') {
+      //   if (!cell.config) {
+      //     errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑寮圭獥鏍囩灏氭湭璁剧疆`})
+      //   } else if (!cell.config.enabled) {
+      //     errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑寮圭獥鏍囩鏈惎鐢╜})
+      //   }
+      // }
+      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+        if (!cell.modal || cell.modal.fields.length === 0) {
+          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)) {
+        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+      } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+      }
+      if (doubleClick === cell.uuid) {
+        doubleClick = ''
+      }
+    })
+  }
+
+  if (card.$c_sc) {
+    card.subcards.forEach((item, i) => {
+      let linkbtn = item.setting.linkbtn || ''
+      item.elements.forEach(cell => {
+        if (cell.eleType === 'button') {
+          if (cell.hidden === 'true') return
+          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+            if (!cell.modal || cell.modal.fields.length === 0) {
+              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)) {
+            errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+          } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+            errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+          }
+          if (linkbtn && linkbtn === cell.uuid) {
+            linkbtn = ''
+          }
+        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
+          errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
+        }
+      })
+  
+      if (card.subtype === 'dualdatacard' || (item.setting.type === 'multi' && item.backElements && sessionStorage.getItem('appType') !== 'mob')) {
+        item.backElements.forEach(cell => {
+          if (cell.eleType === 'button') {
+            if (cell.hidden === 'true') return
+            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+              if (!cell.modal || cell.modal.fields.length === 0) {
+                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)) {
+              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+            } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+            }
+            if (linkbtn && linkbtn === cell.uuid) {
+              linkbtn = ''
+            }
+          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
+            errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
+          }
+        })
+      }
+  
+      if (linkbtn) {
+        errors.push({ level: 1, detail: `绗�${i + 1}寮犲崱鐗囦腑缁戝畾鎸夐挳宸插垹闄})
+      }
+    })
+
+    if (card.subcards.length === 0) {
+      errors.push({ level: 0, detail: '鍗$墖涓嶅彲涓虹┖锛�'})
+    }
+  }
+
+  if (card.$c_el) {
+    card.elements.forEach(cell => {
+      if (cell.eleType === 'button') {
+        if (cell.hidden === 'true') return
+        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+          if (!cell.modal || cell.modal.fields.length === 0) {
+            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)) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+        } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+        }
+      } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
+        errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
+      }
+    })
+  }
+
+  if (card.$c_cl) {
+    card.cols.forEach(col => {
+      if (col.type === 'custom') {
+        col.elements.forEach(cell => {
+          if (cell.eleType === 'button') {
+            if (cell.hidden === 'true') return
+            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+              if (!cell.modal || cell.modal.fields.length === 0) {
+                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)) {
+              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+            } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
+              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+            }
+
+            if (doubleClick === cell.uuid) {
+              doubleClick = ''
+            }
+          } else {
+            if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
+              errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑鍔ㄦ�佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
+            }
+          }
+        })
+      } else if (col.field && !columns.includes(col.field)) {
+        errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑瀛楁鈥�${col.field}鈥濇棤鏁坄})
+      }
+    })
+
+    if (doubleClick) {
+      errors.push({ level: 1, detail: `缁戝畾鐨勫弻鍑绘寜閽凡鍒犻櫎`})
+    }
+  }
+
+  return errors
 }
\ No newline at end of file
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 09aede5..5f9d942 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -142,19 +142,19 @@
   static verifySql (sql, type) {
     if (!sql) return ''
     let chars = [
-      {key: 'create', reg: /(^|\s)create\s/ig},
-      {key: 'insert', reg: /(^|\s)insert\s/ig},
-      {key: 'delete', reg: /(^|\s)delete\s/ig},
-      {key: 'update', reg: /(^|\s)update\s/ig},
-      {key: 'set', reg: /(^|\s)set\s/ig},
-      {key: 'drop', reg: /(^|\s)drop\s/ig},
-      {key: 'alter', reg: /(^|\s)alter\s/ig},
-      {key: 'truncate', reg: /(^|\s)truncate\s/ig},
-      {key: 'if', reg: /(^|\s)if\s/ig},
-      {key: 'exec', reg: /(^|\s)exec(\s|\()/ig},
-      {key: 'OBJECT', reg: /(^|\s)object(\s|\()/ig},
-      {key: 'sys.', reg: /(^|\s)sys\./ig},
-      {key: 'kill', reg: /(^|\s)kill\s/ig}
+      {key: 'create', reg: /(^|\s|\(|\))create\s/ig},
+      {key: 'insert', reg: /(^|\s|\(|\))insert\s/ig},
+      {key: 'delete', reg: /(^|\s|\(|\))delete\s/ig},
+      {key: 'update', reg: /(^|\s|\(|\))update\s/ig},
+      {key: 'set', reg: /(^|\s|\(|\))set\s/ig},
+      {key: 'drop', reg: /(^|\s|\(|\))drop\s/ig},
+      {key: 'alter', reg: /(^|\s|\(|\))alter\s/ig},
+      {key: 'truncate', reg: /(^|\s|\(|\))truncate\s/ig},
+      {key: 'if', reg: /(^|\s|\(|\))if\s/ig},
+      {key: 'exec', reg: /(^|\s|\(|\))exec(\s|\()/ig},
+      {key: 'OBJECT', reg: /(^|\s|\(|\))object(\s|\()/ig},
+      {key: 'sys.', reg: /(^|\s|\(|\))sys\./ig},
+      {key: 'kill', reg: /(^|\s|\(|\))kill\s/ig}
     ]
     
     if (type === 'customscript') {
@@ -808,6 +808,8 @@
     }
     if (['select', 'radio', 'link', 'checkcard'].includes(item.type) && item.linkSubField && item.linkSubField.length > 0) {
       arrfield.push(...item.linkSubField)
+    } else if (item.type === 'text' && item.editType === 'select' && item.linkSubField && item.linkSubField.length > 0) { // 鍙紪杈戣〃
+      arrfield.push(...item.linkSubField)
     }
     if (item.disableField) {
       arrfield.push(item.disableField)
@@ -856,10 +858,9 @@
  * @description 鑾峰彇excel瀵煎叆鍙傛暟
  * @return {Object} item   鎸夐挳淇℃伅
  * @return {Array}  data   excel鏁版嵁
- * @return {Object} dict   瀛楀吀椤�
  * @return {String} BID    涓婄骇Id
  */
-export function getExcelInSql (item, data, dict, BID, primaryId) {
+export function getExcelInSql (item, data, BID, primaryId) {
   let btn = item.verify
   let keys = ['delete', 'drop', 'insert', 'truncate', 'update']
   let userName = sessionStorage.getItem('User_Name') || ''
@@ -956,64 +957,43 @@
 
       let val = item[col.Column] !== undefined ? item[col.Column] : ''
       let _colindex = cols[cindex] || (cindex + 1)
-      let _position = (_topline + lindex + 1) + dict['main.excel.line'] + ' ' + _colindex + dict['main.excel.column']  + ' '
+      let _position = (_topline + lindex + 1) + '琛� ' + _colindex + '鍒� '
 
       if (/^Nvarchar/ig.test(col.type)) {
-        if (typeof(val) === 'number') {
-          val = val.toString()
+        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 + dict['main.excel.content.emptyerror'])
+          errors.push(_position + '鍐呭涓嶅彲涓虹┖')
         } else if (col.limit && val.length > col.limit) { // 闀垮害鏍¢獙
-          errors.push(_position + dict['main.excel.content.maxlimit'])
+          errors.push(_position + '鍐呭瓒呴暱')
         } else {                                          // 鍏抽敭瀛楁牎楠�
           keys.forEach(key => {
             let _patten = new RegExp('(^' + key + '\\s+)|(\\s+' + key + '\\s+)', 'ig')
             if (_patten.test(val)) {
-              errors.push(_position + dict['main.excel.includekey'] + key)
+              errors.push(_position + '鍚湁鍏抽敭瀛�' + key)
             }
           })
         }
-      } else if (/^int/ig.test(col.type)) {
+      } else if (/^Decimal/ig.test(col.type) || /^int/ig.test(col.type)) {
         if (!val && val !== 0) {
-          errors.push(_position + dict['main.excel.content.emptyerror'])
-        } else {
-          let _val = val + ''
-
-          if (!/^(([^0][0-9]+|0)$)|^(([1-9]+)$)/.test(_val)) {               // 妫�楠屾槸鍚︿负鏁存暟
-            errors.push(_position + dict['main.excel.content.interror'])
-          } else if ((col.min || col.min === 0) && val < col.min) {          // 鏈�灏忓�兼楠�
-            errors.push(_position + dict['main.excel.content.limitmin'])
-          } else if ((col.max || col.max === 0) && val > col.max) {          // 鏈�澶у�兼楠�
-            errors.push(_position + dict['main.excel.content.limitmax'])
-          }
-        }
-      } else if (/^Decimal/ig.test(col.type)) {
-        if (!val && val !== 0) {
-          errors.push(_position + dict['main.excel.content.emptyerror'])
-        } else {
-          let _val = val + ''
-          let _vals = _val.split('.')
-
-          if (!/^(([^0][0-9]+|0)\.([0-9]+)$)|^(([^0][0-9]+|0)$)|^(([1-9]+)\.([0-9]+)$)|^(([1-9]+)$)/.test(_val)) {                           // 妫�楠屾槸鍚︿负娴偣鏁�
-            errors.push(_position + dict['main.excel.content.floaterror'])
-          } else if (_vals[0].length > 18) {                          // 妫�楠屾暣鏁颁綅
-            errors.push(_position + dict['main.excel.content.floatIntover'])
-          } else if (_vals[1] && _vals[1].length > col.limit) {       // 鏈�灏忓�兼楠�
-            errors.push(_position + dict['main.excel.content.floatPointover'])
-          } else if ((col.min || col.min === 0) && val < col.min) {   // 鏈�灏忓�兼楠�
-            errors.push(_position + dict['main.excel.content.limitmin'])
-          } else if ((col.max || col.max === 0) && val > col.max) {   // 鏈�澶у�兼楠�
-            errors.push(_position + dict['main.excel.content.limitmax'])
-          }
+          errors.push(_position + '鍐呭涓嶅彲涓虹┖')
+        } else if (isNaN(val)) {                                  // 妫�楠屾槸鍚︿负鏁板��
+          errors.push(_position + '鍐呭搴斾负鏁板��')
+        } else if ((col.min || col.min === 0) && val < col.min) { // 鏈�灏忓�兼楠�
+          errors.push(_position + '灏忎簬鏈�灏忓��')
+        } else if ((col.max || col.max === 0) && val > col.max) { // 鏈�澶у�兼楠�
+          errors.push(_position + '澶т簬鏈�澶у��')
         }
       } else if (col.type === 'date') {
         if (typeof(val) === 'number') {
           if (val > 2958465 || val <= 0) {                 // 鏃堕棿杩囧ぇ鎴栧皬浜庣瓑浜�0
-            errors.push(_position + dict['main.excel.content.date.over'])
+            errors.push(_position + '鏃堕棿涓鸿礋鍊兼垨澶ぇ')
           } else {                                         // 鏃堕棿鏍煎紡鍖�
             if (val < 60) {                                // 1900-2-29锛宔xcel涓瓨鍦紝瀹為檯涓嶅瓨鍦�
               val++
@@ -1023,12 +1003,12 @@
         } else if (typeof(val) === 'string') {
           val = val.replace(/(^\s*$)|\t*|\v*/ig, '')
           if (!val && col.required === 'true') {           // 鏃堕棿蹇呭~鏍¢獙
-            errors.push(_position + dict['main.excel.content.emptyerror'])
+            errors.push(_position + '鍐呭涓嶅彲涓虹┖')
           } else if (val && !/^[1-9][0-9]{3}/.test(val)) { // 鏃堕棿姝e垯鏍¢獙
-            errors.push(_position + dict['main.excel.content.date.formatError'])
+            errors.push(_position + '鏃堕棿鏍煎紡閿欒')
           }
         } else {                                           // 鏃堕棿鏍煎紡閿欒
-          errors.push(_position + dict['main.excel.content.date.formatError'])
+          errors.push(_position + '鏃堕棿鏍煎紡閿欒')
         }
       }
 
@@ -1067,14 +1047,14 @@
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
       btn.uniques.forEach(unique => {
-        if (unique.status === 'false') return
+        if (unique.status === 'false' || !unique.verifyType) return
 
         let _fields = unique.field.split(',')
         let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
         let _afields = _fields.map(_field => `a.${_field}`)
         _fields_ = _fields_.join(' and ')
 
-        if (unique.verifyType !== 'physical') {
+        if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
           _fields_ += ' and b.deleted=0'
         }
 
@@ -1089,14 +1069,14 @@
         goto aaa
       end
       
-      Set @tbid=''
+      ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
       Select top 1 @tbid=${_afields.join('+\' \'+')} from  @${sheet} a Inner join ${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
         select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
         goto aaa
-      end
+      end` : ''}
       `
       })
     }
@@ -1288,14 +1268,14 @@
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
       btn.uniques.forEach(unique => {
-        if (unique.status === 'false') return
+        if (unique.status === 'false' || !unique.verifyType) return
 
         let _fields = unique.field.split(',')
         let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
         let _afields = _fields.map(_field => `a.${_field}`)
         _fields_ = _fields_.join(' and ')
 
-        if (unique.verifyType !== 'physical') {
+        if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
           _fields_ += ' and b.deleted=0'
         }
 
@@ -1310,14 +1290,14 @@
         goto aaa
       end
       
-      Set @tbid=''
+      ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
       Select top 1 @tbid=${_afields.join('+\' \'+')} from  @${sheet} a Inner join ${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
         select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
         goto aaa
-      end
+      end` : ''}
       `
       })
     }
@@ -1450,7 +1430,7 @@
   })
 
   // 闇�瑕佸0鏄庣殑鍙橀噺闆�
-  let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
+  let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'mk_deleted', 'bid']
 
   // 涓婚敭瀛楁
   let primaryKey = setting.primaryKey || 'id'
@@ -1470,17 +1450,24 @@
 
     if (!_initvars.includes(_key)) {
       _initvars.push(_key)
+      let val = form.value
 
       if (form.type === 'number' || form.type === 'rate') {
-        let val = form.value
         if (isNaN(val)) {
           val = 0
         }
         _initFormfields.push(`@${_key}=${val}`)
       } else if (['date', 'datemonth'].includes(form.type)) {
-        _initFormfields.push(`@${_key}='${form.value || '1949-10-01'}'`)
+        _initFormfields.push(`@${_key}='${val || '1949-10-01'}'`)
       } else {
-        _initFormfields.push(`@${_key}='${form.value}'`)
+        if (/'/.test(val)) {
+          val = val.replace(/'/ig, '"')
+        }
+        if (form.isconst) {
+          _initFormfields.push(`@${_key}=N'${val}'`)
+        } else {
+          _initFormfields.push(`@${_key}='${val}'`)
+        }
       }
     }
     
@@ -1505,15 +1492,16 @@
     }
   })
 
+  let _data = {}
   if (data) {
     Object.keys(data).forEach(key => {
-      data[key.toLowerCase()] = data[key]
+      _data[key.toLowerCase()] = data[key]
     })
   }
 
   // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
   if (data && btn.Ot !== 'notRequired' && columns && columns.length > 0) {
-    datavars = {...data, ...datavars}
+    datavars = {..._data, ...datavars}
 
     const setField = (col) => {
       if (!col.field) return
@@ -1524,6 +1512,10 @@
 
         if (col.datatype && /^date/ig.test(col.datatype) && !_val) {
           _val = '1949-10-01'
+        }
+
+        if (/'/.test(_val)) {
+          _val = _val.replace(/'/ig, '"')
         }
 
         _initvars.push(_key)
@@ -1571,7 +1563,7 @@
     _declarefields = ',' + _declarefields
   }
   _sql = `/* 绯荤粺鐢熸垚 */
-      Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @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),@bid nvarchar(50)${_declarefields}
+      Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @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),@mk_deleted int,@bid nvarchar(50)${_declarefields}
     `
 
   let userName = sessionStorage.getItem('User_Name') || ''
@@ -1594,7 +1586,7 @@
   // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
   _sql += `
       /* 鍑瘉鍙婄敤鎴蜂俊鎭垵濮嬪寲璧嬪�� */
-      select @BVoucher='',@FIBVoucherDate='',@FiYear='',@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}', @bid='${BID}', @BillCode='', @ModularDetailCode=''
+      select @BVoucher='',@FIBVoucherDate='',@FiYear='',@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}', @mk_deleted=1, @bid='${BID}', @BillCode='', @ModularDetailCode=''
       `
 
   // 琛ㄥ崟鍙橀噺璧嬪��
@@ -1708,7 +1700,7 @@
       /* 澶辨晥楠岃瘉 */
       select @tbid='', @ErrorCode='',@retmsg=''
       select @tbid='X' from ${datasource} right join (select ID from  dbo.SplitComma(@ID@)) sp
-      on tb.id =sp.id where tb.id is null
+      on tb.${primaryKey} =sp.id where tb.${primaryKey} is null
 
       If @tbid!=''
       Begin
@@ -1782,8 +1774,8 @@
         let _val = ''
         if (_linkKey === 'bid' && BID) { // 鏇挎崲bid
           _val = BID
-        } else if (data && data.hasOwnProperty(_linkKey)) {
-          _val = data[_linkKey]
+        } else if (_data.hasOwnProperty(_linkKey)) {
+          _val = _data[_linkKey]
         }
         _ModularDetailCode = `'${item.TypeCharOne + _val}'`
       } else {
@@ -1912,7 +1904,7 @@
     _sql += `
       /* 鍒涘缓鍑瘉 */
       exec s_BVoucher_Create
-        @Bill ='${data[_voucher.linkField.toLowerCase()]}',
+        @Bill ='${_data[_voucher.linkField.toLowerCase()]}',
         @BVoucherType ='${_voucher.BVoucherType}',
         @VoucherTypeOne ='${_voucher.VoucherTypeOne}',
         @VoucherTypeTwo ='${_voucher.VoucherTypeTwo}',
@@ -2067,7 +2059,7 @@
 
     _sql += `
       /* 榛樿sql */
-      update ${btn.sql} set deleted=1,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@ where ${primaryKey}${_ID};`
+      update ${btn.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@ where ${primaryKey}${_ID};`
   
   } else if (_actionType === 'delete') {      // 鐗╃悊鍒犻櫎
     let _msg = ''
@@ -2254,36 +2246,21 @@
  */
 export function setGLOBFuncs () {
   window.GLOB.funcs = []
-  if (!window.GLOB.WebSql && !window.GLOB.IndexDB) {
+  if (!window.GLOB.IndexDB) {
     return
   }
 
-  if (window.GLOB.WebSql) {
-    window.GLOB.WebSql.transaction(tx => {
-      tx.executeSql("SELECT * FROM FUNCS", [], (tx, results) => {
-        let rows = results.rows
-        if (!rows || rows.length === 0) return
-        for (let i = 0; i < rows.length; i++) {
-          window.GLOB.funcs.push({
-            func_code: rows[i].func_code,
-            key_sql: window.decodeURIComponent(window.atob(rows[i].key_sql))
-          })
-        }
+  let objectStore = window.GLOB.IndexDB.transaction('funcs').objectStore('funcs')
+
+  objectStore.openCursor().onsuccess = (event) => {
+    let cursor = event.target.result
+
+    if (cursor) {
+      window.GLOB.funcs.push({
+        func_code: cursor.value.func_code,
+        key_sql: window.decodeURIComponent(window.atob(cursor.value.key_sql))
       })
-    })
-  } else {
-    let objectStore = window.GLOB.IndexDB.transaction('funcs').objectStore('funcs')
-
-    objectStore.openCursor().onsuccess = (event) => {
-      let cursor = event.target.result
-
-      if (cursor) {
-        window.GLOB.funcs.push({
-          func_code: cursor.value.func_code,
-          key_sql: window.decodeURIComponent(window.atob(cursor.value.key_sql))
-        })
-        cursor.continue()
-      }
+      cursor.continue()
     }
   }
 }
diff --git a/src/views/appmanage/index.jsx b/src/views/appmanage/index.jsx
index a54a3b7..ff500da 100644
--- a/src/views/appmanage/index.jsx
+++ b/src/views/appmanage/index.jsx
@@ -508,15 +508,24 @@
           let _href = window.location.href.split('#')[0] + 'app_record'
           let record = localStorage.getItem(_href)
           record = record ? JSON.parse(record) : null
-          
-          if (record) {
-            if (record.activeId) {
-              let index = applist.findIndex(item => item.ID === record.activeId)
-              if (index === -1) {
-                localStorage.setItem(_href, JSON.stringify({preId: '', activeId: ''}))
-              } else if (index !== 0) {
-                applist.unshift(...applist.splice(index, 1))
+
+          if (record && record.dates) {
+            let ids = applist.map(item => item.ID)
+            let reset = false
+
+            Object.keys(record.dates).forEach(key => {
+              if (!ids.includes(key)) {
+                delete record.dates[key]
+                reset = true
               }
+            })
+
+            applist.sort((a, b) => {
+              return (record.dates[b.ID] || 0) - (record.dates[a.ID] || 0)
+            })
+
+            if (reset) {
+              localStorage.setItem(_href, JSON.stringify(record))
             }
           }
         }
@@ -698,11 +707,11 @@
     let record = localStorage.getItem(_href)
     record = record ? JSON.parse(record) : null
 
-    if (!record) {
-      localStorage.setItem(_href, JSON.stringify({preId: selectApp.ID, activeId: ''}))
+    if (!record || !record.dates) {
+      localStorage.setItem(_href, JSON.stringify({preId: selectApp.ID, activeId: selectApp.ID, dates: {[selectApp.ID]: new Date().getTime()}}))
     } else {
-      if (record.preId === selectApp.ID) {
-        localStorage.setItem(_href, JSON.stringify({preId: selectApp.ID, activeId: selectApp.ID}))
+      if (record.preId === selectApp.ID || record.activeId === selectApp.ID) {
+        localStorage.setItem(_href, JSON.stringify({preId: selectApp.ID, activeId: selectApp.ID, dates: {...record.dates, [selectApp.ID]: new Date().getTime()}}))
       } else {
         localStorage.setItem(_href, JSON.stringify({...record, preId: selectApp.ID}))
       }
diff --git a/src/views/billprint/index.jsx b/src/views/billprint/index.jsx
index b616463..de28f47 100644
--- a/src/views/billprint/index.jsx
+++ b/src/views/billprint/index.jsx
@@ -26,6 +26,7 @@
 const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table'))
 const SandBox = asyncComponent(() => import('@/tabviews/custom/components/code/sand-box'))
 const TimeLine = asyncComponent(() => import('@/tabviews/custom/components/timeline/normal-timeline'))
+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 DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
@@ -60,7 +61,6 @@
         let param = JSON.parse(window.decodeURIComponent(window.atob(params.param)))
   
         sessionStorage.setItem('dataM', param.dataM || '')
-        sessionStorage.setItem('localDataM', param.dataM || '')
         this.setState({
           BID: param.id || '',
           tempId: param.tempId,
@@ -333,18 +333,66 @@
 
           if (component.type === 'table') {
             let getColumns = (cols) => {
-              return cols.map(item => {
+              return cols.filter(item => {
                 if (item.type === 'colspan') {
                   item.subcols = getColumns(item.subcols)
+                  if (item.subcols.length === 0) {
+                    return false
+                  }
+                } else if (item.type === 'custom') {
+                  item.elements = item.elements.filter(cell => {
+                    if (cell.eleType === 'button') return false
+
+                    cell = this.resetElement(cell)
+                    return cell
+                  })
+                  if (item.elements.length === 0) {
+                    return false
+                  }
                 } else {
                   item.IsSort = 'false'
                 }
           
-                return item
+                return true
               })
             }
             component.cols = getColumns(component.cols)
             component.statFields = []
+          } else if (['card', 'carousel', 'timeline'].includes(component.type)) {
+            component.subcards && component.subcards.forEach(card => {
+              if (card.style.boxShadow) {
+                delete card.style.hShadow
+                delete card.style.vShadow
+                delete card.style.shadowBlur
+                delete card.style.shadowColor
+              }
+    
+              card.elements = card.elements.filter(cell => {
+                if (cell.eleType === 'button') return false
+   
+                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
+   
+                cell = this.resetElement(cell)
+    
+                return true
+              })
+            })
+          } else if (component.type === 'balcony') {
+            component.elements = component.elements.filter(cell => {
+              if (cell.eleType === 'button') return false
+                
+              cell = this.resetElement(cell)
+    
+              return true
+            })
           }
 
           if (component.wrap && component.wrap.datatype === 'static') {
@@ -454,14 +502,41 @@
     })
   }
 
+  resetElement = (cell) => {
+    cell.style = cell.style || {}
+    if (['text', 'number', 'formula'].includes(cell.eleType)) {
+      cell.innerHeight = cell.innerHeight || 'auto'
+      cell.alignItems = cell.height > 1 ? cell.alignItems : ''
+
+      if (cell.eleType === 'number' && typeof(cell.decimal) === 'number') {
+        cell.round = Math.pow(10, cell.decimal)
+        if (cell.format === 'percent') {
+          cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
+        }
+      }
+    }
+
+    return cell
+  }
+
   reload = () => {
+    const { tempId } = this.state
+    
     this.setState({
       loadingview: true,
       pages: null,
       data: '',
       config: null
     }, () => {
-      this.getMenuParam()
+      Api.deleteMenuStorage(tempId)
+      setTimeout(() => {
+        this.getMenuParam()
+      }, 50)
+      // Api.getAppVersion(tempId).then(() => {
+      //   this.getMenuParam()
+      // }, () => {
+      //   this.getMenuParam()
+      // })
     })
   }
 
@@ -874,6 +949,12 @@
             <TimeLine config={item} initdata={item.data} mainSearch={[]}/>
           </Col>
         )
+      } else if (item.type === 'editor') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <BraftEditor config={item} initdata={item.data} mainSearch={[]}/>
+          </Col>
+        )
       } else if (item.type === 'antvG6') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
diff --git a/src/views/design/header/editfirstmenu/index.jsx b/src/views/design/header/editfirstmenu/index.jsx
index 58bee24..45a5b8d 100644
--- a/src/views/design/header/editfirstmenu/index.jsx
+++ b/src/views/design/header/editfirstmenu/index.jsx
@@ -141,6 +141,7 @@
         onOk() {
           return Api.getSystemConfig(param).then(res => {
             if (res.status) {
+              that.setState({ change: false })
               that.props.reload()
             } else {
               notification.warning({
diff --git a/src/views/design/header/index.jsx b/src/views/design/header/index.jsx
index 39078cd..2155478 100644
--- a/src/views/design/header/index.jsx
+++ b/src/views/design/header/index.jsx
@@ -237,7 +237,7 @@
   }
 
   setSystemFuncs = () => {
-    if (!window.GLOB.WebSql && !window.GLOB.IndexDB) {
+    if (!window.GLOB.IndexDB) {
       return
     }
     this.getfuncTime().then(res => {
@@ -256,80 +256,44 @@
   }
 
   writeFuncs = (funcs) => {
-    let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    let shim = +sessionStorage.getItem('sys_time_shim')
+    let timestamp = moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss')
 
-    let sys_datetime = sessionStorage.getItem('sys_datetime')
-    let app_datetime = sessionStorage.getItem('app_datetime')
-    if (sys_datetime && app_datetime) {
-      let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000)
-      timestamp = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss')
-    }
+    let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs')
 
-    if (window.GLOB.WebSql) {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql('DELETE FROM FUNCS')
+    objectStore.clear()
 
-        funcs.forEach(item => {
-          if (!item.key_sql) return
-          tx.executeSql('INSERT INTO FUNCS (func_code, key_sql) VALUES (?, ?)', [item.func_code, item.key_sql])
-        })
-        tx.executeSql(`UPDATE VERSIONS SET createDate='${timestamp}' where CDefine1='funcs'`)
-      })
-    } else {
-      let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs')
+    funcs.forEach(item => {
+      if (!item.key_sql) return
+      item.id = item.func_code
+      objectStore.add(item)
+    })
 
-      objectStore.clear()
-
-      funcs.forEach(item => {
-        if (!item.key_sql) return
-        item.id = item.func_code
-        objectStore.add(item)
-      })
-
-      let funcStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version')
-      funcStore.put({id: 'funcs', version: '1.0', createDate: timestamp})
-    }
+    let funcStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version')
+    funcStore.put({id: 'funcs', version: '1.0', createDate: timestamp})
   }
 
   getfuncTime = () => {
     return new Promise((resolve, reject) => {
-      if (window.GLOB.WebSql) {
-        window.GLOB.WebSql.transaction(tx => {
-          tx.executeSql("SELECT * FROM VERSIONS where CDefine1='funcs'", [], (tx, results) => {
-            let rows = results.rows
-            if (rows.length === 0) {
-              tx.executeSql('DELETE FROM FUNCS')
-              tx.executeSql('INSERT INTO VERSIONS (version, createDate, CDefine1) VALUES (?, ?, ?)', ['1.0', '1970-01-01 14:59:09.000', 'funcs'])
-              resolve({createDate: '1970-01-01 14:59:09.000'})
-            } else {
-              resolve(rows[0])
-            }
-          }, (tx, results) => {
+      let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version')
+      let request = objectStore.get('funcs')
+
+      request.onerror = (event) => {
+        console.warn(event)
+        reject()
+      }
+
+      request.onsuccess = () => {
+        if (request.result) {
+          resolve(request.result)
+        } else {
+          let add = objectStore.add({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'})
+  
+          add.onerror = () => {
             reject()
-            console.warn(results)
-          })
-        })
-      } else {
-        let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version')
-        let request = objectStore.get('funcs')
-
-        request.onerror = (event) => {
-          console.warn(event)
-          reject()
-        }
-
-        request.onsuccess = () => {
-          if (request.result) {
-            resolve(request.result)
-          } else {
-            let add = objectStore.add({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'})
-    
-            add.onerror = () => {
-              reject()
-            }
-            add.onsuccess = () => {
-              resolve({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'})
-            }
+          }
+          add.onsuccess = () => {
+            resolve({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'})
           }
         }
       }
diff --git a/src/views/design/sidemenu/editsecmenu/index.jsx b/src/views/design/sidemenu/editsecmenu/index.jsx
index ad44fad..57e0cff 100644
--- a/src/views/design/sidemenu/editsecmenu/index.jsx
+++ b/src/views/design/sidemenu/editsecmenu/index.jsx
@@ -126,6 +126,7 @@
         onOk() {
           return Api.getSystemConfig(param).then(res => {
             if (res.status) {
+              that.setState({ change: false })
               MKEmitter.emit('mkUpdateMenuList')
             } else {
               notification.warning({
diff --git a/src/views/design/sidemenu/editthdmenu/index.jsx b/src/views/design/sidemenu/editthdmenu/index.jsx
index 4da6159..7b575a2 100644
--- a/src/views/design/sidemenu/editthdmenu/index.jsx
+++ b/src/views/design/sidemenu/editthdmenu/index.jsx
@@ -157,6 +157,7 @@
         onOk() {
           return Api.getSystemConfig(param).then(res => {
             if (res.status) {
+              that.setState({ change: false })
               MKEmitter.emit('mkUpdateMenuList')
             } else {
               notification.warning({
diff --git a/src/views/interface/api/index.js b/src/views/interface/api/index.js
index 59f4941..37b374b 100644
--- a/src/views/interface/api/index.js
+++ b/src/views/interface/api/index.js
@@ -1,25 +1,30 @@
 import axios from 'axios'
 import md5 from 'md5'
 import jsSHA from 'jssha'
-import { notification } from 'antd'
 
-window.GLOB.WebSql = null
+window.GLOB.IndexDB = null
 
-if (window.openDatabase) {
-  let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : ''
+let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : ''
+let db = `mk_inter${service}`
+
+if (window.indexedDB) {
   try {
-    window.GLOB.WebSql = openDatabase(`mkdb${service}`, '1', 'mk-pc-database', 50 * 1024 * 1024)
-    window.GLOB.WebSql.transaction(tx => {
-      tx.executeSql('CREATE TABLE IF NOT EXISTS INTERFACES (uuid varchar(50), createDate varchar(50), method varchar(50), interface text, params text, headers text, active varchar(50), raw text, formData text, CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50), CDefine4 varchar(50), CDefine5 text)', [], () => {
-
-      }, () => {
-        // eslint-disable-next-line
-        throw 'CREATE TABLE ERROR'
-      })
-    })
+    let request = window.indexedDB.open(db, 1)
+    request.onerror = () => {
+      console.warn('IndexedDB 鍒濆鍖栧け璐ワ紒')
+    }
+    request.onsuccess = () => {
+      window.GLOB.IndexDB = request.result
+    }
+    request.onupgradeneeded = (event) => {
+      window.GLOB.IndexDB = event.target.result
+      if (!window.GLOB.IndexDB.objectStoreNames.contains('interfaces')) {
+        window.GLOB.IndexDB.createObjectStore('interfaces', { keyPath: 'id' })
+      }
+    }
   } catch (e) {
-    console.warn('WebSql 鍒濆鍖栧け璐ワ紒')
-    window.GLOB.WebSql = null
+    console.warn('IndexedDB 鍒濆鍖栧け璐ワ紝鍘嗗彶璁板綍灏嗘棤娉曟煡璇㈡垨淇敼锛�')
+    window.GLOB.IndexDB = null
   }
 }
 
@@ -102,73 +107,46 @@
     return axios(config)
   }
 
-  writeInWebSql (data) {
-    if (!window.GLOB.WebSql) {
-      notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 })
-      return
-    }
-    return new Promise((resolve, reject) => {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`INSERT INTO INTERFACES (uuid, createDate, method, interface, params, headers, active, raw, formData) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, data, (tx, results) => {
-          resolve(results)
-        }, () => {
-          resolve()
-        })
-      })
-    })
+  writeInIndexDB (data) {
+    if (!window.GLOB.IndexDB) return
+
+    window.GLOB.IndexDB.transaction(['interfaces'], 'readwrite').objectStore('interfaces').add(data)
   }
 
   getInterfaces () {
-    if (!window.GLOB.WebSql) {
-      notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 })
-      return
-    }
+    if (!window.GLOB.IndexDB) return Promise.resolve()
+
     return new Promise((resolve, reject) => {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`SELECT * FROM INTERFACES`, [], (tx, results) => {
-          // let paramItem = results.rows[0]
-          resolve(results)
-        }, () => {
-          window.GLOB.WebSql = null
-          reject()
-        })
-      })
+      let request = window.GLOB.IndexDB.transaction(['interfaces']).objectStore('interfaces').openCursor()
+      let list = []
+
+      request.onsuccess = (e) => {
+        let cursor = e.target.result
+        if (cursor) {
+          if (cursor.value) {
+            list.push(cursor.value)
+          }
+          cursor.continue()
+        } else {
+          resolve(list)
+        }
+      }
     })
   }
 
-  delInterface (uuid) {
-    if (!window.GLOB.WebSql) {
-      notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 })
-      return
-    }
-    return new Promise((resolve, reject) => {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`DELETE FROM INTERFACES where uuid = '${uuid}'`, [], (tx, results) => {
-          resolve(results)
-        }, () => {
-          resolve()
-        })
-      })
-    })
+  delInterface (id) {
+    if (!window.GLOB.IndexDB) return
+
+    window.GLOB.IndexDB.transaction(['interfaces'], 'readwrite').objectStore('interfaces').delete(id)
   }
 
   /**
    * @description 娓呯┖鎺ュ彛璋冪敤璁板綍
    */
   clearInterfaces () {
-    if (!window.GLOB.WebSql) {
-      notification.warning({ top: 92, message: 'WebSql寮�鍚け璐ワ紒', duration: 5 })
-      return
-    }
-    return new Promise((resolve, reject) => {
-      window.GLOB.WebSql.transaction(tx => {
-        tx.executeSql(`DELETE FROM INTERFACES`, [], (tx, results) => {
-          resolve(results)
-        }, () => {
-          resolve()
-        })
-      })
-    })
+    if (!window.GLOB.IndexDB) return
+
+    window.GLOB.IndexDB.transaction(['interfaces'], 'readwrite').objectStore('interfaces').clear()
   }
 }
 
diff --git a/src/views/interface/history/index.jsx b/src/views/interface/history/index.jsx
index 0db24fe..c9c9143 100644
--- a/src/views/interface/history/index.jsx
+++ b/src/views/interface/history/index.jsx
@@ -22,69 +22,13 @@
   componentDidMount() {
     MKEmitter.addListener('insertInterface', this.insertInterface)
     setTimeout(() => {
-      Api.getInterfaces().then(res => {
-        if (!res || !res.rows) return
-
-        let rows = [...res.rows]
-        rows.sort((a,b) => {
-          return a.createDate < b.createDate ? 1 : -1
-        })
-
-        let list = []
-        let item = null
-        
-        rows.forEach(m => {
-          let date = m.createDate.substring(0, 10)
-
-          if (m.params) {
-            try {
-              m.params = JSON.parse(m.params)
-            } catch (e) {
-              m.params = []
-            }
-          } else {
-            m.params = []
-          }
-
-          if (m.headers) {
-            try {
-              m.headers = JSON.parse(m.headers)
-            } catch (e) {
-              m.headers = []
-            }
-          } else {
-            m.headers = []
-          }
-          
-          if (m.formData) {
-            try {
-              m.formData = JSON.parse(m.formData)
-            } catch (e) {
-              m.formData = []
-            }
-          } else {
-            m.formData = []
-          }
-
-          if (item && item.date !== date) {
-            list.push(item)
-            item = null
-          }
-
-          if (!item) {
-            item = {date, sublist: []}
-            item.sublist.push(m)
-          } else if (item && item.date === date) {
-            item.sublist.push(m)
-          }
-        })
-
-        if (item) {
-          list.push(item)
-        }
-
-        this.setState({list, historys: fromJS(list).toJS()})
-      })
+      if (window.GLOB.IndexDB) {
+        this.getHistory()
+      } else {
+        setTimeout(() => {
+          this.getHistory()
+        }, 1000)
+      }
     }, 200)
   }
 
@@ -103,91 +47,136 @@
     confirm({
       content: 'Are you sure you want to clear all your history requests?',
       onOk() {
-        Api.clearInterfaces().then(res => {
-          if (res && res.rows.length === 0) {
-            _this.setState({list: [], historys: []})
-            Modal.success({
-              title: '娓呴櫎鎴愬姛銆�'
-            })
-          } else {
-            Modal.error({
-              title: '娓呴櫎澶辫触锛佽鍒锋柊閲嶈瘯銆�'
-            })
-          }
-        })
+        Api.clearInterfaces()
+
+        _this.setState({list: [], historys: []})
       },
       onCancel() {}
     })
   }
 
-  delete = (m) => {
-    const { searchKey } = this.state
-    Api.delInterface(m.uuid).then(res => {
-      if (res) {
-        let list = this.state.list.filter(item => {
-          item.sublist = item.sublist.filter(cell => cell.uuid !== m.uuid)
-  
-          return item.sublist.length > 0
-        })
+  getHistory = () => {
+    Api.getInterfaces().then(res => {
+      if (!res) return
 
-        let historys = fromJS(list).toJS()
-        if (searchKey) {
-          historys = historys.filter(item => {
-            item.sublist = item.sublist.filter(cell => cell.interface.indexOf(searchKey) > -1)
-    
-            return item.sublist.length > 0
-          })
+      res.sort((a,b) => {
+        return a.createDate < b.createDate ? 1 : -1
+      })
+
+      let list = []
+      let item = null
+      
+      res.forEach(m => {
+        let date = m.createDate.substring(0, 10)
+
+        if (m.params) {
+          try {
+            m.params = JSON.parse(m.params)
+          } catch (e) {
+            m.params = []
+          }
+        } else {
+          m.params = []
         }
 
-        this.setState({list, historys})
-      } else {
-        Modal.error({
-          title: '鍒犻櫎澶辫触锛佽鍒锋柊閲嶈瘯銆�'
-        })
+        if (m.headers) {
+          try {
+            m.headers = JSON.parse(m.headers)
+          } catch (e) {
+            m.headers = []
+          }
+        } else {
+          m.headers = []
+        }
+        
+        if (m.formData) {
+          try {
+            m.formData = JSON.parse(m.formData)
+          } catch (e) {
+            m.formData = []
+          }
+        } else {
+          m.formData = []
+        }
+
+        if (item && item.date !== date) {
+          list.push(item)
+          item = null
+        }
+
+        if (!item) {
+          item = {date, sublist: []}
+          item.sublist.push(m)
+        } else if (item && item.date === date) {
+          item.sublist.push(m)
+        }
+      })
+
+      if (item) {
+        list.push(item)
       }
+
+      this.setState({list, historys: fromJS(list).toJS()})
     })
   }
 
+  delete = (m) => {
+    const { searchKey } = this.state
+
+    Api.delInterface(m.id)
+
+    let list = this.state.list.filter(item => {
+      item.sublist = item.sublist.filter(cell => cell.id !== m.id)
+
+      return item.sublist.length > 0
+    })
+
+    let historys = fromJS(list).toJS()
+    if (searchKey) {
+      historys = historys.filter(item => {
+        item.sublist = item.sublist.filter(cell => cell.interface.indexOf(searchKey) > -1)
+
+        return item.sublist.length > 0
+      })
+    }
+
+    this.setState({list, historys})
+  }
+
   insertInterface = (item) => {
-    item.uuid = Utils.getuuid()
+    item.id = Utils.getuuid()
     item.createDate = moment().format('YYYY-MM-DD HH:mm:ss')
 
-    Api.writeInWebSql([item.uuid, item.createDate, item.method, item.interface, JSON.stringify(item.params), JSON.stringify(item.headers), item.active, item.raw, JSON.stringify(item.formData)]).then(res => {
-      if (res) {
-        let list = fromJS(this.state.list).toJS()
+    Api.writeInIndexDB(item)
 
-        if (list[0]) {
-          if (list[0].date === item.createDate.substring(0, 10)) {
-            list[0].sublist.unshift(item)
-          } else {
-            list.unshift({
-              date: item.createDate.substring(0, 10),
-              sublist: [item]
-            })
-          }
-        } else {
-          list.push({
-            date: item.createDate.substring(0, 10),
-            sublist: [item]
-          })
-        }
+    let list = fromJS(this.state.list).toJS()
 
-        let historys = fromJS(list).toJS()
-        if (this.state.searchKey) {
-          historys = historys.filter(item => {
-            item.sublist = item.sublist.filter(cell => cell.interface.indexOf(this.state.searchKey) > -1)
-    
-            return item.sublist.length > 0
-          })
-        }
-
-        this.setState({ list, historys })
+    if (list[0]) {
+      if (list[0].date === item.createDate.substring(0, 10)) {
+        list[0].sublist.unshift(item)
       } else {
-        Modal.error({
-          title: '娣诲姞澶辫触锛佽鍒锋柊閲嶈瘯銆�'
+        list.unshift({
+          date: item.createDate.substring(0, 10),
+          sublist: [item]
         })
       }
-    })
+    } else {
+      list.push({
+        date: item.createDate.substring(0, 10),
+        sublist: [item]
+      })
+    }
+
+    let historys = fromJS(list).toJS()
+    if (this.state.searchKey) {
+      historys = historys.filter(item => {
+        item.sublist = item.sublist.filter(cell => cell.interface.indexOf(this.state.searchKey) > -1)
+
+        return item.sublist.length > 0
+      })
+    }
+
+    this.setState({ list, historys })
   }
 
   use = (m) => {
@@ -204,7 +193,7 @@
       method: 'POST',
       params: [],
       raw: "{\n \"UserName\":\"******\",\n \"Password\":\"******\",\n \"systemType\":\"local\",\n \"Type\":\"鍏挜\",\n \"privatekey\":\"绉侀挜\",\n \"timestamp\":\"" + moment().format('YYYY-MM-DD HH:mm:ss') + "\",\n \"appkey\":\"" + window.GLOB.appkey + "\"\n}",
-      uuid: 'dologon'
+      id: 'dologon'
     }
 
     if (window.GLOB.mainSystemApi) {
@@ -223,7 +212,7 @@
       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}",
-      uuid: 'dologon'
+      id: 'dologon'
     }
     MKEmitter.emit('useInterface', m)
   }
@@ -258,7 +247,7 @@
             <div className="list-line" key={index}>
               <div className="line-title">{item.date}</div>
               {item.sublist.map(m => (
-                <div className="line-item" key={m.uuid}>
+                <div className="line-item" key={m.id}>
                   <div className="method">POST</div>
                   <div className="inter">{m.interface}</div>
                   <div className="action">
diff --git a/src/views/interface/workspace/index.jsx b/src/views/interface/workspace/index.jsx
index 58c0b71..a750938 100644
--- a/src/views/interface/workspace/index.jsx
+++ b/src/views/interface/workspace/index.jsx
@@ -12,7 +12,7 @@
 class WorkSpace extends Component {
   state = {
     tabviews: [{
-      uuid: Utils.getuuid(),
+      id: Utils.getuuid(),
       createDate: '',
       method: 'POST',
       interface: '',
@@ -39,24 +39,24 @@
   }
 
   useInterface = (item) => {
-    item.uuid = Utils.getuuid()
+    item.id = Utils.getuuid()
     
     this.setState({tabviews: [...this.state.tabviews, item]}, () => {
-      let div = document.getElementById(item.uuid)
+      let div = document.getElementById(item.id)
       div && div.click && div.click()
     })
   }
 
   handleTabview = (view) => {
     let tabviews = fromJS(this.state.tabviews).toJS()
-    tabviews = tabviews.filter(item => item.uuid !== view.uuid)
+    tabviews = tabviews.filter(item => item.id !== view.id)
 
     this.setState({tabviews}, () => {
       if (tabviews.length > 0) return
 
       setTimeout(() => {
         this.setState({tabviews: [{
-          uuid: Utils.getuuid(),
+          id: Utils.getuuid(),
           createDate: '',
           method: 'POST',
           interface: '',
@@ -72,7 +72,7 @@
 
   handleAdd = () => {
     let item = {
-      uuid: Utils.getuuid(),
+      id: Utils.getuuid(),
       createDate: '',
       method: 'POST',
       interface: '',
@@ -83,7 +83,7 @@
       formData: []
     }
     this.setState({tabviews: [...this.state.tabviews, item]}, () => {
-      let div = document.getElementById(item.uuid)
+      let div = document.getElementById(item.id)
       div && div.click && div.click()
     })
   }
@@ -99,7 +99,7 @@
             return (
               <Tabs.TabPane
                 tab={
-                  <span className="control" id={view.uuid || ''}>
+                  <span className="control" id={view.id || ''}>
                     <span className="method">
                       {view.method || 'POST'}
                     </span>
@@ -109,7 +109,7 @@
                     <CloseOutlined onClick={() => this.handleTabview(view)}/>
                   </span>
                 }
-                key={view.uuid}
+                key={view.id}
               >
                 <Request config={view} />
               </Tabs.TabPane>
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index 2edd976..80c0c73 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -52,7 +52,6 @@
     localStorage.removeItem('localDataM')
     localStorage.removeItem('debug')
     localStorage.removeItem('role_id')
-    localStorage.removeItem('localRole_id')
 
     sessionStorage.clear()
   }
@@ -112,7 +111,6 @@
       localStorage.setItem('departmentcode', res.departmentcode || '')
       localStorage.setItem('organization', res.organization || '')
       localStorage.setItem('mk_user_type', res.mk_user_type || '')
-      localStorage.setItem('localRole_id', res.role_id || '')
 
       localStorage.setItem('lang', 'zh-CN')
 
@@ -194,16 +192,8 @@
         sessionStorage.setItem('debug', res.debug || '')
         sessionStorage.setItem('role_id', res.role_id || '')
         sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
-        sessionStorage.setItem('localRole_id', res.role_id || '')
 
-        let _history = sessionStorage.getItem('history')
-        if (_history) {
-          sessionStorage.removeItem('history')
-          // 鏌ョ湅鏄惁涓哄叾浠栭〉闈㈣烦杞紝璺緞瀛樺湪鏃讹紝璺冲洖鍘熼〉闈�
-          this.props.history.replace(_history)
-        } else {
-          this.props.history.replace('/main')
-        }
+        this.props.history.replace('/main')
       }
     } else if (res.ErrCode === 'Need_Get_Appkey' && options.sysType === 'SSO') {
       message.warning('搴旂敤灏氭湭鍒涘缓锛岃鍚戜簯绔悓姝ュ簲鐢紒')
@@ -241,13 +231,11 @@
       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('departmentcode', res.departmentcode || '')
       sessionStorage.setItem('organization', res.organization || '')
       sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
-      sessionStorage.setItem('localRole_id', res.role_id || '')
       
       if (res.paas_externalDatabase) {
         sessionStorage.setItem('externalDatabase', res.paas_externalDatabase)
@@ -260,14 +248,7 @@
       sessionStorage.removeItem('visitorUserID')
       sessionStorage.removeItem('visitorLoginUID')
 
-      let _history = sessionStorage.getItem('history')
-      if (_history) {
-        sessionStorage.removeItem('history')
-        // 鏌ョ湅鏄惁涓哄叾浠栭〉闈㈣烦杞紝璺緞瀛樺湪鏃讹紝璺冲洖鍘熼〉闈�
-        this.props.history.replace(_history)
-      } else {
-        this.props.history.replace('/main')
-      }
+      this.props.history.replace('/main')
     } else if (res.ErrCode === 'Need_Get_Appkey' && options.sysType === 'SSO') {
       message.warning('搴旂敤灏氭湭鍒涘缓锛岃鍚戜簯绔悓姝ュ簲鐢紒')
 
@@ -292,13 +273,11 @@
         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('departmentcode', res.departmentcode || '')
         sessionStorage.setItem('organization', res.organization || '')
         sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
-        sessionStorage.setItem('localRole_id', res.role_id || '')
 
         if (res.paas_externalDatabase) {
           sessionStorage.setItem('externalDatabase', res.paas_externalDatabase)
@@ -308,14 +287,7 @@
         sessionStorage.removeItem('visitorUserID')
         sessionStorage.removeItem('visitorLoginUID')
   
-        let _history = sessionStorage.getItem('history')
-        if (_history) {
-          sessionStorage.removeItem('history')
-          // 鏌ョ湅鏄惁涓哄叾浠栭〉闈㈣烦杞紝璺緞瀛樺湪鏃讹紝璺冲洖鍘熼〉闈�
-          this.props.history.replace(_history)
-        } else {
-          this.props.history.replace('/main')
-        }
+        this.props.history.replace('/main')
       } else if (res.ErrCode === 'Need_Get_Appkey' && options.sysType === 'SSO') {
         message.warning('搴旂敤灏氭湭鍒涘缓锛岃鍚戜簯绔悓姝ュ簲鐢紒')
   
@@ -657,10 +629,12 @@
             }
 
             sessionStorage.setItem('home_background', res.index_background_color || '')
+
+            let seconds = 0
             if (res.sys_datetime) {
-              sessionStorage.setItem('sys_datetime', res.sys_datetime)
-              sessionStorage.setItem('app_datetime', new Date().getTime())
+              seconds = Math.floor((new Date(res.sys_datetime).getTime() - new Date().getTime()) / 1000)
             }
+            sessionStorage.setItem('sys_time_shim', isNaN(seconds) ? 0 : seconds)
 
             // url鏍囬
             document.title = systemMsg.platTitle
@@ -911,14 +885,7 @@
             }
           }
 
-          let _history = sessionStorage.getItem('history')
-          if (_history) {
-            sessionStorage.removeItem('history')
-            // 鏌ョ湅鏄惁涓哄叾浠栭〉闈㈣烦杞紝璺緞瀛樺湪鏃讹紝璺冲洖鍘熼〉闈�
-            this.props.history.replace(_history)
-          } else {
-            this.props.history.replace('/main')
-          }
+          this.props.history.replace('/main')
         } else {
           notification.warning({
             top: 92,
diff --git a/src/views/login/logincloudform.jsx b/src/views/login/logincloudform.jsx
index a8c70fc..c87cf3f 100644
--- a/src/views/login/logincloudform.jsx
+++ b/src/views/login/logincloudform.jsx
@@ -20,6 +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, '')
           resolve(values)
         } else {
           reject(err)
diff --git a/src/views/login/loginform.jsx b/src/views/login/loginform.jsx
index 38e3d44..cb74ecf 100644
--- a/src/views/login/loginform.jsx
+++ b/src/views/login/loginform.jsx
@@ -96,6 +96,13 @@
     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})
         } else {
           reject(err)
diff --git a/src/views/main/index.jsx b/src/views/main/index.jsx
index 8dd7821..3fa342e 100644
--- a/src/views/main/index.jsx
+++ b/src/views/main/index.jsx
@@ -17,7 +17,15 @@
 const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 
 class Main extends Component {
-  state = {}
+  state = {
+    userId: sessionStorage.getItem('UserID')
+  }
+
+  UNSAFE_componentWillMount() {
+    if (!this.state.userId) {
+      this.props.history.replace('/login')
+    }
+  }
 
   componentDidMount () {
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
@@ -50,7 +58,9 @@
 
   render () {
     const navBar = window.GLOB.navBar
-    
+
+    if (!this.state.userId) return null
+
     return (
       <div className="mk-main-view">
         <ConfigProvider locale={_locale}>
diff --git a/src/views/menudesign/homeform/index.jsx b/src/views/menudesign/homeform/index.jsx
index 1fc96b3..4454c32 100644
--- a/src/views/menudesign/homeform/index.jsx
+++ b/src/views/menudesign/homeform/index.jsx
@@ -171,9 +171,10 @@
               {getFieldDecorator('timeUnit', {
                 initialValue: config.timeUnit || 'day'
               })(
-                <Radio.Group onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
+                <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>
@@ -189,7 +190,7 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit !== 'hour' ? 7 : 23} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
               )}
             </Form.Item>
           </Col> : null}
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index ce3e6e5..eac50e4 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -73,8 +73,16 @@
   }
 
   UNSAFE_componentWillMount() {
+    if (!sessionStorage.getItem('UserID')) {
+      sessionStorage.removeItem('isEditState')
+      sessionStorage.removeItem('appType')
+      this.props.history.replace('/login')
+      return
+    }
+
     sessionStorage.setItem('editMenuType', 'menu') // 缂栬緫鑿滃崟绫诲瀷
 
+    window.GLOB.curDate = moment().format('YYYY-MM-DD')
     window.GLOB.UserComponentMap = new Map() // 缂撳瓨鐢ㄦ埛鑷畾涔夌粍浠�
     window.GLOB.TabsMap = new Map()          // 缂撳瓨鐢ㄦ埛鎿嶄綔鐨勬爣绛鹃〉
     window.GLOB.urlFields = []               // url鍙橀噺
@@ -106,6 +114,8 @@
   }
 
   componentDidMount () {
+    if (!sessionStorage.getItem('UserID')) return
+    
     MKEmitter.addListener('changePopview', this.initPopview)
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
     MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent)
@@ -370,6 +380,8 @@
       _btn.config.MenuID = _btn.uuid
       _btn.config.ParentId = card.uuid
       _btn.config.MenuName = _btn.label
+
+      _btn.config.components = this.updateComponents(_btn.config.components || [])
     } else {
       _btn.config = {
         uuid: _btn.uuid,
@@ -485,6 +497,7 @@
           })
           this.updatePage(config)
         } else {
+          config.components = this.updateComponents(config.components)
           this.setState({
             oriConfig: fromJS(config).toJS(),
             config: config
@@ -498,6 +511,27 @@
           duration: 5
         })
       }
+    })
+  }
+
+  updateComponents = (components) => { // 鍏煎鎬у崌绾� table
+    return components.map(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components = this.updateComponents(tab.components)
+        })
+      } else if (item.type === 'group') {
+        item.components = this.updateComponents(item.components)
+      } else if (item.type === 'table') {
+        item.cols = item.cols.map(col => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
+          return col
+        })
+      }
+
+      return item
     })
   }
 
@@ -519,6 +553,13 @@
 
       if (item.subtype === 'tablecard') { // 鍏煎
         item.type = 'card'
+      } else if (item.type === 'table') {
+        item.cols = item.cols.map(col => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
+          return col
+        })
       }
 
       delete item.tabId
@@ -556,15 +597,23 @@
       })
     })
 
-    config.cols && config.cols.forEach(col => {
-      if (col.type === 'action') {
-        col.elements.forEach(cell => {
-          if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
-            cell.config = popbtns[cell.uuid]
+    if (config.cols) {
+      let loopCol = (cols) => {
+        cols.forEach(col => {
+          if (col.type === 'colspan') {
+            loopCol(col.subcols)
+          } else if (col.type === 'custom') {
+            col.elements.forEach(cell => {
+              if (cell.eleType !== 'button') return
+              if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
+                cell.config = popbtns[cell.uuid]
+              }
+            })
           }
         })
       }
-    })
+      loopCol(config.cols)
+    }
 
     config.elements && config.elements.forEach(cell => {
       if (cell.eleType !== 'button') return
@@ -684,6 +733,11 @@
         if (item.$tables) {
           tbs.push(...item.$tables)
         }
+
+        if (item.wrap && item.wrap.permission === 'false') {
+          return
+        }
+        
         if (item.action && item.action.length > 0) {
           item.action.forEach(btn => {
             if (btn.hidden === 'true') return
@@ -720,14 +774,20 @@
             _sort++
           })
         } else if (item.type === 'table') {
-          item.cols && item.cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements.forEach(btn => {
-              if (btn.hidden === 'true') return
-              buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
-              _sort++
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
+                  _sort++
+                })
+              }
             })
-          })
+          }
+          loopCol(item.cols)
         }
       })
     }
@@ -758,6 +818,35 @@
     return true
   }
 
+  resetSyncQuery = (components) => {
+    return components.map(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components = this.resetSyncQuery(tab.components)
+        })
+      } else if (item.type === 'group') {
+        item.components = this.resetSyncQuery(item.components)
+      } else if (item.setting && item.setting.interType === 'system' && item.setting.sync === 'true') {
+        let sql = ''
+        if (item.setting.execute !== 'false' && item.setting.dataresource) {
+          sql = item.setting.dataresource
+        }
+
+        item.scripts && item.scripts.forEach(script => {
+          if (script.status === 'false') return
+
+          sql += script.sql
+        })
+
+        if (sql.length > 8000) {
+          item.setting.sync = 'false'
+        }
+      }
+
+      return item
+    })
+  }
+
   submitConfig = () => {
     const { MenuType } = this.state
     let config = fromJS(this.state.config).toJS()
@@ -775,9 +864,21 @@
       menuloading: true
     })
 
+    window.GLOB.saving = true
+
     setTimeout(() => {
-      if (config.enabled && this.verifyConfig()) {
+      let _pass = this.verifyConfig(config)
+
+      if (config.enabled && !_pass) {
         config.enabled = false
+        config.force = true
+      } else if (!config.enabled && config.force && _pass) {
+        config.enabled = true
+        delete config.force
+      }
+
+      if (config.cacheUseful !== 'true') {
+        config.components = this.resetSyncQuery(config.components)
       }
 
       let tbs = []
@@ -928,6 +1029,8 @@
           menuloading: false
         })
 
+        window.GLOB.saving = false
+
         if (!res) return
 
         if (res.status) {
@@ -952,6 +1055,9 @@
     this.setState({
       menuloading: false
     })
+
+    window.GLOB.saving = false
+
     if (!error) {
       notification.warning({
         top: 92,
@@ -997,17 +1103,23 @@
   onEnabledChange = () => {
     const { config } = this.state
 
-    if (!config || (!config.enabled && this.verifyConfig(true))) {
-      return
-    }
+    let _config = {...config, enabled: !config.enabled}
 
-    this.setState({
-      config: {...config, enabled: !config.enabled}
-    })
+    delete _config.force
+
+    if (!_config.enabled) {
+      this.setState({
+        config: _config
+      })
+    } else if (this.verifyConfig(_config)) {
+      this.setState({
+        config: _config
+      })
+    }
   }
 
-  verifyConfig = (show) => {
-    const { config, MenuType } = this.state
+  verifyConfig = (config) => {
+    const { MenuType } = this.state
     let error = ''
 
     let check = (components) => {
@@ -1035,7 +1147,7 @@
 
     check(config.components)
 
-    if (show && error) {
+    if (config.enabled && error) {
       notification.warning({
         top: 92,
         message: error,
@@ -1051,7 +1163,7 @@
         carousel: '杞挱',
         tree: '鏍戝舰鍒楄〃',
         chart: '鑷畾涔夊浘琛�',
-        editor: '瀵屾枃鏈�',
+        // editor: '瀵屾枃鏈�',
         group: '鍒嗙粍',
         iframe: 'iframe'
       }
@@ -1069,7 +1181,7 @@
         }
       })
 
-      if (show && error) {
+      if (config.enabled && error) {
         notification.warning({
           top: 92,
           message: error,
@@ -1078,7 +1190,7 @@
       }
     }
 
-    return error
+    return error === ''
   }
 
   // 鏇存柊閰嶇疆淇℃伅
@@ -1193,7 +1305,7 @@
                     <PictureController/>
                     <StyleCombControlButton menu={config} />
                     <PasteController insert={this.insert} />
-                    <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config && config.enabled} onChange={this.onEnabledChange} />
+                    {config ? <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                     <Button type="primary" id="save-config" className={needUpdate ? 'update-tip' : ''} onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
                     <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
                   </div>
diff --git a/src/views/menudesign/menuform/index.jsx b/src/views/menudesign/menuform/index.jsx
index bd6d38f..f746df1 100644
--- a/src/views/menudesign/menuform/index.jsx
+++ b/src/views/menudesign/menuform/index.jsx
@@ -193,47 +193,14 @@
         this.props.form.setFieldsValue({parentId: _id})
         this.props.updateConfig({...config, fstMenuId: value, parentId: _id})
       })
-    } else if (key === 'parentId') {
-      this.props.updateConfig({...config, parentId: value})
-    } else if (key === 'cacheUseful') {
-      this.props.updateConfig({...config, cacheUseful: value})
-    } else if (key === 'timeUnit') {
-      this.props.updateConfig({...config, timeUnit: value})
-    } else if (key === 'OpenType') {
-      this.props.updateConfig({...config, OpenType: value})
-    } else if (key === 'hidden') {
-      this.props.updateConfig({...config, hidden: value})
-    } else if (key === 'permission') {
-      this.props.updateConfig({...config, permission: value})
-    } else if (key === 'cacheLocal') {
-      this.props.updateConfig({...config, cacheLocal: value})
+    } else {
+      if (key === 'cacheTime' || key === 'minWidth') {
+        if (typeof(value) !== 'number') {
+          value = ''
+        }
+      }
+      this.props.updateConfig({...config, [key]: 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})
-  }
-
-  // 鍔╄鐮�
-  changeEasyCode = (e) => {
-    this.props.updateConfig({...this.props.config, easyCode: 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() {
@@ -306,7 +273,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}>
@@ -319,7 +286,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}>
@@ -336,6 +303,23 @@
                 <Radio.Group onChange={(e) => {this.selectChange('OpenType', e.target.value)}}>
                   <Radio value="newtab">鏍囩椤�</Radio>
                   <Radio value="newpage">鏂伴〉闈�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="璺宠繃鏉冮檺楠岃瘉鏃讹紝椤甸潰涓粍浠跺強鎸夐挳涓嶅湪杩涜鏉冮檺鎺у埗銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏉冮檺楠岃瘉
+              </Tooltip>
+            }>
+              {getFieldDecorator('permission', {
+                initialValue: config.permission || 'true'
+              })(
+                <Radio.Group onChange={(e) => {this.selectChange('permission', e.target.value)}}>
+                  <Radio value="true">浣跨敤</Radio>
+                  <Radio value="false">涓嶄娇鐢�</Radio>
                 </Radio.Group>
               )}
             </Form.Item>
@@ -374,31 +358,15 @@
               )}
             </Form.Item>
           </Col>
-          <Col span={24}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="璺宠繃鏉冮檺楠岃瘉鏃讹紝椤甸潰涓粍浠跺強鎸夐挳涓嶅湪杩涜鏉冮檺鎺у埗銆�">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鏉冮檺楠岃瘉
-              </Tooltip>
-            }>
-              {getFieldDecorator('permission', {
-                initialValue: config.permission || 'true'
-              })(
-                <Radio.Group onChange={(e) => {this.selectChange('permission', 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 onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
+                <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>
@@ -414,15 +382,29 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit !== 'hour' ? 7 : 23} 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="濡傛灉椤甸潰鍐呭鍦ㄧ獥鍙d腑鏃犳硶瀹屽叏灞曠ず锛屽彲璁剧疆鏈�灏忓搴︼紝瀹炵幇椤甸潰鐨勬í鍚戞粴鍔ㄣ��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏈�灏忓搴�
+              </Tooltip>
+            }>
+              {getFieldDecorator('minWidth', {
+                initialValue: config.minWidth
+              })(
+                <InputNumber min={0} precision={0} onChange={(val) => {this.selectChange('minWidth', val)}}/>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
             <Form.Item label="鍔╄鐮�">
               {getFieldDecorator('easyCode', {
                 initialValue: config.easyCode
-              })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)}
+              })(<Input placeholder="" autoComplete="off" onChange={(e) => {this.selectChange('easyCode', e.target.value)}}/>)}
             </Form.Item>
           </Col>
           <Col span={24}>
@@ -432,7 +414,7 @@
               }} />
             </Form.Item>
           </Col>
-          <Col span={24}>
+          <Col span={24} className="red-font">
             <Form.Item label="澶囨敞">
               {getFieldDecorator('Remark', {
                 initialValue: config.Remark || '',
@@ -442,7 +424,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/menudesign/menuform/index.scss b/src/views/menudesign/menuform/index.scss
index fa61282..39343af 100644
--- a/src/views/menudesign/menuform/index.scss
+++ b/src/views/menudesign/menuform/index.scss
@@ -5,4 +5,12 @@
       font-size: 12px;
     }
   }
+  .red-font {
+    label {
+      color: red;
+    }
+    textarea {
+      color: red;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/views/menudesign/popview/index.jsx b/src/views/menudesign/popview/index.jsx
index 7e63303..8a783ea 100644
--- a/src/views/menudesign/popview/index.jsx
+++ b/src/views/menudesign/popview/index.jsx
@@ -130,8 +130,14 @@
       return
     }
 
-    if (config.enabled && this.verifyConfig()) {
+    let _pass = this.verifyConfig(config)
+
+    if (config.enabled && !_pass) {
       config.enabled = false
+      config.force = true
+    } else if (!config.enabled && config.force && _pass) {
+      config.enabled = true
+      delete config.force
     }
 
     this.getMenuMessage(config)
@@ -149,17 +155,22 @@
   onEnabledChange = () => {
     const { config } = this.state
 
-    if (!config.enabled && this.verifyConfig(true)) {
-      return
-    }
+    let _config = {...config, enabled: !config.enabled}
 
-    this.setState({
-      config: {...config, enabled: !config.enabled}
-    })
+    delete _config.force
+
+    if (!_config.enabled) {
+      this.setState({
+        config: _config
+      })
+    } else if (this.verifyConfig(_config)) {
+      this.setState({
+        config: _config
+      })
+    }
   }
 
-  verifyConfig = (show) => {
-    const { config } = this.state
+  verifyConfig = (config) => {
     let error = ''
 
     let check = (components) => {
@@ -186,7 +197,7 @@
 
     check(config.components)
 
-    if (show && error) {
+    if (config.enabled && error) {
       notification.warning({
         top: 92,
         message: error,
@@ -194,7 +205,7 @@
       })
     }
 
-    return error
+    return error === ''
   }
 
   // 鏇存柊閰嶇疆淇℃伅
diff --git a/src/views/menudesign/popview/menuform/index.jsx b/src/views/menudesign/popview/menuform/index.jsx
index d2899a2..e84a5af 100644
--- a/src/views/menudesign/popview/menuform/index.jsx
+++ b/src/views/menudesign/popview/menuform/index.jsx
@@ -86,9 +86,10 @@
               {getFieldDecorator('timeUnit', {
                 initialValue: config.timeUnit || 'day'
               })(
-                <Radio.Group onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
+                <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>
@@ -104,7 +105,7 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit !== 'hour' ? 7 : 23} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
               )}
             </Form.Item>
           </Col> : null}
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index 7e740f5..9fca5e9 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -81,6 +81,14 @@
   }
 
   UNSAFE_componentWillMount() {
+    if (!sessionStorage.getItem('UserID')) {
+      sessionStorage.removeItem('isEditState')
+      sessionStorage.removeItem('editMenuType')
+      sessionStorage.removeItem('appType')
+      this.props.history.replace('/login')
+      return
+    }
+    
     if (memberLevel < 30) return
     try {
       let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
@@ -103,6 +111,7 @@
         window.GLOB.winHeight = 738
         window.GLOB.shellWidth = 376
         window.GLOB.shellHeight = 680
+        window.GLOB.curDate = moment().format('YYYY-MM-DD')
 
         let adapters = sessionStorage.getItem('adapter')
         if (adapters) {
@@ -139,6 +148,7 @@
   }
 
   componentDidMount () {
+    if (!sessionStorage.getItem('UserID')) return
     if (memberLevel < 30) {
       document.getElementById('mk-mob-design-view').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh; height: 100vh; background: #fff;">鏈簲鐢ㄦ病鏈塒C绔〉闈㈢殑缂栬緫鏉冮檺锛岃鑱旂郴绠$悊鍛橈紒</div>'
       return
@@ -232,6 +242,8 @@
       _btn.config.MenuID = _btn.uuid
       _btn.config.ParentId = card.uuid
       _btn.config.MenuName = _btn.label
+
+      _btn.config.components = this.updateComponents(_btn.config.components || [])
     } else {
       _btn.config = {
         uuid: _btn.uuid,
@@ -298,15 +310,23 @@
       })
     })
 
-    config.cols && config.cols.forEach(col => {
-      if (col.type === 'action') {
-        col.elements.forEach(cell => {
-          if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
-            cell.config = popbtns[cell.uuid]
+    if (config.cols) {
+      let loopCol = (cols) => {
+        cols.forEach(col => {
+          if (col.type === 'colspan') {
+            loopCol(col.subcols)
+          } else if (col.type === 'custom') {
+            col.elements.forEach(cell => {
+              if (cell.eleType !== 'button') return
+              if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
+                cell.config = popbtns[cell.uuid]
+              }
+            })
           }
         })
       }
-    })
+      loopCol(config.cols)
+    }
 
     config.elements && config.elements.forEach(cell => {
       if (cell.eleType !== 'button') return
@@ -604,6 +624,8 @@
           this.setState({
             needUpdate: true
           })
+        } else {
+          config.components = this.updateComponents(config.components)
         }
 
         let navItem = null
@@ -823,6 +845,8 @@
           this.setState({
             needUpdate: true
           })
+        } else {
+          config.components = this.updateComponents(config.components)
         }
 
         config.enabled = false
@@ -921,6 +945,27 @@
     })
   }
 
+  updateComponents = (components) => { // 鍏煎鎬у崌绾� table
+    return components.map(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components = this.updateComponents(tab.components)
+        })
+      } else if (item.type === 'group') {
+        item.components = this.updateComponents(item.components)
+      } else if (item.type === 'table') {
+        item.cols = item.cols.map(col => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
+          return col
+        })
+      }
+
+      return item
+    })
+  }
+
   collectTB = (components) => {
     return components.map(item => {
       if (item.type === 'tabs') {
@@ -939,6 +984,13 @@
 
       if (item.subtype === 'tablecard') { // 鍏煎
         item.type = 'card'
+      } else if (item.type === 'table') {
+        item.cols = item.cols.map(col => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
+          return col
+        })
       }
 
       delete item.tabId
@@ -1081,17 +1133,22 @@
               title: btn.label,
             })
           })
-          item.cols && item.cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements.forEach(btn => {
-              if (btn.hidden === 'true') return
-
-              m.children.push({
-                key: btn.uuid,
-                title: btn.label,
-              })
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  m.children.push({
+                    key: cell.uuid,
+                    title: cell.label,
+                  })
+                })
+              }
             })
-          })
+          }
+          loopCol(item.cols)
         }
 
         list.push(m)
@@ -1181,19 +1238,25 @@
               })
             }
             card.elements && card.elements.forEach(cell => {
-              if (cell.eleType !== 'button') return
-
               if (cell.linkmenu && menuObj[cell.linkmenu]) {
                 menus.push(menuObj[cell.linkmenu])
               } else if (cell.openmenu && menuObj[cell.openmenu]) {
                 menus.push(menuObj[cell.openmenu])
               }
             })
+
+            if (item.subtype === 'dualdatacard') {
+              card.backElements && card.backElements.forEach(cell => {
+                if (cell.linkmenu && menuObj[cell.linkmenu]) {
+                  menus.push(menuObj[cell.linkmenu])
+                } else if (cell.openmenu && menuObj[cell.openmenu]) {
+                  menus.push(menuObj[cell.openmenu])
+                }
+              })
+            }
           })
         } else if (item.type === 'balcony') {
           item.elements && item.elements.forEach(cell => {
-            if (cell.eleType !== 'button') return
-
             if (cell.linkmenu && menuObj[cell.linkmenu]) {
                 menus.push(menuObj[cell.linkmenu])
               } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1214,16 +1277,22 @@
               menus.push(menuObj[btn.openmenu])
             }
           })
-          item.cols && item.cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements.forEach(btn => {
-              if (btn.linkmenu && menuObj[btn.linkmenu]) {
-                menus.push(menuObj[btn.linkmenu])
-              } else if (btn.openmenu && menuObj[btn.openmenu]) {
-                menus.push(menuObj[btn.openmenu])
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.linkmenu && menuObj[cell.linkmenu]) {
+                    menus.push(menuObj[cell.linkmenu])
+                  } else if (cell.openmenu && menuObj[cell.openmenu]) {
+                    menus.push(menuObj[cell.openmenu])
+                  }
+                })
               }
             })
-          })
+          }
+          loopCol(item.cols)
         }
       })
     }
@@ -1287,7 +1356,7 @@
             return cols.map(col => {
               if (col.type === 'colspan') {
                 col.subcols = getCols(col.subcols || [])
-              } else if (col.type === 'custom' || col.type === 'action') {
+              } else if (col.type === 'custom') {
                 col.elements = col.elements.map(cell => {
                   cell.miniStyle = this.transferStyle(cell.style)
                   return cell
@@ -1321,6 +1390,35 @@
     return _style
   }
 
+  resetSyncQuery = (components) => {
+    return components.map(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components = this.resetSyncQuery(tab.components)
+        })
+      } else if (item.type === 'group') {
+        item.components = this.resetSyncQuery(item.components)
+      } else if (item.setting && item.setting.interType === 'system' && item.setting.sync === 'true') {
+        let sql = ''
+        if (item.setting.execute !== 'false' && item.setting.dataresource) {
+          sql = item.setting.dataresource
+        }
+
+        item.scripts && item.scripts.forEach(script => {
+          if (script.status === 'false') return
+
+          sql += script.sql
+        })
+       
+        if (sql.length > 8000) {
+          item.setting.sync = 'false'
+        }
+      }
+
+      return item
+    })
+  }
+
   submitConfig = () => {
     const { adapters } = this.state
     let config = fromJS(this.state.config).toJS()
@@ -1342,9 +1440,21 @@
       menuloading: true
     })
 
+    window.GLOB.saving = true
+
     setTimeout(() => {
-      if (config.enabled && this.verifyConfig()) {
+      let _pass = this.verifyConfig(config)
+
+      if (config.enabled && !_pass) {
         config.enabled = false
+        config.force = true
+      } else if (!config.enabled && config.force && _pass) {
+        config.enabled = true
+        delete config.force
+      }
+
+      if (config.cacheUseful !== 'true') {
+        config.components = this.resetSyncQuery(config.components)
       }
 
       let tbs = []
@@ -1589,6 +1699,8 @@
           menuloading: false
         })
 
+        window.GLOB.saving = false
+
         if (!res) return
 
         if (res.status) {
@@ -1623,6 +1735,9 @@
     this.setState({
       menuloading: false
     })
+
+    window.GLOB.saving = false
+
     if (!error) {
       notification.warning({
         top: 92,
@@ -1668,17 +1783,22 @@
   onEnabledChange = () => {
     const { config } = this.state
 
-    if (!config || (!config.enabled && this.verifyConfig(true))) {
-      return
-    }
+    let _config = {...config, enabled: !config.enabled}
 
-    this.setState({
-      config: {...config, enabled: !config.enabled}
-    })
+    delete _config.force
+
+    if (!_config.enabled) {
+      this.setState({
+        config: _config
+      })
+    } else if (this.verifyConfig(_config)) {
+      this.setState({
+        config: _config
+      })
+    }
   }
 
-  verifyConfig = (show) => {
-    const { config } = this.state
+  verifyConfig = (config) => {
     let error = ''
     let searchSum = 0
     let swipes = []
@@ -1745,7 +1865,7 @@
       }
     }
 
-    if (show && error) {
+    if (config.enabled && error) {
       notification.warning({
         top: 92,
         message: error,
@@ -1753,7 +1873,7 @@
       })
     }
 
-    return error
+    return error === ''
   }
 
   // 鏇存柊閰嶇疆淇℃伅
@@ -1769,12 +1889,22 @@
     let config = fromJS(this.state.config).toJS()
 
     if (item.type === 'search') {
-      notification.warning({
-        top: 92,
-        message: '绉诲姩绔悳绱㈢粍浠朵笉鍙矘璐达紒',
-        duration: 5
-      })
-      return
+      if (config.components.filter(card => card.type === 'topbar' && card.wrap.type !== 'navbar').length > 0) {
+        notification.warning({
+          top: 92,
+          message: '瀵艰埅鏍忎娇鐢ㄤ簡鎼滅储锛屼笉鍙坊鍔犳悳绱㈢粍浠讹紒',
+          duration: 5
+        })
+        return
+      }
+      if (config.components.filter(card => card.type === 'search').length > 0) {
+        notification.warning({
+          top: 92,
+          message: '鎼滅储鏉′欢涓嶅彲閲嶅娣诲姞锛�',
+          duration: 5
+        })
+        return
+      }
     }
     
     if (item.type === 'topbar') {
@@ -2036,7 +2166,7 @@
               </div>
               <div className="wrap">
                 <Button type="primary" className={needUpdate ? 'update-tip' : ''} onClick={this.submitConfig} id="save-config" loading={menuloading}>淇濆瓨</Button>
-                <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config && config.enabled} onChange={this.onEnabledChange} />
+                {config ? <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                 <ArrowLeftOutlined title="鍚庨��" className="back-view" onClick={this.backView}/>
                 <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 缁勪欢鍚�</Button>
                 <CreateView resetmenu={this.getAppMenus} />
diff --git a/src/views/mobdesign/menuform/index.jsx b/src/views/mobdesign/menuform/index.jsx
index 9846e84..b6371cf 100644
--- a/src/views/mobdesign/menuform/index.jsx
+++ b/src/views/mobdesign/menuform/index.jsx
@@ -168,9 +168,10 @@
               {getFieldDecorator('timeUnit', {
                 initialValue: config.timeUnit || 'day'
               })(
-                <Radio.Group onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
+                <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>
@@ -186,7 +187,7 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit !== 'hour' ? 7 : 23} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
               )}
             </Form.Item>
           </Col> : null}
@@ -331,7 +332,7 @@
               )}
             </Form.Item>
           </Col> : null}
-          <Col span={24}>
+          <Col span={24} className="red-font">
             <Form.Item label="澶囨敞">
               {getFieldDecorator('Remark', {
                 initialValue: config.Remark || '',
diff --git a/src/views/mobdesign/menuform/index.scss b/src/views/mobdesign/menuform/index.scss
index 9c0c867..71c35b5 100644
--- a/src/views/mobdesign/menuform/index.scss
+++ b/src/views/mobdesign/menuform/index.scss
@@ -39,4 +39,12 @@
       }
     }
   }
+  .red-font {
+    label {
+      color: red;
+    }
+    textarea {
+      color: red;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/views/mobdesign/popview/index.jsx b/src/views/mobdesign/popview/index.jsx
index 316deca..03cfee3 100644
--- a/src/views/mobdesign/popview/index.jsx
+++ b/src/views/mobdesign/popview/index.jsx
@@ -132,8 +132,14 @@
       return
     }
 
-    if (config.enabled && this.verifyConfig()) {
+    let _pass = this.verifyConfig(config)
+
+    if (config.enabled && !_pass) {
       config.enabled = false
+      config.force = true
+    } else if (!config.enabled && config.force && _pass) {
+      config.enabled = true
+      delete config.force
     }
 
     this.getMenuMessage(config)
@@ -151,17 +157,22 @@
   onEnabledChange = () => {
     const { config } = this.state
 
-    if (!config.enabled && this.verifyConfig(true)) {
-      return
-    }
+    let _config = {...config, enabled: !config.enabled}
 
-    this.setState({
-      config: {...config, enabled: !config.enabled}
-    })
+    delete _config.force
+
+    if (!_config.enabled) {
+      this.setState({
+        config: _config
+      })
+    } else if (this.verifyConfig(_config)) {
+      this.setState({
+        config: _config
+      })
+    }
   }
 
-  verifyConfig = (show) => {
-    const { config } = this.state
+  verifyConfig = (config) => {
     let error = ''
 
     let check = (components) => {
@@ -188,7 +199,7 @@
 
     check(config.components)
 
-    if (show && error) {
+    if (config.enabled && error) {
       notification.warning({
         top: 92,
         message: error,
@@ -196,7 +207,7 @@
       })
     }
 
-    return error
+    return error === ''
   }
 
   // 鏇存柊閰嶇疆淇℃伅
diff --git a/src/views/mobdesign/popview/menuform/index.jsx b/src/views/mobdesign/popview/menuform/index.jsx
index d2899a2..e84a5af 100644
--- a/src/views/mobdesign/popview/menuform/index.jsx
+++ b/src/views/mobdesign/popview/menuform/index.jsx
@@ -86,9 +86,10 @@
               {getFieldDecorator('timeUnit', {
                 initialValue: config.timeUnit || 'day'
               })(
-                <Radio.Group onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
+                <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>
@@ -104,7 +105,7 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit !== 'hour' ? 7 : 23} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
               )}
             </Form.Item>
           </Col> : null}
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index c524734..2badd14 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -76,10 +76,18 @@
   }
 
   UNSAFE_componentWillMount() {
+    if (!sessionStorage.getItem('UserID')) {
+      sessionStorage.removeItem('isEditState')
+      sessionStorage.removeItem('appType')
+      this.props.history.replace('/login')
+      return
+    }
+    
     if (memberLevel < 30) return
 
     sessionStorage.setItem('editMenuType', 'menu') // 缂栬緫鑿滃崟绫诲瀷
 
+    window.GLOB.curDate = moment().format('YYYY-MM-DD')
     window.GLOB.TabsMap = new Map()          // 缂撳瓨鐢ㄦ埛鎿嶄綔鐨勬爣绛鹃〉
     window.GLOB.CacheIndependent = new Map()
     window.GLOB.urlFields = []               // url鍙橀噺
@@ -123,6 +131,7 @@
   }
 
   componentDidMount () {
+    if (!sessionStorage.getItem('UserID')) return
     if (memberLevel < 30) {
       document.getElementById('mk-pc-design-view').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh; height: 100vh; background: #fff;">鏈簲鐢ㄦ病鏈塒C绔〉闈㈢殑缂栬緫鏉冮檺锛岃鑱旂郴绠$悊鍛橈紒</div>'
       return
@@ -365,6 +374,8 @@
       _btn.config.MenuID = _btn.uuid
       _btn.config.ParentId = card.uuid
       _btn.config.MenuName = _btn.label
+
+      _btn.config.components = this.updateComponents(_btn.config.components || [])
     } else {
       _btn.config = {
         uuid: _btn.uuid,
@@ -420,15 +431,23 @@
       })
     })
 
-    config.cols && config.cols.forEach(col => {
-      if (col.type === 'action') {
-        col.elements.forEach(cell => {
-          if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
-            cell.config = popbtns[cell.uuid]
+    if (config.cols) {
+      let loopCol = (cols) => {
+        cols.forEach(col => {
+          if (col.type === 'colspan') {
+            loopCol(col.subcols)
+          } else if (col.type === 'custom') {
+            col.elements.forEach(cell => {
+              if (cell.eleType !== 'button') return
+              if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
+                cell.config = popbtns[cell.uuid]
+              }
+            })
           }
         })
       }
-    })
+      loopCol(config.cols)
+    }
 
     config.elements && config.elements.forEach(cell => {
       if (cell.eleType !== 'button') return
@@ -556,6 +575,8 @@
           this.setState({
             needUpdate: true
           })
+        } else {
+          config.components = this.updateComponents(config.components)
         }
 
         let navItem = null
@@ -581,6 +602,27 @@
     this.getAppMenus()
   }
 
+  updateComponents = (components) => { // 鍏煎鎬у崌绾� table
+    return components.map(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components = this.updateComponents(tab.components)
+        })
+      } else if (item.type === 'group') {
+        item.components = this.updateComponents(item.components)
+      } else if (item.type === 'table') {
+        item.cols = item.cols.map(col => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
+          return col
+        })
+      }
+
+      return item
+    })
+  }
+
   collectTB = (components) => {
     return components.map(item => {
       if (item.type === 'tabs') {
@@ -599,6 +641,13 @@
 
       if (item.subtype === 'tablecard') { // 鍏煎
         item.type = 'card'
+      } else if (item.type === 'table') {
+        item.cols = item.cols.map(col => {
+          if (col.type === 'action') {
+            col.type = 'custom'
+          }
+          return col
+        })
       }
 
       delete item.tabId
@@ -913,17 +962,22 @@
               title: btn.label,
             })
           })
-          item.cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements.forEach(btn => {
-              if (btn.hidden === 'true') return
-              
-              m.children.push({
-                key: btn.uuid,
-                title: btn.label,
-              })
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  m.children.push({
+                    key: cell.uuid,
+                    title: cell.label,
+                  })
+                })
+              }
             })
-          })
+          }
+          loopCol(item.cols)
         }
 
         list.push(m)
@@ -996,8 +1050,14 @@
               })
             }
             card.elements && card.elements.forEach(cell => {
-              if (cell.eleType !== 'button') return
+              if (cell.linkmenu && menuObj[cell.linkmenu]) {
+                menus.push(menuObj[cell.linkmenu])
+              } else if (cell.openmenu && menuObj[cell.openmenu]) {
+                menus.push(menuObj[cell.openmenu])
+              }
+            })
 
+            card.backElements && card.backElements.forEach(cell => {
               if (cell.linkmenu && menuObj[cell.linkmenu]) {
                 menus.push(menuObj[cell.linkmenu])
               } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1007,8 +1067,6 @@
           })
         } else if (item.type === 'balcony') {
           item.elements && item.elements.forEach(cell => {
-            if (cell.eleType !== 'button') return
-
             if (cell.linkmenu && menuObj[cell.linkmenu]) {
                 menus.push(menuObj[cell.linkmenu])
               } else if (cell.openmenu && menuObj[cell.openmenu]) {
@@ -1029,16 +1087,22 @@
               menus.push(menuObj[btn.openmenu])
             }
           })
-          item.cols && item.cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements.forEach(btn => {
-              if (btn.linkmenu && menuObj[btn.linkmenu]) {
-                menus.push(menuObj[btn.linkmenu])
-              } else if (btn.openmenu && menuObj[btn.openmenu]) {
-                menus.push(menuObj[btn.openmenu])
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.linkmenu && menuObj[cell.linkmenu]) {
+                    menus.push(menuObj[cell.linkmenu])
+                  } else if (cell.openmenu && menuObj[cell.openmenu]) {
+                    menus.push(menuObj[cell.openmenu])
+                  }
+                })
               }
             })
-          })
+          }
+          loopCol(item.cols)
         }
       })
     }
@@ -1074,6 +1138,35 @@
     return true
   }
 
+  resetSyncQuery = (components) => {
+    return components.map(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          tab.components = this.resetSyncQuery(tab.components)
+        })
+      } else if (item.type === 'group') {
+        item.components = this.resetSyncQuery(item.components)
+      } else if (item.setting && item.setting.interType === 'system' && item.setting.sync === 'true') {
+        let sql = ''
+        if (item.setting.execute !== 'false' && item.setting.dataresource) {
+          sql = item.setting.dataresource
+        }
+
+        item.scripts && item.scripts.forEach(script => {
+          if (script.status === 'false') return
+
+          sql += script.sql
+        })
+       
+        if (sql.length > 8000) {
+          item.setting.sync = 'false'
+        }
+      }
+
+      return item
+    })
+  }
+
   submitConfig = () => {
     let config = fromJS(this.state.config).toJS()
 
@@ -1085,9 +1178,21 @@
       menuloading: true
     })
 
+    window.GLOB.saving = true
+
     setTimeout(() => {
-      if (config.enabled && this.verifyConfig()) {
+      let _pass = this.verifyConfig(config)
+
+      if (config.enabled && !_pass) {
         config.enabled = false
+        config.force = true
+      } else if (!config.enabled && config.force && _pass) {
+        config.enabled = true
+        delete config.force
+      }
+
+      if (config.cacheUseful !== 'true') {
+        config.components = this.resetSyncQuery(config.components)
       }
 
       let tbs = []
@@ -1314,6 +1419,8 @@
           menuloading: false
         })
 
+        window.GLOB.saving = false
+
         if (!res) return
 
         if (res.status) {
@@ -1348,6 +1455,9 @@
     this.setState({
       menuloading: false
     })
+
+    window.GLOB.saving = false
+    
     if (!error) {
       notification.warning({
         top: 92,
@@ -1392,17 +1502,22 @@
   onEnabledChange = () => {
     const { config } = this.state
 
-    if (!config || (!config.enabled && this.verifyConfig(true))) {
-      return
-    }
+    let _config = {...config, enabled: !config.enabled}
 
-    this.setState({
-      config: {...config, enabled: !config.enabled}
-    })
+    delete _config.force
+
+    if (!_config.enabled) {
+      this.setState({
+        config: _config
+      })
+    } else if (this.verifyConfig(_config)) {
+      this.setState({
+        config: _config
+      })
+    }
   }
 
-  verifyConfig = (show) => {
-    const { config } = this.state
+  verifyConfig = (config) => {
     let error = ''
 
     let check = (components) => {
@@ -1429,7 +1544,7 @@
 
     check(config.components)
 
-    if (show && error) {
+    if (config.enabled && error) {
       notification.warning({
         top: 92,
         message: error,
@@ -1437,7 +1552,7 @@
       })
     }
 
-    return error
+    return error === ''
   }
 
   // 鏇存柊閰嶇疆淇℃伅
@@ -1664,7 +1779,7 @@
               </div>
               <div className="wrap">
                 <Button type="primary" className={needUpdate ? 'update-tip' : ''} id="save-config" onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
-                <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config && config.enabled} onChange={this.onEnabledChange} />
+                {config ? <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                 <ArrowLeftOutlined title="鍚庨��" className="back-view" onClick={this.backView}/>
                 <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 缁勪欢鍚�</Button>
                 <CreateView resetmenu={this.getAppMenus} />
diff --git a/src/views/pcdesign/menuform/index.jsx b/src/views/pcdesign/menuform/index.jsx
index 1d7147c..8c6262b 100644
--- a/src/views/pcdesign/menuform/index.jsx
+++ b/src/views/pcdesign/menuform/index.jsx
@@ -187,9 +187,10 @@
               {getFieldDecorator('timeUnit', {
                 initialValue: config.timeUnit || 'day'
               })(
-                <Radio.Group onChange={(e) => {this.selectChange('timeUnit', e.target.value)}}>
+                <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>
@@ -205,11 +206,11 @@
                   }
                 ]
               })(
-                <InputNumber min={1} max={config.timeUnit !== 'hour' ? 7 : 23} precision={0} onChange={this.changeCacheDay}/>
+                <InputNumber min={1} max={config.timeUnit === 'day' ? 7 : (config.timeUnit === 'hour' ? 23 : 59)} precision={0} onChange={this.changeCacheDay}/>
               )}
             </Form.Item>
           </Col> : null}
-          <Col span={24}>
+          <Col span={24} className="red-font">
             <Form.Item label="澶囨敞">
               {getFieldDecorator('Remark', {
                 initialValue: config.Remark || '',
diff --git a/src/views/pcdesign/menuform/index.scss b/src/views/pcdesign/menuform/index.scss
index fa61282..39343af 100644
--- a/src/views/pcdesign/menuform/index.scss
+++ b/src/views/pcdesign/menuform/index.scss
@@ -5,4 +5,12 @@
       font-size: 12px;
     }
   }
+  .red-font {
+    label {
+      color: red;
+    }
+    textarea {
+      color: red;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/views/sso/index.jsx b/src/views/sso/index.jsx
index d5acb4e..a26036a 100644
--- a/src/views/sso/index.jsx
+++ b/src/views/sso/index.jsx
@@ -32,13 +32,11 @@
         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('departmentcode', res.departmentcode || '')
         sessionStorage.setItem('organization', res.organization || '')
         sessionStorage.setItem('mk_user_type', res.mk_user_type || '')
-        sessionStorage.setItem('localRole_id', res.role_id || '')
         
         this.getMessage()
       } else {
@@ -108,10 +106,12 @@
         }
 
         sessionStorage.setItem('home_background', res.index_background_color || '')
+
+        let seconds = 0
         if (res.sys_datetime) {
-          sessionStorage.setItem('sys_datetime', res.sys_datetime)
-          sessionStorage.setItem('app_datetime', new Date().getTime())
+          seconds = Math.floor((new Date(res.sys_datetime).getTime() - new Date().getTime()) / 1000)
         }
+        sessionStorage.setItem('sys_time_shim', isNaN(seconds) ? 0 : seconds)
 
         // url鏍囬
         document.title = systemMsg.platTitle
diff --git a/src/views/systemfunc/index.jsx b/src/views/systemfunc/index.jsx
index c0ef10e..6910e9b 100644
--- a/src/views/systemfunc/index.jsx
+++ b/src/views/systemfunc/index.jsx
@@ -4,6 +4,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import Header from './header'
+import MKEmitter from '@/utils/events.js'
 import Sidemenu from './sidemenu'
 
 // import './index.scss'
@@ -12,6 +13,8 @@
 
 class Design 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
@@ -25,6 +28,18 @@
       value: false
     })
   }
+
+  componentDidMount () {
+    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+  }
+
+  componentWillUnmount () {
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+  }
+
+  resetParentParam = (MenuID, id, data) => {
+    window.GLOB.CacheData.set(MenuID, {...data, $BID: id})
+  }
   
   render () {
     return (
diff --git a/src/views/systemfunc/sidemenu/config.jsx b/src/views/systemfunc/sidemenu/config.jsx
index 9adbd43..e62128f 100644
--- a/src/views/systemfunc/sidemenu/config.jsx
+++ b/src/views/systemfunc/sidemenu/config.jsx
@@ -12,33 +12,26 @@
     MenuName: '鏁版嵁瀛楀吀',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1581734956310scks442ul2d955g9tu5',
     MenuNo: 'sVersionM',
     MenuName: '浼犺緭鍙风鐞�',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1583991994144ndddg0bhh0is6shi0v1',
     MenuNo: 'sVersionQueryM',
     MenuName: '浼犺緭鍙锋煡璇�',
   }, {
     src: '',
     systems: ['production', 'local', 'SSO', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1583979633842550imkchl4qt4qppsiv',
     MenuNo: 'sVersionMUpgrade',
     MenuName: '鐗堟湰鍗囩骇',
-  // }, {
-  //   src: '',
-  //   PageParam: {OpenType: 'newtab', Template: 'TabManage'},
-  //   type: 'TabManage',
-  //   MenuID: 'TabManageView',
-  //   MenuNo: 'TabManage',
-  //   MenuName: '鏍囩椤电鐞�',
   }, {
     src: '',
     PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
@@ -48,60 +41,46 @@
     MenuName: '鏍囩鎵撳嵃妯℃澘',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '16044812935562g807p3p12huk8kokmb',
     MenuNo: 'sPrintTemplate_webM',
     MenuName: '鍗曟嵁鎵撳嵃妯℃澘',
   }, {
     src: '',
     systems: ['SSO', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1585192949946f3et2ts8tn82krmumdf',
     MenuNo: 'MyAppManage',
     MenuName: '绯荤粺UI',
   }, {
     src: '',
     systems: ['SSO', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '15855615451212m12ip23vpcm79kloro',
     MenuNo: 'sUsersAppM',
     MenuName: '绯荤粺鐢ㄦ埛绠$悊',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1587005717541lov40vg61q7l1rbveon',
     MenuNo: 's_custom_scriptM',
     MenuName: '鑷畾涔夊嚱鏁�',
   }, {
-  //   src: '',
-  //   PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-  //   type: 'CommonTable',
-  //   MenuID: '1590458676585agbbr63t6ihighg2i1g',
-  //   MenuNo: 'LdropdownmenuNewM',
-  //   MenuName: '閫氱敤涓嬫媺鑿滃崟',
-  // }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1602315375262ikd33ii0nii34pt861o',
     MenuNo: 's_worksflow_roleM',
     MenuName: '鍏抽敭瑙掕壊绠$悊',
-  // }, {
-  //   src: '',
-  //   PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-  //   type: 'CommonTable',
-  //   MenuID: '1606794243739c5ihs58lucpskp3r4s2',
-  //   MenuNo: 's_custom_componentsM',
-  //   MenuName: '鑷畾涔夌粍浠�',
   }, {
     src: '',
     systems: ['production', 'local'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '15827879285193g85m3i2uprektpgmpf',
     MenuNo: 'bd_mes_techM',
     MenuName: '宸ヨ壓涓绘暟鎹�',
@@ -112,8 +91,8 @@
   PageParam: {Icon: 'folder'},
   children: [{
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1582771068837vsv54a089lgp45migbg',
     MenuNo: 'KUNTitleM',
     MenuName: '鎺ュ彛涓绘暟鎹�',
@@ -154,8 +133,8 @@
     MenuName: '鍐欏叆鎺ュ彛',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '15848421131551gg04ie8sitsd3f7467',
     MenuNo: 'KUNOsMainM',
     MenuName: '澶栭儴鎺ュ彛',
@@ -166,32 +145,18 @@
   PageParam: {Icon: 'folder'},
   children: [{
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1589782279158ngr675kk3oksin35sul',
     MenuNo: 'bd_msn_emailM',
     MenuName: '閭欢鏈嶅姟鍣�',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1589788042787ffdt9hle4s45k9r1nvs',
     MenuNo: 'bd_msn_email_tempM',
     MenuName: '閭欢妯℃澘',
-  // }, {
-  //   src: '',
-  //   PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-  //   type: 'CommonTable',
-  //   MenuID: '15900310928174dro07ihfckghpb5h13',
-  //   MenuNo: 'bd_msn_sms_tempM',
-  //   MenuName: '澶т簬鐭俊妯℃澘',
-  // }, {
-  //   src: '',
-  //   PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-  //   type: 'CommonTable',
-  //   MenuID: '1599613340050c8nu6rbst9d4emnnbsq',
-  //   MenuNo: 's_sms_qxM',
-  //   MenuName: '濂囦簯鐭俊妯℃澘',
   }]
 }, {
   MenuID: 'systemPayManage',
@@ -200,8 +165,8 @@
   children: [{
     src: '',
     systems: ['local', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1594095599055qicg2eb642v5qglhnuo',
     MenuNo: 's_weixin_pay_bdM',
     MenuName: '寰俊鏀粯',
@@ -213,46 +178,46 @@
   children: [{
     src: '',
     systems: ['production', 'local', 'SSO', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1577972969199lei1g0qkvlh4tkc908m',
     MenuNo: 'sModularM',
     MenuName: '绯荤粺妯″潡',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1578479100252lfbp29v1kafk4s4q4ig',
     MenuNo: 'BDLanguagePacksM',
     MenuName: '璇█鍖�',
   }, {
     src: '',
     systems: ['production', 'local', 'SSO', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1577971621421tg4v0i1ur8873k7e0ob',
     MenuNo: 'sSystemParametersM',
     MenuName: '鎺ュ彛鍦板潃',
   }, {
     src: '',
     systems: ['production', 'local', 'SSO', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1577929944419lgc5h3hepum765e2k7u',
     MenuNo: 'sProcExcepM',
     MenuName: '鎶ラ敊鏃ュ織',
   }, {
     src: '',
-    PageParam: {OpenType: 'newtab', Template: 'CommonTable'},
-    type: 'CommonTable',
+    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
+    type: 'BaseTable',
     MenuID: '1588493493409k9guqp067d31lu7blsv',
     MenuNo: 's_job_stepM',
     MenuName: '璁″垝浠诲姟',
   }, {
     src: '',
     systems: ['production', 'local', 'SSO', 'cloud'],
-    PageParam: {OpenType: 'newtab', Template: 'BaseTable'},
-    type: 'BaseTable',
+    PageParam: {OpenType: 'newtab', Template: 'CustomPage'},
+    type: 'CustomPage',
     MenuID: '1670296054432ab9d5c0pf76o93315ag',
     MenuNo: 's_sys_job_history_M',
     MenuName: '浠g悊浣滀笟璁板綍',
diff --git a/src/views/systemproc/proc/index.jsx b/src/views/systemproc/proc/index.jsx
index cad4d02..f5156bb 100644
--- a/src/views/systemproc/proc/index.jsx
+++ b/src/views/systemproc/proc/index.jsx
@@ -108,7 +108,8 @@
         {key: 'alter', reg: /(^|\s)alter\s/ig},
         {key: 'object', reg: /(^|\s)object(\s|\()/ig},
         {key: 'kill', reg: /(^|\s)kill\s/ig},
-        {key: '--', reg: /--/ig}
+        {key: '--', reg: /--/ig},
+        {key: ',,', reg: /,,/ig}
       ]
 
       let error = ''
diff --git a/src/views/tabledesign/index.jsx b/src/views/tabledesign/index.jsx
index 0689387..25d0d54 100644
--- a/src/views/tabledesign/index.jsx
+++ b/src/views/tabledesign/index.jsx
@@ -63,8 +63,16 @@
   }
 
   UNSAFE_componentWillMount() {
+    if (!sessionStorage.getItem('UserID')) {
+      sessionStorage.removeItem('isEditState')
+      sessionStorage.removeItem('appType')
+      this.props.history.replace('/login')
+      return
+    }
+    
     sessionStorage.setItem('editMenuType', 'menu') // 缂栬緫鑿滃崟绫诲瀷
 
+    window.GLOB.curDate = moment().format('YYYY-MM-DD')
     window.GLOB.UserComponentMap = new Map() // 缂撳瓨鐢ㄦ埛鑷畾涔夌粍浠�
     window.GLOB.TabsMap = new Map()          // 缂撳瓨鐢ㄦ埛鎿嶄綔鐨勬爣绛鹃〉
     window.GLOB.urlFields = []               // url鍙橀噺
@@ -95,6 +103,8 @@
   }
 
   componentDidMount () {
+    if (!sessionStorage.getItem('UserID')) return
+    
     MKEmitter.addListener('changePopview', this.initPopview)
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
     setTimeout(() => {
@@ -235,6 +245,26 @@
       _btn.config.MenuID = _btn.uuid
       _btn.config.ParentId = card.uuid
       _btn.config.MenuName = _btn.label
+      _btn.config.components = _btn.config.components || []
+      _btn.config.components.forEach(item => {
+        if (item.type === 'tabs') {
+          item.subtabs.forEach(tab => {
+            tab.components[0].cols = tab.components[0].cols.map(col => {
+              if (col.type === 'action') {
+                col.type = 'custom'
+              }
+              return col
+            })
+          })
+        } else if (item.cols) {
+          item.cols = item.cols.map(col => {
+            if (col.type === 'action') {
+              col.type = 'custom'
+            }
+            return col
+          })
+        }
+      })
     } else {
       _btn.config = {
         uuid: _btn.uuid,
@@ -263,6 +293,21 @@
   submitPopConfig = (btnconfig) => {
     let config = fromJS(this.state.config).toJS()
 
+    let loopCol = (cols) => {
+      cols.forEach(col => {
+        if (col.type === 'colspan') {
+          loopCol(col.subcols)
+        } else if (col.type === 'custom') {
+          col.elements.forEach(cell => {
+            if (cell.eleType !== 'button') return
+            if (cell.OpenType === 'popview' && cell.uuid === btnconfig.uuid) {
+              cell.config = btnconfig
+            }
+          })
+        }
+      })
+    }
+
     config.components.forEach(item => {
       if (item.type === 'tabs') {
         item.subtabs.forEach(tab => {
@@ -273,14 +318,8 @@
               btn.config = btnconfig
             }
           })
-          tab.components[0].cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements.forEach(btn => {
-              if (btn.OpenType === 'popview' && btn.uuid === btnconfig.uuid) {
-                btn.config = btnconfig
-              }
-            })
-          })
+
+          loopCol(tab.components[0].cols)
 
           tab.components[0].$tables = getTables(tab.components[0])
         })
@@ -290,14 +329,8 @@
             btn.config = btnconfig
           }
         })
-        item.cols.forEach(col => {
-          if (col.type !== 'action') return
-          col.elements.forEach(btn => {
-            if (btn.OpenType === 'popview' && btn.uuid === btnconfig.uuid) {
-              btn.config = btnconfig
-            }
-          })
-        })
+
+        loopCol(item.cols)
 
         item.$tables = getTables(item)
       }
@@ -407,8 +440,20 @@
             if (item.type === 'tabs') {
               item.subtabs.forEach(tab => {
                 tab.components[0].name = tab.label
+                tab.components[0].cols = tab.components[0].cols.map(col => {
+                  if (col.type === 'action') {
+                    col.type = 'custom'
+                  }
+                  return col
+                })
               })
             } else {
+              item.cols = item.cols.map(col => {
+                if (col.type === 'action') {
+                  col.type = 'custom'
+                }
+                return col
+              })
               item.name = '涓昏〃'
             }
           })
@@ -457,15 +502,22 @@
             buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
             _s++
           })
-          tab.components[0].cols.forEach(col => {
-            if (col.type !== 'action') return
-            col.elements.forEach(btn => {
-              if (btn.hidden === 'true') return
 
-              buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
-              _s++
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  buttons.push(`select '${cell.uuid}' as menuid, '${cell.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
+                  _s++
+                })
+              }
             })
-          })
+          }
+
+          loopCol(tab.components[0].cols)
         })
       } else {
         if (item.$tables) {
@@ -477,15 +529,22 @@
           buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
           _sort++
         })
-        item.cols.forEach(col => {
-          if (col.type !== 'action') return
-          col.elements.forEach(btn => {
-            if (btn.hidden === 'true') return
 
-            buttons.push(`select '${btn.uuid}' as menuid,  '${btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
-            _sort++
+        let loopCol = (cols) => {
+          cols.forEach(col => {
+            if (col.type === 'colspan') {
+              loopCol(col.subcols)
+            } else if (col.type === 'custom') {
+              col.elements.forEach(cell => {
+                if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                buttons.push(`select '${cell.uuid}' as menuid,  '${cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
+                _sort++
+              })
+            }
           })
-        })
+        }
+
+        loopCol(item.cols)
       }
     })
 
@@ -517,9 +576,17 @@
       menuloading: true
     })
 
+    window.GLOB.saving = true
+
     setTimeout(() => {
-      if (config.enabled && this.verifyConfig()) {
+      let _pass = this.verifyConfig(config)
+
+      if (config.enabled && !_pass) {
         config.enabled = false
+        config.force = true
+      } else if (!config.enabled && config.force && _pass) {
+        config.enabled = true
+        delete config.force
       }
 
       let tbs = []
@@ -613,6 +680,8 @@
           menuloading: false
         })
 
+        window.GLOB.saving = false
+
         if (!res) return
 
         if (res.status) {
@@ -637,6 +706,9 @@
     this.setState({
       menuloading: false
     })
+
+    window.GLOB.saving = false
+
     if (!error) {
       notification.warning({
         top: 92,
@@ -681,17 +753,22 @@
   onEnabledChange = () => {
     const { config } = this.state
 
-    if (!config || (!config.enabled && this.verifyConfig(true))) {
-      return
-    }
+    let _config = {...config, enabled: !config.enabled}
 
-    this.setState({
-      config: {...config, enabled: !config.enabled}
-    })
+    delete _config.force
+
+    if (!_config.enabled) {
+      this.setState({
+        config: _config
+      })
+    } else if (this.verifyConfig(_config)) {
+      this.setState({
+        config: _config
+      })
+    }
   }
 
-  verifyConfig = (show) => {
-    const { config } = this.state
+  verifyConfig = (config) => {
     let error = ''
 
     config.components.forEach(item => {
@@ -725,7 +802,7 @@
       }
     }
 
-    if (show && error) {
+    if (config.enabled && error) {
       notification.warning({
         top: 92,
         message: error,
@@ -733,7 +810,7 @@
       })
     }
 
-    return error
+    return error === ''
   }
 
   // 鏇存柊閰嶇疆淇℃伅
@@ -843,7 +920,7 @@
                     <TableNodes config={config} />
                     <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                     <PasteBaseTable type="page" insert={this.insert}/>
-                    <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config && config.enabled} onChange={this.onEnabledChange} />
+                    {config ? <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                     <Button type="primary" id="save-config" onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
                     <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
                   </div>
diff --git a/src/views/tabledesign/menuform/index.jsx b/src/views/tabledesign/menuform/index.jsx
index 5e16759..fe0a8e6 100644
--- a/src/views/tabledesign/menuform/index.jsx
+++ b/src/views/tabledesign/menuform/index.jsx
@@ -194,8 +194,6 @@
       })
     } else if (key === 'parentId') {
       this.props.updateConfig({...config, parentId: value})
-    } else if (key === 'timeUnit') {
-      this.props.updateConfig({...config, timeUnit: value})
     } else if (key === 'OpenType') {
       this.props.updateConfig({...config, OpenType: value})
     } else if (key === 'hidden') {
@@ -347,7 +345,7 @@
               })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)}
             </Form.Item>
           </Col>
-          <Col span={24}>
+          <Col span={24} className="red-font">
             <Form.Item label="澶囨敞">
               {getFieldDecorator('Remark', {
                 initialValue: config.Remark || '',
diff --git a/src/views/tabledesign/menuform/index.scss b/src/views/tabledesign/menuform/index.scss
index fa61282..39343af 100644
--- a/src/views/tabledesign/menuform/index.scss
+++ b/src/views/tabledesign/menuform/index.scss
@@ -5,4 +5,12 @@
       font-size: 12px;
     }
   }
+  .red-font {
+    label {
+      color: red;
+    }
+    textarea {
+      color: red;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/views/tabledesign/source.jsx b/src/views/tabledesign/source.jsx
index eb08829..5e43351 100644
--- a/src/views/tabledesign/source.jsx
+++ b/src/views/tabledesign/source.jsx
@@ -231,12 +231,6 @@
       label: '搴忓彿',
       subType: 'index',
       $init: true
-    },
-    {
-      type: 'col',
-      label: '鎿嶄綔',
-      subType: 'action',
-      $init: true
     }
   ],
   tabItems: [

--
Gitblit v1.8.0