From 6ca240a14ccf55d4e0a94fff77e95f64db2cdfcc Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 11 十月 2024 17:34:25 +0800
Subject: [PATCH] 2024-10-11

---
 src/templates/zshare/modalform/index.jsx                                                 |   14 
 src/menu/datasource/verifycard/excelout/index.jsx                                        |   76 
 src/tabviews/custom/components/editor/braft-editor/index.jsx                             |   48 
 src/tabviews/zshare/mutilform/index.scss                                                 |    5 
 src/mob/mobshell/index.jsx                                                               |   45 
 src/tabviews/custom/components/share/braftContent/index.scss                             |   18 
 src/components/resetPassword/index.jsx                                                   |   23 
 src/menu/components/card/balcony/options.jsx                                             |    1 
 src/tabviews/zshare/settingcomponent/index.jsx                                           |   49 
 src/templates/zshare/verifycard/customscript/index.jsx                                   |   37 
 src/views/menudesign/printmenuform/index.jsx                                             |  401 
 src/tabviews/custom/popview/index.jsx                                                    |   59 
 src/views/design/header/transmenu/index.scss                                             |   36 
 src/mob/components/navbar/normal-navbar/menus/index.jsx                                  |   12 
 src/menu/components/table/edit-table/columns/editColumn/index.scss                       |    9 
 src/tabviews/home/index.jsx                                                              |    2 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx        |  114 
 src/tabviews/zshare/mutilform/mkInput/index.jsx                                          |    4 
 public/README.txt                                                                        |   12 
 src/menu/components/table/edit-table/columns/editColumn/index.jsx                        |   32 
 src/tabviews/zshare/actionList/changeuserbutton/index.jsx                                |   16 
 src/menu/datasource/verifycard/index.jsx                                                 |  116 
 src/assets/css/main.scss                                                                 |   44 
 src/mob/components/navbar/normal-navbar/menus/menuform/index.jsx                         |    1 
 src/menu/components/card/cardcellcomponent/index.jsx                                     |   28 
 src/menu/components/form/tab-form/index.jsx                                              |   24 
 src/menu/components/carousel/prop-card/index.jsx                                         |    5 
 src/menu/components/search/main-search/dragsearch/card.jsx                               |    9 
 src/templates/modalconfig/dragelement/index.scss                                         |    4 
 src/views/pay/index.jsx                                                                  |  113 
 src/views/menudesign/index.scss                                                          |   12 
 src/views/systemproc/index.jsx                                                           |    8 
 src/pc/components/login/normal-login/signform.jsx                                        |    4 
 src/menu/components/card/prop-card/index.jsx                                             |    4 
 src/templates/zshare/customscript/index.jsx                                              |    2 
 src/templates/sharecomponent/treesettingcomponent/index.jsx                              |   22 
 src/menu/components/table/edit-table/columns/index.jsx                                   |   28 
 src/menu/datasource/verifycard/utils.jsx                                                 |   78 
 package-lock.json                                                                        |    6 
 src/views/login/loginform.jsx                                                            |   88 
 src/views/menudesign/popview/index.jsx                                                   |    2 
 src/menu/datasource/verifycard/index.scss                                                |   33 
 src/menu/components/share/actioncomponent/dragaction/card.jsx                            |    4 
 src/tabviews/zshare/topSearch/index.jsx                                                  |  231 
 src/templates/comtableconfig/index.jsx                                                   |    4 
 src/menu/components/form/simple-form/options.jsx                                         |   16 
 src/menu/components/form/simple-form/index.jsx                                           |   20 
 src/views/basedesign/index.jsx                                                           |  166 
 src/tabviews/custom/components/table/edit-table/index.jsx                                |   71 
 src/api/index.js                                                                         |  333 
 src/tabviews/zshare/topSearch/index.scss                                                 |    5 
 src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx                       |    2 
 src/templates/sharecomponent/cardcomponent/index.jsx                                     |   10 
 src/mob/mobshell/card.jsx                                                                |    3 
 src/templates/zshare/codemirror/index.jsx                                                |    3 
 src/menu/sysinterface/index.jsx                                                          |    2 
 src/menu/components/table/base-table/columns/editColumn/index.jsx                        |    9 
 public/index.html                                                                        |    4 
 src/views/interface/workspace/request/index.jsx                                          |    3 
 src/views/pcdesign/index.jsx                                                             |  162 
 src/menu/datasource/verifycard/settingform/index.jsx                                     |   48 
 src/mob/components/formdragelement/index.jsx                                             |    2 
 src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx                        |    2 
 src/menu/components/share/actioncomponent/index.jsx                                      |   19 
 src/menu/components/share/copycomponent/index.jsx                                        |   62 
 src/components/pasteboard/index.jsx                                                      |    6 
 src/views/systemfunc/sidemenu/config.jsx                                                 |    8 
 src/menu/components/share/colsControl/index.jsx                                          |   12 
 src/pc/createview/settingform/index.jsx                                                  |    1 
 src/templates/zshare/editTable/index.jsx                                                 |    8 
 src/menu/components/editor/braft-editor/options.jsx                                      |   27 
 src/mob/components/tabs/antv-tabs/index.jsx                                              |    6 
 src/tabviews/zshare/actionList/popupbutton/index.jsx                                     |   15 
 src/tabviews/custom/components/tabs/antv-tabs/index.jsx                                  |    4 
 src/tabviews/zshare/normalTable/index.jsx                                                |    2 
 src/menu/components/share/searchcomponent/index.jsx                                      |   19 
 src/templates/comtableconfig/updatetable/index.jsx                                       |   42 
 src/views/mkiframe/index.jsx                                                             |   21 
 src/templates/treepageconfig/index.jsx                                                   |    4 
 src/menu/datasource/index.jsx                                                            |  122 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx                    |    6 
 src/menu/components/form/formaction/index.jsx                                            |    4 
 src/views/billprint/index.jsx                                                            |  220 
 src/menu/datasource/verifycard/excelout/index.scss                                       |    0 
 src/menu/components/editor/braft-editor/index.scss                                       |   23 
 src/tabviews/subtabtable/index.jsx                                                       |    6 
 src/tabviews/zshare/actionList/normalbutton/index.jsx                                    | 1173 ++
 src/views/tabledesign/index.scss                                                         |    5 
 src/views/menudesign/index.jsx                                                           |  102 
 src/tabviews/custom/components/card/data-card/index.jsx                                  |  206 
 src/menu/replaceField/settingform/index.jsx                                              |    4 
 src/views/appmanage/index.scss                                                           |    8 
 src/tabviews/custom/components/module/voucher/index.jsx                                  |    8 
 src/templates/zshare/pasteform/index.jsx                                                 |    6 
 src/menu/components/card/double-data-card/index.jsx                                      |    4 
 src/views/login/logincloudform.jsx                                                       |   14 
 src/views/tabledesign/popview/index.scss                                                 |    5 
 src/menu/pastecontroller/index.jsx                                                       |   57 
 src/menu/components/card/data-card/index.jsx                                             |    4 
 src/mob/header/index.scss                                                                |    7 
 src/views/appmanage/index.jsx                                                            |  581 
 src/menu/components/search/main-search/options.jsx                                       |   12 
 src/menu/components/tabs/antv-tabs/index.jsx                                             |   12 
 src/templates/sharecomponent/searchcomponent/index.scss                                  |   10 
 src/tabviews/zshare/actionList/index.scss                                                |    3 
 src/mob/searchconfig/searchdragelement/index.jsx                                         |    2 
 src/templates/sharecomponent/settingcomponent/index.jsx                                  |   68 
 src/views/design/index.jsx                                                               |    4 
 src/views/pay/index.scss                                                                 |    8 
 src/menu/components/table/normal-table/options.jsx                                       |   21 
 src/components/header/index.jsx                                                          |   56 
 src/tabviews/custom/components/card/double-data-card/index.jsx                           |  203 
 src/templates/zshare/verifycard/callbackcustomscript/index.jsx                           |   14 
 src/menu/transfer/index.jsx                                                              |   18 
 src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx                   |   36 
 src/views/rolemanage/index.jsx                                                           |  155 
 src/templates/sharecomponent/fieldscomponent/index.jsx                                   |   24 
 src/views/billprint/index.scss                                                           |    3 
 src/tabviews/custom/components/calendar/board/index.jsx                                  |    4 
 src/templates/zshare/verifycard/customform/index.jsx                                     |   14 
 src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx             |    3 
 src/templates/sharecomponent/settingcomponent/settingform/utils.jsx                      |   24 
 src/tabviews/zshare/actionList/tabbutton/index.jsx                                       |   22 
 src/components/normalform/modalform/index.jsx                                            |   52 
 src/menu/stylecontroller/index.jsx                                                       |    7 
 src/views/rolemanage/index.scss                                                          |   14 
 src/menu/components/table/base-table/options.jsx                                         |   33 
 src/templates/zshare/verifycard/index.jsx                                                |   80 
 src/menu/components/share/sourcecomponent/index.jsx                                      |    4 
 src/tabviews/zshare/actionList/printbutton/index.jsx                                     |  177 
 src/store/options.js                                                                     |   15 
 src/views/appmanage/transmenu/index.scss                                                 |   16 
 src/tabviews/custom/components/table/edit-table/normalTable/index.scss                   |   10 
 src/menu/components/card/cardcellcomponent/formconfig.jsx                                |   31 
 src/templates/sharecomponent/actioncomponent/index.jsx                                   |    8 
 src/assets/img/map.jpg                                                                   |    0 
 src/menu/components/editor/braft-editor/index.jsx                                        |   23 
 src/tabviews/zshare/fileupload/index.jsx                                                 |   98 
 src/views/menudesign/popview/index.scss                                                  |    5 
 src/mob/header/index.jsx                                                                 |    4 
 src/mob/searchconfig/index.jsx                                                           |   33 
 src/tabviews/zshare/actionList/funcbutton/index.jsx                                      |  300 
 src/menu/components/share/markcomponent/index.jsx                                        |    6 
 src/views/basedesign/updateFormTab/index.jsx                                             |    4 
 src/components/editor/index.scss                                                         |   17 
 src/views/appmanage/transmenu/index.jsx                                                  |  521 +
 src/menu/components/card/cardcellcomponent/index.scss                                    |    2 
 src/menu/components/card/cardcellcomponent/dragaction/action.jsx                         |    4 
 src/menu/components/card/cardcellcomponent/elementform/index.jsx                         |   40 
 src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.jsx            |  224 
 src/menu/components/tabs/antv-tabs/index.scss                                            |    2 
 src/menu/components/share/actioncomponent/dragaction/index.jsx                           |    2 
 src/menu/components/table/edit-table/options.jsx                                         |   19 
 src/templates/modalconfig/index.jsx                                                      |   18 
 src/templates/sharecomponent/searchcomponent/searchform/index.scss                       |   11 
 src/views/systemfunc/index.jsx                                                           |   10 
 src/tabviews/zshare/actionList/newpagebutton/index.jsx                                   |  435 +
 src/views/design/sidemenu/index.jsx                                                      |    8 
 src/mob/modalconfig/index.jsx                                                            |   14 
 src/mob/modalconfig/index.scss                                                           |    5 
 src/tabviews/commontable/index.jsx                                                       |    6 
 src/components/header/loginform.jsx                                                      |   38 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx                     |    6 
 src/views/interface/index.jsx                                                            |   27 
 src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx                   |   20 
 src/utils/sqlFormatter.js                                                                |   46 
 src/menu/components/form/formaction/formconfig.jsx                                       |   33 
 src/tabviews/custom/components/card/cardcellList/index.jsx                               |   64 
 src/menu/components/share/searchcomponent/dragsearch/index.jsx                           |    2 
 src/tabviews/zshare/actionList/funczip/index.jsx                                         |   27 
 src/menu/components/carousel/data-card/options.jsx                                       |    5 
 src/menu/components/card/data-card/options.jsx                                           |   28 
 src/components/editor/index.jsx                                                          |  151 
 src/mob/components/menubar/normal-menubar/index.jsx                                      |    6 
 src/tabviews/custom/components/table/normal-table/index.jsx                              |  150 
 src/menu/components/tabs/antv-tabs/options.jsx                                           |   15 
 src/mob/components/menubar/normal-menubar/menucomponent/options.jsx                      |    1 
 src/templates/subtableconfig/index.jsx                                                   |    4 
 src/tabviews/custom/components/table/edit-table/normalTable/index.jsx                    |  377 
 src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx                  |   22 
 src/components/breadview/index.jsx                                                       |   20 
 src/tabviews/custom/components/editor/braft-editor/index.scss                            |   23 
 src/tabviews/custom/components/module/invoice/index.scss                                 |    2 
 src/tabviews/zshare/mutilform/index.jsx                                                  |  216 
 src/templates/zshare/modalform/index.scss                                                |    9 
 src/menu/components/share/actioncomponent/actionform/index.jsx                           |  109 
 src/tabviews/custom/index.jsx                                                            |   91 
 src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx                  |   14 
 src/menu/components/table/normal-table/columns/index.jsx                                 |   28 
 src/views/appmanage/submutilform/index.jsx                                               |   94 
 src/menu/components/timeline/normal-timeline/options.jsx                                 |    1 
 src/menu/components/card/cardcellcomponent/dragaction/index.scss                         |   21 
 src/views/design/header/index.jsx                                                        |  132 
 src/views/printTemplate/index.jsx                                                        |   62 
 src/menu/components/form/formaction/actionform/index.jsx                                 |   17 
 src/menu/components/card/cardcellcomponent/dragaction/index.jsx                          |    2 
 src/menu/components/table/base-table/columns/editColumn/formconfig.jsx                   |   15 
 src/pc/menushell/index.jsx                                                               |   45 
 src/templates/zshare/verifycard/fullScripts/index.jsx                                    |    2 
 src/menu/components/tabs/table-tabs/index.jsx                                            |    6 
 src/tabviews/zshare/actionList/exceloutbutton/index.jsx                                  |  132 
 src/menu/components/card/cardcellcomponent/dragaction/card.jsx                           |    8 
 src/views/design/sidemenu/index.scss                                                     |   20 
 src/views/tabledesign/index.jsx                                                          |  106 
 src/tabviews/zshare/actionList/index.jsx                                                 |   10 
 src/tabviews/subtable/index.jsx                                                          |    6 
 src/templates/sharecomponent/tabscomponent/index.jsx                                     |   18 
 src/menu/components/carousel/data-card/index.jsx                                         |    4 
 src/tabviews/custom/components/card/table-card/index.jsx                                 |    2 
 src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx                       |    2 
 src/menu/components/form/step-form/index.jsx                                             |   24 
 src/tabviews/zshare/mutilform/mkCheckCard/index.jsx                                      |    2 
 public/manifest.json                                                                     |    2 
 src/pc/components/login/normal-login/loginform.jsx                                       |    2 
 src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx                    |    4 
 src/menu/urlfieldcomponent/index.jsx                                                     |    4 
 src/menu/components/search/main-search/index.jsx                                         |   19 
 src/templates/sharecomponent/actioncomponent/dragaction/index.jsx                        |    2 
 src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx              |    6 
 src/components/sidemenu/index.jsx                                                        |    2 
 src/views/login/index.jsx                                                                |  121 
 src/mob/components/navbar/normal-navbar/index.jsx                                        |    2 
 src/utils/utils-datamanage.js                                                            |  237 
 src/menu/picturecontroller/index.jsx                                                     |    8 
 src/menu/components/card/table-card/index.jsx                                            |    4 
 src/utils/utils-custom.js                                                                | 4304 +++++++++++
 src/views/main/index.jsx                                                                 |   17 
 src/mob/modulesource/option.jsx                                                          |    4 
 src/templates/sharecomponent/actioncomponent/verifypay/index.scss                        |   84 
 src/tabviews/custom/components/share/normalTable/index.scss                              |   25 
 src/views/design/header/editfirstmenu/index.jsx                                          |    4 
 src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.scss           |    0 
 src/tabviews/zshare/actionList/excelInbutton/index.jsx                                   |  694 +
 src/views/design/header/transmenu/index.jsx                                              |  889 ++
 public/options.json                                                                      |    5 
 src/pc/components/login/normal-login/options.jsx                                         |   15 
 src/menu/components/table/normal-table/columns/editColumn/index.jsx                      |    9 
 src/tabviews/basetable/index.jsx                                                         |   34 
 src/menu/tablenodes/index.jsx                                                            |    7 
 src/tabviews/custom/components/module/invoice/index.jsx                                  |  688 +
 src/views/pcdesign/index.scss                                                            |    3 
 src/templates/sharecomponent/settingcomponent/settingform/index.jsx                      |   22 
 src/templates/modalconfig/dragelement/card.jsx                                           |    2 
 src/views/design/sidemenu/editthdmenu/index.jsx                                          |    4 
 src/views/mobdesign/index.jsx                                                            |  338 
 src/views/interface/history/index.jsx                                                    |    4 
 src/components/normalform/modalform/mkSelect/index.jsx                                   |   41 
 src/menu/components/module/invoice/verifycard/customscript/index.jsx                     |    2 
 src/api/cacheutils.js                                                                    |    6 
 src/menu/components/card/double-data-card/options.jsx                                    |   41 
 src/mob/colorsketch/index.jsx                                                            |    7 
 src/menu/components/share/actioncomponent/formconfig.jsx                                 |  428 
 src/menu/components/editor/braft-editor/editorcontent/index.scss                         |   10 
 src/tabviews/custom/components/tabs/antv-tabs/index.scss                                 |   10 
 src/tabviews/zshare/mutilform/mkPopSelect/index.jsx                                      |  168 
 src/menu/components/table/base-table/columns/index.jsx                                   |   14 
 src/menu/debug/index.jsx                                                                 |  596 +
 src/views/imdesign/index.jsx                                                             |  173 
 src/views/design/sidemenu/thdmenuplus/index.jsx                                          |    6 
 src/menu/components/group/normal-group/index.jsx                                         |    6 
 src/tabviews/zshare/normalTable/index.scss                                               |   10 
 src/templates/sharecomponent/searchcomponent/searchform/index.jsx                        |   21 
 src/components/tabview/index.jsx                                                         |   20 
 src/menu/components/form/simple-form/index.scss                                          |   11 
 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx                 |   15 
 src/tabviews/custom/components/table/base-table/index.jsx                                |  146 
 src/tabviews/custom/components/card/double-data-card/index.scss                          |   40 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx       |    4 
 src/components/resetPassword/resetpwd/index.jsx                                          |   57 
 src/views/appcheck/index.jsx                                                             |  228 
 src/views/mobdesign/menuform/index.jsx                                                   |   27 
 src/menu/datasource/verifycard/customscript/index.jsx                                    |    4 
 src/mob/searchconfig/index.scss                                                          |    4 
 src/templates/sharecomponent/searchcomponent/index.jsx                                   |   26 
 src/templates/sharecomponent/columncomponent/index.jsx                                   |   10 
 src/views/mobdesign/index.scss                                                           |   42 
 src/tabviews/custom/components/share/normalTable/index.jsx                               |  101 
 src/templates/modalconfig/dragelement/index.jsx                                          |    2 
 src/menu/components/form/step-form/options.jsx                                           |    1 
 src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx                          |   14 
 src/pc/components/navbar/normal-navbar/linksetting/linktable/index.jsx                   |    4 
 src/tabviews/custom/components/card/data-card/index.scss                                 |   26 
 src/menu/components/search/main-search/index.scss                                        |   15 
 src/utils/utils.js                                                                       |  307 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx                    |    4 
 src/index.js                                                                             |  183 
 src/tabviews/custom/components/module/voucher/resetAttach/addAttach/fileupload/index.jsx |  109 
 src/views/sso/index.jsx                                                                  |   12 
 src/menu/components/search/main-search/dragsearch/index.jsx                              |    2 
 src/tabviews/custom/components/share/tabtransfer/index.jsx                               |   48 
 src/templates/treepageconfig/updatetable/index.jsx                                       |    8 
 src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx        |  167 
 src/templates/zshare/formconfig.jsx                                                      |   37 
 src/pc/createview/index.jsx                                                              |    8 
 /dev/null                                                                                |   17 
 src/templates/sharecomponent/actioncomponent/verifypay/index.jsx                         |  516 +
 src/menu/modalconfig/index.scss                                                          |    4 
 src/menu/modalconfig/index.jsx                                                           |   20 
 src/tabviews/custom/components/card/cardcellList/index.scss                              |    4 
 src/templates/zshare/verifycard/baseform/index.jsx                                       |  192 
 src/menu/menushell/index.jsx                                                             |    1 
 src/views/tabledesign/popview/index.jsx                                                  |    2 
 src/templates/sharecomponent/chartgroupcomponent/index.jsx                               |   10 
 303 files changed, 17,258 insertions(+), 5,098 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index c560381..7e3b8fd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5508,9 +5508,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001588",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz",
-      "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ=="
+      "version": "1.0.30001643",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz",
+      "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg=="
     },
     "canvg": {
       "version": "3.0.10",
diff --git a/public/README.txt b/public/README.txt
index 6cbdae7..d1ff2b5 100644
--- a/public/README.txt
+++ b/public/README.txt
@@ -11,14 +11,16 @@
 defaultLang       -- 鎵撳紑鐨勫瓙搴旂敤璇█绫诲瀷锛岄粯璁や负zh-CN
 WXAppID           -- 浣跨敤鍏紬鍙锋椂锛岀粦瀹氱殑鍏紬鍙稩D
 WXminiAppID       -- 浣跨敤寰俊灏忕▼搴忔椂锛岀粦瀹氱殑灏忕▼搴廔D
-nginx             -- 鏄惁寮�鍚簡nginx鏈嶅姟锛屽�间负 true 鏃跺紑鍚紝濡傞渶浣跨敤寰俊妯℃澘娑堟伅绛夋湇鍔★紝璇峰厛璁剧疆nginx鏈嶅姟骞跺紑鍚閰嶇疆
-debugger          -- 鍊间负 true 鏃跺紑鍚皟璇曟ā寮忥紝寮�鍚悗绉诲姩绔瓙搴旂敤涓細鏈夋帶鍒跺彴
+WXMerchID         -- 浣跨敤寰俊鏀粯鏃讹紝缁戝畾鐨勫晢鎴稩D
+WXNotice          -- 鏄惁寮�鍚槑绉戜簯鍏紬鍙锋秷鎭彁閱掞紝鍊间负 true 鏃跺紑鍚紝鍙�氳繃鏄庣浜戝彂閫佹ā鏉挎秷鎭�
+WXApps            -- 瀛樺湪澶氫釜鍏紬鍙枫�佸皬绋嬪簭鎴栧晢鎴锋椂鍙娇鐢ㄥ井淇PP鍒楄〃锛屾敞鎰忓~鍐欓粯璁ゅ叕浼楀彿銆佸皬绋嬪簭涓庡晢鎴峰彿锛屾牸寮� [{"appId": "", "appName": "", "appType": "public/miniProgram/merchant"}]
+debugger          -- 鍊间负 true 鏃跺紑鍚皟璇曟ā寮忥紝寮�鍚悗绉诲姩绔瓙搴旂敤涓細鏈夋帶鍒跺彴锛屽�间负 forbid 鏃讹紝绂佹绯荤粺鎵撳嵃鑴氭湰
+systemRun         -- 绯荤粺鎺ュ彛鐨勬墽琛屾柟寮忥紝鍊间负 backend 鏃讹紝鍦ㄥ悗绔繍琛�
 licenseKey        -- 璁稿彲瀵嗛挜锛屽湪鍐呴儴缃戠粶涓娇鐢ㄧ郴缁熸椂锛屼細璺宠繃epc楠岃瘉
 storeKey          -- 鐢靛瓙妗f鏈湴鎺堟潈鐮侊紝浣跨敤鏈湴璁稿彲瀵嗛挜鏃舵湁鏁�
 probation         -- 璇曠敤鏈燂紙YYYY-MM-DD锛夛紝鍦ㄦ寮忕郴缁熶腑锛岃瘯鐢ㄦ湡鍐呰皟鐢ㄧ郴缁熸帴鍙g殑鑴氭湰浼氳褰曚笅鏉�
 transfer          -- 鏄惁浣跨敤杞帴鍙o紝浣跨敤杞帴鍙f椂璇疯缃负 true, 浣跨敤杞帴鍙f椂锛屽閮ㄦ帴鍙h皟鐢ㄥ墠涓嶄細鍋氱櫥褰曢獙璇�
-keepPassword      -- 璁颁綇瀵嗙爜锛岄粯璁ゅ紑鍚紝褰撳�间负 false 鏃剁鐢�
+keepPwd           -- 璁颁綇瀵嗙爜锛岄粯璁ゅ紑鍚紝褰撳�间负 false 鏃剁鐢紝褰撳�间负 invisible 鏃惰浣忓瘑鐮佷絾瀵嗙爜涓嶅彲鏌ョ湅
 execType          -- 鑴氭湰浼犺緭鏂瑰紡锛屽�间负x鏃讹紝鍚敤AES鍔犲瘑
 updateStatus      -- 鏄惁鏇存柊寮�鍙戠姸鎬侊紝榛樿寮�鍚紝褰撳�间负 false 鏃剁鐢�
-forcedUpdate      -- 浼犺緭鍙峰崌绾ф椂锛屾槸鍚﹁嚜鍔ㄩ��鍑猴紝鏍煎紡涓猴紙YYYY-MM-DD锛夛紝鐢ㄤ簬鍗囩骇鍚庡埛鏂扮敤鎴锋湰鍦伴厤缃�
-platforms         -- 绉诲姩绔彲浣跨敤鐨勫钩鍙扮被鍨嬶紝榛樿涓� ["H5", "wechat", "android", "ios", "wxMiniProgram"] 鍒嗗埆浠h〃H5椤甸潰銆佸井淇″叕浼楀彿銆佸畨鍗揂PP銆佽嫻鏋淎PP銆佸井淇″皬绋嬪簭
\ No newline at end of file
+forcedUpdate      -- 浼犺緭鍙峰崌绾ф椂锛屾槸鍚﹁嚜鍔ㄩ��鍑猴紝鏍煎紡涓猴紙YYYY-MM-DD锛夛紝鐢ㄤ簬鍗囩骇鍚庡埛鏂扮敤鎴锋湰鍦伴厤缃�
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index 3da241a..7719992 100644
--- a/public/index.html
+++ b/public/index.html
@@ -58,6 +58,10 @@
             }
           })
       }
+
+      window.mkInfo = function(value, color = '') {
+        console.info(value, color)
+      }
     </script>
   </head>
   <body>
diff --git a/public/manifest.json b/public/manifest.json
index 6f976ee..3027059 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -6,5 +6,5 @@
   "display": "standalone",
   "theme_color": "#000000",
   "background_color": "#ffffff",
-  "mk_version": "20240501"
+  "mk_version": "20241002"
 }
diff --git a/public/options.json b/public/options.json
index e52946f..0a34756 100644
--- a/public/options.json
+++ b/public/options.json
@@ -11,13 +11,14 @@
   "WXAppID": "",
   "WXminiAppID": "",
   "WXNotice": "true",
-  "nginx": "true",
   "debugger": true,
+  "systemRun": "backend",
+  "execType": "",
   "licenseKey": "",
   "storeKey": "",
   "probation": "",
   "transfer": "true",
-  "keepPassword": "true",
+  "keepPwd": "true",
   "platforms": ["H5", "wechat", "android", "ios", "wxMiniProgram"],
   "host": "http://dms-test.worx.cn",
   "service": "new/"
diff --git a/src/api/cacheutils.js b/src/api/cacheutils.js
index 3184290..b20d3f6 100644
--- a/src/api/cacheutils.js
+++ b/src/api/cacheutils.js
@@ -27,9 +27,9 @@
         if (!window.GLOB.IndexDB.objectStoreNames.contains('caches')) {
           window.GLOB.IndexDB.createObjectStore('caches', { keyPath: 'menuid' })
         }
-        if (!window.GLOB.IndexDB.objectStoreNames.contains('funcs')) {
-          window.GLOB.IndexDB.createObjectStore('funcs', { keyPath: 'id' })
-        }
+        // if (!window.GLOB.IndexDB.objectStoreNames.contains('funcs')) {
+        //   window.GLOB.IndexDB.createObjectStore('funcs', { keyPath: 'id' })
+        // }
       }
     } catch (e) {
       console.warn('IndexedDB 鍒濆鍖栧け璐ワ紒')
diff --git a/src/api/index.js b/src/api/index.js
index 6c2d8cc..72e889c 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -15,7 +15,8 @@
 window.GLOB.$error = false
 
 let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : ''
-let db = `mkdb${service}`
+let lang = sessionStorage.getItem('lang') !== 'zh-CN' ? sessionStorage.getItem('lang') : ''
+let db = `mkdb${service + lang}`
 
 if (window.indexedDB) {
   CacheUtils.openIndexDB(db)
@@ -128,37 +129,21 @@
   }
 
   /* @description 鐩存帴璇锋眰
-   * @description 寰俊涓氬姟璇锋眰
+   * @description 寰俊涓氬姟璇锋眰 鍘熸帴鍙� 'wxpay/getaccesstoken'
    */
-  wxAccessToken (domain = '') {
-    let _url = window.GLOB.baseurl + 'wxpay/getaccesstoken'
+  // wxAccessToken (appId, domain = '') {
+  //   let _url = domain || window.GLOB.baseurl
 
-    if (domain) {
-      _url = domain + 'wxpay/getaccesstoken'
-    }
-
-    return new Promise(resolve => {
-      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 = {domain}
-        axios({
-          url: _url,
-          method: 'get'
-        }).then(res => {
-          if (res.oa_access_token || res.mini_access_token) {
-            window.GLOB.accessToken.accessTime = parseInt(new Date().getTime() / 1000)
-            window.GLOB.accessToken.oa_access_token = res.oa_access_token
-            window.GLOB.accessToken.mini_access_token = res.mini_access_token
-          }
-          resolve(res)
-        })
-      }
-    })
-  }
+  //   return axios({
+  //     url: _url + 'wechat/getaccesstoken',
+  //     method: 'post',
+  //     data: JSON.stringify({app_id: appId})
+  //   })
+  // }
 
   /**
    * @description 寰俊涓氬姟璇锋眰
+   * 39涓� qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn
    */
   wxNginxRequest (url, method, param) {
     let _url = url
@@ -168,17 +153,12 @@
       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
-        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
-        }
-      }
+    }
+    if (/qingqiumarket.cn|cloud.mk9h.cn/.test(_url)) {
+      _url = _url.replace('http://qingqiumarket.cn/', 'http://qingqiumarket.cn:8080/')
+      _url = _url.replace('http://cloud.mk9h.cn/', 'http://cloud.mk9h.cn:8080/')
+      _url = _url.replace('https://qingqiumarket.cn/', 'https://qingqiumarket.cn:8443/')
+      _url = _url.replace('https://cloud.mk9h.cn/', 'https://cloud.mk9h.cn:8443/')
     }
     
     if (param) {
@@ -198,7 +178,27 @@
   /**
    * @description 鐩存帴璇锋眰
    */
-  directRequest (params) {
+  directRequest (params, script, position) {
+    if (script) {
+      try {
+        // eslint-disable-next-line
+        let func = new Function('axios', 'Api', 'param', 'position', 'systemType', 'notification', script)
+        let promise = func(axios, this, params, position, window.GLOB.systemType, notification)
+
+        if (promise instanceof Promise) {
+          return promise
+        }
+      } catch (e) {
+        console.warn(e)
+      }
+
+      return Promise.resolve({
+        status: false,
+        message: '鑷畾涔夎剼鏈墽琛岄敊璇�',
+        ErrCode: 'E'
+      })
+    }
+    
     return axios(params)
   }
 
@@ -558,26 +558,26 @@
   /**
    * @description 鑾峰彇鎴栦慨鏀圭郴缁熼厤缃紝澧炲姞appkey
    */
-  getSystemFuncs (time) {
-    let param = {
-      func: 's_get_func_base_sso',
-      update_date: time,
-      userid: sessionStorage.getItem('UserID') || '',
-      lang: sessionStorage.getItem('lang') || '',
-      SessionUid: localStorage.getItem('SessionUid') || '',
-      LoginUID: sessionStorage.getItem('LoginUID') || '',
-      appkey: window.GLOB.appkey
-    }
+  // getSystemFuncs (time) {
+  //   let param = {
+  //     func: 's_get_func_base_sso',
+  //     update_date: time,
+  //     userid: sessionStorage.getItem('UserID') || '',
+  //     lang: sessionStorage.getItem('lang') || '',
+  //     SessionUid: localStorage.getItem('SessionUid') || '',
+  //     LoginUID: sessionStorage.getItem('LoginUID') || '',
+  //     appkey: window.GLOB.appkey
+  //   }
 
-    let url = window.GLOB.mainSystemApi || '/webapi/dostars'
-    param = this.encryptParam(param)
+  //   let url = window.GLOB.mainSystemApi || '/webapi/dostars'
+  //   param = this.encryptParam(param)
 
-    return axios({
-      url: `${url}/${param.func}`,
-      method: 'post',
-      data: JSON.stringify(param)
-    })
-  }
+  //   return axios({
+  //     url: `${url}/${param.func}`,
+  //     method: 'post',
+  //     data: JSON.stringify(param)
+  //   })
+  // }
 
   /**
    * @description 鑾峰彇鎴栦慨鏀圭郴缁熼厤缃紝澧炲姞appkey
@@ -736,6 +736,65 @@
     param.SessionUid = localStorage.getItem('SessionUid') || ''
     param.LoginUID = param.LoginUID || sessionStorage.getItem('LoginUID') || ''
     param.appkey = window.GLOB.appkey || ''
+
+    if (param.$backend) {
+      delete param.$backend
+
+      let id = ''
+      if (cache) {
+        id = param.data[0].id
+
+        if (window.GLOB.CacheMap.has(id)) {
+          return Promise.resolve(window.GLOB.CacheMap.get(id))
+        }
+      }
+
+      param.username = sessionStorage.getItem('User_Name') || ''
+      param.fullname = sessionStorage.getItem('Full_Name') || ''
+      param.s_debug = window.GLOB.debugger ? 'Y' : ''
+      param.data_md5 = param.data_md5 || ''
+      param.time_limit = param.time_limit || 0
+
+      let url = '/webapi/exstars'
+      if (param.rduri) {
+        param.rduri = param.rduri.replace(/dostars/ig, 'exstars')
+        if (!window.GLOB.transfer) {
+          url = param.rduri
+          delete param.rduri
+        }
+      }
+
+      if (param.$type) {
+        url += '/' + param.$type
+      }
+
+      delete param.$type
+
+      param = this.encryptParam(param)
+
+      return new Promise((resolve) => {
+        axios({
+          url: url,
+          method: 'post',
+          data: JSON.stringify(param)
+        }).then(res => {
+          if (res.mksqls) {
+            res.mksqls.forEach(n => {
+              n = n.replace(/(UNION ALL\s+)?SELECT obj_name='[\S\s]+sub_field=''\s+/ig, '')
+              window.mkInfo(n)
+            })
+          }
+          if (res.ErrCode === 'version_error') {
+            res.ErrCode = '-2'
+            MKEmitter.emit('reloadTabs')
+          }
+          if (res.status && id) {
+            window.GLOB.CacheMap.set(id, res)
+          }
+          resolve(res)
+        })
+      })
+    }
 
     let url = '/webapi/dostars'
     if (param.rduri && !window.GLOB.transfer) { // positecgroup
@@ -1004,9 +1063,55 @@
           }
         })
       })
+    } else if (param.$backend) {
+      delete param.$backend
+
+      let url = '/webapi/exstars'
+      if (param.rduri) {
+        param.rduri = param.rduri.replace(/dostars/ig, 'exstars')
+        if (!window.GLOB.transfer) {
+          url = param.rduri
+          delete param.rduri
+        }
+      }
+
+      if (param.$type) {
+        url += '/' + param.$type
+      }
+
+      delete param.$type
+
+      param.username = sessionStorage.getItem('User_Name') || ''
+      param.fullname = sessionStorage.getItem('Full_Name') || ''
+      param.s_debug = window.GLOB.debugger ? 'Y' : ''
+      param.data_md5 = param.data_md5 || ''
+      param.time_limit = param.time_limit || 0
+
+      param = this.encryptParam(param)
+
+      return new Promise((resolve) => {
+        axios({
+          url: url,
+          method: 'post',
+          data: JSON.stringify(param),
+          requestId
+        }).then(res => {
+          if (res.mksqls) {
+            res.mksqls.forEach(n => {
+              n = n.replace(/(UNION ALL\s+)?SELECT obj_name='[\S\s]+sub_field=''\s+/ig, '')
+              window.mkInfo(n)
+            })
+          }
+          if (res.ErrCode === 'version_error') {
+            res.ErrCode = '-2'
+            MKEmitter.emit('reloadTabs')
+          }
+          resolve(res)
+        })
+      })
     } else {
       let url = '/webapi/dostars'
-      if (param.rduri && !window.GLOB.transfer && /\/dostars/.test(param.rduri) && param.func !== 'webapi_ChangeUser') {
+      if (param.rduri && (!window.GLOB.transfer || /https:\/\/sso.mk9h.cn/.test(param.rduri)) && /\/dostars/.test(param.rduri) && param.func !== 'webapi_ChangeUser') {
         url = param.rduri
         delete param.rduri
       }
@@ -1020,6 +1125,27 @@
         requestId
       })
     }
+  }
+
+  /**
+   * @description 娓呯┖鍚庣缂撳瓨
+   */
+  cacheInterface (param) {
+    param.appkey = window.GLOB.appkey || ''
+
+    let url = '/webapi/excache'
+    if (param.rduri && !window.GLOB.transfer) {
+      url = param.rduri
+      delete param.rduri
+    }
+
+    param = this.encryptParam(param)
+
+    return axios({
+      url: url,
+      method: 'post',
+      data: JSON.stringify(param),
+    })
   }
 
   /**
@@ -1065,26 +1191,45 @@
   /**
    * @description 澶ф枃浠朵笂浼�
    */
-  getLargeFileUpload (param) {
-    return axios({
-      url: '/webapi/doupload',
-      method: 'post',
-      headers: { 'Content-Type': 'multipart/form-data' },
-      data: param
+  getFileUpload (param) {
+    param.append('shardingCnt', 1)
+    param.append('LoginUID', sessionStorage.getItem('LoginUID') || '')
+    param.append('UserID', sessionStorage.getItem('UserID') || '')
+
+    return new Promise((resolve, reject) => {
+      axios({
+        url: '/webapi/doupload',
+        method: 'post',
+        headers: { 'Content-Type': 'multipart/form-data' },
+        data: param
+      }).then(res => {
+        if (res.status && res.urlPath) {
+          if (!/Content\/images/.test(res.urlPath)) {
+            let key = CryptoJS.enc.Utf8.parse('D1185ED7B32568C9')
+            let wordArray = CryptoJS.enc.Base64.parse(res.urlPath)
+            let decryptedWordArray = CryptoJS.AES.decrypt({ ciphertext: wordArray }, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
+            res.urlPath = CryptoJS.enc.Utf8.stringify(decryptedWordArray)
+          }
+          if (!/^http/.test(res.urlPath)) {
+            res.urlPath = window.GLOB.baseurl + res.urlPath
+          }
+        }
+        resolve(res)
+      })
     })
   }
 
   /**
    * @description 鏌ヨ鏂囦欢鏄惁宸蹭笂浼�
    */
-  getFilePreUpload (param) {
-    return axios({
-      url: '/webapi/dopreload',
-      method: 'post',
-      headers: { 'Content-Type': 'multipart/form-data' },
-      data: param
-    })
-  }
+  // getFilePreUpload (param) {
+  //   return axios({
+  //     url: '/webapi/dopreload',
+  //     method: 'post',
+  //     headers: { 'Content-Type': 'multipart/form-data' },
+  //     data: param
+  //   })
+  // }
 
   /**
    * @description oss鏂囦欢涓婁紶
@@ -1094,16 +1239,11 @@
     if (process.env.NODE_ENV === 'production') {
       _url = document.location.origin + '/file/oss/upload'
     }
-    if (/^http:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
-      _url = window.GLOB.location + ':8080/file/oss/upload'
-      if (process.env.NODE_ENV === 'production') {
-        _url = document.location.origin + ':8080/file/oss/upload'
-      }
-    } else if (/^https:\/\/(qingqiumarket.cn|cloud.mk9h.cn|sso.mk9h.cn)/.test(_url)) {
-      _url = window.GLOB.location + ':8443/file/oss/upload'
-      if (process.env.NODE_ENV === 'production') {
-        _url = document.location.origin + ':8443/file/oss/upload'
-      }
+    if (/qingqiumarket.cn|cloud.mk9h.cn/.test(_url)) {
+      _url = _url.replace('http://qingqiumarket.cn/', 'http://qingqiumarket.cn:8080/')
+      _url = _url.replace('http://cloud.mk9h.cn/', 'http://cloud.mk9h.cn:8080/')
+      _url = _url.replace('https://qingqiumarket.cn/', 'https://qingqiumarket.cn:8443/')
+      _url = _url.replace('https://cloud.mk9h.cn/', 'https://cloud.mk9h.cn:8443/')
     }
     
     return axios({
@@ -1115,30 +1255,24 @@
   }
 
   /**
-   * @description 鑾峰彇寰俊鏀粯浜岀淮鐮�
+   * @description 鑾峰彇寰俊鏀粯浜岀淮鐮� 鍘熸帴鍙xpay/wxNativePay
    */
   getWxNativePay (param) {
-    let _url = window.GLOB.baseurl + 'wxpay/wxNativePay'
-
     return axios({
-      url: _url,
+      url: window.GLOB.baseurl + 'wechat/native',
       method: 'post',
-      data: qs.stringify(param)
+      data: JSON.stringify(param)
     })
   }
 
   /**
-   * @description 寰俊鏀粯閫�娆�
+   * @description 寰俊鏀粯閫�娆� 鍘熸帴鍙xpay/wxRefund
    */
-  setRefund (orderId) {
-    let _param = new FormData()
-    _param.append('out_biz_no', orderId)
-
+  setRefund (param) {
     return axios({
-      url: '/wxpay/wxRefund',
-      headers: { 'Content-Type': 'multipart/form-data' },
+      url: window.GLOB.baseurl + 'wechat/wxRefund',
       method: 'post',
-      data: _param
+      data: JSON.stringify(param)
     })
   }
 
@@ -1153,7 +1287,7 @@
   /**
    * @description sql妫�楠�
    */
-  sDebug (sql, rduri = null) {
+  sDebug (sql) {
     let param = {
       func: 's_debug_sql',
       exec_type: window.GLOB.execType || 'y',
@@ -1172,13 +1306,14 @@
     sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid')}'`)
     sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID')}'`)
     sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey}'`)
+    sql = sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
     // sql = sql.replace(/@datam@/ig, `''`)
 
     if (window.GLOB.externalDatabase !== null) {
       sql = sql.replace(/@db@/ig, window.GLOB.externalDatabase)
     }
 
-    console.info(`/* sql 楠岃瘉 */\n${sql.replace(/\n\s{6,20}/ig, '\n')}`)
+    window.mkInfo(`/* sql 楠岃瘉 */\n${sql.replace(/\n\s{6,20}/ig, '\n')}`)
 
     sql = sql.replace(/\n/ig, ' ')
 
@@ -1188,10 +1323,6 @@
     param = this.encryptParam(param)
 
     let url = '/webapi/dostars'
-
-    if (rduri) {
-      url = rduri
-    }
 
     let timer = setTimeout(() => {
       let _param = {
diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index 41db689..7f4eea2 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -322,6 +322,7 @@
   }
   .ant-modal-body::-webkit-scrollbar {
     width: 7px;
+    height: 0;
   }
   .ant-modal-body::-webkit-scrollbar-thumb {
     border-radius: 5px;
@@ -728,6 +729,49 @@
     vertical-align: bottom;
   }
 }
+.fixed-table-height {
+  tr, td, th {
+    overflow: hidden;
+  }
+  ::-webkit-scrollbar {
+    width: 17px;
+    height: 17px;
+  }
+  ::-webkit-scrollbar-thumb {
+    background: rgba(193, 193, 193, 0.7);
+  }
+  ::-webkit-scrollbar-track {
+    background: #fafafa;
+  }
+  .ant-table-body {
+    min-height: 1px;
+    border-bottom: 1px solid rgba(0, 0, 0, .05);
+    .ant-table-fixed {
+      border-bottom: 0;
+    }
+  }
+}
+@media screen and (max-width: 1400px) {
+  .fixed-table-height {
+    ::-webkit-scrollbar {
+      width: 16px;
+    }
+  }
+}
+@media screen and (min-width: 1600px) {
+  .fixed-table-height {
+    ::-webkit-scrollbar {
+      width: 18px;
+    }
+  }
+}
+@media screen and (min-width: 1900px) {
+  .fixed-table-height {
+    ::-webkit-scrollbar {
+      width: 21px;
+    }
+  }
+}
 
 // 绯荤粺鑹茶缃�
 .mk-main-view {
diff --git a/src/assets/img/map.jpg b/src/assets/img/map.jpg
index 5dd38ff..757308d 100644
--- a/src/assets/img/map.jpg
+++ b/src/assets/img/map.jpg
Binary files differ
diff --git a/src/components/breadview/index.jsx b/src/components/breadview/index.jsx
index 44494c8..340b188 100644
--- a/src/components/breadview/index.jsx
+++ b/src/components/breadview/index.jsx
@@ -18,7 +18,9 @@
 const Iframe = asyncComponent(() => import('@/tabviews/iframe'))
 const RoleManage = asyncComponent(() => import('@/tabviews/rolemanage'))
 
-moment.locale('zh-cn')
+if (sessionStorage.getItem('lang') === 'zh-CN') {
+  moment.locale('zh-cn')
+}
 
 class BreadView extends Component {
   state = {
@@ -32,7 +34,7 @@
   UNSAFE_componentWillMount () {
     let home = {
       MenuID: 'home_page_id',
-      MenuName: '棣栭〉',
+      MenuName: window.GLOB.dict['home'] || '棣栭〉',
       type: 'Home'
     }
     this.setState({tabview: home})
@@ -40,9 +42,7 @@
 
   componentDidMount () {
     MKEmitter.addListener('modifyTabs', this.modifyTabs)
-    if (window.GLOB.forcedUpdate) {
-      MKEmitter.addListener('reloadTabs', this.reloadTabs)
-    }
+    MKEmitter.addListener('reloadTabs', this.reloadTabs)
   }
 
   /**
@@ -138,7 +138,7 @@
   gotoHome = () => {
     let home = {
       MenuID: 'home_page_id',
-      MenuName: '棣栭〉',
+      MenuName: window.GLOB.dict['home'] || '棣栭〉',
       type: 'Home'
     }
     this.setState({tabview: home})
@@ -158,9 +158,15 @@
   reloadTabs = () => {
     if (this.reloading) return
 
-    this.reloading = true
     let time = new Date().getTime()
 
+    let oldTime = sessionStorage.getItem('mk_reloadTabs')
+    
+    if (oldTime && time - oldTime < 180000) return
+
+    sessionStorage.setItem('mk_reloadTabs', time)
+
+    this.reloading = true
     this.setState({visible: true})
 
     Api.getAppVersion(true).then((list) => {
diff --git a/src/components/editor/index.jsx b/src/components/editor/index.jsx
index ede20dc..a9e96de 100644
--- a/src/components/editor/index.jsx
+++ b/src/components/editor/index.jsx
@@ -1,12 +1,10 @@
-import React, {Component} from 'react'
+import React, { Component } from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import BraftEditor from 'braft-editor'
 import 'braft-editor/dist/index.css'
 import 'braft-extensions/dist/table.css'
 import Table from 'braft-extensions/dist/table'
-import SparkMD5 from 'spark-md5'
-import moment from 'moment'
 
 import Api from '@/api'
 import './index.scss'
@@ -21,7 +19,7 @@
 
   state = {
     editorState: '',
-    encryption: 'false',
+    encryption: 'false'
   }
 
   UNSAFE_componentWillMount () {
@@ -51,6 +49,7 @@
       encryption
     })
   }
+
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.props), fromJS(nextProps))
   }
@@ -72,37 +71,21 @@
     }
   }
 
-  shardupload = (params, param) => {
-    let _param = params.chunks.shift()
+  handleUpload(param) {
     let form = new FormData()
 
-    form.append('file', _param.binary)
-    form.append('fileMd5', params.file.fileMd5)
-    form.append('shardingMd5', _param.chunkMd5)
-    form.append('baseDomain', window.GLOB.baseurl)
-    form.append('rootPath', 'Content/images/upload/')
-    form.append('fileName', params.file.fileName)
-    form.append('fileExt', params.file.fileType)
-    form.append('shardingCnt', _param.chunks)
-    form.append('shardingNo', _param.chunk)
-    form.append('LoginUID', sessionStorage.getItem('LoginUID') || '')
-    form.append('UserID', sessionStorage.getItem('UserID') || '')
+    form.append('file', param.file)
 
-    Api.getLargeFileUpload(form).then(res => {
+    Api.getFileUpload(form).then(res => {
       if (res.status) {
-        if (params.chunks.length > 0) {
-          param.progress(Math.floor(100 * (_param.chunk / _param.chunks)))
-          this.shardupload(params, param)
+        if (res.urlPath) {
+          param.success({
+            url: res.urlPath
+          })
         } else {
-          if (res.urlPath) {
-            param.success({
-              url: res.urlPath
-            })
-          } else {
-            param.error({
-              url: '涓婁紶澶辫触锛�'
-            })
-          }
+          param.error({
+            url: '涓婁紶澶辫触锛�'
+          })
         }
       } else {
         param.error({
@@ -112,111 +95,17 @@
     })
   }
 
-  getuuid = () => {
-    let uuid = []
-    let _options = '0123456789abcdefghigklmnopqrstuv'
-    for (let i = 0; i < 19; i++) {
-      uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
-    }
-    uuid = uuid.join('')
-    return uuid
-  }
-
-  handleUpload(param) {
-    const file = param.file
-
-    let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
-    let chunkSize = 1024 * 1024 * 2                // 鍒囩墖姣忔2M
-    let chunks = Math.ceil(file.size / chunkSize)  // 鍒囩墖鎬绘暟
-    let currentChunk = 0                           // 褰撳墠涓婁紶鐨刢hunk
-    let spark = new SparkMD5.ArrayBuffer()         // 瀵筧rrayBuffer鏁版嵁杩涜md5鍔犲瘑锛屼骇鐢熶竴涓猰d5瀛楃涓�
-    let chunkFileReader = new FileReader()         // 鐢ㄤ簬璁$畻鍑烘瘡涓猚hunkMd5
-    let totalFileReader = new FileReader()         // 鐢ㄤ簬璁$畻鍑烘�绘枃浠剁殑fileMd5
-    let params = {chunks: [], file: {}}            // 鐢ㄤ簬涓婁紶鎵�鏈夊垎鐗囩殑md5淇℃伅
-
-    params.file.fileName = file.name.replace(/\.{1}[^.]*$/ig, '')  // 鏂囦欢鍚嶏紙鍘婚櫎鍚庣紑鍚嶏級
-    params.file.fileType = file.name.replace(/^.*\.{1}/ig, '')     // 鏂囦欢绫诲瀷
-    params.file.fileSize = file.size                               // 鏂囦欢澶у皬
-    params.file.fileChunks = chunks                                // 璁板綍鎵�鏈塩hunks鐨勯暱搴�
-
-    if (!/^[A-Za-z0-9]+$/.test(params.file.fileName)) {            // 鏂囦欢鍚嶇О鍚湁鑻辨枃鍙婃暟瀛椾箣澶栧瓧绗︽椂锛屽悕绉扮郴缁熺敓鎴�
-      params.file.fileName = moment().format('YYYYMMDDHHmmss') + this.getuuid()
-    }
-
-    totalFileReader.readAsArrayBuffer(file)
-    totalFileReader.onload = (e) => {   // 瀵规暣涓猼otalFile鐢熸垚md5
-      spark.append(e.target.result)
-      params.file.fileMd5 = spark.end() // 璁$畻鏁翠釜鏂囦欢鐨刦ileMd5
-
-      let _param = new FormData()
-      _param.append('fileMd5', params.file.fileMd5)
-      
-      Api.getFilePreUpload(_param).then(res => {
-        if (res.status && res.urlPath) {
-          param.success({
-            url: res.urlPath
-          })
-        } else if (res.shardings && res.shardings.length > 0) {
-          res.shardings.forEach(shard => {
-            if (shard.shardingNo && parseInt(shard.shardingNo) > currentChunk) {
-              currentChunk = parseInt(shard.shardingNo)
-            }
-          })
-          loadNext()
-        } else {
-          loadNext()
-        }
-      })
-    }
-
-    chunkFileReader.onload = (e) => {
-      spark.append(e.target.result)      // 瀵规瘡涓�鐗囧垎鐗囪繘琛宮d5鍔犲瘑
-      
-      params.chunks[params.chunks.length - 1].chunkMd5 = spark.end() // 娣诲姞鍒囩墖md5
-      
-      currentChunk++  // 姣忎竴娆″垎鐗噊nload,currentChunk閮介渶瑕佸鍔狅紝浠ヤ究鏉ヨ绠楀垎鐗囩殑娆℃暟
-
-      if (currentChunk < chunks) { // 褰撳墠鍒囩墖鎬绘暟娌℃湁杈惧埌鎬绘暟鏃�
-        loadNext()
-      } else {
-        this.shardupload(params, param)
-      }
-    }
-
-    chunkFileReader.onerror = () => {
-      param.error({
-        url: '涓婁紶澶辫触锛�'
-      })
-      console.warn('File reading failed.')
-    }
-    totalFileReader.onerror = () => {
-      param.error({
-        url: '涓婁紶澶辫触锛�'
-      })
-    }
-
-    let loadNext = () => {
-      let start = currentChunk * chunkSize              // 璁$畻鍒嗙墖鐨勮捣濮嬩綅缃�
-      let end = Math.min(file.size, start + chunkSize)  // 璁$畻鍒嗙墖鐨勭粨鏉熶綅缃�
-
-      let obj = {                                       // 姣忎竴涓垎鐗囬渶瑕佸寘鍚殑淇℃伅
-        chunk: currentChunk + 1,
-        binary: file.slice(start, end),
-        start: start,
-        end: end,
-        chunks
-      }
-
-      params.chunks.push(obj)
-      chunkFileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
-    }
-  }
-
   render() {
+    const { config } = this.props
     const { editorState } = this.state
 
+    let style = null
+    if (config && config.contHeidht) {
+      style = {'--editor-height': config.contHeidht < 100 ? config.contHeidht + 'vh' : config.contHeidht + 'px'}
+    }
+
     return (
-      <div className="normal-braft-editor">
+      <div className="normal-braft-editor" style={style}>
         <BraftEditor
           value={editorState}
           onChange={this.handleEditorChange}
diff --git a/src/components/editor/index.scss b/src/components/editor/index.scss
index 44e33dc..9f9132f 100644
--- a/src/components/editor/index.scss
+++ b/src/components/editor/index.scss
@@ -1,12 +1,25 @@
 .normal-braft-editor {
+  overflow: hidden;
+  border: 1px solid #d9d9d9;
+  border-radius: 4px;
+  
   .bf-content {
     overflow-x: hidden;
     overflow-y: auto;
-    height: auto;
-    min-height: 500px;
+    height: var(--editor-height, auto);
+    min-height: var(--editor-height, 500px);
     padding-bottom: 0px;
     .public-DraftEditor-content {
       padding-bottom: 0;
+
+      * {
+        font-weight: inherit;
+        font-style: inherit;
+      }
+    }
+    .DraftEditor-root, .DraftEditor-editorContainer, .public-DraftEditor-content {
+      height: var(--editor-height, auto);
+      min-height: var(--editor-height, 500px);
     }
   }
   .bf-content::-webkit-scrollbar {
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index f06c705..4ea94db 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -34,7 +34,8 @@
     thdMenuList: [],
     debug: sessionStorage.getItem('debug') === 'true' && window.GLOB.memberLevel > 0,
     collapse: sessionStorage.getItem('collapse') === 'true',
-    lang: sessionStorage.getItem('lang') || ''
+    lang: sessionStorage.getItem('lang') || '',
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -55,7 +56,9 @@
   componentDidMount () {
     // 鑾峰彇绯荤粺鐨勭増鏈俊鎭紝寤舵椂鏌ヨ
     setTimeout(() => {
-      Api.getAppVersion()
+      if (!window.GLOB.$error) {
+        Api.getAppVersion()
+      }
     }, 1000)
 
     // sessionStorage 璺ㄩ〉闈㈠叡浜�
@@ -108,21 +111,24 @@
       setTimeout(() => {
         sessionStorage.clear()
         this.props.history.replace('/login')
+        window.location.reload()
       }, 2000)
     })
   }
 
   logout = () => {
+    const { dict } = this.state
     // 閫�鍑虹櫥褰�
-    let _this = this
+    let that = this
     confirm({
-      title: '鎮ㄧ‘瀹氳閫�鍑哄悧?',
+      title: dict['logout_query'] || '鎮ㄧ‘瀹氳閫�鍑哄悧锛�',
       content: '',
-      okText: '纭畾',
-      cancelText: '鍙栨秷',
+      okText: dict['ok'] || '纭畾',
+      cancelText: dict['cancel'] || '鍙栨秷',
       onOk() {
         sessionStorage.clear()
-        _this.props.history.replace('/login')
+        that.props.history.replace('/login')
+        window.location.reload()
       },
       onCancel() {}
     })
@@ -441,11 +447,10 @@
 
           sessionStorage.setItem('CloudLogo', res.open_logo || '')
 
-          let _url = window.location.href.split('#')[0] + 'cloud'
           if (param.remember) {
-            localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify({time: new Date().getTime(), username: param.username, password: param.password}))))
+            localStorage.setItem(window.GLOB.sysSign + 'cloud', window.btoa(window.encodeURIComponent(JSON.stringify({time: new Date().getTime(), username: param.username, password: param.password}))))
           } else {
-            localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify({time: new Date().getTime(), username: param.username, password: ''}))))
+            localStorage.setItem(window.GLOB.sysSign + 'cloud', window.btoa(window.encodeURIComponent(JSON.stringify({time: new Date().getTime(), username: param.username, password: ''}))))
           }
 
           window.GLOB.mainMenu = null
@@ -563,15 +568,19 @@
   }
 
   verup = () => {
+    const { dict } = this.state
+
     confirm({
-      title: '椤甸潰鏇存柊',
-      content: '閲嶆柊鍔犺浇搴旂敤淇℃伅',
+      title: dict['page_upd'] || '椤甸潰鏇存柊',
+      content: dict['reload_app'] || '閲嶆柊鍔犺浇搴旂敤淇℃伅',
+      okText: dict['ok'] || '纭畾',
+      cancelText: dict['cancel'] || '鍙栨秷',
       onOk() {
         return new Promise(resolve => {
           if (!window.GLOB.IndexDB) {
             notification.warning({
               top: 92,
-              message: '鏇存柊澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯锛�',
+              message: dict['exc_fail'] || '鏇存柊澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯锛�',
               duration: 2
             })
             resolve()
@@ -583,7 +592,7 @@
             setTimeout(() => {
               notification.success({
                 top: 92,
-                message: '鏇存柊鎴愬姛锛�',
+                message: dict['exc_success'] || '鏇存柊鎴愬姛锛�',
                 duration: 2
               })
               resolve()
@@ -597,7 +606,8 @@
 
   about = () => {
     Modal.success({
-      title: '绯荤粺鐗堟湰v' + window.GLOB.appVersion
+      title: (window.GLOB.dict['sys_ver'] || '绯荤粺鐗堟湰') + ' v' + window.GLOB.appVersion,
+      okText: window.GLOB.dict['got_it'] || '鐭ラ亾浜�',
     })
   }
 
@@ -608,32 +618,32 @@
   }
 
   render () {
-    const { thdMenuList, searchkey, debug, menulist, collapse } = this.state
+    const { thdMenuList, searchkey, debug, menulist, collapse, dict } = this.state
     const navBar = window.GLOB.navBar
 
     const menu = (
       <Menu className="header-dropdown">
         {debug && <Menu.Item key="switch">
-          缂栬緫
+          {dict['edit'] || '缂栬緫'}
           <Switch size="small" style={{marginLeft: '7px'}} checked={false} onChange={this.changeEditState} />
         </Menu.Item>}
-        <Menu.Item key="password" onClick={this.changePassword}>淇敼瀵嗙爜</Menu.Item>
-        {this.state.systems.length ? <Menu.SubMenu style={{minWidth: '110px'}} title="鍒囨崲绯荤粺">
+        <Menu.Item key="password" onClick={this.changePassword}>{dict['ch_pwd'] || '淇敼瀵嗙爜'}</Menu.Item>
+        {this.state.systems.length ? <Menu.SubMenu style={{minWidth: '110px'}} title={dict['swt_sys'] || '鍒囨崲绯荤粺'}>
           {this.state.systems.map((system, index) => (
             <Menu.Item style={{minWidth: '100px', lineHeight: '30px'}} key={'sub' + index} onClick={() => {this.changeSystem(system)}}> {system.AppName} </Menu.Item>
           ))}
         </Menu.SubMenu> : null}
-        <Menu.Item key="doc" onClick={this.gotoDoc}>鏂囨。涓績</Menu.Item>
+        <Menu.Item key="doc" onClick={this.gotoDoc}>{dict['doc_center'] || '鏂囨。涓績'}</Menu.Item>
         <Menu.Item key="verup" onClick={this.verup}>
-          椤甸潰鏇存柊
+          {dict['page_upd'] || '椤甸潰鏇存柊'}
         </Menu.Item>
         {window.GLOB.WXNotice ? <Menu.Item key="wxnotice" onClick={() => this.setState({wxVisible: true})}>
           寰俊娑堟伅
         </Menu.Item> : null}
         {window.GLOB.appVersion ? <Menu.Item key="version" onClick={this.about}>
-          鍏充簬
+          {dict['about'] || '鍏充簬'}
         </Menu.Item> : null}
-        <Menu.Item key="logout" onClick={this.logout}>閫�鍑�</Menu.Item>
+        <Menu.Item key="logout" onClick={this.logout}>{dict['logout'] || '閫�鍑�'}</Menu.Item>
       </Menu>
     )
 
diff --git a/src/components/header/loginform.jsx b/src/components/header/loginform.jsx
index 95e702f..cca3f3d 100644
--- a/src/components/header/loginform.jsx
+++ b/src/components/header/loginform.jsx
@@ -3,8 +3,6 @@
 import { Form, Input, Checkbox } from 'antd'
 import { UserOutlined, LockOutlined } from '@ant-design/icons'
 
-import zhCN from '@/locales/zh-CN/login.js'
-import enUS from '@/locales/en-US/login.js'
 import './index.scss'
 
 class HeaderLoginForm extends Component {
@@ -13,17 +11,15 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     remember: false,
+    lock: false,
     username: '',
     password: '',
-    oripassword: '',
     delay: +sessionStorage.getItem('mkDelay')
   }
 
   UNSAFE_componentWillMount () {
-    let _url = window.location.href.split('#')[0] + 'cloud'
-    let _user = localStorage.getItem(_url)
+    let _user = localStorage.getItem(window.GLOB.sysSign + 'cloud')
     
     if (_user) {
       try {
@@ -36,29 +32,24 @@
 
     if (_user && new Date().getTime() - _user.time > 1000 * 7 * 24 * 60 * 60) {
       _user = ''
-      localStorage.removeItem(_url)
+      localStorage.removeItem(window.GLOB.sysSign + 'cloud')
     }
 
     if (_user) {
       this.setState({
         remember: true,
         username: _user.username,
-        password: _user.password ? '*********' : '',
-        oripassword: _user.password
+        password: _user.password,
+        lock: true
       })
     }
   }
 
   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, '')
 
@@ -86,11 +77,16 @@
 
   rememberChange = (e) => {
     let val = e.target.checked
-    let _url = window.location.href.split('#')[0] + 'cloud'
 
     if (!val) {
-      localStorage.removeItem(_url)
+      localStorage.removeItem(window.GLOB.sysSign + 'cloud')
     }
+  }
+
+  unLock = (e) => {
+    if (e.target.value) return
+    
+    this.setState({ lock: false })
   }
 
   componentDidMount () {
@@ -107,7 +103,7 @@
 
   render() {
     const { getFieldDecorator } = this.props.form
-    const { remember, username, password, delay } = this.state
+    const { remember, username, password, delay, lock } = this.state
 
     return (
       <Form style={{margin: '0px 10px'}}>
@@ -116,12 +112,12 @@
         </Form.Item> : null}
         <Form.Item style={{marginBottom: '0px', height: '60px'}}>
           {getFieldDecorator('username', {
-            rules: [{ required: true, message: this.state.dict['login.username.empty'] }],
+            rules: [{ required: true, message: '璇疯緭鍏ョ敤鎴峰悕' }],
             initialValue: username,
           })(
             <Input
               prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }}/>}
-              placeholder={this.state.dict['login.username']}
+              placeholder="鐢ㄦ埛鍚�"
               autoComplete="off"
               onPressEnter={(e) => {this.handleSubmit(e, 'password')}}
             />
@@ -133,10 +129,10 @@
             rules: [
               {
                 required: true,
-                message: this.state.dict['login.password.empty'],
+                message: '璇疯緭鍏ュ瘑鐮�',
               }
             ]
-          })(<Input.Password onPressEnter={(e) => {this.handleSubmit(e, 'username')}} placeholder={this.state.dict['login.password']} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
+          })(<Input.Password onPressEnter={(e) => {this.handleSubmit(e, 'username')}} placeholder="瀵嗙爜" visibilityToggle={!lock} onChange={this.unLock} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
         </Form.Item>
         {window.GLOB.keepKey ? <Form.Item style={{marginBottom: '10px'}}>
           {getFieldDecorator('remember', {
diff --git a/src/components/normalform/modalform/index.jsx b/src/components/normalform/modalform/index.jsx
index c685080..0ab789f 100644
--- a/src/components/normalform/modalform/index.jsx
+++ b/src/components/normalform/modalform/index.jsx
@@ -32,6 +32,7 @@
 
   state = {
     formlist: [],    // 琛ㄥ崟椤�
+    formId: ''
   }
 
   record = {}
@@ -40,6 +41,15 @@
     let record = {}
     let controlFields = {}
     let fieldMap = new Map()
+    let formId = (() => {
+      let uuid = []
+      let _options = '0123456789abcdefghigklmnopqrstuv'
+      for (let i = 0; i < 19; i++) {
+        uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
+      }
+      uuid = uuid.join('')
+      return uuid
+    })()
 
     let formlist = this.props.formlist.filter(item => {
       if (item.controlFields) { // 澶氬眰琛ㄥ崟鎺у埗
@@ -56,6 +66,7 @@
       if (item.options) {
         item.oriOptions = fromJS(item.options).toJS()
       }
+      item.$formId = formId
 
       if (item.type === 'text') {
         let _rules = [{
@@ -121,10 +132,11 @@
 
         let cell = fieldMap.get(item.field)
 
-        if (cell.hidden) return
+        cell.$ctrls = cell.$ctrls || []
+        cell.$ctrls.push(key)
 
-        if (cell.skip && supItem.forbid) { // 涓婄骇琛ㄥ崟绂佺敤鏃讹紝姝よ〃鍗曚笉鍙楁帶鍒�
-
+        if (cell.hidden) {
+          
         } else if (supItem.hidden) {
           cell.hidden = true
         } else if (item.notNull) {
@@ -151,6 +163,10 @@
     formlist = formlist.map(cell => {
       let item = fieldMap.get(cell.field)
 
+      if (item.$ctrls && item.$ctrls.length === 1) {
+        delete item.$ctrls
+      }
+
       if (item.linkField) {
         let supInitVal = fieldMap.get(item.linkField).initval || ''
         
@@ -162,7 +178,7 @@
 
     this.record = record
 
-    this.setState({ formlist })
+    this.setState({ formlist, formId })
   }
 
   checkNumber = (rule, value, callback, item) => {
@@ -217,6 +233,32 @@
             }
           } else {
             m.hidden = !cell.values.includes(val)
+          }
+
+          if (!m.hidden && m.$ctrls) {
+            m.$ctrls.forEach(n => {
+              if (n === current.field || m.hidden) return
+
+              let oth = map.get(n)
+              let _val = this.record[n]
+
+              if (_val && JSON.stringify(_val) === '[]') {
+                _val = ''
+              }
+
+              let p = oth.controlFields.filter(q => q.field === m.field)[0]
+
+              if (oth.hidden || (p.notNull && !_val)) {
+                m.hidden = true
+              } else if (oth.type === 'checkbox' || oth.type === 'multiselect') {
+                let _vals = [...(_val || []), ...p.values]
+                if (_vals.length === new Set(_vals).size) {
+                  m.hidden = true
+                }
+              } else if (!p.values.includes(_val)) {
+                m.hidden = true
+              }
+            })
           }
 
           if (m.hidden) {
@@ -385,7 +427,7 @@
     }
 
     return (
-      <Form {...formItemLayout} className="normal-form-field">
+      <Form {...formItemLayout} className="normal-form-field" id={this.state.formId}>
         <Row gutter={24}>{this.getFields()}</Row>
       </Form>
     )
diff --git a/src/components/normalform/modalform/mkSelect/index.jsx b/src/components/normalform/modalform/mkSelect/index.jsx
index abbd6ac..7c7d8ed 100644
--- a/src/components/normalform/modalform/mkSelect/index.jsx
+++ b/src/components/normalform/modalform/mkSelect/index.jsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react'
+import React, { Component } from 'react'
 import { is, fromJS } from 'immutable'
 import { Select } from 'antd'
 
@@ -115,24 +115,7 @@
     const { value, config, options } = this.state
 
     if (config.type !== 'multiselect') {
-      if (config.extendName) {
-        return (
-          <Select
-            showSearch
-            allowClear
-            value={value}
-            dropdownMatchSelectWidth={config.dropdown !== 'false'}
-            filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
-              option.props.extend.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-            onSelect={this.selectChange}
-            onChange={(val) => val === undefined && this.selectChange('')}
-          >
-            {options.map((option, i) =>
-              <Select.Option key={i} disabled={option.disabled} title={option.label || option.text} extend={option[config.extendName] || ''} value={option.value || option.field || ''}>{option.label || option.text}</Select.Option>
-            )}
-          </Select>
-        )
-      } else {
+      if (config.joint) {
         return (
           <Select
             showSearch
@@ -142,13 +125,30 @@
             filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
             onSelect={this.selectChange}
             onChange={(val) => val === undefined && this.selectChange('')}
+            getPopupContainer={() => config.$formId ? document.getElementById(config.$formId) : document.body}
           >
             {options.map((option, i) =>
-              <Select.Option key={i} disabled={option.disabled} value={option.value || option.field || ''}>{option.label || option.text}</Select.Option>
+              <Select.Option key={i} disabled={option.disabled} value={option.field || ''}>{`${option.label}锛�${option.field}锛塦}</Select.Option>
             )}
           </Select>
         )
       }
+      return (
+        <Select
+          showSearch
+          allowClear
+          value={value}
+          dropdownMatchSelectWidth={config.dropdown !== 'false'}
+          filterOption={(input, option) => (option.props.children + option.props.extend).toLowerCase().indexOf(input.toLowerCase()) >= 0}
+          onSelect={this.selectChange}
+          onChange={(val) => val === undefined && this.selectChange('')}
+          getPopupContainer={() => config.$formId ? document.getElementById(config.$formId) : document.body}
+        >
+          {options.map((option, i) =>
+            <Select.Option key={i} disabled={option.disabled} title={option.label || option.text} extend={config.extendName ? (option[config.extendName] || '') : ''} value={option.value || option.field || ''}>{option.label || option.text}</Select.Option>
+          )}
+        </Select>
+      )
     } else {
       return (<Select
         showSearch
@@ -156,6 +156,7 @@
         defaultValue={value}
         filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
         onChange={this.mutilselectChange}
+        getPopupContainer={() => config.$formId ? document.getElementById(config.$formId) : document.body}
       >
         {options.map((option, i) =>
           <Select.Option key={i} disabled={option.disabled} value={option.value || option.field}>{option.label || option.text}</Select.Option>
diff --git a/src/components/pasteboard/index.jsx b/src/components/pasteboard/index.jsx
index aae3fa1..66c00c4 100644
--- a/src/components/pasteboard/index.jsx
+++ b/src/components/pasteboard/index.jsx
@@ -46,7 +46,7 @@
       _config = JSON.parse(window.decodeURIComponent(window.atob(_config)))
 
       if (typeof(_config) === 'object' && _config.$srcId) {
-        let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+        let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
         if (srcid && _config.$srcId !== srcid) {
           notification.warning({
             top: 92,
@@ -61,14 +61,14 @@
       }
     } catch (e) {
       // 閫氳繃sql璇彞娣诲姞瀛楁闆�
-      if (/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int)/ig.test(config)) {
+      if (/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int|datetime|date)/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)
+        let list = config.match(/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int|datetime|date)/ig)
 
         list.forEach(item => {
           _config.data.unshift({
diff --git a/src/components/resetPassword/index.jsx b/src/components/resetPassword/index.jsx
index 71ca86a..de2862b 100644
--- a/src/components/resetPassword/index.jsx
+++ b/src/components/resetPassword/index.jsx
@@ -14,7 +14,8 @@
     visible: false,
     loading: false,
     type: 'account',
-    okText: '纭畾',
+    okText: window.GLOB.dict['ok'] || '纭畾',
+    dict: window.GLOB.dict,
     smsId: '',
     mob: '',
     code: ''
@@ -40,7 +41,7 @@
       visible: true,
       loading: false,
       type: 'account',
-      okText: '纭畾',
+      okText: window.GLOB.dict['ok'] || '纭畾',
       mob: '',
       code: '',
       smsId: sessionStorage.getItem('mk_sms_id') || ''
@@ -48,7 +49,7 @@
   }
 
   resetPwdSubmit = () => {
-    const { type } = this.state
+    const { type, dict } = this.state
 
     if (type === 'account') {
       this.formRef.handleConfirm().then(res => {
@@ -77,7 +78,7 @@
             })
             notification.success({
               top: 92,
-              message: '淇敼鎴愬姛锛岃閲嶆柊鐧诲綍銆�',
+              message: dict['re_login'] || '淇敼鎴愬姛锛岃閲嶆柊鐧诲綍銆�',
               duration: 2
             })
             this.callback && this.callback()
@@ -98,7 +99,7 @@
         if (!/^1[3456789]\d{9}$/.test(res.phone)) {
           notification.warning({
             top: 92,
-            message: '鎵嬫満鍙锋牸寮忛敊璇紝璇烽噸濉紒',
+            message: dict['phone_error'] || '鎵嬫満鍙锋牸寮忛敊璇紝璇烽噸濉紒',
             duration: 5
           })
           return
@@ -114,7 +115,7 @@
         this.setState({
           code: res.vercode,
           type: 'phonepwd',
-          okText: '纭畾'
+          okText: dict['ok'] || '纭畾'
         })
       }, () => {})
     } else if (type === 'phonepwd') {
@@ -146,7 +147,7 @@
             })
             notification.success({
               top: 92,
-              message: '淇敼鎴愬姛锛岃閲嶆柊鐧诲綍銆�',
+              message: dict['re_login'] || '淇敼鎴愬姛锛岃閲嶆柊鐧诲綍銆�',
               duration: 2
             })
             this.callback && this.callback()
@@ -166,23 +167,23 @@
   }
 
   render() {
-    const { visible, loading, okText, type, mob, smsId } = this.state
+    const { visible, loading, okText, type, mob, smsId, dict } = this.state
 
     return (
       <Modal
-        title="淇敼瀵嗙爜"
+        title={dict['ch_pwd'] || '淇敼瀵嗙爜'}
         wrapClassName="reset-password-modal"
         visible={visible}
         maskClosable={false}
         onOk={this.resetPwdSubmit}
         onCancel={() => { this.setState({ visible: false })}}
         okText={okText}
-        cancelText="鍙栨秷"
+        cancelText={dict['cancel'] || '鍙栨秷'}
         confirmLoading={loading}
         destroyOnClose
       >
         <Resetpwd type={type} mob={mob} smsId={smsId} wrappedComponentRef={(inst) => this.formRef = inst} resetPwdSubmit={this.resetPwdSubmit}/>
-        {type === 'account' && smsId ? <div className="forget-pwd"><span onClick={() => this.setState({type: 'mob', okText: '涓嬩竴姝�'})}>蹇樿瀵嗙爜锛�</span></div> : null}
+        {type === 'account' && smsId ? <div className="forget-pwd"><span onClick={() => this.setState({type: 'mob', okText: dict['next'] || '涓嬩竴姝�'})}>{dict['forgot_pwd'] || '蹇樿瀵嗙爜锛�'}</span></div> : null}
       </Modal>
     )
   }
diff --git a/src/components/resetPassword/resetpwd/index.jsx b/src/components/resetPassword/resetpwd/index.jsx
index 514bab5..829571b 100644
--- a/src/components/resetPassword/resetpwd/index.jsx
+++ b/src/components/resetPassword/resetpwd/index.jsx
@@ -9,7 +9,8 @@
   state = {
     confirmDirty: false,
     autoCompleteResult: [],
-    level: localStorage.getItem(window.location.href.split('#')[0] + 'pwdlevel') || ''
+    level: localStorage.getItem(window.GLOB.sysSign + 'pwdlevel') || '',
+    dict: window.GLOB.dict,
   }
 
   LoginTimer = null
@@ -63,7 +64,7 @@
   compareToFirstPassword = (rule, value, callback) => {
     const { form } = this.props
     if (value && value !== form.getFieldValue('password')) {
-      callback('涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷达紒')
+      callback(window.GLOB.dict['pwd_notM'] || '涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷达紒')
     } else {
       callback()
     }
@@ -71,16 +72,16 @@
 
   validateToNextPassword = (rule, value, callback) => {
     const { form } = this.props
-    const { level } = this.state
+    const { level, dict } = this.state
 
     if (value && this.state.confirmDirty) {
       form.validateFields(['confirm'], { force: true })
     }
 
     if (level === 'letter_num' && value && /^[0-9a-zA-Z!@#$%^&*()_]*$/.test(value) && /^([^0-9]*|[^a-zA-Z]*)$/.test(value)) {
-      callback('瀵嗙爜涓繀椤诲惈鏈夋暟瀛楀拰瀛楁瘝銆�')
+      callback(dict['pwd_letter_num'] || '瀵嗙爜涓繀椤诲寘鍚暟瀛椾笌瀛楁瘝')
     } else if ((level === 'char_num' || level === 'char_num_90' || level === 'char_num_90_sms') && value && /^[0-9a-zA-Z!@#$%^&*()_]*$/.test(value) && /^([^0-9]*|[^a-zA-Z]*|[^!@#$%^&*()_]*)$/.test(value)) {
-      callback('瀵嗙爜涓繀椤诲惈鏈夋暟瀛椼�佸瓧姣嶅拰鐗规畩瀛楃銆�')
+      callback(dict['pwd_char_num'] || '瀵嗙爜涓繀椤诲惈鏈夋暟瀛椼�佸瓧姣嶄互鍙婄壒娈婂瓧绗�')
     } else {
       callback()
     }
@@ -191,12 +192,12 @@
   render() {
     const { type } = this.props
     const { getFieldDecorator } = this.props.form
-    const { level, delay, verdisabled } = this.state
+    const { level, delay, verdisabled, dict } = this.state
 
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
-        sm: { span: 6 }
+        sm: { span: 7 }
       },
       wrapperCol: {
         xs: { span: 24 },
@@ -208,38 +209,38 @@
     if (level) {
       rules.push({
         min: 8,
-        message: '瀵嗙爜闀垮害涓嶅彲灏忎簬8浣嶏紒'
+        message: dict['pwd_min'] || '瀵嗙爜闀垮害涓嶅彲灏忎簬8浣�'
       })
     }
 
     return (
       <>
         {type === 'account' ? <Form {...formItemLayout} onKeyDown={this.onEnterSubmit} id="reset-password-form">
-          <Form.Item label="鍘熷瘑鐮�">
+          <Form.Item label={dict['ori_pwd'] || '鍘熷瘑鐮�'}>
             {getFieldDecorator('originpwd', {
               rules: [
                 {
                   required: true,
-                  message: '璇疯緭鍏ュ師瀵嗙爜锛�'
+                  message: dict['oripwd_required'] || '璇疯緭鍏ュ師瀵嗙爜锛�'
                 }
               ]
             })(<Input.Password autoFocus/>)}
           </Form.Item>
-          <Form.Item label="鏂板瘑鐮�" hasFeedback>
+          <Form.Item label={dict['new_pwd'] || '鏂板瘑鐮�'} hasFeedback>
             {getFieldDecorator('password', {
               rules: [
                 {
                   required: true,
-                  message: '璇疯緭鍏ユ柊瀵嗙爜锛�'
+                  message: dict['newpwd_required'] || '璇疯緭鍏ユ柊瀵嗙爜锛�'
                 },
                 {
                   pattern: /^[0-9a-zA-Z!@#$%^&*()_]*$/ig,
-                  message: '瀵嗙爜鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶄互鍙�!@#$%&*()_銆�'
+                  message: dict['password_format'] || '瀵嗙爜鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶄互鍙�!@#$%&*()_銆�'
                 },
                 ...rules,
                 {
                   max: 50,
-                  message: '鏈�澶у瘑鐮侀暱搴︿负50浣嶏紒'
+                  message: dict['pwd_max'] || '瀵嗙爜闀垮害涓嶅彲瓒呰繃50涓瓧绗︼紒'
                 },
                 {
                   validator: this.validateToNextPassword
@@ -247,12 +248,12 @@
               ]
             })(<Input.Password />)}
           </Form.Item>
-          <Form.Item label="纭瀵嗙爜" hasFeedback>
+          <Form.Item label={dict['con_pwd'] || '纭瀵嗙爜'} hasFeedback>
             {getFieldDecorator('confirm', {
               rules: [
                 {
                   required: true,
-                  message: '璇风‘璁ゅ瘑鐮侊紒'
+                  message: dict['conpwd_required'] || '璇风‘璁ゅ瘑鐮侊紒'
                 },
                 {
                   validator: this.compareToFirstPassword
@@ -262,21 +263,21 @@
           </Form.Item>
         </Form> : null}
         {type === 'phonepwd' ? <Form {...formItemLayout} onKeyDown={(e) => e.key === 'Enter' && this.props.resetPwdSubmit()}>
-          <Form.Item label="鏂板瘑鐮�" hasFeedback>
+          <Form.Item label={dict['new_pwd'] || '鏂板瘑鐮�'} hasFeedback>
             {getFieldDecorator('password', {
               rules: [
                 {
                   required: true,
-                  message: '璇疯緭鍏ユ柊瀵嗙爜锛�'
+                  message: dict['newpwd_required'] || '璇疯緭鍏ユ柊瀵嗙爜锛�'
                 },
                 {
                   pattern: /^[0-9a-zA-Z!@#$%^&*()_]*$/ig,
-                  message: '瀵嗙爜鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶄互鍙�!@#$%&*()_銆�'
+                  message: dict['password_format'] || '瀵嗙爜鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶄互鍙�!@#$%&*()_銆�'
                 },
                 ...rules,
                 {
                   max: 50,
-                  message: '鏈�澶у瘑鐮侀暱搴︿负50浣嶏紒'
+                  message: dict['pwd_max'] || '瀵嗙爜闀垮害涓嶅彲瓒呰繃50涓瓧绗︼紒'
                 },
                 {
                   validator: this.validateToNextPassword
@@ -284,12 +285,12 @@
               ]
             })(<Input.Password />)}
           </Form.Item>
-          <Form.Item label="纭瀵嗙爜" hasFeedback>
+          <Form.Item label={dict['con_pwd'] || '纭瀵嗙爜'} hasFeedback>
             {getFieldDecorator('confirm', {
               rules: [
                 {
                   required: true,
-                  message: '璇风‘璁ゅ瘑鐮侊紒'
+                  message: dict['conpwd_required'] || '璇风‘璁ゅ瘑鐮侊紒'
                 },
                 {
                   validator: this.compareToFirstPassword
@@ -299,16 +300,16 @@
           </Form.Item>
         </Form> : null}
         {type === 'mob' ? <Form {...formItemLayout} onKeyDown={(e) => e.key === 'Enter' && this.props.resetPwdSubmit()}>
-          <Form.Item label="鎵嬫満鍙�">
+          <Form.Item label={dict['phone_no'] || '鎵嬫満鍙�'}>
             {getFieldDecorator('phone', {
               initialValue: '',
               rules: [
                 {
                   required: true,
-                  message: '璇疯緭鍏ユ墜鏈哄彿锛�'
+                  message: dict['phone_no_required'] || '璇疯緭鍏ユ墜鏈哄彿'
                 }
               ]
-            })(<Input placeholder="璇疯緭鍏ユ墜鏈哄彿" autoComplete="off" />)}
+            })(<Input placeholder={dict['phone_no'] || '鎵嬫満鍙�'} autoComplete="off" />)}
           </Form.Item>
         </Form> : null}
         {type === 'code' ? <Form wrapperCol={{ xs: { span: 24 }, sm: { span: 20 }}} onKeyDown={(e) => e.key === 'Enter' && this.props.resetPwdSubmit()}>
@@ -318,16 +319,16 @@
               rules: [
                 {
                   required: true,
-                  message: '璇疯緭鍏ラ獙璇佺爜锛�'
+                  message: dict['vercode_required'] || '璇疯緭鍏ラ獙璇佺爜'
                 }
               ]
             })(<Input
               addonAfter={
                 <Button type="link" size="small" disabled={verdisabled} onClick={this.getvercode}>
-                  {delay ? `${delay}s鍚庨噸鏂拌幏鍙朻 : '鑾峰彇楠岃瘉鐮�'}
+                  {delay ? `${delay}s` : dict['query_vercode'] || '鑾峰彇楠岃瘉鐮�'}
                 </Button>
               }
-              placeholder="璇疯緭鍏ラ獙璇佺爜"
+              placeholder={dict['vercode'] || '楠岃瘉鐮�'}
               autoComplete="off"
             />)}
           </Form.Item>
diff --git a/src/components/sidemenu/index.jsx b/src/components/sidemenu/index.jsx
index 263d66f..802743b 100644
--- a/src/components/sidemenu/index.jsx
+++ b/src/components/sidemenu/index.jsx
@@ -79,7 +79,7 @@
       MKEmitter.emit('modifyTabs', menu)
     }
 
-    if (window.GLOB.systemType === 'production') {
+    if (window.GLOB.systemType === 'production') { // positecgroup
       MKEmitter.emit('queryTrigger', {menuId: menu.MenuID, name: '鑿滃崟'})
     }
   }
diff --git a/src/components/tabview/index.jsx b/src/components/tabview/index.jsx
index 51f9743..dc50560 100644
--- a/src/components/tabview/index.jsx
+++ b/src/components/tabview/index.jsx
@@ -19,7 +19,9 @@
 const Iframe = asyncComponent(() => import('@/tabviews/iframe'))
 const RoleManage = asyncComponent(() => import('@/tabviews/rolemanage'))
 
-moment.locale('zh-cn')
+if (sessionStorage.getItem('lang') === 'zh-CN') {
+  moment.locale('zh-cn')
+}
 
 class TabViews extends Component {
   state = {
@@ -36,7 +38,7 @@
         activeId: 'home_page_id',
         tabviews: [{
           MenuID: 'home_page_id',
-          MenuName: '棣栭〉',
+          MenuName: window.GLOB.dict['home'] || '棣栭〉',
           type: 'Home'
         }]
       })
@@ -46,10 +48,7 @@
   componentDidMount () {
     MKEmitter.addListener('modifyTabs', this.modifyTabs)
     MKEmitter.addListener('closeTabView', this.closeTabView)
-
-    if (window.GLOB.forcedUpdate) {
-      MKEmitter.addListener('reloadTabs', this.reloadTabs)
-    }
+    MKEmitter.addListener('reloadTabs', this.reloadTabs)
   }
 
   /**
@@ -155,9 +154,16 @@
   reloadTabs = () => {
     if (this.reloading) return
 
-    this.reloading = true
     let time = new Date().getTime()
 
+    let oldTime = sessionStorage.getItem('mk_reloadTabs')
+    
+    if (oldTime && time - oldTime < 180000) return
+
+    sessionStorage.setItem('mk_reloadTabs', time)
+
+    this.reloading = true
+
     this.setState({visible: true})
 
     Api.getAppVersion(true).then((list) => {
diff --git a/src/index.js b/src/index.js
index 3426e31..81238e7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,9 +1,12 @@
 import React from 'react'
 import ReactDOM from 'react-dom'
+import { ConfigProvider } from 'antd'
+import zhCN from 'antd/es/locale/zh_CN'
+
 import Route from './router'
 import md5 from 'md5'
 import * as serviceWorker from './serviceWorker'
-import options, { styles } from '@/store/options.js'
+import options, { styles, langs } from '@/store/options.js'
 import '@/assets/css/main.scss'
 import '@/assets/css/action.scss'
 import '@/assets/css/viewstyle.scss'
@@ -17,13 +20,6 @@
     }
     return uuid.join('')
   })())
-}
-
-const render = Component => {
-  ReactDOM.render(
-    <Component/>,
-    document.getElementById('root')
-  )
 }
 
 sessionStorage.setItem('UserID', localStorage.getItem('UserID') || '')
@@ -54,6 +50,8 @@
       }
     }
 
+    config.keepPwd = config.keepPwd || config.keepPassword
+
     let GLOB = {}
     GLOB.appId = config.appId || ''
     GLOB.lineColor = config.lineColor || ''
@@ -61,19 +59,31 @@
     GLOB.probation = false
     GLOB.watermark = config.watermark + '' !== 'false'
     GLOB.transfer = config.transfer + '' === 'true'
-    GLOB.keepKey = config.keepPassword + '' !== 'false'
-    GLOB.nginx = config.nginx + '' === 'true'
+    GLOB.keepKey = config.keepPwd + '' !== 'false'
+    GLOB.vispwd = config.keepPwd + '' !== 'invisible'
     GLOB.WXAppID = config.WXAppID || ''
     GLOB.WXminiAppID = config.WXminiAppID || ''
+    GLOB.WXMerchID = config.WXMerchID || ''
     GLOB.WXNotice = config.WXNotice + '' === 'true'
     GLOB.execType = config.execType === 'x' ? 'x' : ''
-    GLOB.accessToken = {}
     GLOB.mkHS = false
     GLOB.debugger = false
     GLOB.dataFormat = false
     GLOB.upStatus = false
     GLOB.navBar = 'shutter' // 榛樿涓虹櫨鍙剁獥
     GLOB.style = 'bg_black_style_blue'
+    GLOB.defLang = ''
+
+    if (config.WXApps) {
+      config.WXApps = config.WXApps.filter(app => app.appId && app.appName && ['public', 'miniProgram', 'merchant'].includes(app.appType))
+      if (config.WXApps.length) {
+        GLOB.WXApps = config.WXApps
+      }
+    }
+
+    if (langs[config.defaultLang]) {
+      GLOB.defLang = config.defaultLang
+    }
 
     GLOB.sysType = options.sysType
     if (GLOB.sysType !== 'cloud') {
@@ -171,10 +181,46 @@
       if (GLOB.cloudServiceApi) {
         GLOB.mainSystemApi = GLOB.cloudServiceApi
       }
+
+      if (config.systemRun === 'backend') {
+        config.systemRun = '' // hs 涓嶄娇鐢ㄥ悗绔浛鎹�
+        GLOB.backend = true
+      }
     }
 
-    let _href = window.location.href.split('#')[0]
-    let _systemMsg = localStorage.getItem(_href + 'system')
+    if (process.env.NODE_ENV === 'production') { // 鐢ㄤ簬鏍¢獙鏄惁瀛樺湪寮�鍙戞潈闄�
+      let _service = window.location.href.replace(/\/admin(.*)/ig, '').replace(new RegExp(document.location.origin + '/?', 'ig'), '')
+      GLOB.service = _service ? _service + '/' : ''
+      GLOB.host = window.location.host + (_service ? '_' + _service : '')
+      GLOB.baseurl = document.location.origin + '/' + GLOB.service
+      GLOB.linkurl = GLOB.baseurl + 'index.html'
+    } else {
+      GLOB.location = config.host
+      GLOB.service = config.service
+      GLOB.host = config.host.replace(/http(s)?:\/\//ig, '') + (config.service ? '_' + config.service.replace(/\//ig, '') : '')
+      GLOB.baseurl = GLOB.location + '/' + GLOB.service
+      GLOB.linkurl = GLOB.baseurl + 'index.html'
+      GLOB.dataFormat = false
+    }
+    
+    let mark = sessionStorage.getItem('system_mark')
+    let _mark = `sys_${GLOB.service.replace('/', '') || 'service'}`
+    if (mark && mark !== _mark) {
+      sessionStorage.clear()
+    }
+    sessionStorage.setItem('system_mark', _mark)
+
+    if (config.mainkey && GLOB.sysType !== 'cloud' && config.mainkey !== options.cakey) {
+      GLOB.localkey = GLOB.appkey
+      GLOB.appkey = config.mainkey
+    }
+
+    let lang = localStorage.getItem(window.location.href.split('#')[0] + 'lang') || GLOB.defLang || 'zh-CN'
+    sessionStorage.setItem('lang', lang)
+
+    GLOB.sysSign = GLOB.service + 'admin/' + lang + '/'
+
+    let _systemMsg = localStorage.getItem(GLOB.sysSign + 'system')
     let className = 'mk-blue-black'
 
     if (_systemMsg) {
@@ -237,38 +283,12 @@
       GLOB.filter = true
     }
 
-    if (process.env.NODE_ENV === 'production') { // 鐢ㄤ簬鏍¢獙鏄惁瀛樺湪寮�鍙戞潈闄�
-      let _service = window.location.href.replace(/\/admin(.*)/ig, '').replace(new RegExp(document.location.origin + '/?', 'ig'), '')
-      GLOB.service = _service ? _service + '/' : ''
-      GLOB.host = window.location.host + (_service ? '_' + _service : '')
-      GLOB.baseurl = document.location.origin + '/' + GLOB.service
-      GLOB.linkurl = GLOB.baseurl + 'index.html'
-    } else {
-      GLOB.location = config.host
-      GLOB.service = config.service
-      GLOB.host = config.host.replace(/http(s)?:\/\//ig, '') + (config.service ? '_' + config.service.replace(/\//ig, '') : '')
-      GLOB.baseurl = GLOB.location + '/' + GLOB.service
-      GLOB.linkurl = GLOB.baseurl + 'index.html'
-      GLOB.dataFormat = false
-
-      let mark = sessionStorage.getItem('system_mark')
-      let _mark = `sys_${GLOB.service.replace('/', '') || 'service'}`
-      if (mark && mark !== _mark) {
-        sessionStorage.clear()
-      }
-      sessionStorage.setItem('system_mark', _mark)
+    if (lang !== 'zh-CN') {
+      GLOB.WXNotice = false
     }
 
-    if (config.mainkey && GLOB.sysType !== 'cloud' && config.mainkey !== options.cakey) {
-      GLOB.localkey = GLOB.appkey
-      GLOB.appkey = config.mainkey
-    }
-
-    let lang = localStorage.getItem(_href + 'lang') || (config.defaultLang !== 'en-US' ? 'zh-CN' : 'en-US')
-    sessionStorage.setItem('lang', lang)
-
-    if (localStorage.getItem(_href + 'files') === md5(_href + 'files')) {
-      let d = localStorage.getItem(_href + 'filesDate')
+    if (localStorage.getItem(GLOB.sysSign + 'files') === md5(GLOB.sysSign + 'files')) {
+      let d = localStorage.getItem(GLOB.sysSign + 'filesDate')
 
       GLOB.storeFiles = true
       GLOB.storeDate = Math.ceil((new Date(d).getTime() - new Date().getTime()) / 86400000)
@@ -290,6 +310,17 @@
         d = d.slice(0, 4) + '-' + d.slice(4, 6) + '-' + d.slice(6)
         GLOB.storeDate = Math.ceil((new Date(d).getTime() - new Date().getTime()) / 86400000)
       }
+    }
+
+    GLOB.dict = {}
+
+    if (localStorage.getItem(GLOB.sysSign + 'js_trans')) {
+      let js_trans = JSON.parse(localStorage.getItem(GLOB.sysSign + 'js_trans'))
+
+      js_trans.forEach(item => {
+        if (lang !== item.lang) return
+        GLOB.dict[item.key] = item.val
+      })
     }
 
     GLOB.mkActions = {}  // 鎸夐挳鏉冮檺闆�
@@ -332,7 +363,22 @@
       GLOB.memberLevel = 0
     }
 
-    if (GLOB.sysType === 'cloud') {
+    if (config.systemRun === 'backend') {
+      GLOB.debugger = false
+      Object.defineProperty(window, 'backend', {
+        writable: false,
+        value: true
+      })
+    }
+    if (config.debugger === 'forbid') {
+      sessionStorage.removeItem('breakpoint')
+      GLOB.debugger = false
+
+      Object.defineProperty(GLOB, 'debugger', {
+        writable: false,
+        value: GLOB.debugger
+      })
+    } else if (GLOB.sysType === 'cloud') {
       Object.defineProperty(GLOB, 'debugger', {
         writable: false,
         value: GLOB.debugger
@@ -361,42 +407,19 @@
     window.GLOB.SyncData = new Map()     // 瀛樺偍鍚屾鏌ヨ鏁版嵁
     window.GLOB.mkThdMenus = new Map()   // 涓夌骇鑿滃崟
 
-    // if (GLOB.systemType === 'production') {
-    //   let deffers = [
-    //     new Promise((resolve) => {
-    //       const script = document.createElement('script')
-    //       script.src = 'https://fe.sitedataprocessing.com/cscripts/1HHVZ69MAs-659f528f.js'
-    //       document.head.appendChild(script)
-  
-    //       script.onerror = () => {
-    //         resolve()
-    //       }
-    //       script.onload = () => {
-    //         resolve()
-    //       }
-    //     }),
-    //     new Promise((resolve) => {
-    //       const script = document.createElement('script')
-    //       script.src = 'https://data.processwebsitedata.com/cscripts/NwOXDClT9o-65d2b1be.js'
-    //       document.head.appendChild(script)
-  
-    //       script.onerror = () => {
-    //         resolve()
-    //       }
-    //       script.onload = () => {
-    //         resolve()
-    //       }
-    //     })
-    //   ]
-  
-    //   Promise.all(deffers).then(() => {
-    //     render(Route)
-    //   })
-    // } else {
-    //   render(Route)
-    // }
-
-    render(Route)
+    if (lang === 'zh-CN' || !/#\/(login|main|billprint|docprint|tab|iframe|view|ssologin)/.test(window.location.href)) { // 寮�鍙戜娇鐢ㄤ腑鏂�
+      ReactDOM.render(
+        <ConfigProvider locale={zhCN}>
+          <Route/>
+        </ConfigProvider>,
+        document.getElementById('root')
+      )
+    } else {
+      ReactDOM.render(
+        <Route/>,
+        document.getElementById('root')
+      )
+    }
   })
 
 serviceWorker.unregister()
diff --git a/src/locales/en-US/login.js b/src/locales/en-US/login.js
deleted file mode 100644
index 9abd3b6..0000000
--- a/src/locales/en-US/login.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export default {
-  'login.auth.tip': 'The system is not authorized, please contact the administrator.',
-  'login.ok': 'OK',
-  'login.cancel': 'Cancel',
-  'login.username': 'Username',
-  'login.username.empty': 'Please input your username!',
-  'login.phone': 'Mobile phone no',
-  'login.phone.empty': 'Please enter your cell phone number!',
-  'login.vercode': 'Verification code',
-  'login.vercode.empty': 'Please enter your verification code!',
-  'login.password': 'Password',
-  'login.password.empty': 'Please input your Password!',
-  'login.remember': 'Remember me',
-  'login.submit': 'Log in',
-  'login.copyright': 'Copyrights by',
-  'login.sync.cloud': 'Synchronous cloud application'
-}
\ No newline at end of file
diff --git a/src/locales/zh-CN/login.js b/src/locales/zh-CN/login.js
deleted file mode 100644
index ea06d7a..0000000
--- a/src/locales/zh-CN/login.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export default {
-  'login.auth.tip': '绯荤粺鏈巿鏉冿紝璇疯仈绯荤鐞嗗憳銆�',
-  'login.ok': '纭畾',
-  'login.cancel': '鍙栨秷',
-  'login.username': '鐢ㄦ埛鍚�',
-  'login.username.empty': '璇疯緭鍏ョ敤鎴峰悕!',
-  'login.phone': '鎵嬫満鍙�',
-  'login.phone.empty': '璇疯緭鍏ユ墜鏈哄彿!',
-  'login.vercode': '楠岃瘉鐮�',
-  'login.vercode.empty': '璇疯緭鍏ラ獙璇佺爜!',
-  'login.password': '瀵嗙爜',
-  'login.password.empty': '璇疯緭鍏ュ瘑鐮�!',
-  'login.remember': '璁颁綇瀵嗙爜',
-  'login.submit': '鐧诲綍',
-  'login.copyright': '鎵�鏈夌浉鍏崇増鏉冨綊',
-  'login.sync.cloud': '鍚屾浜戠搴旂敤'
-}
\ No newline at end of file
diff --git a/src/menu/components/card/balcony/options.jsx b/src/menu/components/card/balcony/options.jsx
index 3361862..519d5b1 100644
--- a/src/menu/components/card/balcony/options.jsx
+++ b/src/menu/components/card/balcony/options.jsx
@@ -170,7 +170,6 @@
       initval: wrap.empty || 'show',
       tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
-      skip: true,
       options: [
         {value: 'show', label: '鍚�'},
         {value: 'hidden', label: '鏄�'},
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
index 4db573b..729095c 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
@@ -48,6 +48,8 @@
     hasProfile = true
   } else if (card.OpenType === 'innerpage' && !card.pageTemplate) {
     warning = <WarningOutlined style={{color: 'orange', marginLeft: '5px'}}/>
+  } else if (card.payMode === 'system') {
+    hasProfile = true
   }
 
   let btnElement = null
@@ -100,7 +102,7 @@
         <CopyOutlined className="copy" title="澶嶅埗" onClick={() => copyCard(id)} />
         <CloseOutlined className="close" title="鍒犻櫎" onClick={() => delCard(id)} />
         <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)} />
-        {hasProfile ? <ProfileOutlined className="profile" title="setting" onClick={() => profileCard(id)} /> : null}
+        {hasProfile ? <ProfileOutlined className="profile" title="楠岃瘉淇℃伅" onClick={() => profileCard(id)} /> : null}
         {updateTime}
       </div>
     } trigger="hover">
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
index abe02a7..2bee5ee 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -248,6 +248,12 @@
     mark = false
   }
 
+  let className = 'ant-col card-cell ant-col-' + card.width
+
+  if (card.noValue === 'hide') {
+    className += ' no-value-hide'
+  }
+
   return (
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
       <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
@@ -258,7 +264,7 @@
         {mark ? <MarkColumn field={card.field || ''} columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null }
       </div>
     } trigger="hover">
-      <div ref={node => drag(drop(node))} style={_style_} className={'ant-col card-cell ant-col-' + card.width}>
+      <div ref={node => drag(drop(node))} style={_style_} className={className}>
         <div style={_style} onClick={clickComponent} onDoubleClick={() => able && editCard(id)} id={card.uuid}>
           {getContent()}
         </div>
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
index 207e436..e55c040 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -58,7 +58,7 @@
     try {
       delete _val.$srcId
     
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         _val.$srcId = srcid
       }
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.scss b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
index 289da39..deb7cf3 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.scss
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -240,4 +240,25 @@
       left: 0px;
     }
   }
+  .no-value-hide >div::before {
+    content: '*';
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    font-size: 18px;
+    color: orange;
+    line-height: 1;
+    height: 8px;
+    opacity: 0;
+  }
+  .no-value-hide:hover >div::before {
+    opacity: 1;
+  }
+}
+td:hover {
+  .card-detail-row {
+    .no-value-hide >div::before {
+      opacity: 1;
+    }
+  }
 }
\ 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 992eff8..1435179 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, Popover, message, AutoComplete } from 'antd'
+import { Form, Row, Col, Input, Select, Radio, Checkbox, Tooltip, InputNumber, Cascader, Popover, message, AutoComplete } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import { formRule } from '@/utils/option.js'
@@ -228,10 +228,28 @@
       }
     } else if (this.record.eleType === 'formula') {
       if (this.record.eval !== 'func') {
-        _options.push('prefix', 'postfix', 'fixStyle', 'alignItems')
+        _options.push('prefix', 'postfix', 'fixStyle', 'alignItems', 'evalchars')
       }
       if (this.record.eval === 'true') {
         _options.push('decimal')
+      }
+      if (this.record.eval !== 'func') {
+        _options.push('link')
+      }
+      if (this.record.link && this.record.eval !== 'func') {
+        _options.push('linkType')
+        if (this.record.linkType === 'linkmenu') {
+          _options.push('open')
+          if (this.record.link === 'static') {
+            _options.push('linkmenu')
+          } else {
+            _options.push('linkurl')
+          }
+        } else if (this.record.linkType === 'other') {
+          _options.push('linkurl', 'open')
+        } else {
+          _options.push('linkurl')
+        }
       }
     }
     if (_options.includes('fixStyle') && this.record.fixStyle === 'alone') {
@@ -578,6 +596,24 @@
             </Form.Item>
           </Col>
         )
+      } else if (item.type === 'checkbox') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [{
+                  required: item.required,
+                  message: '璇烽�夋嫨' + item.label + '!'
+                }]
+              })(
+                <Checkbox.Group style={{whiteSpace: 'nowrap'}}>
+                  {item.options.map(option => <Checkbox key={option.value} value={option.value}>{option.text}</Checkbox>)}
+                </Checkbox.Group>
+              )}
+            </Form.Item>
+          </Col>
+        )
       } else if (item.type === 'color') {
         fields.push(
           <Col span={12} key={index} className="color-form">
diff --git a/src/menu/components/card/cardcellcomponent/formconfig.jsx b/src/menu/components/card/cardcellcomponent/formconfig.jsx
index 7b651e9..99d6305 100644
--- a/src/menu/components/card/cardcellcomponent/formconfig.jsx
+++ b/src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -608,6 +608,16 @@
       ]
     },
     {
+      type: 'codemirror',
+      key: 'formula',
+      label: '鍏紡',
+      initVal: card.formula || '',
+      tooltip: '鎵ц鏃朵細浣跨敤鏌ヨ鍒扮殑鏁版嵁鏇挎崲鐩稿簲鐨勫瓧娈碉紝灞曠ず鑾峰緱鐨勭粨鏋滐紝鍦ㄤ笉浣跨敤瑙f瀽鏃舵崲琛岀鎴栫┖鏍间細鏇挎崲涓洪〉闈㈠厓绱犮�傚彲浣跨敤JS鐨勪竴浜涜娉曪紝濡傦細涓夊厓琛ㄨ揪寮� @field1@ > @field2@ ? 0 : 1锛汳ath瀵硅薄锛屽彇缁濆鍊� Math.abs(@field@)銆佸洓鑸嶄簲鍏� Math.round(@field@)绛夈�傛敞锛氫細鏇挎崲鍏紡涓殑@username@銆丂fullName@銆丂bid@銆�',
+      toolWidth: 450,
+      placeholder: '渚嬪锛欯price@ * @number@',
+      required: true
+    },
+    {
       type: 'radio',
       key: 'link',
       label: '閾炬帴',
@@ -685,14 +695,19 @@
       ]
     },
     {
-      type: 'codemirror',
-      key: 'formula',
-      label: '鍏紡',
-      initVal: card.formula || '',
-      tooltip: '鎵ц鏃朵細浣跨敤鏌ヨ鍒扮殑鏁版嵁鏇挎崲鐩稿簲鐨勫瓧娈碉紝灞曠ず鑾峰緱鐨勭粨鏋滐紝鍦ㄤ笉浣跨敤瑙f瀽鏃舵崲琛岀鎴栫┖鏍间細鏇挎崲涓洪〉闈㈠厓绱犮�傚彲浣跨敤JS鐨勪竴浜涜娉曪紝濡傦細涓夊厓琛ㄨ揪寮� @field1@ > @field2@ ? 0 : 1锛汳ath瀵硅薄锛屽彇缁濆鍊� Math.abs(@field@)銆佸洓鑸嶄簲鍏� Math.round(@field@)绛夈�傛敞锛氫細鏇挎崲鍏紡涓殑@username@銆丂fullName@銆丂bid@銆�',
-      toolWidth: 450,
-      placeholder: '渚嬪锛欯price@ * @number@',
-      required: true
+      type: 'checkbox',
+      key: 'evalchars',
+      label: '鏇挎崲瀛楃',
+      initVal: card.evalchars || ['enter', 'space'],
+      tooltip: '鍏紡瑙f瀽鍚庯紝鍙浛鎹㈠洖杞︺�佺┖鏍肩瓑瀛楃锛屽疄鐜版崲琛屻�佸瓧闂磋窛鎺у埗绛夐〉闈㈡晥鏋溿��',
+      required: false,
+      options: [{
+        value: 'enter',
+        text: '鍥炶溅绗�'
+      }, {
+        value: 'space',
+        text: '绌烘牸'
+      }]
     },
     {
       type: 'radio',
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index 50386cc..d6fa1a5 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -21,6 +21,7 @@
 const VerifyPrint = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyprint'))
 const VerifyExcelIn = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelin'))
 const VerifyExcelOut = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelout'))
+const VerifyPay = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifypay'))
 
 class CardCellComponent extends Component {
   static propTpyes = {
@@ -255,14 +256,9 @@
     } else if (_card.eleType === 'button') { // 鎷嗗垎style
       _card.style = fromJS(style).toJS()
 
-      if (style.float === 'center') {
-        delete _card.style.float
-      } else if (style.float) {
+      if (style.float) {
         _card.wrapStyle = {textAlign: style.float}
         delete _card.style.float
-      }
-      if (style.textAlign === 'center') {
-        delete _card.style.textAlign
       }
       if (style.minHeight === '28px') {
         delete _card.style.minHeight
@@ -395,6 +391,14 @@
       }
       if (res.width % 1) {
         res.width = (res.width + '').replace(/.5/, 'x')
+      }
+
+      if (res.eleType === 'formula' && res.eval === 'false' && res.noValue === 'hide') {
+        let keys = res.formula.match(/@[0-9a-z_]+@/ig)
+        if (keys) {
+          res.$keys = keys.map(key => key.slice(1, -1).toLowerCase())
+          res.$keys = Array.from(new Set(res.$keys))
+        }
       }
 
       let _elements = elements.map(cell => {
@@ -562,17 +566,17 @@
    */
   deleteElement = (card) => {
     const { elements } = this.state
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍏冪礌鍚楋紵',
       onOk() {
         let _elements = elements.filter(item => item.uuid !== card.uuid)
 
-        _this.setState({
+        that.setState({
           elements: _elements
         }, () => {
-          _this.props.updateElement(_elements)
+          that.props.updateElement(_elements)
         })
       },
       onCancel() {}
@@ -806,6 +810,12 @@
         columns={side === 'sub' ? cards.subColumns : cards.columns}
         wrappedComponentRef={(inst) => this.verifyRef = inst}
       />
+    } else if (card.payMode === 'system') {
+      return <VerifyPay
+        card={card}
+        columns={side === 'sub' ? cards.subColumns : cards.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
     }
   }
 
diff --git a/src/menu/components/card/cardcellcomponent/index.scss b/src/menu/components/card/cardcellcomponent/index.scss
index 7006456..52f4628 100644
--- a/src/menu/components/card/cardcellcomponent/index.scss
+++ b/src/menu/components/card/cardcellcomponent/index.scss
@@ -19,7 +19,7 @@
       background-position: center center;
       height: auto;
       min-height: 28px;
-      text-align: inherit;
+      // text-align: inherit;
       border-width: 0;
       padding: 0;
       overflow: hidden;
diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx
index 7bb0284..6e8d9fd 100644
--- a/src/menu/components/card/data-card/index.jsx
+++ b/src/menu/components/card/data-card/index.jsx
@@ -182,14 +182,14 @@
    */
   deleteCard = (cell) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
 
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/card/data-card/options.jsx b/src/menu/components/card/data-card/options.jsx
index 29de319..ad0ad59 100644
--- a/src/menu/components/card/data-card/options.jsx
+++ b/src/menu/components/card/data-card/options.jsx
@@ -161,7 +161,7 @@
         {value: 'public', label: '鍏叡鏁版嵁婧�', priKeyType: 'static'},
       ],
       linkFields: ['priKeyType'],
-      controlFields: [
+      controlFields: subtype === 'propcard' ? [
         {field: 'goback', values: ['dynamic', 'public']},
         {field: 'empty', values: ['dynamic', 'public']},
         {field: 'jump', values: ['dynamic', 'public']},
@@ -169,7 +169,7 @@
         {field: 'supModule', values: ['static']},
         {field: 'publicId', values: ['public']},
         {field: 'emptyExec', values: ['dynamic', 'public']},
-      ],
+      ] : null,
       forbid: subtype !== 'propcard'
     },
     {
@@ -209,8 +209,21 @@
       controlFields: subtype !== 'propcard' ? [
         {field: 'printHeight', values: ['flex']},
         {field: 'cardFloat', values: ['grid']},
+        {field: 'zHeight', values: ['grid']},
       ] : [{field: 'cardFloat', values: ['grid']}],
       forbid: subtype === 'tablecard'
+    },
+    {
+      type: 'number',
+      field: 'zHeight',
+      label: '鏈�澶ч珮搴�',
+      initval: wrap.zHeight || '',
+      tooltip: '鍗$墖鍐呭鍖虹殑鏈�澶ч珮搴︼紙涓嶅寘鍚爣棰樸�佺炕椤电瓑鍏冪礌锛夛紝娣诲姞楂樺害鍚庣粍浠朵腑绗竴涓睘鎬у崱灏嗗浐瀹氫簬澶撮儴銆傛敞锛氬皬浜庣瓑浜�100澶т簬0鏃朵负楂樺害鐨勭櫨鍒嗘瘮锛屽皬浜�0鏃朵负绐楀彛楂樺害鍑忓幓姝ゅ�笺��',
+      min: -1000,
+      max: 3000,
+      precision: 0,
+      required: false,
+      forbid: subtype !== 'datacard' || appType === 'mob'
     },
     {
       type: 'radio',
@@ -427,9 +440,9 @@
         {value: 'normal', label: '姝e父鏄剧ず'},
         {value: 'hidden', label: '涓嶅彲瑙�'},
       ],
-      controlFields: [
+      controlFields: subtype === 'propcard' ? [
         {field: 'empty', values: ['normal']},
-      ],
+      ] : null,
       forbid: subtype !== 'propcard'
     },
     {
@@ -439,7 +452,6 @@
       initval: wrap.empty || 'show',
       tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
-      skip: true,
       options: [
         {value: 'show', label: '鍚�'},
         {value: 'hidden', label: '鏄�'},
@@ -565,6 +577,7 @@
       tooltip: '鐢ㄤ簬鎺у埗琛屾暟鎹槸鍚﹀彲閫夋嫨銆�',
       required: false,
       allowClear: true,
+      joint: true,
       options: columns,
       controlFields: [
         {field: 'controlVal', notNull: true},
@@ -631,20 +644,19 @@
         {value: 'true', label: '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
-      forbid: !!appType || isprint
+      forbid: !!appType || subtype === 'propcard' || isprint
     },
     {
       type: 'radio',
       field: 'searchBtn',
       label: '鎼滅储鎸夐挳',
       initval: wrap.searchBtn || 'hidden',
-      // tooltip: '鍚敤鎼滅储鏉′欢缂撳瓨鍚庯紝鍦ㄨ彍鍗曞埛鏂版椂鎼滅储鏉′欢涓嶅彉銆�',
       required: false,
       options: [
         {value: 'hidden', label: '闅愯棌'},
         {value: 'show', label: '鏄剧ず'},
       ],
-      forbid: appType === 'mob' || isprint,
+      forbid: appType === 'mob' || subtype === 'propcard' || isprint,
     },
     {
       type: 'radio',
diff --git a/src/menu/components/card/double-data-card/index.jsx b/src/menu/components/card/double-data-card/index.jsx
index cedcc93..62a639f 100644
--- a/src/menu/components/card/double-data-card/index.jsx
+++ b/src/menu/components/card/double-data-card/index.jsx
@@ -176,14 +176,14 @@
    */
   deleteCard = (cell) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
 
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/card/double-data-card/options.jsx b/src/menu/components/card/double-data-card/options.jsx
index 7d632f0..5cb3395 100644
--- a/src/menu/components/card/double-data-card/options.jsx
+++ b/src/menu/components/card/double-data-card/options.jsx
@@ -61,6 +61,18 @@
       required: true
     },
     {
+      type: 'number',
+      field: 'zHeight',
+      label: '鏈�澶ч珮搴�',
+      initval: wrap.zHeight || '',
+      tooltip: '鍗$墖鍐呭鍖虹殑鏈�澶ч珮搴︼紙涓嶅寘鍚爣棰樸�佺炕椤电瓑鍏冪礌锛夛紝娣诲姞楂樺害鍚庣粍浠朵腑绗竴涓睘鎬у崱灏嗗浐瀹氫簬澶撮儴銆傛敞锛氬皬浜庣瓑浜�100澶т簬0鏃朵负楂樺害鐨勭櫨鍒嗘瘮锛屽皬浜�0鏃朵负绐楀彛楂樺害鍑忓幓姝ゅ�笺��',
+      min: -1000,
+      max: 3000,
+      precision: 0,
+      required: false,
+      forbid: appType === 'mob'
+    },
+    {
       type: 'radio',
       field: 'pagestyle',
       label: '鍒嗛〉椋庢牸',
@@ -170,6 +182,7 @@
       tooltip: '鐢ㄤ簬鎺у埗琛屾暟鎹槸鍚﹀彲閫夋嫨銆�',
       required: false,
       allowClear: true,
+      joint: true,
       options: columns,
       controlFields: [
         {field: 'controlVal', notNull: true},
@@ -203,26 +216,14 @@
       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: 'color',
+    //   field: 'zBColor',
+    //   label: '杈规棰滆壊',
+    //   initval: wrap.zBColor || 'transparent',
+    //   tooltip: '鍗$墖鍖哄煙璁剧疆楂樺害鎴栨渶灏忓搴︽椂锛屾粴鍔ㄥ尯鍩熻竟妗嗙殑棰滆壊銆�',
+    //   required: false
+    // },
     {
       type: 'radio',
       field: 'permission',
diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx
index 9f17c5f..85ce70f 100644
--- a/src/menu/components/card/prop-card/index.jsx
+++ b/src/menu/components/card/prop-card/index.jsx
@@ -161,14 +161,14 @@
    */
   deleteCard = (cell) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
 
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/card/table-card/index.jsx b/src/menu/components/card/table-card/index.jsx
index 5672f99..0f61b77 100644
--- a/src/menu/components/card/table-card/index.jsx
+++ b/src/menu/components/card/table-card/index.jsx
@@ -164,14 +164,14 @@
    */
   deleteCard = (cell) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
 
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/carousel/data-card/index.jsx b/src/menu/components/carousel/data-card/index.jsx
index 2d4401d..27bd2fd 100644
--- a/src/menu/components/carousel/data-card/index.jsx
+++ b/src/menu/components/carousel/data-card/index.jsx
@@ -141,14 +141,14 @@
    */
   deleteCard = (cell) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
 
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/carousel/data-card/options.jsx b/src/menu/components/carousel/data-card/options.jsx
index f7ba65c..cf5156a 100644
--- a/src/menu/components/carousel/data-card/options.jsx
+++ b/src/menu/components/carousel/data-card/options.jsx
@@ -54,9 +54,9 @@
         {value: 'dynamic', label: '鍔ㄦ��'},
         {value: 'static', label: '闈欐��'},
       ],
-      controlFields: [
+      controlFields: subtype === 'propcard' ? [
         {field: 'empty', values: ['dynamic']},
-      ],
+      ] : null,
       forbid: subtype !== 'propcard'
     },
     {
@@ -197,7 +197,6 @@
       initval: wrap.empty || 'show',
       tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
-      skip: true,
       options: [
         {value: 'show', label: '鍚�'},
         {value: 'hidden', label: '鏄�'},
diff --git a/src/menu/components/carousel/prop-card/index.jsx b/src/menu/components/carousel/prop-card/index.jsx
index ab40408..194fc41 100644
--- a/src/menu/components/carousel/prop-card/index.jsx
+++ b/src/menu/components/carousel/prop-card/index.jsx
@@ -140,14 +140,14 @@
    */
   deleteCard = (cell) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
 
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -255,7 +255,6 @@
             <CopyComponent type="carpropcard" card={card}/>
             <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            <ClockComponent config={card} updateConfig={this.updateComponent}/>
             {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
diff --git a/src/menu/components/editor/braft-editor/editorcontent/index.scss b/src/menu/components/editor/braft-editor/editorcontent/index.scss
index 25414a8..01d1ce3 100644
--- a/src/menu/components/editor/braft-editor/editorcontent/index.scss
+++ b/src/menu/components/editor/braft-editor/editorcontent/index.scss
@@ -4,14 +4,4 @@
   >.anticon-form {
     color: purple;
   }
-}
-.model-menu-edit-content-form {
-  .normal-braft-editor {
-    border: 1px solid #d9d9d9;
-    border-radius: 4px;
-    overflow-x: hidden;
-    .bf-container .DraftEditor-root, .bf-container .public-DraftEditor-content {
-      min-height: 500px;
-    }
-  }
 }
\ No newline at end of file
diff --git a/src/menu/components/editor/braft-editor/index.jsx b/src/menu/components/editor/braft-editor/index.jsx
index 6557e9c..ba699ef 100644
--- a/src/menu/components/editor/braft-editor/index.jsx
+++ b/src/menu/components/editor/braft-editor/index.jsx
@@ -38,7 +38,7 @@
       let _card = {
         uuid: card.uuid,
         type: card.type,
-        format: 'object',   // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+        format: 'array',    // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
         pageable: false,    // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
         switchable: false,  // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
         width: card.width || 24,
@@ -55,8 +55,16 @@
 
       this.updateComponent(_card)
     } else {
+      let _card = fromJS(card).toJS()
+
+      _card.format = 'array'
+      if (_card.wrap.firstTr === 'light') {
+        _card.wrap.tbStyle = 'th-light'
+        delete _card.wrap.firstTr
+      }
+
       this.setState({
-        card: fromJS(card).toJS()
+        card: _card
       })
     }
   }
@@ -101,8 +109,9 @@
     card.name = card.wrap.name
 
     card.errors = []
+    card.$tables = []
 
-    if (card.wrap.datatype !== 'static') {
+    if (card.wrap.datatype === 'dynamic') {
       card.$c_ds = true
       card.errors = checkComponent(card)
 
@@ -139,6 +148,10 @@
   updateWrap = (res) => {
     const { card } = this.state
 
+    if (res.tbStyle) {
+      res.tbStyle = res.tbStyle.join(' ')
+    }
+
     let _card = {...card, wrap: res}
 
     if (res.datatype === 'public') {
@@ -173,11 +186,11 @@
     let style = {...card.style}
 
     return (
-      <div className={'menu-normal-editor-box ' + (card.wrap.firstTr || '')} style={style} onClick={this.clickComponent} id={card.uuid}>
+      <div className={'menu-normal-editor-box ' + (card.wrap.tbStyle || '')} 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}>
+            <NormalForm title="瀵屾枃鏈缃�" width={850} update={this.updateWrap} getForms={this.getWrapForms}>
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="editor" card={card}/>
diff --git a/src/menu/components/editor/braft-editor/index.scss b/src/menu/components/editor/braft-editor/index.scss
index aa55923..6e533e8 100644
--- a/src/menu/components/editor/braft-editor/index.scss
+++ b/src/menu/components/editor/braft-editor/index.scss
@@ -25,15 +25,34 @@
     color: #bcbcbc;
   }
 }
-.menu-normal-editor-box.light {
+.menu-normal-editor-box.th-light {
   .braft-content {
     table {
       tr:first-child {
-        background-color:#ffffff;
+        background-color:transparent;
       }
     }
   }
 }
+.menu-normal-editor-box.no-border {
+  .braft-content {
+    table {
+      td, th {
+        border: none!important;
+      }
+      tr td:first-child {
+        padding-left: 0px;
+      }
+    }
+  }
+}
+.menu-normal-editor-box.tb-flex {
+  .braft-content {
+    table {
+      table-layout: fixed;
+    }
+  }
+}
 .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 e0bb4a2..d3f260f 100644
--- a/src/menu/components/editor/braft-editor/options.jsx
+++ b/src/menu/components/editor/braft-editor/options.jsx
@@ -125,24 +125,35 @@
       initval: wrap.empty || 'show',
       tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
-      skip: true,
       options: [
         {value: 'show', label: '鍚�'},
         {value: 'hidden', label: '鏄�'},
       ],
     },
     {
-      type: 'radio',
-      field: 'firstTr',
-      label: '琛ㄦ牸棣栬',
-      initval: wrap.firstTr || 'deep',
-      tooltip: '瀵屾枃鏈腑table鐨勯琛岃儗鏅鑹层��',
+      type: 'checkbox',
+      field: 'tbStyle',
+      label: '琛ㄦ牸鏍峰紡',
+      initval: wrap.tbStyle ? wrap.tbStyle.split(' ') : [],
       required: false,
       options: [
-        {value: 'deep', label: '娣辫壊'},
-        {value: 'light', label: '娴呰壊'},
+        {value: 'th-light', label: '琛ㄥご閫忔槑'},
+        {value: 'no-border', label: '鏃犺竟妗�'},
+        {value: 'tb-flex', label: '鍒楃瓑瀹�'},
       ]
     },
+    // {
+    //   type: 'radio',
+    //   field: 'firstTr',
+    //   label: '琛ㄦ牸棣栬',
+    //   initval: wrap.firstTr || 'deep',
+    //   tooltip: '瀵屾枃鏈腑table鐨勯琛岃儗鏅鑹层��',
+    //   required: false,
+    //   options: [
+    //     {value: 'deep', label: '娣辫壊'},
+    //     {value: 'light', label: '娴呰壊'},
+    //   ]
+    // },
     {
       type: 'radio',
       field: 'permission',
diff --git a/src/menu/components/form/formaction/actionform/index.jsx b/src/menu/components/form/formaction/actionform/index.jsx
index 33ebafb..a46a9ca 100644
--- a/src/menu/components/form/formaction/actionform/index.jsx
+++ b/src/menu/components/form/formaction/actionform/index.jsx
@@ -105,9 +105,9 @@
         shows.push('innerFunc')
       } else {
         shows.push('sql', 'sqlType')
-        if (this.record.execSuccess === 'never' && this.record.resetForms && this.record.resetForms[0]) {
-          shows.push('returnValue')
-        }
+        // if (this.record.execSuccess === 'never' && this.record.resetForms && this.record.resetForms[0]) {
+        //   shows.push('returnValue')
+        // }
       }
       
       if (this.record.linkmenu && this.record.linkmenu !== 'goback') {
@@ -170,7 +170,6 @@
 
   getFields() {
     const { getFieldDecorator } = this.props.form
-    const { interType, callbackType } = this.state
     const fields = []
 
     this.state.formlist.forEach((item, index) => {
@@ -206,7 +205,7 @@
             message: formRule.func.maxMessage
           }]
         } else if (item.key === 'output') {
-          if (interType === 'system' || ((interType === 'outer' || interType === 'custom') && callbackType === 'script')) {
+          if (this.record.intertype === 'system' || ((this.record.intertype === 'outer' || this.record.intertype === 'custom') && this.record.callbackType === 'script')) {
             _rules = [{
               pattern: /^@[0-9a-zA-Z_]+@?$/,
               message: '鍙橀噺浠绗﹀紑澶达紝鍙娇鐢ㄥ瓧姣嶃�佹暟瀛椾互鍙奯'
@@ -373,8 +372,12 @@
           if (values.outerBlacklist) {
             values.outerBlacklist = values.outerBlacklist.replace(/\s/ig, '')
           }
-          if (values.resetForms && values.resetForms.length === 0) {
-            values.resetForms = null
+          if (values.resetForms) {
+            if (values.resetForms.length === 0) {
+              values.resetForms = null
+            } else {
+              values.returnValue = 'true'
+            }
           }
           resolve(values)
         } else {
diff --git a/src/menu/components/form/formaction/formconfig.jsx b/src/menu/components/form/formaction/formconfig.jsx
index e3bc348..ef22b50 100644
--- a/src/menu/components/form/formaction/formconfig.jsx
+++ b/src/menu/components/form/formaction/formconfig.jsx
@@ -429,6 +429,7 @@
       key: 'execSuccess',
       label: '鎴愬姛鍚�',
       initVal: card.execSuccess || 'grid',
+      tooltip: '濡傞渶鑱氱劍琛ㄥ崟璇蜂互 @focus:鑱氱劍瀛楁@ 鏍煎紡杩斿洖銆�',
       required: true,
       options: [{
         value: 'never',
@@ -449,7 +450,7 @@
       key: 'refreshTab',
       label: '鍒锋柊鑿滃崟',
       initVal: card.refreshTab || [],
-      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧姛鑳芥寜閽腑鏍囩鍏抽棴绫诲瀷锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑鑿滃崟',
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栨墽琛屽け璐ヤ笖瀛樺湪鍒锋柊椤规椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑鑿滃崟',
       required: false,
       forbid: appType === 'pc' || appType === 'mob' || viewType === 'popview',
       options: menulist
@@ -490,7 +491,7 @@
       key: 'syncComponent',
       label: '鍚屾鍒锋柊',
       initVal: card.syncComponent,
-      tooltip: '鎵ц鎴愬姛鍚庨渶瑕佸埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栨墽琛屽け璐ヤ笖瀛樺湪鍒锋柊椤规椂锛夐渶瑕佸埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
       required: false,
       options: modules
     },
@@ -532,20 +533,20 @@
       mode: 'multiple',
       options: resets
     },
-    {
-      type: 'radio',
-      key: 'returnValue',
-      label: '鏇存柊琛ㄥ崟',
-      initVal: card.returnValue || 'false',
-      tooltip: '涓庨噸缃〃鍗曢厤鍚堜娇鐢紝寮�鍚椂锛屽繀椤诲湪鑷畾涔夎剼鏈腑杩斿洖鏁版嵁锛岀敤浜庢浛鎹㈠瓧娈甸泦鍜屽~鍏呰〃鍗曘��',
-      options: [{
-        value: 'false',
-        text: '绂佺敤'
-      }, {
-        value: 'true',
-        text: '鍚敤'
-      }]
-    },
+    // {
+    //   type: 'radio',
+    //   key: 'returnValue',
+    //   label: '鏇存柊琛ㄥ崟',
+    //   initVal: card.returnValue || 'false',
+    //   tooltip: '涓庨噸缃〃鍗曢厤鍚堜娇鐢紝寮�鍚椂锛屽繀椤诲湪鑷畾涔夎剼鏈腑杩斿洖鏁版嵁锛岀敤浜庢浛鎹㈠瓧娈甸泦鍜屽~鍏呰〃鍗曘��',
+    //   options: [{
+    //     value: 'false',
+    //     text: '绂佺敤'
+    //   }, {
+    //     value: 'true',
+    //     text: '鍚敤'
+    //   }]
+    // },
     {
       type: 'radio',
       key: 'reload',
diff --git a/src/menu/components/form/formaction/index.jsx b/src/menu/components/form/formaction/index.jsx
index 3ca3fb7..b577b18 100644
--- a/src/menu/components/form/formaction/index.jsx
+++ b/src/menu/components/form/formaction/index.jsx
@@ -223,10 +223,10 @@
           <div className="mk-popover-control">
             <EditOutlined className="edit" title="缂栬緫" onClick={() => this.handleAction(group.subButton)} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.handleStyle(group.subButton)}/>
-            <ProfileOutlined className="profile" title="setting" onClick={() => this.profileAction()} />
+            <ProfileOutlined className="profile" title="楠岃瘉淇℃伅" onClick={() => this.profileAction()} />
           </div>
         } trigger="hover">
-          <Button type="link" className="submit mk-primary" onDoubleClick={this.changeMenu} style={resetStyle(group.subButton.style)}>{group.subButton.label}</Button>
+          <Button type="link" className="submit" onDoubleClick={this.changeMenu} style={resetStyle(group.subButton.style)}>{group.subButton.label}</Button>
         </Popover>
         {group.resetButton && group.resetButton.enable === 'true' ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index 07e1e2f..60e1f9f 100644
--- a/src/menu/components/form/simple-form/index.jsx
+++ b/src/menu/components/form/simple-form/index.jsx
@@ -7,7 +7,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent, getInterfaces } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -241,7 +241,7 @@
   
   changecols = (type) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     card.subcards[0].fields = card.subcards[0].fields.map(item => {
       item.labelwidth = 33.3
@@ -267,7 +267,7 @@
     confirm({
       content: `纭畾鍒囨崲涓�${type}鍒楀悧锛焋,
       onOk() {
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -288,14 +288,14 @@
 
   closeForm = (cell) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     card.subcards[0].fields = card.subcards[0].fields.filter(item => item.uuid !== cell.uuid)
 
     confirm({
       content: `纭畾鍒犻櫎<<${cell.label}>>鍚楋紵`,
       onOk() {
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -340,6 +340,8 @@
     card.subcards[0].fields = card.subcards[0].fields.filter(item => !item.focus)
 
     this.setState({card, visible: false, editform: null})
+
+    this.updateComponent(card)
   }
 
   /**
@@ -466,9 +468,9 @@
         _card.setting.supModule = ''
       }
     } else if (res.datatype === 'public') {
-      let interfaces = window.GLOB.customMenu.interfaces || []
+      let interfaces = getInterfaces()
 
-      let d = interfaces.filter(m => m.uuid === res.publicId && m.status === 'true')[0]
+      let d = interfaces.filter(m => m.value === res.publicId)[0]
 
       if (d) {
         _card.columns = fromJS(d.columns).toJS()
@@ -501,14 +503,14 @@
 
   clearGroup = () => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     card.subcards[0].fields = []
 
     confirm({
       content: `纭畾娓呯┖琛ㄥ崟鍚楋紵`,
       onOk() {
-        _this.updateComponent(card)
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/form/simple-form/index.scss b/src/menu/components/form/simple-form/index.scss
index 2615482..a88431e 100644
--- a/src/menu/components/form/simple-form/index.scss
+++ b/src/menu/components/form/simple-form/index.scss
@@ -58,17 +58,6 @@
       background-color: transparent;
     }
   }
-  // .form-area.mk-shadow {
-  //   .mob-form {
-  //     .am-list-line {
-  //       border: none!important;
-
-  //       .am-input-control {
-  //         background-color: var(--mk-sys-color1);
-  //       }
-  //     }
-  //   }
-  // }
 }
 .menu-simple-form-edit-box::after {
   display: block;
diff --git a/src/menu/components/form/simple-form/options.jsx b/src/menu/components/form/simple-form/options.jsx
index b9108ff..ab8acc7 100644
--- a/src/menu/components/form/simple-form/options.jsx
+++ b/src/menu/components/form/simple-form/options.jsx
@@ -1,4 +1,4 @@
-import MenuUtils from '@/utils/utils-custom.js'
+import MenuUtils, { getInterfaces } from '@/utils/utils-custom.js'
 
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
@@ -45,18 +45,7 @@
     }
   }
 
-  let interfaces = []
-  if (menu.interfaces) {
-    menu.interfaces.forEach(item => {
-      if (item.status === 'true') {
-        interfaces.push({
-          value: item.uuid,
-          label: item.name
-        })
-      }
-    })
-  }
-
+  let interfaces = getInterfaces()
   let buttons = []
 
   if (!wrap.enable || wrap.enable === 'true') {
@@ -244,7 +233,6 @@
       initval: wrap.empty || 'show',
       tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
-      skip: true,
       options: [
         {value: 'show', label: '鍚�'},
         {value: 'hidden', label: '鏄�'},
diff --git a/src/menu/components/form/step-form/index.jsx b/src/menu/components/form/step-form/index.jsx
index 4395d59..dd5790b 100644
--- a/src/menu/components/form/step-form/index.jsx
+++ b/src/menu/components/form/step-form/index.jsx
@@ -273,7 +273,7 @@
   closeGroup = (cell) => {
     const { group } = this.state
     let card = fromJS(this.state.card).toJS()
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍒嗙粍鍚楋紵',
@@ -285,8 +285,8 @@
           _group = card.subcards[0] || null
         }
 
-        _this.setState({group: _group})
-        _this.updateComponent(card)
+        that.setState({group: _group})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -317,7 +317,7 @@
   changecols = (type) => {
     let card = fromJS(this.state.card).toJS()
     let config = fromJS(this.state.group).toJS()
-    let _this = this
+    let that = this
 
     config.fields = config.fields.map(item => {
       item.labelwidth = 33.3
@@ -349,8 +349,8 @@
           }
           return item
         })
-        _this.setState({group: config})
-        _this.updateComponent(card)
+        that.setState({group: config})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -380,7 +380,7 @@
   closeForm = (cell) => {
     let group = fromJS(this.state.group).toJS()
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     group.fields = group.fields.filter(item => item.uuid !== cell.uuid)
 
@@ -394,8 +394,8 @@
     confirm({
       content: `纭畾鍒犻櫎<<${cell.label}>>鍚楋紵`,
       onOk() {
-        _this.setState({group})
-        _this.updateComponent(card)
+        that.setState({group})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -571,7 +571,7 @@
   clearGroup = () => {
     let group = fromJS(this.state.group).toJS()
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     group.fields = []
 
@@ -585,8 +585,8 @@
     confirm({
       content: `纭畾娓呯┖琛ㄥ崟鍚楋紵`,
       onOk() {
-        _this.setState({group})
-        _this.updateComponent(card)
+        that.setState({group})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/form/step-form/options.jsx b/src/menu/components/form/step-form/options.jsx
index aca8cd7..a580960 100644
--- a/src/menu/components/form/step-form/options.jsx
+++ b/src/menu/components/form/step-form/options.jsx
@@ -204,7 +204,6 @@
       initval: wrap.empty || 'show',
       tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
-      skip: true,
       options: [
         {value: 'show', label: '鍚�'},
         {value: 'hidden', label: '鏄�'},
diff --git a/src/menu/components/form/tab-form/index.jsx b/src/menu/components/form/tab-form/index.jsx
index c895e37..1758d75 100644
--- a/src/menu/components/form/tab-form/index.jsx
+++ b/src/menu/components/form/tab-form/index.jsx
@@ -279,7 +279,7 @@
   closeGroup = (cell) => {
     const { group } = this.state
     let card = fromJS(this.state.card).toJS()
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍒犻櫎鍒嗙粍鍚楋紵',
@@ -291,8 +291,8 @@
           _group = card.subcards[0] || null
         }
 
-        _this.setState({group: _group})
-        _this.updateComponent(card)
+        that.setState({group: _group})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -323,7 +323,7 @@
   changecols = (type) => {
     let card = fromJS(this.state.card).toJS()
     let config = fromJS(this.state.group).toJS()
-    let _this = this
+    let that = this
 
     config.fields = config.fields.map(item => {
       item.labelwidth = 33.3
@@ -355,8 +355,8 @@
           }
           return item
         })
-        _this.setState({group: config})
-        _this.updateComponent(card)
+        that.setState({group: config})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -386,7 +386,7 @@
   closeForm = (cell) => {
     let group = fromJS(this.state.group).toJS()
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     group.fields = group.fields.filter(item => item.uuid !== cell.uuid)
 
@@ -400,8 +400,8 @@
     confirm({
       content: `纭畾鍒犻櫎<<${cell.label}>>鍚楋紵`,
       onOk() {
-        _this.setState({group})
-        _this.updateComponent(card)
+        that.setState({group})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
@@ -573,7 +573,7 @@
   clearGroup = () => {
     let group = fromJS(this.state.group).toJS()
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     group.fields = []
 
@@ -587,8 +587,8 @@
     confirm({
       content: `纭畾娓呯┖琛ㄥ崟鍚楋紵`,
       onOk() {
-        _this.setState({group})
-        _this.updateComponent(card)
+        that.setState({group})
+        that.updateComponent(card)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/group/normal-group/index.jsx b/src/menu/components/group/normal-group/index.jsx
index e26fb57..aa41f27 100644
--- a/src/menu/components/group/normal-group/index.jsx
+++ b/src/menu/components/group/normal-group/index.jsx
@@ -136,15 +136,15 @@
 
     if (group.components.length === 0) return
 
-    const _this = this
+    const that = this
     confirm({
       title: '纭畾閲婃斁鍒嗙粍鍏冪礌鍚楋紵',
       content: '',
       onOk() {
-        _this.props.unGroup(group.uuid)
+        that.props.unGroup(group.uuid)
 
         setTimeout(() => {
-          _this.updataGroup()
+          that.updataGroup()
         }, 10)
       },
       onCancel() {}
diff --git a/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx b/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx
index c5cf723..786f5c5 100644
--- a/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx
+++ b/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx
@@ -219,7 +219,7 @@
           </Col> : null}
           {!type ? <Col span={8}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+              errorcode, retmsg
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={24} className="sqlfield">
@@ -253,7 +253,6 @@
                 filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                 onChange={this.selectScript}
               >
-                <Select.Option key="default" value="defaultSql">榛樿sql</Select.Option>
                 {systemScripts.map((option, i) =>
                   <Select.Option key={i} value={option.value}>{option.name}</Select.Option>
                 )}
diff --git a/src/menu/components/module/invoice/verifycard/customscript/index.jsx b/src/menu/components/module/invoice/verifycard/customscript/index.jsx
index c9a1299..8d848ce 100644
--- a/src/menu/components/module/invoice/verifycard/customscript/index.jsx
+++ b/src/menu/components/module/invoice/verifycard/customscript/index.jsx
@@ -201,7 +201,7 @@
         <Row gutter={24}>
           {!type ? <Col span={8}>
             <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
-              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+              errorcode, retmsg
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={24} className="sqlfield">
diff --git a/src/menu/components/search/main-search/dragsearch/card.jsx b/src/menu/components/search/main-search/dragsearch/card.jsx
index 6e153b6..72462e7 100644
--- a/src/menu/components/search/main-search/dragsearch/card.jsx
+++ b/src/menu/components/search/main-search/dragsearch/card.jsx
@@ -132,6 +132,11 @@
     </>)
   }
 
+  let labelwidth = card.labelwidth || 33.3
+  if (card.labelShow === 'false') {
+    labelwidth = 0
+  }
+
   return (
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
       <div className="mk-popover-control">
@@ -143,8 +148,8 @@
       <div className={'page-card ' + (card.labelShow === 'false' ? 'label-hide ' : '') + card.type + (card.advanced === 'true' ? ' advanced' : '') + (card.query === 'false' ? ' no-query' : '')} style={{ opacity: opacity}}>
         <div ref={node => drag(drop(node))}>
           <Form.Item
-            labelCol={{xs: { span: 24 }, sm: { span: 8 }}}
-            wrapperCol = {{xs: { span: 24 }, sm: { span: 16 }}}
+            labelCol={{style: {width: labelwidth + '%'}}}
+            wrapperCol={{style: {width: (100 - labelwidth) + '%'}}}
             label={card.labelShow !== 'false' ? card.label : ''}
             required={card.required === 'true'}
             help={card.field + (card.datefield ? ', ' + card.datefield : '') + (card.advanced === 'true' ? '锛堥珮绾ф悳绱級' : '')}
diff --git a/src/menu/components/search/main-search/dragsearch/index.jsx b/src/menu/components/search/main-search/dragsearch/index.jsx
index 5af808c..04d5372 100644
--- a/src/menu/components/search/main-search/dragsearch/index.jsx
+++ b/src/menu/components/search/main-search/dragsearch/index.jsx
@@ -52,7 +52,7 @@
     try {
       delete _val.$srcId
     
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         _val.$srcId = srcid
       }
diff --git a/src/menu/components/search/main-search/index.jsx b/src/menu/components/search/main-search/index.jsx
index 270358a..33814cc 100644
--- a/src/menu/components/search/main-search/index.jsx
+++ b/src/menu/components/search/main-search/index.jsx
@@ -250,7 +250,7 @@
         return
       }
 
-      if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && res.database !== 'sso' && /\s/.test(res.dataSource)) {
         this.setState({
           sqlVerifing: true
         })
@@ -258,13 +258,8 @@
         let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
         ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
-
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
         
-        Api.sDebug(sql, rduri).then(result => {
+        Api.sDebug(sql).then(result => {
           if (result.status || result.ErrCode === '-2') {
             this.setState({
               sqlVerifing: false,
@@ -294,15 +289,15 @@
    * @description 鎼滅储鏉′欢鍒犻櫎
    */
   deleteElement = (cell) => {
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 - ${cell.label} 锛焋,
       onOk() {
-        let _card = fromJS(_this.state.card).toJS()
+        let _card = fromJS(that.state.card).toJS()
         _card.search = _card.search.filter(item => item.uuid !== cell.uuid)
 
-        _this.updateComponent(_card)
+        that.updateComponent(_card)
       },
       onCancel() {}
     })
@@ -381,7 +376,7 @@
     let _style = resetStyle(card.style)
 
     return (
-      <div className={`main-search-edit-list ${card.wrap.float} ${showField ? 'show-field' : ''}`} onClick={this.clickComponent} id={card.uuid} style={_style}>
+      <div className={`main-search-edit-list ${card.wrap.float} ${showField ? 'show-field' : ''} mk-size-${card.wrap.searchSize || ''}`} onClick={this.clickComponent} id={card.uuid} style={_style}>
         <FieldsComponent config={card} type="search" />
         <Switch checkedChildren="寮�" size="small" unCheckedChildren="鍏�" defaultChecked={showField} onChange={this.onFieldChange} />
         <DragElement
@@ -422,7 +417,7 @@
           title="鎼滅储鏉′欢-缂栬緫"
           wrapClassName="mk-scroll-modal"
           visible={visible}
-          width={850}
+          width={950}
           maskClosable={false}
           onOk={this.handleSubmit}
           confirmLoading={sqlVerifing}
diff --git a/src/menu/components/search/main-search/index.scss b/src/menu/components/search/main-search/index.scss
index 656580b..b5a03a5 100644
--- a/src/menu/components/search/main-search/index.scss
+++ b/src/menu/components/search/main-search/index.scss
@@ -44,7 +44,11 @@
     .ant-form-item {
       position: relative;
       margin-bottom: 0px;
+      .ant-form-item-label {
+        float: left;
+      }
       .ant-form-item-control-wrapper {
+        float: left;
         .ant-select {
           width: 100%;
           margin-top: 4px;
@@ -153,6 +157,17 @@
   }
 }
 
+.main-search-edit-list.mk-size-small {
+  .page-card {
+    height: 45px;
+  }
+  .mk-search-item-wrap.action {
+    .ant-form-item {
+      height: 45px!important;
+    }
+  }
+}
+
 .main-search-edit-list:not(.show-field) {
   .ant-form-explain {
     display: none;
diff --git a/src/menu/components/search/main-search/options.jsx b/src/menu/components/search/main-search/options.jsx
index 2ed6c06..32f04b1 100644
--- a/src/menu/components/search/main-search/options.jsx
+++ b/src/menu/components/search/main-search/options.jsx
@@ -160,6 +160,18 @@
     },
     {
       type: 'radio',
+      field: 'searchSize',
+      label: '鎼滅储闂磋窛',
+      initval: wrap.searchSize || 'middle',
+      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      required: false,
+      options: [
+        {value: 'middle', label: '榛樿'},
+        {value: 'small', label: '灏�'},
+      ],
+    },
+    {
+      type: 'radio',
       field: 'cacheSearch',
       label: '鎼滅储缂撳瓨',
       initval: wrap.cacheSearch || 'false',
diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx
index 3f88b64..dcf94bf 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -18,8 +18,8 @@
   pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'hover', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'hoverTitle', 'hidden', 'preButton'],
   prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'hover', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hoverTitle', 'hidden', 'preButton'],
   exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'hover', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'hoverTitle', 'hidden', 'preButton'],
-  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'hover', 'icon', 'class', 'color', 'sheet', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'width', 'hidden'],
-  excelOut: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'hover', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'pagination', 'search', 'width', 'hidden'],
+  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'hover', 'icon', 'class', 'color', 'sheet', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'width', 'hidden', 'refreshTab'],
+  excelOut: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'hover', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'pagination', 'search', 'width', 'hidden', 'refreshTab'],
   popview: ['label', 'Ot', 'OpenType', 'show', 'hover', 'icon', 'class', 'color', 'popClose', 'width', 'display', 'ratio', 'syncComponent', 'clickouter', 'maskStyle', 'closeButton', 'hidden'],
   tab: ['label', 'Ot', 'OpenType', 'show', 'hover', 'icon', 'class', 'color', 'linkmenu', 'width', 'hidden', 'openTab'],
   innerpage: ['label', 'Ot', 'OpenType', 'pageTemplate', 'show', 'hover', 'swipe', 'icon', 'class', 'color', 'width', 'hidden'],
@@ -221,7 +221,7 @@
         }
         reRequired.innerFunc = true
       } else {
-        shows.push('sql', 'sqlType', 'output')
+        shows.push('sql', 'sqlType', 'output', 'database')
       }
 
       if (Ot === 'required') {
@@ -233,7 +233,7 @@
       if (this.record.openmenu && this.record.openmenu !== 'goback') {
         shows.push('open')
       }
-      if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
+      if (['grid'].includes(this.record.execSuccess) || ['grid'].includes(this.record.execError)) {
         shows.push('resetPageIndex')
       }
 
@@ -299,13 +299,13 @@
         shows.push('innerFunc', 'extraParam')
         reRequired.innerFunc = true
       } else {
-        shows.push('sql', 'sqlType')
+        shows.push('sql', 'sqlType', 'database')
       }
 
       if (this.record.execSuccess === 'goback') {
         shows.push('reload')
       }
-      if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
+      if (['grid'].includes(this.record.execSuccess) || ['grid'].includes(this.record.execError)) {
         shows.push('resetPageIndex')
       }
 
@@ -349,8 +349,10 @@
       } else if (this.record.intertype === 'inner') {
         shows.push('innerFunc', 'extraParam')
         reRequired.innerFunc = true
+      } else {
+        shows.push('database')
       }
-      if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
+      if (['grid'].includes(this.record.execSuccess) || ['grid'].includes(this.record.execError)) {
         shows.push('resetPageIndex')
       }
     } else if (openType === 'excelOut') {
@@ -384,8 +386,10 @@
       } else if (this.record.intertype === 'inner') {
         shows.push('innerFunc', 'extraParam')
         reRequired.innerFunc = true
+      } else {
+        shows.push('database')
       }
-      if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
+      if (['grid'].includes(this.record.execSuccess) || ['grid'].includes(this.record.execError)) {
         shows.push('resetPageIndex')
       }
       if (this.record.Ot !== 'notRequired' && appType === 'mob') {
@@ -439,6 +443,15 @@
         reOptions.Ot = requireOptions
       } else if (this.record.pageTemplate === 'pay') {
         reOptions.Ot = requireOptions.filter(op => op.value === 'requiredSgl')
+
+        shows.push('payMode', 'wxApp', 'wxMerch')
+        if (this.record.payMode === 'inner') {
+          reRequired.innerFunc = true
+          shows.push('innerFunc')
+        }
+        if (this.record.payMode !== 'none') {
+          shows.push('output')
+        }
       }
     } else if (openType === 'funcbutton') {
       reOptions.intertype = this.state.interTypeOptions.filter(op => op.value !== 'custom')
@@ -472,14 +485,16 @@
           shows.push('innerFunc', 'extraParam')
           reRequired.innerFunc = true
         }
-        if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
+        if (['grid'].includes(this.record.execSuccess) || ['grid'].includes(this.record.execError)) {
           shows.push('resetPageIndex')
         }
         if (this.record.execMode === 'pop' || this.record.execMode === 'prompt') {
           shows.push('position')
         }
       } else if (_funcType === 'mkBinding' || _funcType === 'mkUnBinding') {
-        shows.push('execSuccess', 'execError')
+        shows.push('execSuccess', 'execError', 'tipTitle')
+      } else if (_funcType === 'mkUnsubscribe' || _funcType === 'reAuth') {
+        shows.push('tipTitle')
       } else if (_funcType === 'closetab') {
         shows.push('refreshTab')
       } else if (_funcType === 'scan') {
@@ -507,16 +522,38 @@
 
         shows.push('innerFunc', 'Ot', 'execSuccess', 'execError', 'urlkey')
       } else if (_funcType === 'pay') {
-        shows.push('payType', 'Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu')
+        shows.push('payType', 'wxApp', 'wxMerch', 'Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu')
         if (this.record.openmenu && this.record.openmenu !== 'goback') {
           shows.push('open')
         }
         reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
+        shows.push('payMode')
+        if (this.record.payMode === 'inner') {
+          reRequired.innerFunc = true
+          shows.push('innerFunc')
+        }
+        if (this.record.payMode !== 'none') {
+          shows.push('output')
+        }
       } else if (_funcType === 'refund') {
         shows.push('Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu', 'tipTitle')
         reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
+
+        shows.push('payMode')
+        if (this.record.payMode === 'inner') {
+          reRequired.innerFunc = true
+          shows.push('innerFunc')
+        }
+        if (this.record.payMode !== 'none') {
+          shows.push('output')
+        }
       } else if (_funcType === 'shareLink') {
         shows.push('shortUrl', 'shareUrl', 'shareProUrl', 'shareTip')
+      } else if (_funcType === 'openLocation') {
+        shows.push('Ot')
+        if (Ot === 'requiredSgl') {
+          shows.push('nameField', 'addressField')
+        }
       // } else if (_funcType === 'expPdf') {
       //   shows.push('exportType')
       }
@@ -852,22 +889,42 @@
             { max: 512, message: '鏈�澶�512涓瓧绗�' }
           )
         } else if (item.key === 'output') {
-          if (this.record.intertype === 'system' || ((this.record.intertype === 'outer' || this.record.intertype === 'custom') && this.record.callbackType === 'script')) {
-            rules = [{
-              pattern: /^@[0-9a-zA-Z_]+@?$/,
-              message: '鍙橀噺浠绗﹀紑澶达紝鍙娇鐢ㄥ瓧姣嶃�佹暟瀛椾互鍙奯'
-            }, {
-              max: 100,
-              message: '鏈�澶�100涓瓧绗︺��'
-            }]
+          if (['pop', 'prompt', 'exec'].includes(this.record.OpenType)) {
+            if (this.record.intertype === 'system' || ((this.record.intertype === 'outer' || this.record.intertype === 'custom') && this.record.callbackType === 'script')) {
+              rules = [{
+                pattern: /^@[0-9a-zA-Z_]+@?$/,
+                message: '鍙橀噺浠绗﹀紑澶达紝鍙娇鐢ㄥ瓧姣嶃�佹暟瀛椾互鍙奯'
+              }, {
+                max: 100,
+                message: '鏈�澶�100涓瓧绗︺��'
+              }]
+            } else {
+              rules = [{
+                pattern: /^[0-9a-zA-Z_]*$/,
+                message: '瀛楁鍙娇鐢ㄥ瓧姣嶃�佹暟瀛椾互鍙奯'
+              }, {
+                max: 100,
+                message: '鏈�澶�100涓瓧绗︺��'
+              }]
+            }
           } else {
-            rules = [{
-              pattern: /^[0-9a-zA-Z_]*$/,
-              message: '瀛楁鍙娇鐢ㄥ瓧姣嶃�佹暟瀛椾互鍙奯'
-            }, {
-              max: 100,
-              message: '鏈�澶�100涓瓧绗︺��'
-            }]
+            if (this.record.payMode === 'system') {
+              rules = [{
+                pattern: /^@[0-9a-zA-Z_]+@?$/,
+                message: '鍙橀噺浠绗﹀紑澶达紝鍙娇鐢ㄥ瓧姣嶃�佹暟瀛椾互鍙奯'
+              }, {
+                max: 100,
+                message: '鏈�澶�100涓瓧绗︺��'
+              }]
+            } else {
+              rules = [{
+                pattern: /^[0-9a-zA-Z_]*$/,
+                message: '瀛楁鍙娇鐢ㄥ瓧姣嶃�佹暟瀛椾互鍙奯'
+              }, {
+                max: 100,
+                message: '鏈�澶�100涓瓧绗︺��'
+              }]
+            }
           }
         } else {
           rules.push({ max: formRule.input.max, message: formRule.input.message })
diff --git a/src/menu/components/share/actioncomponent/dragaction/card.jsx b/src/menu/components/share/actioncomponent/dragaction/card.jsx
index a90472c..e65eb9b 100644
--- a/src/menu/components/share/actioncomponent/dragaction/card.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/card.jsx
@@ -46,6 +46,8 @@
     hasProfile = true
   } else if (card.funcType === 'megvii') {
     hasProfile = true
+  } else if (card.payMode === 'system') {
+    hasProfile = true
   }
 
   let btnElement = null
@@ -109,7 +111,7 @@
         {!card.$fixed ? <CopyOutlined className="copy" onClick={() => copyCard(id)} /> : null}
         {!card.$fixed ? <CloseOutlined className="close" onClick={() => delCard(id)} /> : null}
         {type !== 'datacard' && type !== 'basetable' && !card.$fixed ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => changeStyle(id)}/> : ''}
-        {hasProfile ? <ProfileOutlined className="profile" title="楠岃瘉" onClick={() => profileCard(id)} /> : null}
+        {hasProfile ? <ProfileOutlined className="profile" title="楠岃瘉淇℃伅" onClick={() => profileCard(id)} /> : null}
         {updateTime}
       </div>
     } trigger="hover">
diff --git a/src/menu/components/share/actioncomponent/dragaction/index.jsx b/src/menu/components/share/actioncomponent/dragaction/index.jsx
index cab1425..a90eb21 100644
--- a/src/menu/components/share/actioncomponent/dragaction/index.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/index.jsx
@@ -74,7 +74,7 @@
     try {
       delete _val.$srcId
     
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         _val.$srcId = srcid
       }
diff --git a/src/menu/components/share/actioncomponent/formconfig.jsx b/src/menu/components/share/actioncomponent/formconfig.jsx
index 8b93c3b..e1544de 100644
--- a/src/menu/components/share/actioncomponent/formconfig.jsx
+++ b/src/menu/components/share/actioncomponent/formconfig.jsx
@@ -18,12 +18,21 @@
   let type = ''
   let alltype = config.type + '_' + config.subtype
 
+  columns = columns.map(item => ({
+    value: item.field,
+    text: `${item.label}锛�${item.field}锛塦
+  }))
+
   if (card.eleType === 'button') {
     type = 'card'
   } else if (config.subtype === 'datacard' || config.subtype === 'tablecard' || config.subtype === 'dualdatacard') {
     type = 'datacard'
   } else if (config.type === 'line' || config.type === 'bar' || config.type === 'scatter') {
     type = 'chart'
+  }
+
+  if (card.color && (type !== 'datacard' || appType !== 'mob') && !card.class) {
+    card.class = 'primary'
   }
 
   let opentypes = [
@@ -207,6 +216,7 @@
       { value: 'copyurl', text: '澶嶅埗閾炬帴鍦板潃' },
       { value: 'expPdf', text: '瀵煎嚭PDF' },
       { value: 'shareLink', text: '鍒嗕韩閾炬帴' },
+      { value: 'openLocation', text: '鎵撳紑鍦板浘'},
       { value: 'logout', text: '閫�鍑�' },
       { value: 'goBack', text: '杩斿洖' },
     ]
@@ -218,6 +228,7 @@
     opentypes = opentypes.filter(item => item.value !== 'tab')
     funTypes = [
       { value: 'print', text: '鏍囩鎵撳嵃' },
+      { value: 'refund', text: '閫�娆�' },
     ]
     pageTemps = [
       { value: 'linkpage', text: '鍏宠仈鑿滃崟' },
@@ -314,7 +325,7 @@
   }
 
   let width = card.width || (card.width === 0 ? 0 : 12)
-  if (/x/.test(card.width)) {
+  if (card.width && /x/.test(card.width)) {
     width = +width.replace(/x/, '.5')
   }
 
@@ -326,9 +337,21 @@
     extraParam.push('dataM')
   }
 
+  let apps = []
+  let merchs = []
   if (!appType) {
     if (typeof(card.openmenu) === 'string') {
       card.openmenu = []
+    }
+
+    if (window.GLOB.WXApps) {
+      window.GLOB.WXApps.forEach(item => {
+        if (item.appType === 'merchant') {
+          merchs.push({value: item.appId, text: item.appName})
+        } else {
+          apps.push({value: item.appId, text: item.appName})
+        }
+      })
     }
   } else {
     if (typeof(card.openmenu) !== 'string') {
@@ -417,20 +440,20 @@
       required: true,
       options: []
     },
-    {
-      type: 'checkbox',
-      key: 'payType',
-      label: '鏀粯鏂瑰紡',
-      initVal: card.payType || [],
-      required: true,
-      options: [{
-        value: 'wxpay',
-        text: '寰俊'
-      // }, {
-      //   value: 'alipay',
-      //   text: '鏀粯瀹�'
-      }]
-    },
+    // {
+    //   type: 'checkbox',
+    //   key: 'payType',
+    //   label: '鏀粯鏂瑰紡',
+    //   initVal: card.payType || [],
+    //   required: true,
+    //   options: [{
+    //     value: 'wxpay',
+    //     text: '寰俊'
+    //   // }, {
+    //   //   value: 'alipay',
+    //   //   text: '鏀粯瀹�'
+    //   }]
+    // },
     {
       type: 'radio',
       key: 'procMode',
@@ -466,15 +489,6 @@
     },
     {
       type: 'text',
-      key: 'innerFunc',
-      label: '鍐呴儴鍑芥暟',
-      initVal: card.innerFunc || '',
-      tooltip: functip,
-      fields: usefulFields,
-      required: false,
-    },
-    {
-      type: 'text',
       key: 'urlkey',
       label: '鍦板潃瀛楁',
       initVal: card.urlkey || '',
@@ -489,6 +503,53 @@
       initVal: card.pageTemplate || '',
       required: true,
       options: pageTemps
+    },
+    {
+      type: 'radio',
+      key: 'payMode',
+      label: '鍙傛暟澶勭悊',
+      initVal: card.payMode || 'none',
+      tooltip: '鏀粯锛堟垨閫�娆撅級鍗曞彿鐨勯澶勭悊鏂瑰紡銆�',
+      required: true,
+      options: [{
+        value: 'system',
+        text: '绯荤粺鍑芥暟'
+      }, {
+        value: 'inner',
+        text: '鍐呴儴鍑芥暟'
+      }, {
+        value: 'none',
+        text: '鏃�'
+      }]
+    },
+    {
+      type: 'select',
+      key: 'wxApp',
+      label: '鍏宠仈搴旂敤',
+      initVal: card.wxApp || '',
+      tooltip: '璇峰叧鑱旀敮浠樼殑鍏紬鍙锋垨灏忕▼搴忋��',
+      required: true,
+      forbid: apps.length === 0,
+      options: apps
+    },
+    {
+      type: 'select',
+      key: 'wxMerch',
+      label: '鍏宠仈鍟嗘埛',
+      initVal: card.wxMerch || '',
+      tooltip: '璇峰叧鑱旀敮浠樼殑鍟嗘埛鍙枫��',
+      required: true,
+      forbid: merchs.length === 0,
+      options: merchs
+    },
+    {
+      type: 'text',
+      key: 'innerFunc',
+      label: '鍐呴儴鍑芥暟',
+      initVal: card.innerFunc || '',
+      tooltip: functip,
+      fields: usefulFields,
+      required: false,
     },
     {
       type: 'printTemps',
@@ -711,7 +772,7 @@
       key: 'execSuccess',
       label: '鎴愬姛鍚�',
       initVal: card.execSuccess || 'grid',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�鑱氱劍琛ㄥ崟璇蜂互 @focus:鑱氱劍瀛楁@ 鏍煎紡杩斿洖銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�鑱氱劍琛ㄥ崟璇蜂互 @focus:鑱氱劍瀛楁@ 鏍煎紡杩斿洖銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�',
       required: true,
       options: [{
         value: 'never',
@@ -742,7 +803,7 @@
       key: 'execError',
       label: '澶辫触鍚�',
       initVal: card.execError || 'never',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙open_target_menu@ 鍙墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙open_target_menu@ 鍙墽琛屾墦寮�鑿滃崟銆�',
       required: true,
       options: [{
         value: 'never',
@@ -800,6 +861,25 @@
         value: 'false',
         text: '涓嶉噸缃�'
       }]
+    },
+    {
+      type: 'select',
+      key: 'nameField',
+      label: '浣嶇疆鍚嶅瓧娈�',
+      initVal: card.nameField || '',
+      tooltip: '鎵撳紑鍦板浘鏃跺彲灞曠ず浣嶇疆鍚嶄笌璇︾粏鍦板潃锛岃缁戝畾鏁版嵁婧愬瓧娈甸泦锛岀粡绾害璇蜂娇鐢╨atitude銆乴ongitude涓旂粡绾害涓嶅彲涓虹┖銆�',
+      required: false,
+      allowClear: true,
+      options: columns
+    },
+    {
+      type: 'select',
+      key: 'addressField',
+      label: '鍦板潃瀛楁',
+      initVal: card.addressField || '',
+      required: false,
+      allowClear: true,
+      options: columns
     },
     {
       type: 'radio',
@@ -975,9 +1055,50 @@
       key: 'syncComponent',
       label: '鍒锋柊缁勪欢',
       initVal: card.syncComponent || [],
-      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧脊绐楁爣绛惧叧闂椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎵ц澶辫触涓斿瓨鍦ㄥ埛鏂伴」銆佸脊绐楁爣绛惧叧闂級锛岄渶瑕佸悓姝ュ埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
       required: false,
       options: modules.length ? [...modules, {value: 'multiComponent', label: '澶氱粍浠�'}] : []
+    },
+    {
+      type: 'cascader',
+      key: 'refreshTab',
+      label: '鍒锋柊鑿滃崟',
+      initVal: card.refreshTab || [],
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栨墽琛屽け璐ヤ笖瀛樺湪鍒锋柊椤规椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑鑿滃崟',
+      required: false,
+      forbid: isApp || viewType === 'popview',
+      options: menulist
+    },
+    {
+      type: !appType ? 'cascader' : 'select',
+      key: 'openmenu',
+      label: '鎵撳紑鑿滃崟',
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧け璐ユ椂杩斿洖@open_target_menu@锛夐渶瑕佹墦寮�鐨勮彍鍗曘��',
+      initVal: card.openmenu || (!appType ? [] : ''),
+      help: appType === 'mob' || appType === 'pc' ? '鍙繑鍥炰笂涓�椤点��' : null,
+      extendName: 'MenuNo',
+      required: false,
+      allowClear: true,
+      options: appType === 'mob' || appType === 'pc' ? appMenus : menulist,
+      forbid: viewType === 'popview'
+    },
+    {
+      type: 'cascader',
+      key: 'switchTab',
+      label: '鍒囨崲鏍囩',
+      initVal: card.switchTab || [],
+      tooltip: '鎵ц鎴愬姛鍚庯紝闇�瑕佸垏鎹㈢殑鏍囩椤点��' + (appType === 'mob' ? '娉細灏忕▼搴忎腑鏃犳晥' : ''),
+      required: false,
+      options: tabs
+    },
+    {
+      type: 'cascader',
+      key: 'anchors',
+      label: '璺宠浆閿氱偣',
+      initVal: card.anchors || [],
+      tooltip: '鎵ц鎴愬姛鍚庯紝闇�瑕佽烦杞殑閿氱偣銆�' + (appType === 'mob' ? '娉細灏忕▼搴忎腑鏃犳晥' : ''),
+      required: false,
+      options: anchors
     },
     {
       type: 'radio',
@@ -1009,47 +1130,6 @@
         text: '闈炲繀濉�'
       }],
       forbid: appType === 'mob'
-    },
-    {
-      type: 'cascader',
-      key: 'refreshTab',
-      label: '鍒锋柊鑿滃崟',
-      initVal: card.refreshTab || [],
-      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧姛鑳芥寜閽腑鏍囩鍏抽棴绫诲瀷锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑鑿滃崟',
-      required: false,
-      forbid: isApp || viewType === 'popview',
-      options: menulist
-    },
-    {
-      type: !appType ? 'cascader' : 'select',
-      key: 'openmenu',
-      label: '鎵撳紑鑿滃崟',
-      tooltip: '鎵ц鎴愬姛鍚庨渶瑕佹墦寮�鐨勮彍鍗曘��',
-      initVal: card.openmenu || (!appType ? [] : ''),
-      help: appType === 'mob' || appType === 'pc' ? '鍙繑鍥炰笂涓�椤点��' : null,
-      extendName: 'MenuNo',
-      required: false,
-      allowClear: true,
-      options: appType === 'mob' || appType === 'pc' ? appMenus : menulist,
-      forbid: viewType === 'popview'
-    },
-    {
-      type: 'cascader',
-      key: 'switchTab',
-      label: '鍒囨崲鏍囩',
-      initVal: card.switchTab || [],
-      tooltip: '鎵ц鎴愬姛鍚庯紝闇�瑕佸垏鎹㈢殑鏍囩椤点��' + (appType === 'mob' ? '娉細灏忕▼搴忎腑鏃犳晥' : ''),
-      required: false,
-      options: tabs
-    },
-    {
-      type: 'cascader',
-      key: 'anchors',
-      label: '璺宠浆閿氱偣',
-      initVal: card.anchors || [],
-      tooltip: '鎵ц鎴愬姛鍚庯紝闇�瑕佽烦杞殑閿氱偣銆�' + (appType === 'mob' ? '娉細灏忕▼搴忎腑鏃犳晥' : ''),
-      required: false,
-      options: anchors
     },
     {
       type: 'select',
@@ -1096,10 +1176,7 @@
       required: false,
       allowClear: true,
       forbid: position !== 'line',
-      options: columns.map(item => ({
-        value: item.field,
-        text: `${item.label}锛�${item.field}锛塦
-      }))
+      options: columns
     },
     {
       type: 'radio',
@@ -1316,10 +1393,7 @@
       initVal: card.controlField || '',
       required: true,
       allowClear: true,
-      options: columns.map(item => ({
-        value: item.field,
-        text: `${item.label}锛�${item.field}锛塦
-      }))
+      options: columns
     },
     {
       type: 'text',
@@ -1363,6 +1437,19 @@
       }, {
         value: 'true',
         text: '鏄�'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'database',
+      label: '鏁版嵁搴�',
+      initVal: card.database || 'local',
+      options: [{
+        value: 'local',
+        text: '鏈湴'
+      }, {
+        value: 'sso',
+        text: '鍗曠偣'
       }]
     },
     {
@@ -1718,6 +1805,24 @@
     extraParam.push('dataM')
   }
 
+  let apps = []
+  let merchs = []
+
+  if (window.GLOB.WXApps) {
+    window.GLOB.WXApps.forEach(item => {
+      if (item.appType === 'merchant') {
+        merchs.push({value: item.appId, text: item.appName})
+      } else {
+        apps.push({value: item.appId, text: item.appName})
+      }
+    })
+  }
+
+  let width = card.width || (card.width === 0 ? 0 : 12)
+  if (card.width && /x/.test(card.width)) {
+    width = +width.replace(/x/, '.5')
+  }
+
   let forms = [
     {
       type: 'select',
@@ -1778,20 +1883,20 @@
       required: true,
       options: []
     },
-    {
-      type: 'checkbox',
-      key: 'payType',
-      label: '鏀粯鏂瑰紡',
-      initVal: card.payType || [],
-      required: true,
-      options: [{
-        value: 'wxpay',
-        text: '寰俊'
-      // }, {
-      //   value: 'alipay',
-      //   text: '鏀粯瀹�'
-      }]
-    },
+    // {
+    //   type: 'checkbox',
+    //   key: 'payType',
+    //   label: '鏀粯鏂瑰紡',
+    //   initVal: card.payType || [],
+    //   required: true,
+    //   options: [{
+    //     value: 'wxpay',
+    //     text: '寰俊'
+    //   // }, {
+    //   //   value: 'alipay',
+    //   //   text: '鏀粯瀹�'
+    //   }]
+    // },
     {
       type: 'radio',
       key: 'procMode',
@@ -1827,15 +1932,6 @@
     },
     {
       type: 'text',
-      key: 'innerFunc',
-      label: '鍐呴儴鍑芥暟',
-      initVal: card.innerFunc || '',
-      tooltip: functip,
-      fields: usefulFields,
-      required: false,
-    },
-    {
-      type: 'text',
       key: 'urlkey',
       label: '鍦板潃瀛楁',
       initVal: card.urlkey || '',
@@ -1850,6 +1946,53 @@
       initVal: card.pageTemplate || '',
       required: true,
       options: pageTemps
+    },
+    {
+      type: 'radio',
+      key: 'payMode',
+      label: '鍙傛暟澶勭悊',
+      initVal: card.payMode || 'none',
+      tooltip: '鏀粯锛堟垨閫�娆撅級鍗曞彿鐨勯澶勭悊鏂瑰紡銆�',
+      required: true,
+      options: [{
+        value: 'system',
+        text: '绯荤粺鍑芥暟'
+      }, {
+        value: 'inner',
+        text: '鍐呴儴鍑芥暟'
+      }, {
+        value: 'none',
+        text: '鏃�'
+      }]
+    },
+    {
+      type: 'select',
+      key: 'wxApp',
+      label: '鍏宠仈搴旂敤',
+      initVal: card.wxApp || '',
+      tooltip: '璇峰叧鑱旀敮浠樼殑鍏紬鍙锋垨灏忕▼搴忋��',
+      required: true,
+      forbid: apps.length === 0,
+      options: apps
+    },
+    {
+      type: 'select',
+      key: 'wxMerch',
+      label: '鍏宠仈鍟嗘埛',
+      initVal: card.wxMerch || '',
+      tooltip: '璇峰叧鑱旀敮浠樼殑鍟嗘埛鍙枫��',
+      required: true,
+      forbid: merchs.length === 0,
+      options: merchs
+    },
+    {
+      type: 'text',
+      key: 'innerFunc',
+      label: '鍐呴儴鍑芥暟',
+      initVal: card.innerFunc || '',
+      tooltip: functip,
+      fields: usefulFields,
+      required: false,
     },
     {
       type: 'printTemps',
@@ -2064,7 +2207,7 @@
       key: 'execSuccess',
       label: '鎴愬姛鍚�',
       initVal: card.execSuccess || 'grid',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊閭d竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�鑱氱劍琛ㄥ崟璇蜂互 @focus:鑱氱劍瀛楁@ 鏍煎紡杩斿洖銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�鑱氱劍琛ㄥ崟璇蜂互 @focus:鑱氱劍瀛楁@ 鏍煎紡杩斿洖銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙no_target_menu@ 涓嶆墽琛屾墦寮�鑿滃崟銆�',
       required: true,
       options: [{
         value: 'never',
@@ -2092,7 +2235,7 @@
       key: 'execError',
       label: '澶辫触鍚�',
       initVal: card.execError || 'never',
-      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊鍝竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級銆�',
+      tooltip: refresh.length ? '鎵ц鍒锋柊婧愮粍浠舵椂锛岃鍦ㄦ簮鎸夐挳锛堝脊绐楁寜閽級涓缃叧闂悗鍒锋柊鍝竴椤癸紝娉細姝ゆ椂浼氬悓姝ュ埛鏂板綋鍓嶇粍浠跺拰涓婄骇缁勪欢-琛屻�傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙open_target_menu@ 鍙墽琛屾墦寮�鑿滃崟銆�' : '閫夋嫨鍒锋柊琛屾椂锛屽鏋滈�夋嫨澶氭潯鏁版嵁浼氬埛鏂扮粍浠讹紱閫夋嫨鍒锋柊琛� / 缁勪欢鏃讹紝濡傛灉褰撳墠琛屾暟鎹笉瀛樺湪浼氬埛鏂扮粍浠躲�傛敞锛氫笂绾х粍浠跺湪鏁版嵁婧愪腑娣诲姞銆傚闇�璇煶鎾姤璇蜂互@speak@寮�澶达紝鎾姤鍐呭鎴栨枃浠舵斁缃簬<<>>涓�傝繑鍥炰俊鎭紙@retmsg锛夌壒娈婃爣璇嗭細@close_tab@ 鎵ц锛堝叧闂爣绛�-绠$悊绯荤粺锛夛紱@close_popup@ 鎵ц锛堝叧闂脊绐楋級锛汙goback@ 鎵ц锛堣繑鍥炰笂涓�椤�-瀛愬簲鐢級锛汙open_target_menu@ 鍙墽琛屾墦寮�鑿滃崟銆�',
       required: true,
       options: [{
         value: 'never',
@@ -2201,18 +2344,18 @@
       tooltip: '鍒嗕韩鏃跺鐢ㄦ埛鐨勬彁绀轰俊鎭��',
       required: false
     },
-    // {
-    //   type: 'number',
-    //   key: 'width',
-    //   min: 1,
-    //   max: 24,
-    //   precision: 0,
-    //   label: '瀹藉害',
-    //   initVal: card.width || 12,
-    //   tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
-    //   forbid: card.eleType !== 'button',
-    //   required: true
-    // },
+    {
+      type: 'number',
+      key: 'width',
+      min: 0,
+      max: 24,
+      precision: 1,
+      label: '瀹藉害',
+      initVal: width,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼�備负 0 鏃跺搴﹁嚜閫傚簲銆傚彲璁剧疆鍗婂垪鍗�.5銆�',
+      forbid: position !== 'line',
+      required: true
+    },
     {
       type: 'radio',
       key: 'show',
@@ -2276,9 +2419,31 @@
       key: 'syncComponent',
       label: '鍒锋柊缁勪欢',
       initVal: card.syncComponent || [],
-      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧脊绐楁爣绛惧叧闂椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎵ц澶辫触涓斿瓨鍦ㄥ埛鏂伴」銆佸脊绐楁爣绛惧叧闂級锛岄渶瑕佸悓姝ュ埛鏂扮殑缁勪欢銆傛敞锛氶�夋嫨褰撳墠缁勪欢鐨勪笂绾х粍浠舵棤鏁堬紝鍒锋柊涓婄骇缁勪欢璇烽�夋嫨鎴愬姛鍚庘�滃埛鏂颁笂绾х粍浠� - 琛屸�濄��',
       required: false,
       options: modules.length ? [...modules, {value: 'multiComponent', label: '澶氱粍浠�'}] : []
+    },
+    {
+      type: 'cascader',
+      key: 'refreshTab',
+      label: '鍒锋柊鑿滃崟',
+      initVal: card.refreshTab || [],
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栨墽琛屽け璐ヤ笖瀛樺湪鍒锋柊椤规椂锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑鑿滃崟',
+      required: false,
+      forbid: viewType === 'popview',
+      options: menulist
+    },
+    {
+      type: 'cascader',
+      key: 'openmenu',
+      label: '鎵撳紑鑿滃崟',
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧け璐ユ椂杩斿洖@open_target_menu@锛夐渶瑕佹墦寮�鐨勮彍鍗曘��',
+      initVal: card.openmenu || [],
+      extendName: 'MenuNo',
+      required: false,
+      allowClear: true,
+      options: menulist,
+      forbid: viewType === 'popview'
     },
     {
       type: 'radio',
@@ -2308,28 +2473,6 @@
         value: 'false',
         text: '闈炲繀濉�'
       }]
-    },
-    {
-      type: 'cascader',
-      key: 'refreshTab',
-      label: '鍒锋柊鑿滃崟',
-      initVal: card.refreshTab || [],
-      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧姛鑳芥寜閽腑鏍囩鍏抽棴绫诲瀷锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑鑿滃崟',
-      required: false,
-      forbid: viewType === 'popview',
-      options: menulist
-    },
-    {
-      type: 'cascader',
-      key: 'openmenu',
-      label: '鎵撳紑鑿滃崟',
-      tooltip: '鎵ц鎴愬姛鍚庨渶瑕佹墦寮�鐨勮彍鍗曘��',
-      initVal: card.openmenu || [],
-      extendName: 'MenuNo',
-      required: false,
-      allowClear: true,
-      options: menulist,
-      forbid: viewType === 'popview'
     },
     {
       type: 'text',
@@ -2558,6 +2701,19 @@
     },
     {
       type: 'radio',
+      key: 'database',
+      label: '鏁版嵁搴�',
+      initVal: card.database || 'local',
+      options: [{
+        value: 'local',
+        text: '鏈湴'
+      }, {
+        value: 'sso',
+        text: '鍗曠偣'
+      }]
+    },
+    {
+      type: 'radio',
       key: 'permission',
       label: '鏉冮檺楠岃瘉',
       initVal: card.permission || 'true',
diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx
index 96a9190..c30f245 100644
--- a/src/menu/components/share/actioncomponent/index.jsx
+++ b/src/menu/components/share/actioncomponent/index.jsx
@@ -20,6 +20,7 @@
 const VerifyExcelIn = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelin'))
 const VerifyExcelOut = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelout'))
 const VerifyMegvii = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifymegvii'))
+const VerifyPay = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifypay'))
 
 class ActionComponent extends Component {
   static propTpyes = {
@@ -162,6 +163,8 @@
   addButton = (cardId, element) => {
     if (cardId !== this.props.config.uuid) return
 
+    delete element.eleType
+    
     const { actionlist } = this.state
 
     this.setState({actionlist: [...actionlist, element]})
@@ -487,19 +490,19 @@
    */
   deleteElement = (card) => {
     const { config } = this.props
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 - ${card.label} 锛焋,
       onOk() {
-        let _actionlist = fromJS(_this.state.actionlist).toJS()
+        let _actionlist = fromJS(that.state.actionlist).toJS()
 
         _actionlist = _actionlist.filter(item => item.uuid !== card.uuid)
 
-        _this.setState({
+        that.setState({
           actionlist: _actionlist
         }, () => {
-          _this.props.updateaction({...config, action: _actionlist})
+          that.props.updateaction({...config, action: _actionlist})
         })
       },
       onCancel() {}
@@ -522,7 +525,7 @@
   verifySubmit = () => {
     const { config } = this.props
     const { card } = this.state
-    
+
     this.verifyRef.handleConfirm().then(res => {
       let _actionlist = fromJS(this.state.actionlist).toJS()
       _actionlist = _actionlist.filter(item => !item.origin || item.uuid === card.uuid)
@@ -696,6 +699,12 @@
         columns={config.columns}
         wrappedComponentRef={(inst) => this.verifyRef = inst}
       />
+    } else if (card.payMode === 'system') {
+      return <VerifyPay
+        card={card}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
     }
   }
 
diff --git a/src/menu/components/share/colsControl/index.jsx b/src/menu/components/share/colsControl/index.jsx
index 882c037..29a113c 100644
--- a/src/menu/components/share/colsControl/index.jsx
+++ b/src/menu/components/share/colsControl/index.jsx
@@ -245,7 +245,7 @@
     _config.colsCtrls = colsCtrls
 
     if (this.customForm && this.customForm.state.editItem) {
-      const _this = this
+      const that = this
       let title = '瀛樺湪鏈繚瀛橀」锛岀‘瀹氬拷鐣ュ悧锛�'
       if (s.length > 0) {
         title = `瀛樺湪鏈繚瀛橀」锛屼笖绗� ${s.join('銆�')} 琛屼腑瀛楁鍦ㄦ悳绱㈡潯浠朵腑涓嶅瓨鍦紝纭畾蹇界暐鍚楋紵`
@@ -253,18 +253,18 @@
       confirm({
         title: title,
         onOk() {
-          _this.setState({ visible: false })
-          _this.props.onSubmit(_config)
+          that.setState({ visible: false })
+          that.props.onSubmit(_config)
         },
         onCancel() {}
       })
     } else if (s.length > 0) {
-      const _this = this
+      const that = this
       confirm({
         title: `绗� ${s.join('銆�')} 琛屼腑瀛楁鍦ㄦ悳绱㈡潯浠朵腑涓嶅瓨鍦紝纭畾蹇界暐鍚楋紵`,
         onOk() {
-          _this.setState({ visible: false })
-          _this.props.onSubmit(_config)
+          that.setState({ visible: false })
+          that.props.onSubmit(_config)
         },
         onCancel() {}
       })
diff --git a/src/menu/components/share/copycomponent/index.jsx b/src/menu/components/share/copycomponent/index.jsx
index af234aa..3cebc71 100644
--- a/src/menu/components/share/copycomponent/index.jsx
+++ b/src/menu/components/share/copycomponent/index.jsx
@@ -11,39 +11,55 @@
     card: PropTypes.object
   }
 
+  transConfig = (config, type) => {
+    if (type === 'menucell') {
+      config.setting.type = 'linkmenu'
+      config.setting.linkMenuId = ''
+      config.setting.copyMenuId = ''
+    } else if (type === 'mobnavbar') {
+      delete config.open_edition
+      delete config.dataName
+
+      config.menus.forEach(item => {
+        item.property = 'menu'
+        item.open = 'self'
+
+        delete item.copyMenuId
+        delete item.clearMenu
+        delete item.linkMenuId
+      })
+    } else if (config.type === 'menubar' && config.subtype === 'menubar') {
+      let cell = config.subMenus[0]
+      config.subMenus = []
+
+      if (cell) {
+        cell.setting.type = 'menu'
+        cell.setting.linkMenuId = ''
+        cell.setting.copyMenuId = ''
+
+        config.subMenus.push(cell)
+      }
+    } else if (['normaltable', 'editable', 'basetable'].includes(type)) {
+      config.action = config.action.filter(item => !item.origin)
+      config.cols = config.cols.filter(item => !item.origin)
+      config.search = config.search.filter(item => !item.origin)
+      delete config.isNew
+    }
+  }
+
   trigger = () => {
     const { card, type } = this.props
     let _val = fromJS(card).toJS()
     _val.copyType = type
 
+    this.transConfig(_val, type)
+
     try {
       delete _val.$srcId
     
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         _val.$srcId = srcid
-      }
-
-      if (type === 'menucell') {
-        _val.setting.type = 'linkmenu'
-        _val.setting.linkMenuId = ''
-        _val.setting.copyMenuId = ''
-      } else if (_val.type === 'menubar' && _val.subtype === 'menubar') {
-        let cell = _val.subMenus[0]
-        _val.subMenus = []
-
-        if (cell) {
-          cell.setting.type = 'menu'
-          cell.setting.linkMenuId = ''
-          cell.setting.copyMenuId = ''
-
-          _val.subMenus.push(cell)
-        }
-      } else if (['normaltable', 'editable', 'basetable'].includes(type)) {
-        _val.action = _val.action.filter(item => !item.origin)
-        _val.cols = _val.cols.filter(item => !item.origin)
-        _val.search = _val.search.filter(item => !item.origin)
-        delete _val.isNew
       }
 
       _val = window.btoa(window.encodeURIComponent(JSON.stringify(_val)))
diff --git a/src/menu/components/share/markcomponent/index.jsx b/src/menu/components/share/markcomponent/index.jsx
index 7185bea..160c1dd 100644
--- a/src/menu/components/share/markcomponent/index.jsx
+++ b/src/menu/components/share/markcomponent/index.jsx
@@ -399,12 +399,12 @@
       })
       this.props.onSubmit(marks)
     } else {
-      const _this = this
+      const that = this
       confirm({
         title: '瀛樺湪鏈繚瀛樻爣璁帮紝纭畾蹇界暐鍚楋紵',
         onOk() {
-          _this.setState({ visible: false })
-          _this.props.onSubmit(marks)
+          that.setState({ visible: false })
+          that.props.onSubmit(marks)
         },
         onCancel() {}
       })
diff --git a/src/menu/components/share/searchcomponent/dragsearch/index.jsx b/src/menu/components/share/searchcomponent/dragsearch/index.jsx
index 87b345e..3ead8c1 100644
--- a/src/menu/components/share/searchcomponent/dragsearch/index.jsx
+++ b/src/menu/components/share/searchcomponent/dragsearch/index.jsx
@@ -46,7 +46,7 @@
     try {
       delete _val.$srcId
     
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         _val.$srcId = srcid
       }
diff --git a/src/menu/components/share/searchcomponent/index.jsx b/src/menu/components/share/searchcomponent/index.jsx
index b809cb9..6eca698 100644
--- a/src/menu/components/share/searchcomponent/index.jsx
+++ b/src/menu/components/share/searchcomponent/index.jsx
@@ -205,7 +205,7 @@
         return
       }
 
-      if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && res.database !== 'sso' && /\s/.test(res.dataSource)) {
         this.setState({
           sqlVerifing: true
         })
@@ -213,13 +213,8 @@
         let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
         ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
-
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
         
-        Api.sDebug(sql, rduri).then(result => {
+        Api.sDebug(sql).then(result => {
           if (result.status || result.ErrCode === '-2') {
             this.setState({
               sqlVerifing: false,
@@ -252,19 +247,19 @@
    */
   deleteElement = (card) => {
     const { config } = this.props
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 - ${card.label} 锛焋,
       onOk() {
-        let _searchlist = fromJS(_this.state.searchlist).toJS()
+        let _searchlist = fromJS(that.state.searchlist).toJS()
 
         _searchlist = _searchlist.filter(item => item.uuid !== card.uuid)
 
-        _this.setState({
+        that.setState({
           searchlist: _searchlist
         }, () => {
-          _this.props.updatesearch({...config, search: _searchlist})
+          that.props.updatesearch({...config, search: _searchlist})
         })
       },
       onCancel() {}
@@ -286,7 +281,7 @@
         <Modal
           title="鎼滅储鏉′欢-缂栬緫"
           visible={visible}
-          width={850}
+          width={950}
           maskClosable={false}
           onOk={this.handleSubmit}
           confirmLoading={sqlVerifing}
diff --git a/src/menu/components/share/sourcecomponent/index.jsx b/src/menu/components/share/sourcecomponent/index.jsx
index fe17598..c8f515b 100644
--- a/src/menu/components/share/sourcecomponent/index.jsx
+++ b/src/menu/components/share/sourcecomponent/index.jsx
@@ -74,12 +74,12 @@
         </Radio.Group> : null}
         {url && type === 'video' ? <div className="mk-source-item-info">
           <PaperClipOutlined />
-          <a target="_blank" rel="noopener noreferrer" href={url}>{name}</a>
+          <a target="_blank" rel="noopener noreferrer" href={url.replace(/@mywebsite@\//ig, window.GLOB.baseurl)}>{name}</a>
           <DeleteOutlined title="鍒犻櫎鏂囦欢" onClick={this.deleteUrl}/>
         </div> : null}
         {url && type !== 'video' && url !== '@icon@' ? <div className="mk-source-item-info picture">
           <img src={url.replace(/@mywebsite@\//ig, window.GLOB.baseurl)} alt="" />
-          <a target="_blank" rel="noopener noreferrer" href={url}>{name}</a>
+          <a target="_blank" rel="noopener noreferrer" href={url.replace(/@mywebsite@\//ig, window.GLOB.baseurl)}>{name}</a>
           <DeleteOutlined title="鍒犻櫎鏂囦欢" onClick={this.deleteUrl}/>
         </div> : null}
         {url && type !== 'video' && url === '@icon@' ? <div className="mk-source-item-info avatar">
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 cd62ff5..9c10aac 100644
--- a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -442,6 +442,21 @@
       required: true
     },
     {
+      type: 'checkbox',
+      key: 'evalchars',
+      label: '鏇挎崲瀛楃',
+      initVal: card.evalchars || ['enter', 'space'],
+      tooltip: '鍏紡瑙f瀽鍚庯紝鍙浛鎹㈠洖杞︺�佺┖鏍肩瓑瀛楃锛屽疄鐜版崲琛屻�佸瓧闂磋窛鎺у埗绛夐〉闈㈡晥鏋溿��',
+      required: false,
+      options: [{
+        value: 'enter',
+        text: '鍥炶溅绗�'
+      }, {
+        value: 'space',
+        text: '绌烘牸'
+      }]
+    },
+    {
       type: 'radio',
       key: 'noValue',
       label: '绌哄��',
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 dac43a3..fd0ad48 100644
--- a/src/menu/components/table/base-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -95,8 +95,13 @@
       } else if (this.record.perspective === 'linkurl') {
         _options.push('linkurl', 'open')
       }
-    } else if (this.record.type === 'formula' && this.record.eval === 'true') {
-      _options.push('decimal')
+    } else if (this.record.type === 'formula') {
+      if (this.record.eval === 'true') {
+        _options.push('decimal')
+      }
+      if (this.record.eval !== 'func') {
+        _options.push('evalchars')
+      }
     } else if (this.record.type === 'custom' && this.record.IsSort === 'true') {
       _options.push('sortField')
     }
diff --git a/src/menu/components/table/base-table/columns/index.jsx b/src/menu/components/table/base-table/columns/index.jsx
index aad0434..96d01c3 100644
--- a/src/menu/components/table/base-table/columns/index.jsx
+++ b/src/menu/components/table/base-table/columns/index.jsx
@@ -21,12 +21,12 @@
 
 class HeaderCol extends Component {
   deleteCol = () => {
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍒犻櫎鏄剧ず鍒楀悧锛�',
       onOk() {
-        _this.props.deleteCol(_this.props.column)
+        that.props.deleteCol(that.props.column)
       },
       onCancel() {}
     })
@@ -193,10 +193,10 @@
         val = '$Index'
       } else if (column.type === 'formula') {
         val = column.formula
-        if (column.eval === 'false') {
-          val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
-          val = <span style={{fontWeight: 'inherit'}} dangerouslySetInnerHTML={{__html: val}}></span>
-        }
+        // if (column.eval === 'false') {
+        //   val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        //   val = <span style={{fontWeight: 'inherit'}} dangerouslySetInnerHTML={{__html: val}}></span>
+        // }
       }
       return (
         <td style={{...style}} className={className}>
@@ -549,7 +549,7 @@
       cols: columns.filter(col => !col.origin)
     }
 
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
diff --git a/src/menu/components/table/base-table/options.jsx b/src/menu/components/table/base-table/options.jsx
index 288cd00..8c3f5fa 100644
--- a/src/menu/components/table/base-table/options.jsx
+++ b/src/menu/components/table/base-table/options.jsx
@@ -76,19 +76,18 @@
         {value: 'mini', 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: 'searchSize',
+      label: '鎼滅储闂磋窛',
+      initval: wrap.searchSize || 'middle',
+      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      required: false,
+      options: [
+        {value: 'middle', label: '榛樿'},
+        {value: 'small', label: '灏�'},
+      ],
+    },
     {
       type: 'radio',
       field: 'tableMode',
@@ -151,10 +150,10 @@
     {
       type: 'number',
       field: 'height',
-      label: '琛ㄦ牸楂樺害',
+      label: '鏈�澶ч珮搴�',
       initval: wrap.height || '',
-      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100鏃朵负楂樺害鐨勭櫨鍒嗘瘮銆�',
-      min: 10,
+      tooltip: '琛ㄦ牸鍐呭鍖虹殑鏈�澶ч珮搴︼紙涓嶅寘鍚〃澶达級锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100澶т簬0鏃朵负楂樺害鐨勭櫨鍒嗘瘮锛屽皬浜�0鏃朵负绐楀彛楂樺害鍑忓幓姝ゅ�笺��',
+      min: -1000,
       max: 3000,
       precision: 0,
       required: false,
@@ -186,6 +185,7 @@
       tooltip: '榧犳爣鎮诞浜庤涓婃柟鏃剁殑鎻愮ず淇℃伅銆�',
       required: false,
       allowClear: true,
+      joint: true,
       options: columns
     },
     {
@@ -196,6 +196,7 @@
       tooltip: '鐢ㄤ簬鎺у埗琛屾暟鎹槸鍚﹀彲閫夋嫨銆�',
       required: false,
       allowClear: true,
+      joint: true,
       options: columns,
       controlFields: [
         {field: 'controlVal', notNull: true},
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 4379c5c..b0b999e 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -446,7 +446,7 @@
       key: 'dataSource',
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
-      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�粿BID@銆�',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�硷細@BID@銆丂Appkey@銆丂UserID@銆丂SessionUid@銆丂LoginUID@銆丂lang@銆�',
       required: true,
     },
     {
@@ -562,6 +562,7 @@
       tooltip: '鐢ㄤ簬鎺у埗琛屾暟鎹槸鍚﹀彲閫夋嫨銆傚瓧娈靛�间负true鏃讹紝閫夐」涓嶅彲閫夈��',
       required: false,
       allowClear: true,
+      joint: true,
       options: 'columns'
     },
     {
@@ -694,7 +695,7 @@
         text: '鏈湴'
       }, {
         value: 'sso',
-        text: '绯荤粺'
+        text: '鍗曠偣'
       }]
     },
     {
@@ -831,6 +832,21 @@
       options: fields
     },
     {
+      type: 'checkbox',
+      key: 'evalchars',
+      label: '鏇挎崲瀛楃',
+      initVal: card.evalchars || ['enter', 'space'],
+      tooltip: '鍏紡瑙f瀽鍚庯紝鍙浛鎹㈠洖杞︺�佺┖鏍肩瓑瀛楃锛屽疄鐜版崲琛屻�佸瓧闂磋窛鎺у埗绛夐〉闈㈡晥鏋溿��',
+      required: false,
+      options: [{
+        value: 'enter',
+        text: '鍥炶溅绗�'
+      }, {
+        value: 'space',
+        text: '绌烘牸'
+      }]
+    },
+    {
       type: 'radio',
       key: 'noValue',
       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 dd97ea0..2515403 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/edit-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, Modal, notification, Popover } from 'antd'
+import { Form, Row, Col, Input, Select, InputNumber, Radio, Checkbox, Tooltip, Modal, notification, Popover } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -107,8 +107,13 @@
         _options.push('hourFormat')
       }
     }
-    if (this.record.type === 'formula' && this.record.eval === 'true') {
-      _options.push('decimal')
+    if (this.record.type === 'formula') {
+      if (this.record.eval === 'true') {
+        _options.push('decimal')
+      }
+      if (this.record.eval !== 'func') {
+        _options.push('evalchars')
+      }
     } else if (this.record.type === 'custom' && this.record.IsSort === 'true') {
       _options.push('sortField')
     }
@@ -402,6 +407,15 @@
         content = <Radio.Group onChange={(e) => {this.typeChange(item.key, e.target.value)}}>
           {item.options.map(option => <Radio key={option.value} value={option.value}>{option.text}</Radio>)}
         </Radio.Group>
+      } else if (item.type === 'checkbox') {
+        rules = [
+          { required: item.required, message: '璇烽�夋嫨' + item.label + '!' }
+        ]
+        initVal = item.initVal
+
+        content = <Checkbox.Group onChange={(e) => {this.typeChange(item.key, e.target.value)}}>
+          {item.options.map(option => <Checkbox key={option.value} value={option.value}>{option.text}</Checkbox>)}
+        </Checkbox.Group>
       } else if (item.type === 'multiselect') { // 澶氶��
         content = <Select
           showSearch
@@ -447,6 +461,7 @@
           extra = <span className="add-resource-empty" onClick={this.handleEmpty}>绌�</span>
         }
         if (item.placeholder) {
+          className = 'show-public-var'
           extra = <><span className="resource-public-var">{item.placeholder}</span>{extra}</>
         }
 
@@ -580,7 +595,7 @@
           if (!pass) return
         }
 
-        if (values.editType === 'select' && values.resourceType === '1' && values.dataSource) {
+        if (values.editType === 'select' && values.resourceType === '1' && values.database !== 'sso' && values.dataSource) {
           let _option = Utils.getSelectQueryOptions(values)
 
           let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
@@ -588,13 +603,8 @@
   
           // LoginUID|SessionUid|UserID|Appkey 宸叉浛鎹�
           sql = sql.replace(/@\$|\$@/ig, '')
-  
-          let rduri = ''
-          if (window.GLOB.mainSystemApi && values.database === 'sso') {
-            rduri = window.GLOB.mainSystemApi
-          }
           
-          Api.sDebug(sql, rduri).then(result => {
+          Api.sDebug(sql).then(result => {
             if (result.status || result.ErrCode === '-2') {
               this.setState({visible: false, loading: false, formlist: null})
               this.props.submitCol(values)
@@ -692,7 +702,7 @@
           title="鏄剧ず鍒楃紪杈�"
           wrapClassName="mk-scroll-modal"
           visible={visible}
-          width={900}
+          width={950}
           maskClosable={false}
           onOk={this.handleSubmit}
           onCancel={this.editModalCancel}
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 f2127e8..35a64a8 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/index.scss
+++ b/src/menu/components/table/edit-table/columns/editColumn/index.scss
@@ -44,11 +44,16 @@
     cursor: pointer;
     font-size: 14px;
   }
+  .show-public-var {
+    margin-top: 20px;
+  }
   .resource-public-var {
     position: absolute;
     left: 0px;
-    top: -25px;
-    font-size: 14px;
+    top: -45px;
+    right: 40px;
+    font-size: 13px;
+    color: rgba(0, 0, 0, 0.65);
   }
 }
 .formula-fields {
diff --git a/src/menu/components/table/edit-table/columns/index.jsx b/src/menu/components/table/edit-table/columns/index.jsx
index 120c12b..fcf33b1 100644
--- a/src/menu/components/table/edit-table/columns/index.jsx
+++ b/src/menu/components/table/edit-table/columns/index.jsx
@@ -22,12 +22,12 @@
 
 class HeaderCol extends Component {
   deleteCol = () => {
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍒犻櫎鏄剧ず鍒楀悧锛�',
       onOk() {
-        _this.props.deleteCol(_this.props.column)
+        that.props.deleteCol(that.props.column)
       },
       onCancel() {}
     })
@@ -47,7 +47,7 @@
       cols: [column]
     }
 
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
@@ -195,10 +195,10 @@
         val = '$Index'
       } else if (column.type === 'formula') {
         val = column.formula
-        if (column.eval === 'false') {
-          val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
-          val = <span style={{fontWeight: 'inherit'}} dangerouslySetInnerHTML={{__html: val}}></span>
-        }
+        // if (column.eval === 'false') {
+        //   val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        //   val = <span style={{fontWeight: 'inherit'}} dangerouslySetInnerHTML={{__html: val}}></span>
+        // }
       }
       return (
         <td style={style} className={className}>
@@ -553,7 +553,7 @@
       cols: columns.filter(col => !col.origin)
     }
 
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
@@ -597,13 +597,13 @@
       columns.push(cell)
     })
 
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍚屾瀛楁闆嗗悧锛�',
       onOk() {
-        _this.setState({columns}, () => {
-          _this.props.updatecolumn({..._this.props.config, cols: columns})
+        that.setState({columns}, () => {
+          that.props.updatecolumn({...that.props.config, cols: columns})
         })
       },
       onCancel() {}
@@ -611,13 +611,13 @@
   }
 
   clear = () => {
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾娓呯┖鏄剧ず鍒楀悧锛�',
       onOk() {
-        _this.setState({columns: []}, () => {
-          _this.props.updatecolumn({..._this.props.config, cols: []})
+        that.setState({columns: []}, () => {
+          that.props.updatecolumn({...that.props.config, cols: []})
         })
       },
       onCancel() {}
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 e1a539a..274f82e 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
@@ -152,6 +152,8 @@
         let sql = this.state.verifySql + _initCustomScript + _prevCustomScript + _backCustomScript + tail
         
         sql = sql.replace(/@\$|\$@/ig, '')
+        sql = sql.replace(/@datam@/ig, `''`)
+        sql = sql.replace(/@typename@/ig, `'debug'`)
 
         if (skip) {
           this.setState({
@@ -266,12 +268,12 @@
           </Col> : null}
           {!type ? <Col span={10}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
+              errorcode, retmsg
             </Form.Item>
           </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={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, LoginUID, SessionUid, UserID, Appkey, lang, typename, datam, 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>
diff --git a/src/menu/components/table/edit-table/options.jsx b/src/menu/components/table/edit-table/options.jsx
index 78c1a63..1e409a4 100644
--- a/src/menu/components/table/edit-table/options.jsx
+++ b/src/menu/components/table/edit-table/options.jsx
@@ -45,10 +45,10 @@
     {
       type: 'number',
       field: 'height',
-      label: '楂樺害',
+      label: '鏈�澶ч珮搴�',
       initval: wrap.height || '',
-      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100鏃朵负楂樺害鐨勭櫨鍒嗘瘮銆�',
-      min: 10,
+      tooltip: '琛ㄦ牸鍐呭鍖虹殑鏈�澶ч珮搴︼紙涓嶅寘鍚〃澶达級锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100澶т簬0鏃朵负楂樺害鐨勭櫨鍒嗘瘮锛屽皬浜�0鏃朵负绐楀彛楂樺害鍑忓幓姝ゅ�笺��',
+      min: -1000,
       max: 3000,
       precision: 0,
       required: false
@@ -127,6 +127,18 @@
         {value: 'small', label: '灏�'},
         // {value: 'mini', label: '杩蜂綘'},
       ]
+    },
+    {
+      type: 'radio',
+      field: 'searchSize',
+      label: '鎼滅储闂磋窛',
+      initval: wrap.searchSize || 'middle',
+      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      required: false,
+      options: [
+        {value: 'middle', label: '榛樿'},
+        {value: 'small', label: '灏�'},
+      ],
     },
     {
       type: 'radio',
@@ -225,6 +237,7 @@
       tooltip: '榧犳爣鎮诞浜庤涓婃柟鏃剁殑鎻愮ず淇℃伅銆�',
       required: false,
       allowClear: true,
+      joint: true,
       options: columns
     },
     {
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 6ad02d3..e5c2d75 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -513,6 +513,21 @@
       required: true
     },
     {
+      type: 'checkbox',
+      key: 'evalchars',
+      label: '鏇挎崲瀛楃',
+      initVal: card.evalchars || ['enter', 'space'],
+      tooltip: '鍏紡瑙f瀽鍚庯紝鍙浛鎹㈠洖杞︺�佺┖鏍肩瓑瀛楃锛屽疄鐜版崲琛屻�佸瓧闂磋窛鎺у埗绛夐〉闈㈡晥鏋溿��',
+      required: false,
+      options: [{
+        value: 'enter',
+        text: '鍥炶溅绗�'
+      }, {
+        value: 'space',
+        text: '绌烘牸'
+      }]
+    },
+    {
       type: 'radio',
       key: 'noValue',
       label: '绌哄��',
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 5f3d09c..9ec8a74 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/index.jsx
@@ -94,8 +94,13 @@
       } else if (this.record.perspective === 'linkurl') {
         _options.push('linkurl', 'open')
       }
-    } else if (this.record.type === 'formula' && this.record.eval === 'true') {
-      _options.push('decimal')
+    } else if (this.record.type === 'formula') {
+      if (this.record.eval === 'true') {
+        _options.push('decimal')
+      }
+      if (this.record.eval !== 'func') {
+        _options.push('evalchars')
+      }
     } else if (this.record.type === 'custom' && this.record.IsSort === 'true') {
       _options.push('sortField')
     } else if (this.record.type === 'extend') {
diff --git a/src/menu/components/table/normal-table/columns/index.jsx b/src/menu/components/table/normal-table/columns/index.jsx
index 0279ed8..e6af839 100644
--- a/src/menu/components/table/normal-table/columns/index.jsx
+++ b/src/menu/components/table/normal-table/columns/index.jsx
@@ -22,12 +22,12 @@
 
 class HeaderCol extends Component {
   deleteCol = () => {
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍒犻櫎鏄剧ず鍒楀悧锛�',
       onOk() {
-        _this.props.deleteCol(_this.props.column)
+        that.props.deleteCol(that.props.column)
       },
       onCancel() {}
     })
@@ -47,7 +47,7 @@
       cols: [column]
     }
 
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
@@ -195,10 +195,10 @@
         val = '$Index'
       } else if (column.type === 'formula') {
         val = column.formula
-        if (column.eval === 'false') {
-          val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
-          val = <span style={{fontWeight: 'inherit'}} dangerouslySetInnerHTML={{__html: val}}></span>
-        }
+        // if (column.eval === 'false') {
+        //   val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        //   val = <span style={{fontWeight: 'inherit'}} dangerouslySetInnerHTML={{__html: val}}></span>
+        // }
       }
       return (
         <td style={{...style}} className={className}>
@@ -518,7 +518,7 @@
       cols: columns.filter(col => !col.origin)
     }
 
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
@@ -595,13 +595,13 @@
       columns.push(cell)
     })
 
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍚屾瀛楁闆嗗悧锛�',
       onOk() {
-        _this.setState({columns}, () => {
-          _this.props.updatecolumn({..._this.props.config, cols: columns})
+        that.setState({columns}, () => {
+          that.props.updatecolumn({...that.props.config, cols: columns})
         })
       },
       onCancel() {}
@@ -609,13 +609,13 @@
   }
 
   clear = () => {
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾娓呯┖鏄剧ず鍒楀悧锛�',
       onOk() {
-        _this.setState({columns: []}, () => {
-          _this.props.updatecolumn({..._this.props.config, cols: []})
+        that.setState({columns: []}, () => {
+          that.props.updatecolumn({...that.props.config, cols: []})
         })
       },
       onCancel() {}
diff --git a/src/menu/components/table/normal-table/options.jsx b/src/menu/components/table/normal-table/options.jsx
index 22662e1..1806ca8 100644
--- a/src/menu/components/table/normal-table/options.jsx
+++ b/src/menu/components/table/normal-table/options.jsx
@@ -52,10 +52,10 @@
     {
       type: 'number',
       field: 'height',
-      label: '楂樺害',
+      label: '鏈�澶ч珮搴�',
       initval: wrap.height || '',
-      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100鏃朵负楂樺害鐨勭櫨鍒嗘瘮銆�',
-      min: 10,
+      tooltip: '琛ㄦ牸鍐呭鍖虹殑鏈�澶ч珮搴︼紙涓嶅寘鍚〃澶达級锛岀┖鍊兼椂楂樺害鑷�傚簲銆傛敞锛氬皬浜庣瓑浜�100澶т簬0鏃朵负楂樺害鐨勭櫨鍒嗘瘮锛屽皬浜�0鏃朵负绐楀彛楂樺害鍑忓幓姝ゅ�笺��',
+      min: -1000,
       max: 3000,
       precision: 0,
       required: false,
@@ -161,6 +161,19 @@
     },
     {
       type: 'radio',
+      field: 'searchSize',
+      label: '鎼滅储闂磋窛',
+      initval: wrap.searchSize || 'middle',
+      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      required: false,
+      options: [
+        {value: 'middle', label: '榛樿'},
+        {value: 'small', label: '灏�'},
+      ],
+      forbid: appType === 'mob'
+    },
+    {
+      type: 'radio',
       field: 'mode',
       label: '妯″紡',
       initval: wrap.mode || 'default',
@@ -233,6 +246,7 @@
       tooltip: '榧犳爣鎮诞浜庤涓婃柟鏃剁殑鎻愮ず淇℃伅銆�',
       required: false,
       allowClear: true,
+      joint: true,
       options: columns
     },
     {
@@ -243,6 +257,7 @@
       tooltip: '鐢ㄤ簬鎺у埗琛屾暟鎹槸鍚﹀彲閫夋嫨銆�',
       required: false,
       allowClear: true,
+      joint: true,
       options: columns,
       controlFields: [
         {field: 'controlVal', notNull: true},
diff --git a/src/menu/components/tabs/antv-tabs/index.jsx b/src/menu/components/tabs/antv-tabs/index.jsx
index eaa3206..145bcdc 100644
--- a/src/menu/components/tabs/antv-tabs/index.jsx
+++ b/src/menu/components/tabs/antv-tabs/index.jsx
@@ -147,7 +147,7 @@
 
   delTab = (tab) => {
     let tabs = fromJS(this.state.tabs).toJS()
-    const _this = this
+    const that = this
 
     tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid)
 
@@ -155,8 +155,8 @@
       title: '纭畾鍒犻櫎鏍囩锛�',
       content: '',
       onOk() {
-        _this.setState({tabs})
-        _this.props.updateConfig(tabs)
+        that.setState({tabs})
+        that.props.updateConfig(tabs)
       },
       onCancel() {}
     })
@@ -223,6 +223,12 @@
     // editab.selectVal = res.selectVal || ''
     editab.blacklist = res.blacklist
 
+    if (/^\s+$/.test(editab.label) && editab.icon) {
+      editab.taType = 'only-icon'
+    } else {
+      delete editab.taType
+    }
+
     if (editab.uuid) {
       tabs.subtabs = tabs.subtabs.map(t => {
         if (t.uuid === editab.uuid) {
diff --git a/src/menu/components/tabs/antv-tabs/index.scss b/src/menu/components/tabs/antv-tabs/index.scss
index e45bad8..e8cac39 100644
--- a/src/menu/components/tabs/antv-tabs/index.scss
+++ b/src/menu/components/tabs/antv-tabs/index.scss
@@ -18,7 +18,7 @@
     padding-left: 0;
   }
   .ant-tabs-right-content {
-    padding-right: 0;
+    padding-right: 0!important;
   }
   .ant-tabs-bottom-bar {
     margin-top: 0;
diff --git a/src/menu/components/tabs/antv-tabs/options.jsx b/src/menu/components/tabs/antv-tabs/options.jsx
index 329358c..b547b6b 100644
--- a/src/menu/components/tabs/antv-tabs/options.jsx
+++ b/src/menu/components/tabs/antv-tabs/options.jsx
@@ -160,6 +160,21 @@
         {value: 'mk-tab-button', label: '鎸夐挳锛堝乏锛�'},
         {value: 'mk-tab-button tab-right', label: '鎸夐挳锛堝彸锛�'},
       ],
+      controlFields: [
+        {field: 'tabAlign', values: ['line']},
+      ]
+    },
+    {
+      type: 'select',
+      field: 'tabAlign',
+      label: '瀵归綈鏂瑰紡',
+      initval: setting.tabAlign || 'left',
+      required: true,
+      options: [
+        {value: 'left', label: '宸﹀榻�'},
+        {value: 'center', label: '灞呬腑瀵归綈'},
+        {value: 'right', label: '鍙冲榻�'},
+      ],
     },
     // {
     //   type: 'select',
diff --git a/src/menu/components/tabs/table-tabs/index.jsx b/src/menu/components/tabs/table-tabs/index.jsx
index 293312c..8dc040e 100644
--- a/src/menu/components/tabs/table-tabs/index.jsx
+++ b/src/menu/components/tabs/table-tabs/index.jsx
@@ -72,7 +72,7 @@
 
   delTab = (tab) => {
     let tabs = fromJS(this.state.tabs).toJS()
-    const _this = this
+    const that = this
 
     tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid)
 
@@ -80,8 +80,8 @@
       title: '纭畾鍒犻櫎鏍囩锛�',
       content: '',
       onOk() {
-        _this.setState({tabs})
-        _this.props.updateConfig(tabs)
+        that.setState({tabs})
+        that.props.updateConfig(tabs)
       },
       onCancel() {}
     })
diff --git a/src/menu/components/timeline/normal-timeline/options.jsx b/src/menu/components/timeline/normal-timeline/options.jsx
index a1ea98b..ae0be4d 100644
--- a/src/menu/components/timeline/normal-timeline/options.jsx
+++ b/src/menu/components/timeline/normal-timeline/options.jsx
@@ -206,7 +206,6 @@
       initval: wrap.empty || 'show',
       tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
       required: false,
-      skip: true,
       options: [
         {value: 'show', label: '鍚�'},
         {value: 'hidden', label: '鏄�'},
diff --git a/src/menu/datasource/index.jsx b/src/menu/datasource/index.jsx
index 92a16b3..f264a81 100644
--- a/src/menu/datasource/index.jsx
+++ b/src/menu/datasource/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Modal, Button } from 'antd'
+import { Modal, Button, notification } from 'antd'
 import { SettingOutlined } from '@ant-design/icons'
 
 import VerifyCard from './verifycard'
@@ -179,38 +179,100 @@
       }
 
       let maxScript = 0
+      let useExec = false
 
-      if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-        window.GLOB.funcs.forEach(m => {
-          let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
-          if (res.setting.dataresource) {
-            res.setting.dataresource = res.setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+      let sFields = []
+      res.searches && res.searches.forEach(item => {
+        if (!item.key) return
+    
+        if (item.type === 'date') {
+          if (sFields.includes(item.key)) {
+            sFields.push(item.key + '1')
+          } else {
+            sFields.push(item.key)
           }
-          res.scripts.forEach(item => {
-            item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-
-            if (item.status === 'false') return
-
-            if (/exec\s/ig.test(item.sql)) {
-              maxScript = 1000
-            } else if (item.sql.length > maxScript) {
-              maxScript = item.sql.length
-            }
+        } else if (item.type === 'dateweek' || item.type === 'range' || (item.type === 'datemonth' && item.match !== '=')) {
+          sFields.push(item.key)
+          sFields.push(item.key + '1')
+        } else if (item.type === 'daterange') {
+          if (/,/.test(item.key)) {
+            sFields.push(item.key.split(',')[0])
+            sFields.push(item.key.split(',')[1])
+          } else {
+            sFields.push(item.key)
+            sFields.push(item.key + '1')
+          }
+        } else if (item.type === 'text' || item.type === 'select') {
+          item.key.split(',').forEach(field => {
+            sFields.push(field)
           })
-        })
-      } else {
-        res.scripts.forEach(item => {
-          if (item.status === 'false') return
+        } else {
+          sFields.push(item.key)
+        }
+      })
+      delete res.searches
+      sFields = sFields.join('|')
 
-          if (/exec\s/ig.test(item.sql)) {
-            maxScript = 1000
-          } else if (item.sql.length > maxScript) {
-            maxScript = item.sql.length
-          }
-        })
+      // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+      //   window.GLOB.funcs.forEach(m => {
+      //     let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
+      //     if (res.setting.dataresource) {
+      //       res.setting.dataresource = res.setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+      //     }
+      //     res.scripts.forEach(item => {
+      //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+
+      //       if (item.status === 'false') return
+
+      //       if (/exec\s/ig.test(item.sql)) {
+      //         useExec = true
+      //         maxScript = 1000
+      //       } else if (item.sql.length > maxScript) {
+      //         maxScript = item.sql.length
+      //       }
+      //     })
+      //   })
+      // } else {
+      //   res.scripts.forEach(item => {
+      //     if (item.status === 'false') return
+
+      //     if (/exec\s/ig.test(item.sql)) {
+      //       useExec = true
+      //       maxScript = 1000
+      //     } else if (item.sql.length > maxScript) {
+      //       maxScript = item.sql.length
+      //     }
+      //   })
+      // }
+
+      if (res.setting.interType === 'system' && res.setting.dataresource && res.setting.execute !== 'false' && sFields) {
+        if (new RegExp(`@(${sFields})@`, 'ig').test(res.setting.dataresource)) {
+          maxScript = 1000
+        }
       }
 
+      res.scripts.forEach(item => {
+        if (item.status === 'false') return
+
+        if (/exec\s/ig.test(item.sql)) {
+          useExec = true
+          maxScript = 1000
+        } else if (sFields && new RegExp(`@(${sFields})@`, 'ig').test(item.sql)) {
+          maxScript = 1000
+        } else if (item.sql.length > maxScript) {
+          maxScript = item.sql.length
+        }
+      })
+
       res.setting.maxScript = maxScript
+
+      if (useExec && res.setting.sync === 'true') {
+        notification.warning({
+          top: 92,
+          message: '褰撳墠鏁版嵁婧愪娇鐢ㄤ簡鍚屾鏌ヨ涓旇嚜瀹氫箟鑴氭湰涓瓨鍦ㄥ嚱鏁癳xec锛屽閬囨帴鍙f姤閿欓渶鍏抽棴鍚屾鏌ヨ鍚庨噸鏂版祴璇曘��',
+          duration: 5
+        })
+      }
 
       if (config.subtype !== 'dualdatacard') {
         delete res.subColumns
@@ -277,6 +339,12 @@
     })
   }
 
+  cancel = () => {
+    this.verifyRef.closeDataSource(() => {
+      this.setState({ visible: false, loading: false })
+    })
+  }
+
   creatFunc = () => {
     const { config } = this.props
     const { mainSearch } = this.state
@@ -319,7 +387,7 @@
           onCancel={() => {this.setState({ visible: false, loading: false }) }}
           footer={[
             config.subtype !== 'dualdatacard' && record.interType === 'inner' ? <CreateFunc key="create" getMsg={this.creatFunc}/> : null,
-            <Button key="cancel" onClick={() => { this.setState({ visible: false, loading: false }) }}>鍙栨秷</Button>,
+            <Button key="cancel" onClick={this.cancel}>鍙栨秷</Button>,
             <Button key="confirm" type="primary" loading={loading} onClick={this.verifySubmit}>纭畾</Button>
           ]}
           destroyOnClose
diff --git a/src/menu/datasource/verifycard/customscript/index.jsx b/src/menu/datasource/verifycard/customscript/index.jsx
index 545d436..1a6b210 100644
--- a/src/menu/datasource/verifycard/customscript/index.jsx
+++ b/src/menu/datasource/verifycard/customscript/index.jsx
@@ -243,9 +243,9 @@
           </Col>
           <Col span={24}>
             <Form.Item label="鍙敤瀛楁" className="field-able">
-              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, LoginUID, SessionUid, UserID, Appkey, time_id, typename, datam</span></Tooltip>,&nbsp;
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, LoginUID, SessionUid, UserID, Appkey, lang, time_id, typename, datam{window.GLOB.getLocation ? ', mk_longitude, mk_latitude' : ''}</span></Tooltip>,&nbsp;
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
-              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎺掑簭銆佸垎椤典互鍙婃悳绱㈡潯浠跺彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆備娇鐢ˊpageSize@鎴朄orderBy@浠h〃鑷畾涔夊垎椤碉紝鎬绘暟璇蜂互mk_total杩斿洖銆�'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{type === 'calendar' ? ', mk_year' : ''}{hasExtend ? ', mk_time' : ''}</Tooltip>
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎺掑簭銆佸垎椤典互鍙婃悳绱㈡潯浠跺彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆備娇鐢ˊpageSize@銆丂orderBy@ 鎴栬剼鏈腑瀛樺湪 @mk_total 浠h〃鑷畾涔夊垎椤碉紝鎬绘暟璇蜂互mk_total杩斿洖銆�'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{type === 'calendar' ? ', mk_year' : ''}{hasExtend ? ', mk_time' : ''}</Tooltip>
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'url鍙橀噺锛岃鎸夌収@xxx@鏍煎紡浣跨敤銆�'}>{urlFields ? ', ' : ''}<span style={{color: '#13c2c2'}}>{urlFields}</span></Tooltip>
               {window.GLOB.process ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'宸ヤ綔娴佸彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}>, <span style={{color: 'purple'}}>works_flow_code</span></Tooltip> : null}
             </Form.Item>
diff --git a/src/menu/datasource/verifycard/excelout/index.jsx b/src/menu/datasource/verifycard/excelout/index.jsx
new file mode 100644
index 0000000..a1fe536
--- /dev/null
+++ b/src/menu/datasource/verifycard/excelout/index.jsx
@@ -0,0 +1,76 @@
+import React, { Component } from 'react'
+import { notification } from 'antd'
+import * as XLSX from 'sheetjs-style'
+import { DownloadOutlined } from '@ant-design/icons'
+import moment from 'moment'
+
+// import './index.scss'
+
+class ExcelOutColumns extends Component {
+  /**
+   * @description 瀵煎嚭瀛楁闆�
+   */
+  actionTrigger = () => {
+    const { data, setting } = this.props
+
+    if (data.length === 0) {
+      notification.warning({
+        top: 92,
+        message: '瀛楁闆嗕笉鍙负绌猴紒',
+        duration: 5
+      })
+      return
+    }
+
+    let columns = [{
+      Column: 'label',
+      Text: '鍚嶇О'
+    }, {
+      Column: 'field',
+      Text: '瀛楁'
+    }, {
+      Column: 'datatype',
+      Text: '鏁版嵁绫诲瀷'
+    }]
+    
+    let table = []
+    let _header = []
+    let _topRow = {}
+    let colwidth = []
+
+    columns.forEach(col => {
+      _header.push(col.Column)
+      _topRow[col.Column] = col.Text
+      colwidth.push({wch: 25})
+    })
+
+    table.push(_topRow)
+
+    data.forEach((item) => {
+      let _row = {}
+
+      columns.forEach((col) => {
+        let val = item[col.Column]
+        _row[col.Column] = val
+      })
+
+      table.push(_row)
+    })
+
+    const ws = XLSX.utils.json_to_sheet(table, {header: _header, skipHeader: true})
+
+    ws['!cols'] = colwidth
+    ws['!rows'] = Array(table.length).fill({hpx: 18})
+
+    const wb = XLSX.utils.book_new()
+    XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
+
+    XLSX.writeFile(wb, `${setting.tableName || ''}${moment().format('YYYYMMDDHHmmss')}.xlsx`)
+  }
+
+  render() {
+    return (<DownloadOutlined className="columns-out" title="涓嬭浇" onClick={this.actionTrigger}/>)
+  }
+}
+
+export default ExcelOutColumns
\ No newline at end of file
diff --git a/src/menu/datasource/verifycard/excelout/index.scss b/src/menu/datasource/verifycard/excelout/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/menu/datasource/verifycard/excelout/index.scss
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index f38a70b..500966b 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -4,7 +4,6 @@
 import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message, Button, Input } from 'antd'
 import { StopOutlined, CheckCircleOutlined, TableOutlined, 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'
@@ -24,6 +23,7 @@
 const { Search } = Input
 const { confirm } = Modal
 
+const ExcelOut = asyncComponent(() => import('./excelout'))
 const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
@@ -42,9 +42,8 @@
     loading: false,
     colLoading: false,
     searchKey: '',
-    initsql: '',          // sql楠岃瘉鏃跺彉閲忓0鏄庡強璧嬪��
     usefulfields: '',
-    defaultsql: '',       // 榛樿Sql
+    defaultsql: '',
     systemScripts: [],
     median: {},
     visible: false,
@@ -52,6 +51,7 @@
     pvisible: false,
     reload: false,
     script: null,
+    oriConfig: null,
     scriptValue: '',
     cols: null,
     colColumns: [
@@ -201,17 +201,17 @@
     let _setting = fromJS(config.setting).toJS()
     let scripts = config.scripts ? fromJS(config.scripts).toJS() : []
 
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(m => {
-        let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
-        if (_setting.dataresource) {
-          _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
-        }
-        scripts && scripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-      })
-    }
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(m => {
+    //     let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
+    //     if (_setting.dataresource) {
+    //       _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     }
+    //     scripts && scripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     })
+    //   })
+    // }
 
     let columns = config.columns ? fromJS(config.columns).toJS() : []
     let subColumns = config.subColumns ? fromJS(config.subColumns).toJS() : []
@@ -250,7 +250,13 @@
       median: _setting,
       searches: formatSearch(search),
       searchKey: '',
-      debugId: _setting.debugId || ''
+      debugId: _setting.debugId || '',
+      oriConfig: fromJS({
+        scripts,
+        columns: columns,
+        subColumns: subColumns,
+        setting: _setting
+      }).toJS()
     })
 
     this.getsysScript()
@@ -548,7 +554,7 @@
 
   submitDataSource = () => {
     const { config, mainSearch } = this.props
-    const { activeKey, setting, columns, subColumns, scripts, cols, median } = this.state
+    const { activeKey, setting, columns, subColumns, scripts, cols, median, searches } = this.state
 
     if (config.subtype === 'dualdatacard') {
       let arr = columns.map(col => col.field.toLowerCase())
@@ -613,12 +619,13 @@
           if (res.useMSearch === 'true') { // 浣跨敤涓绘悳绱㈡潯浠�
             search = [...search, ...mainSearch]
           }
+          let _searches = formatSearch(search)
 
           this.setState({
-            searches: formatSearch(search),
+            searches: _searches,
             setting: res
           }, () => {
-            this.sqlverify(() => { resolve({setting: res, columns, subColumns, scripts, cols }) }, reject, 'submit')
+            this.sqlverify(() => { resolve({setting: res, columns, subColumns, scripts, cols, searches: _searches }) }, reject, 'submit')
           })
         }, () => {
           reject()
@@ -633,7 +640,7 @@
           reject()
           return
         }
-        this.sqlverify(() => { resolve({setting, columns, subColumns, scripts, cols }) }, reject, 'submit')
+        this.sqlverify(() => { resolve({setting, columns, subColumns, scripts, cols, searches }) }, reject, 'submit')
       } else if (activeKey === 'subcolumns') {
         if (this.subdatasource && this.subdatasource.state.editingKey) {
           notification.warning({
@@ -644,11 +651,37 @@
           reject()
           return
         }
-        this.sqlverify(() => { resolve({setting, columns, subColumns, scripts, cols }) }, reject, 'submit')
+        this.sqlverify(() => { resolve({setting, columns, subColumns, scripts, cols, searches }) }, reject, 'submit')
       } else if (activeKey === 'scripts') {
-        this.sqlverify(() => { resolve({setting, columns, subColumns, scripts, cols }) }, reject, 'submit')
+        this.sqlverify(() => { resolve({setting, columns, subColumns, scripts, cols, searches }) }, reject, 'submit')
       }
     })
+  }
+
+  closeDataSource = (callback) => {
+    const { setting, columns, subColumns, scripts, oriConfig } = this.state
+
+    let line = scripts.map(item => item.sql).join('')
+    line += columns.map(item => item.field + item.datatype).join('')
+    line += subColumns.map(item => item.field + item.datatype).join('')
+    line += setting.interType + (setting.dataresource || '') + (setting.order || '') + (setting.primaryKey || '')
+
+    let _line = oriConfig.scripts.map(item => item.sql).join('')
+    _line += oriConfig.columns.map(item => item.field + item.datatype).join('')
+    _line += oriConfig.subColumns.map(item => item.field + item.datatype).join('')
+    _line += oriConfig.setting.interType + (oriConfig.setting.dataresource || '') + (oriConfig.setting.order || '') + (oriConfig.setting.primaryKey || '')
+
+    if (line !== _line) {
+      confirm({
+        content: '鏁版嵁婧愬凡淇敼锛岀‘瀹氬彇娑堝悧锛�',
+        onOk() {
+          callback()
+        },
+        onCancel() {}
+      })
+    } else {
+      callback()
+    }
   }
 
   sqlverify = (resolve, reject, type, testScripts) => {
@@ -683,8 +716,6 @@
 
       let r = SettingUtils.getDebugSql(setting, _scripts, _columns, searches, config.subtype, config.hasExtend)
 
-      let _debugId = md5(r.sql)
-      
       if (r.custompage && setting.laypage === 'true' && _columns.findIndex(col => col.field === 'mk_total') === -1) {
         if (config.subtype !== 'basetable') {
           Modal.warning({
@@ -704,7 +735,7 @@
         }
       }
 
-      if (debugId === _debugId) {
+      if (debugId === r.debugId) {
         resolve()
         return
       }
@@ -719,7 +750,7 @@
 
       Api.sDebug(r.sql).then(result => {
         if (result.status || result.ErrCode === '-2') {
-          this.setState({debugId: _debugId}, () => {
+          this.setState({debugId: r.debugId}, () => {
             resolve()
           })
         } else {
@@ -988,7 +1019,7 @@
     })
 
     if (window.debugger) {
-      console.info('select ' + s.join(', '))
+      window.mkInfo('select ' + s.join(', '))
     }
 
     let extend = ''
@@ -1155,6 +1186,33 @@
     })
   }
 
+  tolowercase = (type) => {
+    const that = this
+    confirm({
+      content: type === 'sub' ? '纭畾灏嗗瓙琛ㄥ瓧娈佃浆涓哄皬鍐欏悧锛�' : '纭畾灏嗗瓧娈佃浆涓哄皬鍐欏悧锛�',
+      onOk() {
+        that.execlowercase(type)
+      },
+      onCancel() {}
+    })
+  }
+
+  execlowercase = (type) => {
+    const { subColumns, columns } = this.state
+
+    if (type === 'sub') {
+      this.setState({subColumns: fromJS(subColumns).toJS().map(col => {
+        col.field = col.field.toLowerCase()
+        return col
+      })})
+    } else {
+      this.setState({columns: fromJS(columns).toJS().map(col => {
+        col.field = col.field.toLowerCase()
+        return col
+      })})
+    }
+  }
+
   /**
    * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
    */
@@ -1202,6 +1260,8 @@
               type="fields"
               updatefield={this.updatefields}
             />
+            <SwapOutlined className="columns-lowercase" title="杞皬鍐�" onClick={() => this.tolowercase()}/>
+            <ExcelOut data={columns} setting={setting}/>
             <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> : <TabPane tab={
             <span>
@@ -1210,6 +1270,7 @@
             </span>
           } key="columns">
             <div className="base-table-columns"></div>
+            <ExcelOut data={columns} setting={setting}/>
             <EditTable actions={[]} searchKey={searchKey} type="datasourcefield" data={columns} columns={colColumns}/>
           </TabPane>}
           {config.subtype === 'dualdatacard' ? <TabPane tab={
@@ -1224,6 +1285,8 @@
               type="fields"
               updatefield={this.updateSubfields}
             />
+            <SwapOutlined className="columns-lowercase" title="杞皬鍐�" onClick={() => this.tolowercase('sub')}/>
+            <ExcelOut data={subColumns} setting={setting}/>
             <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={
@@ -1254,7 +1317,6 @@
               setting={setting}
               searches={searches}
               defaultsql={defaultsql}
-              initsql={this.state.initsql}
               customScripts={scripts}
               systemScripts={this.state.systemScripts}
               scriptsChange={this.scriptsChange}
diff --git a/src/menu/datasource/verifycard/index.scss b/src/menu/datasource/verifycard/index.scss
index 308bfb9..b87af52 100644
--- a/src/menu/datasource/verifycard/index.scss
+++ b/src/menu/datasource/verifycard/index.scss
@@ -146,6 +146,39 @@
       margin-right: 5px;
       cursor: pointer;
     }
+    .columns-lowercase {
+      float: right;
+      position: relative;
+      z-index: 2;
+      right: 30px;
+      height: 0px;
+      top: -15px;
+      color: orange;
+      cursor: pointer;
+    }
+    .columns-out {
+      float: right;
+      position: relative;
+      z-index: 2;
+      right: 5px;
+      height: 0px;
+      top: -15px;
+      color: rgb(24, 144, 255);
+    }
+    .columns-out + .modal-edit-table {
+      .ant-table-thead {
+        .copy-control {
+          top: -18px;
+          right: 55px;
+          .anticon-copy {
+            margin-right: 12px;
+          }
+          .anticon-delete {
+            margin-left: 12px;
+          }
+        }
+      }
+    }
   }
   .full-scripts {
     position: absolute;
diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx
index 97cedeb..7e5f409 100644
--- a/src/menu/datasource/verifycard/settingform/index.jsx
+++ b/src/menu/datasource/verifycard/settingform/index.jsx
@@ -105,6 +105,9 @@
           if (values.interType === 'system' && values.onload === 'false') {
             values.sync = 'false'
           }
+          if (values.interType === 'system' && values.database === 'sso') {
+            values.sync = 'false'
+          }
 
           // 鏁版嵁婧愬墠绔獙璇�
           if (values.interType === 'system' && values.execute !== 'false' && values.dataresource) {
@@ -438,6 +441,10 @@
                     {
                       required: true,
                       message: '璇疯緭鍏ラ粯璁ゆ帓搴�!'
+                    },
+                    {
+                      pattern: /^[^'+]+$/,
+                      message: '鎺掑簭涓笉鍙娇鐢╘'涓�+'
                     }
                   ]
                 })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)}
@@ -515,16 +522,27 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
+            {setting.interType === 'system' ? <Col span={8}>
+              <Form.Item label="鏁版嵁搴�">
+                {getFieldDecorator('database', {
+                  initialValue: setting.database || 'local'
+                })(
+                <Radio.Group>
+                  <Radio value="local">鏈湴</Radio>
+                  <Radio value="sso">鍗曠偣</Radio>
+                </Radio.Group>)}
+              </Form.Item>
+            </Col> : null}
             {/* 1銆佷笉鍒嗛〉涓斾笉瀛樺湪涓婄骇妯″潡 */}
             {!['navbar', 'interface', 'calendar'].includes(config.type) && !['editable', 'basetable', 'dualdatacard', 'invoice', 'invTable'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') && setting.interType === 'system' && setting.onload !== 'false' ? <Col span={8}>
               <Form.Item label={
-                <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹紝娉細濡傝彍鍗曟湭浣跨敤鍚庣缂撳瓨锛屽垯鏌ヨ璇彞澶т簬8000瀛楃鏃舵棤鏁堛��'}>
+                <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
                   鍚屾鏌ヨ
                 </Tooltip>
               }>
                 {getFieldDecorator('sync', {
-                  initialValue: setting.sync || 'true'
+                  initialValue: setting.sync || 'false'
                 })(
                   <Radio.Group>
                     <Radio value="true">鏄�</Radio>
@@ -575,6 +593,18 @@
                   <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'onload')}}>
                     <Radio value="true">鍔犺浇</Radio>
                     <Radio value="false">涓嶅姞杞�</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {window.backend && setting.interType === 'system' ? <Col span={8}>
+              <Form.Item label="浜嬪姟">
+                {getFieldDecorator('transact', {
+                  initialValue: setting.transact || 'false'
+                })(
+                  <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'transact')}}>
+                    <Radio value="true">鍚敤</Radio>
+                    <Radio value="false">绂佺敤</Radio>
                   </Radio.Group>
                 )}
               </Form.Item>
@@ -641,7 +671,7 @@
                   rules: [
                     {
                       required: true,
-                      message: '璇疯緭鍏ラ粯璁ゆ帓搴�!'
+                      message: '璇疯緭鍏ュ瓙琛ㄥ瓧娈�!'
                     }
                   ]
                 })(<Input placeholder={''} autoComplete="off" />)}
@@ -677,6 +707,18 @@
                 )}
               </Form.Item>
             </Col> : null}
+            {setting.onload !== 'false' ? <Col span={8}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鍙欢杩熷垵濮嬪寲鏁版嵁鐨勫姞杞芥椂闂达紝鍗曚綅姣锛坢s锛夈��">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  寤舵椂鍔犺浇
+                </Tooltip>
+              }>
+                {getFieldDecorator('delay', {
+                  initialValue: setting.delay,
+                })(<InputNumber min={0} max={60000} precision={0} />)}
+              </Form.Item>
+            </Col> : null}
           </Row>
         </Form>
         <Modal
diff --git a/src/menu/datasource/verifycard/utils.jsx b/src/menu/datasource/verifycard/utils.jsx
index 67b552d..cb79b71 100644
--- a/src/menu/datasource/verifycard/utils.jsx
+++ b/src/menu/datasource/verifycard/utils.jsx
@@ -1,4 +1,5 @@
 
+import md5 from 'md5'
 import { getSearchRegs, joinMainSearchkey } from '@/utils/utils-custom.js'
 
 export default class SettingUtils {
@@ -41,49 +42,45 @@
       _dataresource = '(' + _dataresource + ') tb'
     }
     
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(item => {
-        let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
-        _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-        _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-      })
-    }
-
-    let getuuid = () => {
-      let uuid = []
-      let timestamp = new Date().getTime()
-      let _options = '0123456789abcdefghigklmnopqrstuv'
-      for (let i = 0; i < 19; i++) {
-        uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
-      }
-      uuid = timestamp + uuid.join('')
-      return uuid
-    }
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(item => {
+    //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
+    //     _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+    //     _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+    //   })
+    // }
 
     let regs = [
-      {reg: /@time_id@/ig, value: `'${getuuid()}'`},
-      {reg: /@BID@/ig, value: `'${getuuid()}'`},
-      {reg: /@upid@/ig, value: `'${getuuid()}'`},
+      // {reg: /@time_id@/ig, value: `'${getuuid()}'`}, // 璁$畻md5鍚庢浛鎹�
+      // {reg: /@BID@/ig, value: `'${getuuid()}'`},
+      // {reg: /@upid@/ig, value: `'${getuuid()}'`},
       {reg: /@typename@/ig, value: `'debug'`},
       {reg: /@datam@/ig, value: `''`},
       {reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID')}'`},
       {reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid')}'`},
       {reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID')}'`},
       {reg: /@Appkey@/ig, value: `'${window.GLOB.appkey}'`},
+      {reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
       {reg: /@\$|\$@/ig, value: ''},
-      {reg: /@select\$|\$select@/ig, value: ''},
-      {reg: /@sum\$|\$sum@/ig, value: ''},
+      // {reg: /@select\$|\$select@/ig, value: ''},
+      // {reg: /@sum\$|\$sum@/ig, value: ''},
     ]
 
     if (window.GLOB.process && type !== 'invoice') {
-      regs.push({reg: /@works_flow_code@/ig, value: `'${getuuid()}'`})
+      regs.push({reg: /@works_flow_code@/ig, value: `'mk_flow_code'`})
     }
 
     if (hasExtend) {
-      regs.push({reg: /@mk_time@/ig, value: '2024-04-29 17:20:00'})
+      regs.push({reg: /@mk_time@/ig, value: `'2024-04-29 17:20:00'`})
     }
     if (type === 'calendar') {
-      regs.push({reg: /@mk_year@/ig, value: '2024'})
+      regs.push({reg: /@mk_year@/ig, value: `'2024'`})
+    }
+    if (window.GLOB.getLocation) {
+      regs.push(
+        {reg: /@mk_longitude@/ig, value: 0},
+        {reg: /@mk_latitude@/ig, value: 0}
+      )
     }
 
     // 澶栬仈鏁版嵁搴撴浛鎹�
@@ -114,7 +111,7 @@
     }
 
     // 姝e垯鏇挎崲
-    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
+    let custompage = /@pageSize@|@orderBy@|@mk_total/i.test(_dataresource + _customScript)
     let _regoptions = getSearchRegs(searches)
 
     let _search = joinMainSearchkey(searches)
@@ -182,6 +179,29 @@
         ${_dataresource}`
     }
 
+    let debugId = md5(sql + window.GLOB.appkey)
+
+    let getuuid = () => {
+      let uuid = []
+      let timestamp = new Date().getTime()
+      let _options = '0123456789abcdefghigklmnopqrstuv'
+      for (let i = 0; i < 19; i++) {
+        uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
+      }
+      uuid = timestamp + uuid.join('')
+      return uuid
+    }
+
+    let _regs = [
+      {reg: /@time_id@/ig, value: `'${getuuid()}'`},
+      {reg: /@BID@/ig, value: `'${getuuid()}'`},
+      {reg: /@upid@/ig, value: `'${getuuid()}'`},
+    ]
+
+    _regs.forEach(item => {
+      sql = sql.replace(item.reg, item.value)
+    })
+
     let errors = []
 
     if (/@[0-9a-zA-Z_]+@/ig.test(sql)) {
@@ -214,8 +234,6 @@
       })
 
       arr.forEach(item => {
-        if (/@time_id@/ig.test(item)) return
-
         let reg = new RegExp(item, 'i')
         if (reg.test(_dataresource)) {
           errors.push(`鏁版嵁婧愪腑瀛樺湪鏈浛鎹㈠��${item}`)
@@ -232,6 +250,6 @@
       })
     }
 
-    return { error, sql, errors: errors.join('锛�'), custompage }
+    return { error, sql, errors: errors.join('锛�'), custompage, debugId }
   }
 }
\ No newline at end of file
diff --git a/src/menu/debug/index.jsx b/src/menu/debug/index.jsx
index c40298c..cdbc753 100644
--- a/src/menu/debug/index.jsx
+++ b/src/menu/debug/index.jsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react'
+import React, { Component } from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
 import { Modal, Button, Drawer, Tooltip } from 'antd'
@@ -26,6 +26,7 @@
 
   sqlList = []
   verSqls = []
+  linkMain = null
 
   trigger = () => {
     let config = fromJS(this.props.config).toJS()
@@ -66,6 +67,7 @@
     }
 
     this.sqlList = []
+    this.linkMain = []
 
     let regs = [
       { reg: /@userName@/ig, value: `'User_Name'` },
@@ -88,76 +90,13 @@
     if (process) {
       regs.push({ reg: /@works_flow_code@/ig, value: `'1949-10-01 15:00:00'` })
     }
-    
-    if (config.interfaces && config.interfaces.length > 0) {
-      config.interfaces.forEach(m => {
-        if (m.status !== 'true' || m.setting.interType !== 'system') return false
-  
-        let sql = this.formatDataSource(m, regs)
-  
-        this.sqlList.push({label: m.setting.name, children: [{label: '鏁版嵁婧�', sql: sql}]})
-      })
-    }
 
-    this.filterComponent(config.components, [], regs, process)
+    let _mainSearch = []
 
-    let sqls = []
-    let foreachSql = (list, name, tabName = '', supName = '') => {
-      list.forEach(item => {
-        if (item.children) {
-          if (item.tabName) {
-            item.children.forEach(cell => {
-              if (cell.children) {
-                foreachSql(cell.children, cell.label, item.tabName, name)
-              }
-            })
-          } else {
-            foreachSql(item.children, name, tabName, supName)
-          }
-        } else if (item.sql) {
-          sqls.push({uuid: Utils.getuuid() ,label: item.label, name: name, tabName: tabName, supName: supName, sql: item.sql})
-        }
-      })
-    }
-
-    this.sqlList.forEach(item => {
-      if (item.children) {
-        foreachSql(item.children, item.label)
-      }
-    })
-
-    if (sqls.length === 0) {
-      Modal.warning({
-        title: '褰撳墠鑿滃崟鏃犲彲楠岃瘉鑴氭湰銆�',
-        okText: '鐭ラ亾浜�'
-      })
-      return
-    }
-
-    this.verSqls = sqls
-    let that = this
-
-    Modal.confirm({
-      content: `褰撳墠鑿滃崟鍏�${this.sqlList.length}涓粍浠讹紝${sqls.length}椤硅剼鏈渶瑕佹楠�${sqls.length > 20 ? '锛屾椂闂村ぇ姒傞渶瑕�' + parseInt(sqls.length / 2) + '绉�' : ''}銆俙,
-      onOk() {
-        that.setState({visible: true, status: 'loading', sqlList: fromJS(sqls).toJS(), successIds: [], errorIds: [], errorMsg: {}, execId: ''}, () => {
-          that.roopSql()
-        })
-      },
-      onCancel() {}
-    })
-
-    this.sqlList = []
-  }
-
-  filterComponent = (components, mainSearch, regs, process, ispop = false) => {
-    let appType = sessionStorage.getItem('appType')
-    let _mainSearch = mainSearch || []
-
-    if (appType === 'mob') {
+    if (sessionStorage.getItem('appType') === 'mob') {
       let search = []
       let ms = null
-      components.forEach(item => {
+      config.components.forEach(item => {
         if (item.type === 'topbar' && item.wrap.type !== 'navbar' && item.search) {
           ms = item.search
         } else if (item.type === 'search' && item.wrap.field) {
@@ -204,20 +143,168 @@
         _mainSearch = search
       }
     } else {
-      components.forEach(component => {
+      config.components.forEach(component => {
         if (component.type !== 'search') return
   
         _mainSearch = component.search || []
       })
     }
+    
+    if (config.interfaces && config.interfaces.length > 0) {
+      config.interfaces.forEach(m => {
+        if (m.status !== 'true' || m.setting.interType !== 'system') return false
+  
+        m.setting.laypage = 'false'
+        m.setting.$top = true
+
+        let sql = this.formatDataSource(m, regs, _mainSearch)
+  
+        this.sqlList.push({label: m.setting.name, children: [{label: '鏁版嵁婧�', sql: sql}]})
+      })
+    }
+
+    this.filterComponent(config.components, _mainSearch, regs, process)
+
+    let sqls = []
+    let foreachSql = (list, name, tabName = '', supName = '') => {
+      list.forEach(item => {
+        if (item.children) {
+          if (item.tabName) {
+            item.children.forEach(cell => {
+              if (cell.children) {
+                foreachSql(cell.children, cell.label, item.tabName, name)
+              }
+            })
+          } else {
+            foreachSql(item.children, name, tabName, supName)
+          }
+        } else if (item.sql) {
+          sqls.push({uuid: Utils.getuuid() ,label: item.label, name: name, tabName: tabName, supName: supName, sql: item.sql})
+        }
+      })
+    }
+
+    this.sqlList.forEach(item => {
+      if (item.children) {
+        foreachSql(item.children, item.label)
+      }
+    })
+
+    if (sqls.length === 0) {
+      Modal.warning({
+        title: '褰撳墠鑿滃崟鏃犲彲楠岃瘉鑴氭湰銆�',
+        okText: '鐭ラ亾浜�'
+      })
+      return
+    }
+
+    this.verSqls = sqls
+    let that = this
+
+    let formErrors = []
+    if (this.linkMain.length) {
+      let map = new Map()
+      if (config.interfaces) {
+        config.interfaces.forEach(m => {
+          if (m.status !== 'true' || !m.columns) return false
+    
+          map.set(m.uuid, m.columns)
+        })
+      }
+
+      let forEachComs = (components) => {
+        components.forEach(item => {
+          if (item.type === 'tabs') {
+            item.subtabs.forEach(tab => {
+              forEachComs(tab.components)
+            })
+          } else if (item.type === 'group') {
+            forEachComs(item.components)
+          } else if (item.columns && item.columns.length) {
+            map.set(item.uuid, item.columns)
+          }
+        })
+      }
+
+      forEachComs(config.components)
+
+      this.linkMain.forEach(item => {
+        if (item.config.wrap && item.config.wrap.datatype === 'public') return
+
+        let supModule = ''
+        if (item.config.wrap && item.config.wrap.datatype === 'static') {
+          supModule = item.config.wrap.supModule ? item.config.wrap.supModule[item.config.wrap.supModule.length - 1] : ''
+        } else if (item.config.setting && item.config.setting.supModule) {
+          supModule = item.config.setting.supModule[item.config.setting.supModule.length - 1] || ''
+          if (supModule === 'empty') {
+            supModule = ''
+          }
+        }
+
+        if (!supModule) return
+
+        let cols = map.get(supModule)
+
+        if (!cols) {
+          formErrors.push(<div key={item.forms[0].uuid}>
+            缁勪欢<span style={{color: '#1890ff', margin: '0 2px 0 2px'}}>{item.config.name}{item.label ? '-' + item.label : ''}</span>涓〃鍗�<span style={{color: 'orange', margin: '0 2px 0 2px'}}>{item.forms.map(c => c.label + ' (' + c.field + ')').join('銆�')}</span>鏃犳晥
+          </div>)
+        } else {
+          let _forms = []
+          let _cols = cols.map(col => col.field.toLowerCase())
+
+          item.forms.forEach(m => {
+            if (_cols.includes(m.field.toLowerCase())) return
+
+            _forms.push(m.label + ' (' + m.field + ')')
+          })
+
+          if (_forms.length) {
+            formErrors.push(<div key={item.forms[0].uuid}>
+              缁勪欢<span style={{color: '#1890ff', margin: '0 2px 0 2px'}}>{item.config.name}{item.label ? '-' + item.label : ''}</span>涓〃鍗�<span style={{color: 'orange', margin: '0 2px 0 2px'}}>{_forms.join('銆�')}</span>鏃犳晥
+            </div>)
+          }
+        }
+      })
+    }
+
+    formErrors = formErrors.length ? formErrors : ''
+
+    Modal.confirm({
+      content: <div style={{paddingLeft: '38px'}}>
+        {`褰撳墠鑿滃崟鍏�${this.sqlList.length}涓粍浠讹紝${sqls.length}椤硅剼鏈渶瑕佹楠�${sqls.length > 20 ? '锛屾椂闂村ぇ姒傞渶瑕�' + parseInt(sqls.length / 2) + '绉�' : ''}銆俙}
+        {formErrors}
+      </div>,
+      onOk() {
+        that.setState({visible: true, status: 'loading', sqlList: fromJS(sqls).toJS(), successIds: [], errorIds: [], errorMsg: {}, execId: ''}, () => {
+          that.roopSql()
+        })
+      },
+      onCancel() {}
+    })
+
+    this.sqlList = []
+  }
+
+  filterComponent = (components, mainSearch, regs, process, ispop = false) => {
+    let appType = sessionStorage.getItem('appType')
 
     components.forEach(item => {
       if (item.type === 'tabs') {
         item.subtabs.forEach(tab => {
+          let _mainSearch = mainSearch || []
+
+          if (appType !== 'mob') {
+            tab.components.forEach(com => {
+              if (com.type !== 'search') return
+        
+              _mainSearch = com.search || []
+            })
+          }
           this.filterComponent(tab.components, _mainSearch, regs, process)
         })
       } else if (item.type === 'group') {
-        this.filterComponent(item.components, _mainSearch, regs, process)
+        this.filterComponent(item.components, mainSearch, regs, process)
       } else {
         let children = []
         if (item.wrap && item.setting) {
@@ -235,13 +322,18 @@
         }
 
         if (item.setting && item.setting.interType === 'system') {
-          let sql = this.formatDataSource(item, regs, _mainSearch)
+          if (item.format === 'object') {
+            item.setting.laypage = 'false'
+            item.setting.$top = true
+          }
+
+          let sql = this.formatDataSource(item, regs, mainSearch)
   
           children.push({label: '鏁版嵁婧�', sql: sql})
         } else if (item.setting && item.setting.useMSearch === 'true') {
           let searches = item.search || []
-          if (_mainSearch.length > 0) {
-            searches = [...searches, ..._mainSearch]
+          if (mainSearch.length > 0) {
+            searches = [...searches, ...mainSearch]
           }
           item.$searches = fromJS(searches).toJS()
         }
@@ -293,7 +385,7 @@
           getCols(item.cols)
   
           if (item.subtype === 'editable' && item.submit.intertype === 'system') {
-            let sql = this.getEditTableSql(item.submit, item.cols, item.columns)
+            let sql = this.getEditTableSql(item.submit, item.cols, item.columns, item.setting)
             children.push({label: '鎻愪氦', sql: sql})
           }
         } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
@@ -354,6 +446,18 @@
             if (!group.subButton.Ot) {
               group.subButton.Ot = item.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
             }
+
+            if (group.fields) {
+              let cells = group.fields.filter(cell => cell.type === 'linkMain')
+
+              if (cells.length) {
+                this.linkMain.push({
+                  config: item,
+                  forms: cells
+                })
+              }
+            }
+
             let res = this.resetButton(item, group.subButton, process, group)
 
             if (res) {
@@ -380,6 +484,19 @@
 
   resetButton = (item, cell, process, group, isback) => {
     let sql = ''
+    if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+      if (cell.modal && cell.modal.fields.length) {
+        let cells = cell.modal.fields.filter(n => n.type === 'linkMain')
+  
+        if (cells.length) {
+          this.linkMain.push({
+            config: item,
+            forms: cells,
+            label: cell.label
+          })
+        }
+      }
+    }
     if (['exec', 'prompt', 'pop', 'form', 'formSubmit'].includes(cell.OpenType)) {
       if (cell.intertype === 'system' || cell.procMode === 'system') { // 绯荤粺鎺ュ彛
         if (item.subtype === 'dualdatacard' && isback) {
@@ -439,6 +556,12 @@
     } else if (cell.OpenType === 'funcbutton') {
       if (cell.funcType === 'print') {
 
+      } else if ((cell.funcType === 'refund' || cell.funcType === 'pay') && cell.payMode === 'system') {
+        sql = this.getPaySql(cell, item)
+      }
+    } else if (cell.OpenType === 'innerpage' || cell.OpenType === 'outerpage') {
+      if (cell.pageTemplate === 'pay' && cell.payMode === 'system') {
+        sql = this.getPaySql(cell, item)
       }
     } else if (cell.OpenType === 'popview') {
       if (cell.config && cell.config.components) {
@@ -454,7 +577,31 @@
         if (process) {
           regs.push({ reg: /@works_flow_code@/ig, value: `'1949-10-01 15:00:00'` })
         }
-        this.filterComponent(cell.config.components, [], regs, process, true)
+
+        let _mainSearch = []
+
+        if (sessionStorage.getItem('appType') === 'mob') {
+          cell.config.components.forEach(item => {
+            if (item.type === 'search' && item.wrap.field) {
+              _mainSearch.push({
+                type: 'text',
+                label: item.wrap.label,
+                field: item.wrap.field,
+                match: item.wrap.match,
+                required: item.wrap.required,
+                value: item.wrap.initval || ''
+              })
+            }
+          })
+        } else {
+          cell.config.components.forEach(component => {
+            if (component.type !== 'search') return
+      
+            _mainSearch = component.search || []
+          })
+        }
+
+        this.filterComponent(cell.config.components, _mainSearch, regs, process, true)
 
         if (this.sqlPopList.length) {
           sql = fromJS(this.sqlPopList).toJS()
@@ -485,7 +632,7 @@
       }
     })
 
-    if (!_prev) return ''
+    if (!_prev) return _back
 
     let tbs = []
     _prev.replace(/\n|\r/g, ' ').split(/\sdeclare\s/ig).forEach(line => {
@@ -551,8 +698,29 @@
     let BID = Utils.getuuid()
     let verify = btn.verify || {}
     let _actionType = null
-    let setting = component.setting
+    let setting = component.setting || {}
     let columns = component.columns || []
+
+    if (verify.invalid === 'true') {
+      if (component.wrap && (component.wrap.datatype === 'static' || component.wrap.datatype === 'public')) {
+        verify.invalid = 'false'
+      } else if (setting.maxScript && setting.maxScript >= 300) {
+        verify.invalid = 'false'
+      } else if (!setting.dataresource) {
+        verify.invalid = 'false'
+      } else if (btn.intertype !== 'system' && btn.procMode !== 'system') {
+        verify.invalid = 'false'
+      } else if (btn.sqlType === 'insert') {
+        verify.invalid = 'false'
+      } else if (btn.Ot === 'notRequired') {
+        verify.invalid = 'false'
+      }
+    }
+    if (verify.uniques && verify.uniques.length > 0 && btn.Ot === 'requiredOnce') {
+      if (component.wrap && (component.wrap.datatype === 'static' || component.wrap.datatype === 'public')) {
+        verify.uniques = []
+      }
+    }
   
     if (verify.default !== 'false') { // 鍒ゆ柇鏄惁浣跨敤榛樿sql
       _actionType = btn.sqlType
@@ -615,8 +783,10 @@
             _item.type = 'text'
           } else if (_item.type === 'number' || _item.type === 'rate') {
             _item.fieldlen = item.decimal || 0
-          } else  if (_item.type === 'date') {
+          } else if (_item.type === 'date') {
             _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
+          } else if (_item.type === 'datetime') {
+            _item.type = 'date'
           } else if (item.declare === 'decimal') {
             _item.type = 'number'
             _item.fieldlen = item.decimal || 0
@@ -662,8 +832,10 @@
             _item.type = 'text'
           } else if (_item.type === 'number' || _item.type === 'rate') {
             _item.fieldlen = item.decimal || 0
-          } else  if (_item.type === 'date') {
+          } else if (_item.type === 'date') {
             _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
+          } else if (_item.type === 'datetime') {
+            _item.type = 'date'
           } else if (item.declare === 'decimal') {
             _item.type = 'number'
             _item.fieldlen = item.decimal || 0
@@ -711,8 +883,8 @@
     })
   
     // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
-    if (btn.Ot !== 'notRequired' && columns && columns.length > 0) {
-      const setField = (col) => {
+    if (btn.Ot !== 'notRequired' && columns.length > 0) {
+      columns.forEach(col => {
         if (!col.field) return
         let _key = col.field.toLowerCase()
   
@@ -730,35 +902,7 @@
         
         if (!_vars.includes(_key)) {
           _vars.push(_key)
-  
-          if (col.datatype) {
-            _declarefields.push(`@${_key} ${col.datatype}`)
-          } else {
-            if (col.fieldlength && col.fieldlength > 4000) {
-              col.fieldlength = 'max'
-            }
-  
-            let _type = `nvarchar(${col.fieldlength || 50})`
-  
-            if (col.type === 'number') {
-              let _length = col.decimal ? col.decimal : 0
-              _type = `decimal(18,${_length})`
-            } else if (col.type === 'picture' || col.type === 'textarea') {
-              _type = `nvarchar(${col.fieldlength || 512})`
-            }
-  
-            _declarefields.push(`@${_key} ${_type}`)
-          }
-        }
-      }
-  
-      columns.forEach(col => {
-        if (col.type === 'colspan' || col.type === 'old_colspan') {
-          col.subcols.forEach(cell => {
-            setField(cell)
-          })
-        } else {
-          setField(col)
+          _declarefields.push(`@${_key} ${col.datatype || 'nvarchar(50)'}`)
         }
       })
     }
@@ -846,37 +990,31 @@
     }
   
     // 澶辨晥楠岃瘉锛屾坊鍔犳暟鎹椂涓嶇敤
-    if (btn.sqlType !== 'insert' && btn.Ot !== 'notRequired' && verify.invalid === 'true' && setting.dataresource) {
+    if (verify.invalid === 'true') {
       let datasource = setting.dataresource
       let customScript = setting.customScript || ''
-      let orderBy = setting.order
+  
+      let regoptions = [{
+        reg: new RegExp('@userName@', 'ig'),
+        value: `'${userName}'`
+      }, {
+        reg: new RegExp('@fullName@', 'ig'),
+        value: `'${fullName}'`
+      }, {
+        reg: new RegExp('@orderBy@', 'ig'),
+        value: setting.order || primaryKey
+      }, {
+        reg: new RegExp('@pageSize@', 'ig'),
+        value: 1
+      }, {
+        reg: new RegExp('@pageIndex@', 'ig'),
+        value: 1
+      }]
 
-      if (setting.queryType === 'statistics' || customScript) {
-        let searches = formatSearch(component.$searches || [])
-        let regoptions = getSearchRegs(searches)
-  
-        regoptions.push({
-          reg: new RegExp('@userName@', 'ig'),
-          value: `'${userName}'`
-        }, {
-          reg: new RegExp('@fullName@', 'ig'),
-          value: `'${fullName}'`
-        }, {
-          reg: new RegExp('@orderBy@', 'ig'),
-          value: orderBy
-        }, {
-          reg: new RegExp('@pageSize@', 'ig'),
-          value: 999999
-        }, {
-          reg: new RegExp('@pageIndex@', 'ig'),
-          value: 1
-        })
-  
-        regoptions.forEach(item => {
-          datasource = datasource.replace(item.reg, item.value)
-          customScript = customScript.replace(item.reg, item.value)
-        })
-      }
+      regoptions.forEach(item => {
+        datasource = datasource.replace(item.reg, item.value)
+        customScript = customScript.replace(item.reg, item.value)
+      })
   
       if (customScript) {
         _sql += `
@@ -951,7 +1089,6 @@
   
         if (!keys.includes(_key)) return // 琛ㄥ崟涓笉鍚崟鍙风敓鎴愬瓧娈�
   
-        let _ModularDetailCode = ''
         let _lpline = ''
         if (item.TypeCharOne === 'Lp') {
           if (_linkKey === 'bid' && BID) { // 鏇挎崲bid
@@ -959,33 +1096,22 @@
           } else {
             _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@${_linkKey},48)`
           }
-          _ModularDetailCode = '@ModularDetailCode'
         } else if (item.TypeCharOne === 'BN') {
-          let _val = ''
           if (_linkKey === 'bid' && BID) { // 鏇挎崲bid
-            _val = BID
+            _lpline = `set @ModularDetailCode= 'BN'+ right(@BID@,48)`
           } else {
-            _val = 0
+            _lpline = `set @ModularDetailCode= 'BN'+ right(@${_linkKey},48)`
           }
-          _ModularDetailCode = `'${item.TypeCharOne + _val}'`
         } else {
-          _ModularDetailCode = `'${item.ModularDetailCode}'`
-        }
-  
-        let _declare = ''
-  
-        if (!_vars.includes(_key)) {
-          _declare = `Declare @${_key} nvarchar(50)`
-          _vars.push(_key)
+          _lpline = `set @ModularDetailCode= right('${item.ModularDetailCode}',50)`
         }
   
         _billcodesSql += `
         /* 鍗曞彿鐢熸垚 */
-        ${_declare}
         select @BillCode='', @${_key}='', @ModularDetailCode=''
         ${_lpline}
         exec s_get_BillCode
-          @ModularDetailCode=${_ModularDetailCode},
+          @ModularDetailCode=@ModularDetailCode,
           @Type=${item.Type},
           @TypeCharOne='${item.TypeCharOne}',
           @TypeCharTwo ='${item.TypeCharTwo}',
@@ -1005,6 +1131,17 @@
   
     // 鍞竴鎬ч獙璇侊紝蹇呴』瀛樺湪琛ㄥ崟锛堣〃鍗曞瓨鍦ㄦ椂锛屼富閿潎涓哄崟鍊硷級,蹇呴』濉啓鏁版嵁婧愶紝澶氳鎷兼帴鏃朵笉鍙敤
     if (formdata && verify.uniques && verify.uniques.length > 0 && btn.Ot !== 'requiredOnce') {
+      let dateForms = []
+      let numForms = []
+      formdata.forEach(form => {
+        let _key = form.key.toLowerCase()
+        if (form.type === 'date') {
+          dateForms.push(_key)
+        } else if (form.type === 'number' || form.type === 'rate') {
+          numForms.push(_key)
+        }
+      })
+
       verify.uniques.forEach(item => {
         let _fieldValue = []                     // 琛ㄥ崟閿�煎field=value
         let _value = []                          // 琛ㄥ崟鍊硷紝鐢ㄤ簬閿欒鎻愮ず
@@ -1018,16 +1155,15 @@
           arr.push(_key)
           if (_key === 'bid') { // 琛ㄥ崟涓病鏈塨id鍒欎娇鐢ㄧ郴缁焍id鍙橀噺
             _val = BID
+          } else if (numForms.includes(_key)) {
+            _val = '1'
+          } else if (dateForms.includes(_key)) {
+            _val = '1949-10-01'
           }
 
           _fieldValue.push(`${_key}='${_val}'`)
           _value.push(`${_labels[index] || ''}锛�${_val || ''}`)
         })
-  
-        let _verifyType = ''
-        if (item.verifyType === 'logic') {
-          _verifyType = ' and deleted=0'
-        }
   
         if (!arr.includes(primaryKey.toLowerCase())) {
           _fieldValue.push(`${primaryKey} !='${primaryId}'`)
@@ -1036,7 +1172,7 @@
         _sql += `
         /* 鍞竴鎬ч獙璇� */
         select @tbid='', @ErrorCode='',@retmsg=''
-        select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')}${_verifyType}
+        select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')}${item.verifyType === 'logic' ? ' and deleted=0' : ''}
         If @tbid!=''
         Begin
           select @ErrorCode='${item.errorCode}',@retmsg='${_value.join(', ')} 宸插瓨鍦�'
@@ -1243,7 +1379,7 @@
       if (columns && columns.length > 0 && btn.Ot !== 'notRequired') {
         let _index = 0
         columns.forEach(col => {
-          if (!col.field || col.Hide === 'true' || _index >= 4) return
+          if (!col.field || col.Hide === 'true' || _index >= 4 || col.field === primaryKey) return
           _msg += col.label + '=0,'
           _index++
         })
@@ -1328,13 +1464,7 @@
       if (_backCustomScript) {
         _sql += _backCustomScript
       }
-  
-      _sql = _sql.replace(/@start_type@/ig, `'寮�濮�'`)
-      _sql = _sql.replace(/@check_type@/ig, `'瀹℃牳'`)
-      _sql = _sql.replace(/@notice_type@/ig, `'鎶勯��'`)
-      _sql = _sql.replace(/@check_userids@/ig, `''`)
-      _sql = _sql.replace(/@notice_userids@/ig, `''`)
-      _sql = _sql.replace(/@works_flow_sign@/ig, `''`)
+
       _sql = _sql.replace(/@works_flow_code@/ig, `'mk'`)
       _sql = _sql.replace(/@works_flow_name@/ig, `'mk'`)
       _sql = _sql.replace(/@works_flow_param@/ig, `''`)
@@ -1343,6 +1473,18 @@
       _sql = _sql.replace(/@statusname@/ig, `'${statusName}'`)
       _sql = _sql.replace(/@work_group@/ig, `'mk'`)
       _sql = _sql.replace(/@work_grade@/ig, `'0'`)
+
+      if (verify.flowType === 'start') {
+        _sql = _sql.replace(/@start_type@/ig, `'寮�濮�'`)
+      } else {
+        _sql = _sql.replace(/@check_type@/ig, `'瀹℃牳'`)
+        _sql = _sql.replace(/@notice_type@/ig, `'鎶勯��'`)
+
+        _sql = _sql.replace(/@check_userids@/ig, `''`)
+        _sql = _sql.replace(/@notice_userids@/ig, `''`)
+
+        _sql = _sql.replace(/@works_flow_sign@/ig, `''`)
+      }
     } else if (_backCustomScript) {
       _sql += _backCustomScript
     }
@@ -1632,7 +1774,7 @@
     return sql
   }
 
-  getEditTableSql = (verify, cols, columns) => {
+  getEditTableSql = (verify, cols, columns, setting) => {
     let btn = verify
     let userName = sessionStorage.getItem('User_Name') || ''
     let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -1660,30 +1802,46 @@
   
     let vals = []
     let forms = []
-    let _fields = {}
-
-    columns.forEach(col => {
-      _fields[col.field] = col.datatype
-    })
+    let _forms = {}
+    let index = 0
 
     let getColumns = (cols) => {
       cols.forEach(item => {
         if (item.type === 'colspan') {
           getColumns(item.subcols)
         } else if (item.editable === 'true') {
-          forms.push({
-            field: item.field,
-            type: item.type,
-            datatype: _fields[item.field] || 'nvarchar(50)'
-          })
+          item.$sort = index
+          _forms[item.field] = item
+          index++
         }
       })
     }
 
     getColumns(cols)
 
+    columns.forEach(item => {
+      if (item.field === setting.primaryKey) return
+
+      if (_forms[item.field]) {
+        let _item = {..._forms[item.field]}
+        if (_item.editType === 'date') {
+          _item.datatype = _item.declareType || 'datetime'
+        } else {
+          _item.datatype = item.datatype
+        }
+
+        forms.push(_item)
+      } else {
+        forms.push({...item, $sort: 999})
+      }
+    })
+
+    forms.sort((a, b) => a.$sort - b.$sort)
+
     forms.forEach(col => {
-      if (col.type === 'number') {
+      if (/date/.test(col.datatype)) {
+        vals.push(`'1949-10-01'`)
+      } else if (col.type === 'number') {
         vals.push(`1`)
       } else {
         vals.push(`'mk'`)
@@ -1896,9 +2054,57 @@
     return sql
   }
 
+  getPaySql = (btn, component) => {
+    let sysfields = ['username', 'fullname', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'tbid', 'bid']
+    let _declare = []
+    let _select = []
+    
+    component.columns.forEach(_f => {
+      if (sysfields.includes(_f.field.toLowerCase())) return
+
+      if (/decimal|int/ig.test(_f.datatype)) {
+        _select.push(`@${_f.field}=1`)
+      } else if (/date/ig.test(_f.datatype)) {
+        _select.push(`@${_f.field}='1949-10-01'`)
+      } else {
+        _select.push(`@${_f.field}=''`)
+      }
+
+      _declare.push(`@${_f.field} ${_f.datatype}`)
+    })
+
+    _declare = _declare.join(', ')
+    _select = _select.join(', ')
+
+    let _sql = `Declare @UserName nvarchar(50), @FullName nvarchar(50), @RoleID nvarchar(512), @mk_departmentcode nvarchar(512), @mk_organization nvarchar(512), @mk_user_type nvarchar(20), @mk_nation nvarchar(50), @mk_province nvarchar(50), @mk_city nvarchar(50), @mk_district nvarchar(50), @mk_address nvarchar(100), @ErrorCode nvarchar(50), @retmsg nvarchar(4000), @bid nvarchar(50), @tbid nvarchar(50), ${_declare}
+    Select @UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address='', @ErrorCode='', @retmsg='', @bid='', ${_select}
+    `
+
+    btn.verify.scripts.forEach(item => {
+      if (item.status === 'false') return
+
+      _sql += `
+      ${item.sql}
+      `
+    })
+
+    if (btn.output) {
+      _sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
+    } else {
+      _sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    }
+
+    _sql = _sql.replace(/@typename@/ig, `'typename'`)
+    _sql = _sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
+
+    return _sql
+  }
+
   formatDataSource = (item, regs, mainSearch = []) => {
     if (!item.setting || item.setting.interType !== 'system') return false
-    
+
     let searches = item.search || []
     if (item.setting.useMSearch === 'true' && mainSearch.length > 0) {
       searches = [...searches, ...mainSearch]
@@ -1956,15 +2162,21 @@
     item.setting.dataresource = _dataresource
     item.setting.customScript = _customScript
 
-    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
+    let custompage = /@pageSize@|@orderBy@|@mk_total/i.test(_dataresource + _customScript)
 
     if (_dataresource) {
       if (custompage) {
         _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search} `
       } else if (item.setting.laypage === 'true' && item.setting.order) {
         _dataresource = `/*system_query*/select top 10 ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${item.setting.order}) as rows from ${_dataresource} ${_search}) tmptable where rows > 0 order by tmptable.rows `
+      } else if (item.setting.$top) {
+        if (item.setting.order) {
+          _dataresource = `/*system_query*/select top 1 ${arr_field} from ${_dataresource} ${_search} order by ${item.setting.order} `
+        } else {
+          _dataresource = `/*system_query*/select top 1 ${arr_field} from ${_dataresource} ${_search}  `
+        }
       } else if (item.setting.order) {
-        _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${item.setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
+        _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search} order by ${item.setting.order} `
       } else {
         _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search} `
       }
@@ -2009,10 +2221,16 @@
     )
 
     if (item.hasExtend) {
-      regs.push({reg: /@mk_time@/ig, value: '2024-04-29 17:20:00'})
+      regoptions.push({reg: /@mk_time@/ig, value: `'2024-04-29 17:20:00'`})
     }
     if (item.type === 'calendar') {
-      regoptions.push({ reg: /@mk_year@/ig, value: '2024' })
+      regoptions.push({ reg: /@mk_year@/ig, value: `'2024'` })
+    }
+    if (window.GLOB.getLocation) {
+      regoptions.push(
+        {reg: /@mk_longitude@/ig, value: 0},
+        {reg: /@mk_latitude@/ig, value: 0}
+      )
     }
 
     regoptions.forEach(cell => {
@@ -2040,7 +2258,7 @@
 
     this.setState({status: this.verSqls.length > 0 ? 'loading' : 'over', execId: item.uuid})
 
-    console.info(`/* 缁勪欢锛�${item.name}  妫�楠岄」锛�${item.label} */`)
+    window.mkInfo(`/* 缁勪欢锛�${item.name}  妫�楠岄」锛�${item.label} */`)
 
     Api.sDebug(item.sql).then(result => {
       if (result.status || result.ErrCode === '-2') {
@@ -2092,14 +2310,6 @@
           destroyOnClose
         >
           <div className="mk-sql-wrap">
-            {/* <div className="header">
-              <div className="sql-item">
-                <div className="sql-1">缁勪欢</div>
-                <div className="sql-2">妫�楠岄」</div>
-                <div className="sql-3">鍏朵粬</div>
-                <div className="sql-4">鐘舵��</div>
-              </div>
-            </div> */}
             <div className="body">
               {sqlList.map(item => {
                 let other = ''
diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx
index 77c601f..6c73b42 100644
--- a/src/menu/menushell/index.jsx
+++ b/src/menu/menushell/index.jsx
@@ -141,7 +141,6 @@
         config: item.config,
         width: item.width || 24,
         name: name,
-        floor: 1,   // 缁勪欢鐨勫眰绾�
         isNew: true // 鏂版坊鍔犳爣蹇楋紝鐢ㄤ簬鍒濆鍖�
       }
       
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index 6f40e02..e76889a 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -165,15 +165,15 @@
    * @description 琛ㄥ崟鍒犻櫎骞跺埛鏂�
    */
   closeForm = (card) => {
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎${card.label ? `<<${card.label}>>` : ''}鍚楋紵`,
       onOk() {
-        let _config = fromJS(_this.state.config).toJS()
+        let _config = fromJS(that.state.config).toJS()
         _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid))
 
-        _this.setState({
+        that.setState({
           config: _config,
         })
       },
@@ -193,13 +193,13 @@
   }
 
   clearConfig = () => {
-    const _this = this
+    const that = this
     let _config = {...this.state.config, fields: []}
 
     confirm({
       content: '纭畾娓呯┖琛ㄥ崟鍚楋紵',
       onOk() {
-        _this.setState({ config: _config })
+        that.setState({ config: _config })
       },
       onCancel() {}
     })
@@ -213,11 +213,11 @@
     const { config, originConfig } = this.state
 
     if (!is(fromJS(config), fromJS(originConfig))) {
-      let _this = this
+      let that = this
       confirm({
         content: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾杩斿洖鍚楋紵',
         onOk() {
-          _this.props.handleBack()
+          that.props.handleBack()
         },
         onCancel() {}
       })
@@ -279,7 +279,7 @@
 
   changecols = (type) => {
     let config = fromJS(this.state.config).toJS()
-    let _this = this
+    let that = this
 
     config.fields = config.fields.map(item => {
       item.labelwidth = 33.3
@@ -305,7 +305,7 @@
     confirm({
       content: `纭畾鍒囨崲涓�${type}鍒楀悧锛焋,
       onOk() {
-        _this.setState({config})
+        that.setState({config})
       },
       onCancel() {}
     })
@@ -394,7 +394,7 @@
               <div>
                 <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>
+                <Button disabled={saving} onClick={this.cancelConfig}>杩斿洖</Button>
               </div>
             } style={{ width: '100%' }}>
               <SettingOutlined onClick={this.changeSetting} />
diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss
index ce93e36..1ddd864 100644
--- a/src/menu/modalconfig/index.scss
+++ b/src/menu/modalconfig/index.scss
@@ -223,10 +223,6 @@
               .ant-input-number {
                 margin-top: 4px;
               }
-              .normal-braft-editor {
-                border: 1px solid #d9d9d9;
-                border-radius: 4px;
-              }
             }
             .ant-form-item-control-wrapper::after {
               content: '';
diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx
index 1ef0452..b9b8937 100644
--- a/src/menu/pastecontroller/index.jsx
+++ b/src/menu/pastecontroller/index.jsx
@@ -9,6 +9,8 @@
 import asyncComponent from '@/utils/asyncComponent'
 // import './index.scss'
 
+const { confirm } = Modal
+
 const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform'))
 
 class PasteController extends Component {
@@ -253,7 +255,7 @@
       options = ['tabs', 'timeline', 'datacard', 'doublecard', 'propcard', 'cardatacard', 'carpropcard', 'simpleform', 'stepform', 'tabform', 'balcony', 'group', 'normaltable', 'tablecard', 'line', 'editor', 'pie', 'scatter', 'iframe', 'sandbox']
   
       if (appType === 'mob') {
-        options.push('menubar', 'singleSearch')
+        options.push('menubar', 'singleSearch', 'mobnavbar')
         if (sessionStorage.getItem('editMenuType') !== 'popview') {
           options.push('topbar')
         }
@@ -336,6 +338,15 @@
             })
             return
           }
+        } else if (res.type === 'navbar') {
+          if (menu.components.findIndex(m => m.type === 'navbar') > -1) {
+            notification.warning({
+              top: 92,
+              message: '鑿滃崟鏍忎笉鍙噸澶嶆坊鍔狅紒',
+              duration: 5
+            })
+            return
+          }
         }
       } else if (res.type === 'search') {
         if (tab) {
@@ -376,15 +387,45 @@
 
       this.resetlink(res, commonId)
       
-      this.props.insert(res)
-
       this.setState({visible: false})
 
-      notification.success({
-        top: 92,
-        message: '绮樿创鎴愬姛锛�',
-        duration: 2
-      })
+      let skip = true
+      if (appType === 'mob' && res.type === 'navbar') {
+        let appMenus = sessionStorage.getItem('appViewList')
+        if (appMenus) {
+          try {
+            appMenus = JSON.parse(appMenus)
+            appMenus = appMenus.filter(item => item.keys_type === 'navbar')
+          } catch (e) {
+            appMenus = []
+          }
+        } else {
+          appMenus = []
+        }
+
+        if (appMenus.length) {
+          const that = this
+          skip = false
+
+          confirm({
+            title: '濡傞渶浣跨敤褰撳墠搴旂敤涓凡鏈夌殑鑿滃崟鏍忥紝璇风偣鍑诲彸渚у叧鑱旇彍鍗曟爮锛屽闇�娣诲姞璇风偣纭畾銆�',
+            onOk() {
+              that.props.insert(res)
+            },
+            onCancel() {}
+          })
+        }
+      }
+
+      if (skip) {
+        this.props.insert(res)
+  
+        notification.success({
+          top: 92,
+          message: '绮樿创鎴愬姛锛�',
+          duration: 2
+        })
+      }
     })
   }
 
diff --git a/src/menu/picturecontroller/index.jsx b/src/menu/picturecontroller/index.jsx
index 34ffe8a..a8633f1 100644
--- a/src/menu/picturecontroller/index.jsx
+++ b/src/menu/picturecontroller/index.jsx
@@ -161,7 +161,7 @@
   }
 
   deleteSource = (item) => {
-    const _this = this
+    const that = this
 
     confirm({
       title: '纭畾鍒犻櫎鍚楋紵',
@@ -181,14 +181,14 @@
             if (res.status) {
               if (item.typecharone === 'image') {
                 window.GLOB.app_pictures = res.data || []
-                _this.resetPicture(res.data || [])
+                that.resetPicture(res.data || [])
               } else if (item.typecharone === 'video') {
                 window.GLOB.app_videos = res.data || []
-                _this.resetVideo(res.data || [])
+                that.resetVideo(res.data || [])
               } else if (item.typecharone === 'color') {
                 window.GLOB.app_colors = res.data || []
                 sessionStorage.setItem('app_colors', JSON.stringify(res.data || []))
-                _this.resetColor(res.data || [])
+                that.resetColor(res.data || [])
               }
             } else {
               notification.warning({
diff --git a/src/menu/replaceField/settingform/index.jsx b/src/menu/replaceField/settingform/index.jsx
index 941c3f3..91d3236 100644
--- a/src/menu/replaceField/settingform/index.jsx
+++ b/src/menu/replaceField/settingform/index.jsx
@@ -76,13 +76,13 @@
   }
 
   clear = () => {
-    let _this = this
+    let that = this
     confirm({
       title: '纭畾娓呴櫎鍘嗗彶璁板綍鍚楋紵',
       content: '',
       onOk() {
         localStorage.removeItem('replaceRecord')
-        _this.setState({fields: [], labels: []})
+        that.setState({fields: [], labels: []})
       },
       onCancel() {}
     })
diff --git a/src/menu/stylecontroller/index.jsx b/src/menu/stylecontroller/index.jsx
index c5ed9e0..850eafb 100644
--- a/src/menu/stylecontroller/index.jsx
+++ b/src/menu/stylecontroller/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import { is, fromJS } from 'immutable'
-import { Collapse, Form, Col, InputNumber, Input, Select, Radio, Drawer, Button, message, Checkbox } from 'antd'
+import { Collapse, Form, Col, InputNumber, Input, Select, Radio, Drawer, Button, message, Checkbox, Tooltip } from 'antd'
 import {
   ColumnHeightOutlined,
   FontSizeOutlined,
@@ -30,7 +30,8 @@
   SwapOutlined,
   EnterOutlined,
   DragOutlined,
-  EyeOutlined
+  EyeOutlined,
+  QuestionCircleOutlined
 } from '@ant-design/icons'
 
 import MKEmitter from '@/utils/events.js'
@@ -1050,7 +1051,7 @@
                   </Form.Item>
                 </Col>
               </Panel> : null}
-              {options.includes('float') ? <Panel header="瀵归綈鏂瑰紡" key="float">
+              {options.includes('float') ? <Panel header={<Tooltip placement="topLeft" title="鎸夐挳鐩稿浜庢爡鏍肩殑浣嶇疆锛屾敞锛氳缃搴︽椂鏈夋晥銆�">瀵归綈鏂瑰紡<QuestionCircleOutlined style={{marginLeft: '3px'}} /></Tooltip>} key="float">
                 <Col span={24}>
                   <Form.Item
                     colon={false}
diff --git a/src/menu/sysinterface/index.jsx b/src/menu/sysinterface/index.jsx
index 1504093..3c61833 100644
--- a/src/menu/sysinterface/index.jsx
+++ b/src/menu/sysinterface/index.jsx
@@ -74,7 +74,7 @@
   copy = (item) => {
     let msg = { key: 'interface', type: 'line', data: item }
 
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       msg.$srcId = srcid
     }
diff --git a/src/menu/tablenodes/index.jsx b/src/menu/tablenodes/index.jsx
index c04da88..4174e4d 100644
--- a/src/menu/tablenodes/index.jsx
+++ b/src/menu/tablenodes/index.jsx
@@ -485,9 +485,12 @@
                 if (m.debug_url) {
                   let _param = JSON.parse(window.decodeURIComponent(window.atob(m.debug_url)))
                   let label = _param.MenuName
+                  _param.lang = _param.lang || 'zh-CN'
 
                   if (_param && _param.type === 'app') {
-                    label += ` (${_param.kei_no} | ${_param.typename}${param.lang !== 'zh-CN' ? ' | ' + param.lang : ''})`
+                    label += ` (${_param.kei_no} | ${_param.typename}${_param.lang !== 'zh-CN' ? ' | ' + _param.lang : ''})`
+                  } else if (_param && _param.lang && _param.lang !== 'zh-CN') {
+                    label += ` (${_param.lang})`
                   }
 
                   cell.children.push({
@@ -534,7 +537,7 @@
       }, 50)
     } else if (menu.param) {
       if (menu.param.type === 'admin') {
-        if (menu.param.MenuType === 'custom') {
+        if (['custom', 'home', 'billPrint'].includes(menu.param.MenuType)) {
           let _param = {...menu.param}
           delete _param.type
           _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
diff --git a/src/menu/transfer/index.jsx b/src/menu/transfer/index.jsx
index 1919b20..cdb834a 100644
--- a/src/menu/transfer/index.jsx
+++ b/src/menu/transfer/index.jsx
@@ -26,7 +26,7 @@
 
   trigger = () => {
     const { config } = this.props
-    const _this = this
+    const that = this
 
     if (!config.enabled) {
       let tb = config.components[0]
@@ -36,7 +36,7 @@
           content: '',
           onOk() {
             return new Promise(resolve => {
-              _this.execUpdate(resolve, true)
+              that.execUpdate(resolve, true)
             })
           },
           onCancel() {}
@@ -58,7 +58,7 @@
       content: '',
       onOk() {
         return new Promise(resolve => {
-          _this.execUpdate(resolve)
+          that.execUpdate(resolve)
         })
       },
       onCancel() {}
@@ -73,8 +73,6 @@
     _config.enabled = false
 
     delete _config.autoMatic
-
-    let useMSearch = false
 
     if (clear) {
       _config.components = []
@@ -91,9 +89,6 @@
             tab.components[0].width = 24
             tab.components[0].wrap.width = 24
             tab.components[0].wrap.name = tab.components[0].name
-            if (tab.components[0].setting.useMSearch === 'true') {
-              useMSearch = true
-            }
   
             tab.components[0].action.forEach(btn => {
               if (btn.OpenType === 'popview' && btn.config) {
@@ -145,14 +140,14 @@
       })
     }
 
-    if (useMSearch) {
+    if (_config.components[0].search && _config.components[0].search.length > 0) {
       let cell = {
         uuid: Utils.getuuid(),
         type: 'search',
         width: 24,
         subtype: 'mainsearch',
         name: '鎼滅储',
-        search: _config.components[0].search || [],
+        search: _config.components[0].search,
         style: {borderBottomColor: '#f0f0f0', borderBottomWidth: '1px'},
         wrap: {float: 'left', blacklist: [], name: '鎼滅储', width: 24}
       }
@@ -218,7 +213,8 @@
       type: 'admin',
       OpenType: _config.OpenType,
       PageParam: {Template: 'CustomPage', OpenType: 'newtab', hidden: _config.hidden},
-      MenuType: 'custom'
+      MenuType: 'custom',
+      lang: sessionStorage.getItem('lang')
     }
 
     let url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
diff --git a/src/menu/urlfieldcomponent/index.jsx b/src/menu/urlfieldcomponent/index.jsx
index a25488e..a6ff171 100644
--- a/src/menu/urlfieldcomponent/index.jsx
+++ b/src/menu/urlfieldcomponent/index.jsx
@@ -61,14 +61,14 @@
 
   deleteField = (field) => {
     let config = JSON.stringify(this.props.config)
-    const _this = this
+    const that = this
 
     if (new RegExp('@' + field + '@', 'ig').test(config)) {
       confirm({
         title: `閰嶇疆涓瓨鍦ˊ${field}@锛岀‘瀹氬垹闄ゅ悧锛焋,
         content: '',
         onOk() {
-          _this.execDelete(field)
+          that.execDelete(field)
         },
         onCancel() {}
       })
diff --git a/src/mob/colorsketch/index.jsx b/src/mob/colorsketch/index.jsx
index ac0a99e..2260cdd 100644
--- a/src/mob/colorsketch/index.jsx
+++ b/src/mob/colorsketch/index.jsx
@@ -12,7 +12,6 @@
   '#eb2f96', '#aeb303', '#c32539', '#1d3661', '#ffd591', '#ffe58f', '#fffb8f', '#eaff8f', '#b7eb8f', '#87e8de', '#91d5ff',
   '#adc6ff', '#EBE9E9', '#d9d9d9', 'rgba(0, 0, 0, 0.65)', 'rgba(0, 0, 0, 0.85)', '#000000', '#ffffff', 'transparent'
 ]
-const _href = window.location.href.split('#')[0]
 let loading = false
 
 class ColorSketch extends Component {
@@ -79,7 +78,7 @@
 
   getColors = (appColors) => {
     let colors = JSON.parse(JSON.stringify(presetColors))
-    let normal_colors = localStorage.getItem(_href + 'normal_colors')
+    let normal_colors = localStorage.getItem(window.GLOB.sysSign + 'normal_colors')
 
     if (normal_colors) {
       try {
@@ -135,7 +134,7 @@
     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')
+      let normal_colors = localStorage.getItem(window.GLOB.sysSign + 'normal_colors')
 
       if (normal_colors) {
         try {
@@ -154,7 +153,7 @@
         normal_colors.length = 10
       }
 
-      localStorage.setItem(_href + 'normal_colors', JSON.stringify(normal_colors))
+      localStorage.setItem(window.GLOB.sysSign + 'normal_colors', JSON.stringify(normal_colors))
     }
   }
 
diff --git a/src/mob/components/formdragelement/index.jsx b/src/mob/components/formdragelement/index.jsx
index 838e79d..d357279 100644
--- a/src/mob/components/formdragelement/index.jsx
+++ b/src/mob/components/formdragelement/index.jsx
@@ -66,7 +66,7 @@
 
     delete val.$srcId
     
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
diff --git a/src/mob/components/menubar/normal-menubar/index.jsx b/src/mob/components/menubar/normal-menubar/index.jsx
index 016fd2f..596f800 100644
--- a/src/mob/components/menubar/normal-menubar/index.jsx
+++ b/src/mob/components/menubar/normal-menubar/index.jsx
@@ -123,7 +123,7 @@
    */
   deleteCard = (cell, type) => {
     let card = fromJS(this.state.card).toJS()
-    let _this = this
+    let that = this
 
     if (type !== 'direct') {
       confirm({
@@ -131,8 +131,8 @@
         onOk() {
           card.subMenus = card.subMenus.filter(item => item.uuid !== cell.uuid)
   
-          _this.setState({card})
-          _this.props.updateConfig(card)
+          that.setState({card})
+          that.props.updateConfig(card)
         },
         onCancel() {}
       })
diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/options.jsx b/src/mob/components/menubar/normal-menubar/menucomponent/options.jsx
index d61728f..eace136 100644
--- a/src/mob/components/menubar/normal-menubar/menucomponent/options.jsx
+++ b/src/mob/components/menubar/normal-menubar/menucomponent/options.jsx
@@ -82,6 +82,7 @@
       required: false,
       options: menulist,
       extendName: 'MenuNo',
+      dropdown: 'false',
       controlFields: [
         {field: 'clearMenu', notNull: true},
       ],
diff --git a/src/mob/components/navbar/normal-navbar/index.jsx b/src/mob/components/navbar/normal-navbar/index.jsx
index e33ea48..48a06f5 100644
--- a/src/mob/components/navbar/normal-navbar/index.jsx
+++ b/src/mob/components/navbar/normal-navbar/index.jsx
@@ -12,6 +12,7 @@
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const MenuComponent = asyncIconComponent(() => import('./menus'))
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
+const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 
 class NormalNavbar extends Component {
   static propTpyes = {
@@ -130,6 +131,7 @@
             <NormalForm title="鑿滃崟鏍忚缃�" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
+            <CopyComponent type="mobnavbar" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} />
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
diff --git a/src/mob/components/navbar/normal-navbar/menus/index.jsx b/src/mob/components/navbar/normal-navbar/menus/index.jsx
index 43e0e28..7ade24d 100644
--- a/src/mob/components/navbar/normal-navbar/menus/index.jsx
+++ b/src/mob/components/navbar/normal-navbar/menus/index.jsx
@@ -114,7 +114,7 @@
       }
 
       if (editMenu.MenuID && editMenu.property === 'menu' && res.property !== 'menu') {
-        const _this = this
+        const that = this
         confirm({
           content: '鑿滃崟灏嗚閲嶇疆锛岀‘瀹氫慨鏀瑰悧锛�',
           onOk() {
@@ -124,8 +124,8 @@
               }
               return item
             })
-            _this.setState({menus: _menus, editMenu: null, visible: false}, () => {
-              _this.props.updateConfig(_menus)
+            that.setState({menus: _menus, editMenu: null, visible: false}, () => {
+              that.props.updateConfig(_menus)
             })
           },
           onCancel() {}
@@ -143,17 +143,17 @@
    */
   deleteElement = (card) => {
     const { menus } = this.state
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎銆�${card.name}銆嬪悧锛焋,
       onOk() {
         let _menus = menus.filter(item => item.MenuID !== card.MenuID)
 
-        _this.setState({
+        that.setState({
           menus: _menus
         }, () => {
-          _this.props.updateConfig(_menus)
+          that.props.updateConfig(_menus)
         })
       },
       onCancel() {}
diff --git a/src/mob/components/navbar/normal-navbar/menus/menuform/index.jsx b/src/mob/components/navbar/normal-navbar/menus/menuform/index.jsx
index cacce83..bb3818d 100644
--- a/src/mob/components/navbar/normal-navbar/menus/menuform/index.jsx
+++ b/src/mob/components/navbar/normal-navbar/menus/menuform/index.jsx
@@ -168,6 +168,7 @@
                 <Select
                   allowClear
                   showSearch
+                  dropdownMatchSelectWidth={false}
                   filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
                     option.props.extend.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                   onChange={(val) => this.setState({copyMenu: val})}
diff --git a/src/mob/components/tabs/antv-tabs/index.jsx b/src/mob/components/tabs/antv-tabs/index.jsx
index 9653b81..4bb2be3 100644
--- a/src/mob/components/tabs/antv-tabs/index.jsx
+++ b/src/mob/components/tabs/antv-tabs/index.jsx
@@ -169,7 +169,7 @@
 
   delTab = (tab) => {
     let tabs = fromJS(this.state.tabs).toJS()
-    const _this = this
+    const that = this
 
     tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid)
 
@@ -177,8 +177,8 @@
       title: '纭畾鍒犻櫎鏍囩锛�',
       content: '',
       onOk() {
-        _this.setState({tabs})
-        _this.props.updateConfig(tabs)
+        that.setState({tabs})
+        that.props.updateConfig(tabs)
       },
       onCancel() {}
     })
diff --git a/src/mob/header/index.jsx b/src/mob/header/index.jsx
index 6d61f1f..7d372fb 100644
--- a/src/mob/header/index.jsx
+++ b/src/mob/header/index.jsx
@@ -1,5 +1,6 @@
 import React, {Component} from 'react'
 
+import { langs } from '@/store/options.js'
 import avatar from '@/assets/img/avatar.jpg'
 import MainLogo from '@/assets/img/main-logo.png'
 import './index.scss'
@@ -13,10 +14,13 @@
 
   render () {
     const { logo } = this.state
+    let lang = sessionStorage.getItem('lang')
+    lang = lang !== 'zh-CN' ? langs[lang] || '' : ''
 
     return (
       <header className="mob-header-container">
         <div className="header-logo"><img src={logo} alt=""/></div>
+        <span className="lang">{lang}</span>
         <div className="header-user">
           <img src={this.state.avatar} alt=""/>
           <span>
diff --git a/src/mob/header/index.scss b/src/mob/header/index.scss
index b4009e2..2f9cd6e 100644
--- a/src/mob/header/index.scss
+++ b/src/mob/header/index.scss
@@ -9,6 +9,13 @@
   background: #001529;
   border-bottom: 1px solid #000;
 
+  .lang {
+    position: absolute;
+    font-size: 18px;
+    left: calc(50% - 12px);
+    top: 10px;
+    color: #ffffff;
+  }
   .header-logo {
     float: left;
     width: 180px;
diff --git a/src/mob/mobshell/card.jsx b/src/mob/mobshell/card.jsx
index c5a1344..ca91322 100644
--- a/src/mob/mobshell/card.jsx
+++ b/src/mob/mobshell/card.jsx
@@ -31,7 +31,6 @@
 const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline'))
 const OfficialAccount = asyncComponent(() => import('@/mob/components/official'))
 const ShareCode = asyncComponent(() => import('@/mob/components/sharecode'))
-const TxMap = asyncComponent(() => import('@/mob/components/txmap'))
 const Iframe = asyncComponent(() => import('@/menu/components/iframe'))
 const DoubleDataCard = asyncComponent(() => import('@/menu/components/card/double-data-card'))
 
@@ -151,8 +150,6 @@
       return (<Iframe card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'sharecode') {
       return (<ShareCode card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
-    } else if (card.type === 'map') {
-      return (<TxMap card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
 
diff --git a/src/mob/mobshell/index.jsx b/src/mob/mobshell/index.jsx
index 257a3d7..de4fabb 100644
--- a/src/mob/mobshell/index.jsx
+++ b/src/mob/mobshell/index.jsx
@@ -183,7 +183,6 @@
         config: item.config,
         width: item.width || 24,
         name: name,
-        floor: 1,   // 缁勪欢鐨勫眰绾�
         isNew: true // 鏂版坊鍔犳爣蹇楋紝鐢ㄤ簬鍒濆鍖�
       }
       
@@ -217,12 +216,48 @@
         _cards.push(Navbar)
       }
 
-      if (style) {
-        handleList({...menu, style, components: _cards})
+      if (item.component === 'navbar') {
+        let appMenus = sessionStorage.getItem('appViewList')
+        if (appMenus) {
+          try {
+            appMenus = JSON.parse(appMenus)
+            appMenus = appMenus.filter(item => item.keys_type === 'navbar')
+          } catch (e) {
+            appMenus = []
+          }
+        } else {
+          appMenus = []
+        }
+
+        if (appMenus.length) {
+          confirm({
+            title: '濡傞渶浣跨敤褰撳墠搴旂敤涓凡鏈夌殑鑿滃崟鏍忥紝璇风偣鍑诲彸渚у叧鑱旇彍鍗曟爮锛屽闇�鏂板璇风偣纭畾銆�',
+            onOk() {
+              if (style) {
+                handleList({...menu, style, components: _cards})
+              } else {
+                handleList({...menu, components: _cards})
+              }
+              setCards(_cards)
+            },
+            onCancel() {}
+          })
+        } else {
+          if (style) {
+            handleList({...menu, style, components: _cards})
+          } else {
+            handleList({...menu, components: _cards})
+          }
+          setCards(_cards)
+        }
       } else {
-        handleList({...menu, components: _cards})
+        if (style) {
+          handleList({...menu, style, components: _cards})
+        } else {
+          handleList({...menu, components: _cards})
+        }
+        setCards(_cards)
       }
-      setCards(_cards)
     }
   })
 
diff --git a/src/mob/modalconfig/index.jsx b/src/mob/modalconfig/index.jsx
index 8ef83d0..0f75a32 100644
--- a/src/mob/modalconfig/index.jsx
+++ b/src/mob/modalconfig/index.jsx
@@ -170,15 +170,15 @@
    * @description 琛ㄥ崟鍒犻櫎骞跺埛鏂�
    */
   closeForm = (card) => {
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎${card.label ? `<<${card.label}>>` : ''}鍚楋紵`,
       onOk() {
-        let _config = fromJS(_this.state.config).toJS()
+        let _config = fromJS(that.state.config).toJS()
         _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid))
 
-        _this.setState({
+        that.setState({
           config: _config,
         })
       },
@@ -201,11 +201,11 @@
     const { config, originConfig } = this.state
 
     if (!is(fromJS(config), fromJS(originConfig))) {
-      let _this = this
+      let that = this
       confirm({
         content: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾杩斿洖鍚楋紵',
         onOk() {
-          _this.props.handleBack()
+          that.props.handleBack()
         },
         onCancel() {}
       })
@@ -316,13 +316,13 @@
   }
 
   clearConfig = () => {
-    const _this = this
+    const that = this
     let _config = {...this.state.config, fields: []}
 
     confirm({
       content: '纭畾娓呯┖琛ㄥ崟鍚楋紵',
       onOk() {
-        _this.setState({ config: _config })
+        that.setState({ config: _config })
       },
       onCancel() {}
     })
diff --git a/src/mob/modalconfig/index.scss b/src/mob/modalconfig/index.scss
index 67a0528..a08b153 100644
--- a/src/mob/modalconfig/index.scss
+++ b/src/mob/modalconfig/index.scss
@@ -218,10 +218,6 @@
               .ant-input-number {
                 margin-top: 4px;
               }
-              .normal-braft-editor {
-                border: 1px solid #d9d9d9;
-                border-radius: 4px;
-              }
             }
             .ant-form-item-control-wrapper::after {
               content: '';
@@ -259,7 +255,6 @@
     background: rgba(0, 0, 0, 0);
   }
 }
-
 
 .modal-fields {
   .ant-modal {
diff --git a/src/mob/modulesource/option.jsx b/src/mob/modulesource/option.jsx
index 9e80200..aa5f650 100644
--- a/src/mob/modulesource/option.jsx
+++ b/src/mob/modulesource/option.jsx
@@ -28,7 +28,7 @@
 import officialAccount from '@/assets/mobimg/guanzhu.jpg'
 import Iframe from '@/assets/img/newpage.jpg'
 import Share from '@/assets/mobimg/share.jpg'
-import MkMap from '@/assets/img/map.jpg'
+// import MkMap from '@/assets/img/map.jpg'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
@@ -62,7 +62,7 @@
   { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
   { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24 },
   { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '娉ㄥ唽/鐧诲綍', width: 24 },
-  { type: 'menu', url: MkMap, component: 'map', subtype: 'txmap', title: '鍦板浘', width: 24, adapter: 'mini' },
+  // { type: 'menu', url: MkMap, component: 'map', subtype: 'txmap', title: '鍦板浘', width: 24, adapter: 'mini' },
   { type: 'menu', url: officialAccount, component: 'officialAccount', subtype: 'officialAccount', title: '鍏虫敞鍏紬鍙凤紙灏忕▼搴忎腑锛�', width: 24, adapter: 'mini' },
   { type: 'menu', url: Share, component: 'sharecode', subtype: 'sharecode', title: '鍒嗕韩鐮�', width: 24 },
   { type: 'menu', url: Iframe, component: 'iframe', subtype: 'iframe', title: 'iframe', width: 24 }
diff --git a/src/mob/searchconfig/index.jsx b/src/mob/searchconfig/index.jsx
index e943736..fbfc001 100644
--- a/src/mob/searchconfig/index.jsx
+++ b/src/mob/searchconfig/index.jsx
@@ -19,7 +19,7 @@
 const { Panel } = Collapse
 const { confirm } = Modal
 const SearchForm = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent/searchform'))
-const PasteComponent = asyncComponent(() => import('./pastecomponent'))
+// const PasteComponent = asyncComponent(() => import('./pastecomponent'))
 const DragElement = asyncComponent(() => import('./searchdragelement'))
 const GDragElement = asyncComponent(() => import('./groupdragelement'))
 const GroupForm = asyncComponent(() => import('./groupform'))
@@ -223,7 +223,7 @@
         return
       }
 
-      if (['checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (['checkcard'].includes(res.type) && res.resourceType === '1' && res.database !== 'sso' && /\s/.test(res.dataSource)) {
         this.setState({
           sqlVerifing: true
         })
@@ -232,12 +232,7 @@
         ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
         
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
-        
-        Api.sDebug(sql, rduri).then(result => {
+        Api.sDebug(sql).then(result => {
           if (result.status || result.ErrCode === '-2') {
             this.setState({
               sqlVerifing: false,
@@ -269,18 +264,18 @@
    * @description 琛ㄥ崟鍒犻櫎骞跺埛鏂�
    */
   closeForm = (card) => {
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎${card.label ? `<<${card.label}>>` : ''}鍚楋紵`,
       onOk() {
-        let _group = fromJS(_this.state.group).toJS()
+        let _group = fromJS(that.state.group).toJS()
         _group.fields = _group.fields.filter(item => item.uuid !== card.uuid)
 
-        _this.setState({
+        that.setState({
           group: _group,
         })
-        _this.resetConfig(_group)
+        that.resetConfig(_group)
       },
       onCancel() {}
     })
@@ -301,11 +296,11 @@
     const { config, originConfig } = this.state
 
     if (!is(fromJS(config), fromJS(originConfig))) {
-      let _this = this
+      let that = this
       confirm({
         content: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾杩斿洖鍚楋紵',
         onOk() {
-          _this.props.handleBack()
+          that.props.handleBack()
         },
         onCancel() {}
       })
@@ -451,15 +446,15 @@
   }
 
   closeGroup = (g) => {
-    const _this = this
+    const that = this
     let _group = fromJS(this.state.group).toJS()
     _group.groups = _group.groups.filter(item => item.uuid !== g.uuid)
 
     confirm({
       content: `纭畾鍒犻櫎鍒嗙粍銆�${g.wrap.name}銆嬪悧锛焋,
       onOk() {
-        _this.setState({ group: _group })
-        _this.resetConfig(_group)
+        that.setState({ group: _group })
+        that.resetConfig(_group)
       },
       onCancel() {}
     })
@@ -494,7 +489,7 @@
             <Button type="primary" loading={saving} onClick={this.submitConfig}>淇濆瓨</Button>
             <Button onClick={this.cancelConfig}>鍏抽棴</Button>
             {!group.floor ? <Button onClick={this.returnUp}>杩斿洖涓婄骇</Button> : null}
-            <PasteComponent insert={this.insert} />
+            {/* <PasteComponent insert={this.insert} /> */}
             <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
           </div>
           <div className="setting">
@@ -537,7 +532,7 @@
         <Modal
           title="缂栬緫"
           visible={this.state.visible}
-          width={850}
+          width={950}
           onCancel={this.editModalCancel}
           onOk={this.handleSubmit}
           confirmLoading={this.state.sqlVerifing}
diff --git a/src/mob/searchconfig/index.scss b/src/mob/searchconfig/index.scss
index 659c627..8148739 100644
--- a/src/mob/searchconfig/index.scss
+++ b/src/mob/searchconfig/index.scss
@@ -243,10 +243,6 @@
               .ant-input-number {
                 margin-top: 4px;
               }
-              .normal-braft-editor {
-                border: 1px solid #d9d9d9;
-                border-radius: 4px;
-              }
             }
             .ant-form-item-control-wrapper::after {
               content: '';
diff --git a/src/mob/searchconfig/searchdragelement/index.jsx b/src/mob/searchconfig/searchdragelement/index.jsx
index 1583c99..cf7e96a 100644
--- a/src/mob/searchconfig/searchdragelement/index.jsx
+++ b/src/mob/searchconfig/searchdragelement/index.jsx
@@ -55,7 +55,7 @@
 
     delete val.$srcId
     
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
diff --git a/src/pc/components/login/normal-login/loginform.jsx b/src/pc/components/login/normal-login/loginform.jsx
index 154fadd..8790dd8 100644
--- a/src/pc/components/login/normal-login/loginform.jsx
+++ b/src/pc/components/login/normal-login/loginform.jsx
@@ -157,7 +157,7 @@
             />
           </Form.Item>
           <Form.Item>
-            <Input.Password placeholder="瀵嗙爜" prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />
+            <Input.Password placeholder="瀵嗙爜" visibilityToggle={wrap.vispwd !== 'false'} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />
           </Form.Item>
           {!activeWay.shortcut || activeWay.shortcut === 'remember' ? <Form.Item className="minline">
             <Checkbox>璁颁綇瀵嗙爜</Checkbox>
diff --git a/src/pc/components/login/normal-login/options.jsx b/src/pc/components/login/normal-login/options.jsx
index 72dae60..76b6eda 100644
--- a/src/pc/components/login/normal-login/options.jsx
+++ b/src/pc/components/login/normal-login/options.jsx
@@ -171,6 +171,21 @@
         {value: 'none', label: '鏃�'},
         {value: 'remember', label: '璁颁綇瀵嗙爜'},
         {value: 'autologon', label: '鑷姩鐧诲綍'},
+      ],
+      controlFields: [
+        {field: 'vispwd', values: ['remember', 'autologon']},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'vispwd',
+      label: '鏌ョ湅瀵嗙爜',
+      initval: wrap.vispwd || 'true',
+      tooltip: '瀵嗙爜鏄惁鍙煡鐪嬶紙瀵嗙爜妗嗗彸渚у浘鏍囨槸鍚︽樉绀猴級銆�',
+      required: false,
+      options: [
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
       ]
     },
     {
diff --git a/src/pc/components/login/normal-login/signform.jsx b/src/pc/components/login/normal-login/signform.jsx
index 4d3d42d..311c433 100644
--- a/src/pc/components/login/normal-login/signform.jsx
+++ b/src/pc/components/login/normal-login/signform.jsx
@@ -42,7 +42,7 @@
       } else if (way === 'weixin') {
         signWays.push({
           type: 'weixin',
-          label: '寰俊鐧诲綍',
+          label: '鎵嬫満鍙峰揩鎹风櫥褰�',
           icon: <WechatOutlined />,
           sort: 3
         })
@@ -79,7 +79,7 @@
         } else if (way === 'weixin') {
           signWays.push({
             type: 'weixin',
-            label: '寰俊鐧诲綍',
+            label: '鎵嬫満鍙峰揩鎹风櫥褰�',
             sort: 3
           })
         }
diff --git a/src/pc/components/navbar/normal-navbar/linksetting/linktable/index.jsx b/src/pc/components/navbar/normal-navbar/linksetting/linktable/index.jsx
index 6a2d85a..e6aa8f7 100644
--- a/src/pc/components/navbar/normal-navbar/linksetting/linktable/index.jsx
+++ b/src/pc/components/navbar/normal-navbar/linksetting/linktable/index.jsx
@@ -78,13 +78,13 @@
 
   delMenu = (record) => {
     const { data } = this.state
-    const _this = this
+    const that = this
 
     confirm({
       title: '纭畾鍒犻櫎鍚楋紵',
       content: '',
       onOk() {
-        _this.setState({data: data.filter(item => item.MenuID !== record.MenuID)})
+        that.setState({data: data.filter(item => item.MenuID !== record.MenuID)})
       },
       onCancel() {}
     })
diff --git a/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx b/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx
index f8ea138..76ad886 100644
--- a/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx
+++ b/src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx
@@ -159,13 +159,13 @@
               {getFieldDecorator('copyMenuId', {
                 initialValue: menu.copyMenuId || ''
               })(
-                <Select allowClear onChange={(val) => this.setState({copyMenu: val})}>
+                <Select allowClear dropdownMatchSelectWidth={false} onChange={(val) => this.setState({copyMenu: val})}>
                   {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))}
                 </Select>
               )}
             </Form.Item>
           </Col> : null}
-          {property === 'menu' && copyMenu ? <Col span={12}>
+          {property === 'menu' && copyMenu ? <Col span={22}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="澶嶅埗鑿滃崟鏃讹紝鏄惁娓呯┖鍘熼〉闈腑鐨勫叧鑱旇彍鍗曘��">
                 <QuestionCircleOutlined className="mk-form-tip" />
diff --git a/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx b/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx
index 3ee2c9c..e0a85cf 100644
--- a/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx
+++ b/src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx
@@ -88,15 +88,15 @@
 
   delMenu = (record) => {
     const { menu } = this.props
-    const _this = this
+    const that = this
     
     confirm({
       title: '纭畾鍒犻櫎鍚楋紵',
       content: '',
       onOk() {
-        let _data = _this.state.data.filter(item => item.MenuID !== record.MenuID)
-        _this.setState({data: _data})
-        _this.props.menuUpdate({...menu, sublist: _data})
+        let _data = that.state.data.filter(item => item.MenuID !== record.MenuID)
+        that.setState({data: _data})
+        that.props.menuUpdate({...menu, sublist: _data})
       },
       onCancel() {}
     })
@@ -137,7 +137,7 @@
         })
       }
       if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') {
-        const _this = this
+        const that = this
         confirm({
           content: '鑿滃崟灏嗚閲嶇疆锛岀‘瀹氫慨鏀瑰悧锛�',
           onOk() {
@@ -147,8 +147,8 @@
               }
               return item
             })
-            _this.setState({data: _data, editMenu: null, visible: false})
-            _this.props.menuUpdate({...menu, sublist: _data})
+            that.setState({data: _data, editMenu: null, visible: false})
+            that.props.menuUpdate({...menu, sublist: _data})
           },
           onCancel() {}
         })
@@ -271,15 +271,15 @@
 
   delMenu = (record) => {
     const { menu } = this.props
-    const _this = this
+    const that = this
     
     confirm({
       title: (record.property === 'classify' && record.sublist.length > 0 ? '鑿滃崟涓嬪惈鏈夊瓙鑿滃崟锛�' : '') + '纭畾鍒犻櫎鍚楋紵',
       content: '',
       onOk() {
-        let _data = _this.state.data.filter(item => item.MenuID !== record.MenuID)
-        _this.setState({data: _data})
-        _this.props.menuUpdate({...menu, sublist: _data})
+        let _data = that.state.data.filter(item => item.MenuID !== record.MenuID)
+        that.setState({data: _data})
+        that.props.menuUpdate({...menu, sublist: _data})
       },
       onCancel() {}
     })
@@ -320,7 +320,7 @@
         })
       }
       if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') {
-        const _this = this
+        const that = this
         confirm({
           content: '鑿滃崟灏嗚閲嶇疆锛岀‘瀹氫慨鏀瑰悧锛�',
           onOk() {
@@ -330,8 +330,8 @@
               }
               return item
             })
-            _this.setState({data: _data, editMenu: null, visible: false})
-            _this.props.menuUpdate({...menu, sublist: _data})
+            that.setState({data: _data, editMenu: null, visible: false})
+            that.props.menuUpdate({...menu, sublist: _data})
           },
           onCancel() {}
         })
@@ -466,13 +466,13 @@
 
   delMenu = (record) => {
     const { data } = this.state
-    const _this = this
+    const that = this
 
     confirm({
       title: (record.property === 'classify' && record.sublist.length > 0 ? '鑿滃崟涓嬪惈鏈夊瓙鑿滃崟锛�' : '') + '纭畾鍒犻櫎鍚楋紵',
       content: '',
       onOk() {
-        _this.setState({data: data.filter(item => item.MenuID !== record.MenuID)})
+        that.setState({data: data.filter(item => item.MenuID !== record.MenuID)})
       },
       onCancel() {}
     })
@@ -513,7 +513,7 @@
       }
 
       if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') {
-        const _this = this
+        const that = this
         confirm({
           content: '鑿滃崟灏嗚閲嶇疆锛岀‘瀹氫慨鏀瑰悧锛�',
           onOk() {
@@ -523,7 +523,7 @@
               }
               return item
             })
-            _this.setState({data: _data, editMenu: null, visible: false})
+            that.setState({data: _data, editMenu: null, visible: false})
           },
           onCancel() {}
         })
diff --git a/src/pc/createview/index.jsx b/src/pc/createview/index.jsx
index 856e54c..bacaa39 100644
--- a/src/pc/createview/index.jsx
+++ b/src/pc/createview/index.jsx
@@ -87,8 +87,8 @@
         MenuName: res.MenuName || '',
         PageParam: JSON.stringify({Template: 'webPage'}),
         open_edition: '',
-        LText: '',
-        LTexttb: ''
+        // LText: '',
+        // LTexttb: ''
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -175,6 +175,10 @@
               config.components = this.collectTB(config.components)
               config.version = 2.0
             }
+
+            if (_config.getLocation) {
+              config.getLocation = _config.getLocation
+            }
           }
   
           param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
diff --git a/src/pc/createview/settingform/index.jsx b/src/pc/createview/settingform/index.jsx
index 0405709..730abc6 100644
--- a/src/pc/createview/settingform/index.jsx
+++ b/src/pc/createview/settingform/index.jsx
@@ -120,6 +120,7 @@
                 <Select
                   allowClear
                   showSearch
+                  dropdownMatchSelectWidth={false}
                   onChange={(val) => this.setState({copymenuId: val})}
                   filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                 >
diff --git a/src/pc/menushell/index.jsx b/src/pc/menushell/index.jsx
index 32b17b4..5d16e71 100644
--- a/src/pc/menushell/index.jsx
+++ b/src/pc/menushell/index.jsx
@@ -153,7 +153,6 @@
         config: item.config,
         width: item.width || 24,
         name: name,
-        floor: 1,   // 缁勪欢鐨勫眰绾�
         isNew: true // 鏂版坊鍔犳爣蹇楋紝鐢ㄤ簬鍒濆鍖�
       }
       
@@ -169,12 +168,48 @@
       const { index: overIndex } = findCard(`${targetId}`)
       const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] })
 
-      if (style) {
-        handleList({...menu, style, components: _cards})
+      if (item.component === 'navbar') {
+        let appMenus = sessionStorage.getItem('appViewList')
+        if (appMenus) {
+          try {
+            appMenus = JSON.parse(appMenus)
+            appMenus = appMenus.filter(item => item.keys_type === 'navbar')
+          } catch (e) {
+            appMenus = []
+          }
+        } else {
+          appMenus = []
+        }
+
+        if (appMenus.length) {
+          confirm({
+            title: '濡傞渶浣跨敤褰撳墠搴旂敤涓凡鏈夌殑鑿滃崟鏍忥紝璇风偣鍑诲彸渚у叧鑱旇彍鍗曟爮锛屽闇�鏂板璇风偣纭畾銆�',
+            onOk() {
+              if (style) {
+                handleList({...menu, style, components: _cards})
+              } else {
+                handleList({...menu, components: _cards})
+              }
+              setCards(_cards)
+            },
+            onCancel() {}
+          })
+        } else {
+          if (style) {
+            handleList({...menu, style, components: _cards})
+          } else {
+            handleList({...menu, components: _cards})
+          }
+          setCards(_cards)
+        }
       } else {
-        handleList({...menu, components: _cards})
+        if (style) {
+          handleList({...menu, style, components: _cards})
+        } else {
+          handleList({...menu, components: _cards})
+        }
+        setCards(_cards)
       }
-      setCards(_cards)
     }
   })
 
diff --git a/src/store/options.js b/src/store/options.js
index 8f3ebd5..1b674dd 100644
--- a/src/store/options.js
+++ b/src/store/options.js
@@ -45,4 +45,19 @@
   bg_white_style_deep_red: 'mk-deep-red-white',
   bg_black_style_deep_blue: 'mk-deep-blue-black',
   bg_white_style_deep_blue: 'mk-deep-blue-white',
+}
+
+/**
+ * @description 璇█
+ */
+export const langs = {
+  'zh-CN': '绠�浣撲腑鏂�',
+  'en-US': 'English',
+  'fr-FR': 'Fran莽ais',
+  'de-DE': 'Deutsch',
+  'ko-KR': '頃滉淡鞏�',
+  'pt-BR': 'Portugu锚s',
+  'ja-jp': '鏃ユ湰瑾�',
+  'ar-AE': '毓乇亘賷 貙',
+  'ru-RU': '褉褍褋褋泻懈泄 褟蟹褘泻'
 }
\ No newline at end of file
diff --git a/src/tabviews/basetable/index.jsx b/src/tabviews/basetable/index.jsx
index b02c94b..9af687c 100644
--- a/src/tabviews/basetable/index.jsx
+++ b/src/tabviews/basetable/index.jsx
@@ -2,6 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Row, Col } from 'antd'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -173,6 +174,21 @@
       }
 
       window.GLOB.CacheData.set(MenuID, urlparam)
+
+      if (window.backend && config.allSqls) {
+        let keys = Object.keys(urlparam)
+        config.allSqls.forEach(item => {
+          item.id = md5(window.GLOB.appkey + item.v_id)
+          if (item.type === 'datasource' || item.type === 'excelOut') {
+            item.urlkeys = keys
+            item.urlparam = urlparam
+            if (config.flow_code) {
+              item.works_flow_code = config.flow_code
+            }
+          }
+          window.GLOB.CacheData.set('sql_' + item.uuid, item)
+        })
+      }
 
       let userName = sessionStorage.getItem('User_Name') || ''
       let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -504,19 +520,13 @@
 
     if (cell.OpenType === 'excelOut') { // 瀵煎嚭
       cell.$menuName = item.$menuname
-
-      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
-        cell.errorType = 'error1'
-      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom' && item.setting.interType !== 'system') {
-        cell.errorType = 'error2'
-      }
+    } else if (cell.OpenType === 'pop' && cell.modal) {
+      cell.modal.uuid = cell.uuid + '_pop'
     }
 
     if (cell.verify) {
       if (cell.verify.invalid === 'true') {
-        if (item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')) {
-          cell.verify.invalid = 'false'
-        } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
+        if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
           cell.verify.invalid = 'false'
         } else if (cell.intertype !== 'system' && cell.procMode !== 'system') {
           cell.verify.invalid = 'false'
@@ -632,6 +642,8 @@
         return component
       }
 
+      component.setting.uuid = component.uuid
+
       let _customScript = ''
       let _tailScript = ''
       component.scripts && component.scripts.forEach(script => {
@@ -677,13 +689,13 @@
       component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
       component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-      component.setting.custompage = /@pageSize@|@orderBy@/i.test(component.setting.dataresource + component.setting.customScript)
+      component.setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(component.setting.dataresource + component.setting.customScript)
 
       if (!component.setting.execute || component.setting.custompage) {
         component.forbidLine = true
       }
       
-      component.setting.delay = delay
+      component.setting.delay = delay + (component.setting.delay || 0)
       delay += 20
 
       return component
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index e94c925..463dc0b 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -305,12 +305,6 @@
 
         if (item.OpenType === 'excelOut') { // 瀵煎嚭
           item.$menuName = MenuName
-    
-          if (!item.verify || !item.verify.columns || item.verify.columns.length === 0) {
-            item.errorType = 'error1'
-          } else if (item.intertype === 'system' && item.verify.dataType !== 'custom' && config.setting.interType !== 'system') {
-            item.errorType = 'error2'
-          }
         }
 
         if (item.verify && item.verify.invalid === 'true') {
diff --git a/src/tabviews/custom/components/calendar/board/index.jsx b/src/tabviews/custom/components/calendar/board/index.jsx
index fddbe03..f4e1e3b 100644
--- a/src/tabviews/custom/components/calendar/board/index.jsx
+++ b/src/tabviews/custom/components/calendar/board/index.jsx
@@ -10,7 +10,9 @@
 
 const { Option } = Select
 
-moment.locale('zh-cn')
+if (sessionStorage.getItem('lang') === 'zh-CN') {
+  moment.locale('zh-cn')
+}
 
 class CalendarBoard extends Component {
   static propTpyes = {
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index d0eb21a..085f046 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -553,6 +553,9 @@
           }
           if (card.format === 'percent') {
             val = val * 100
+            if (!card.round) {
+              val = +val.toFixed(2)
+            }
           } else if (card.format === 'abs') {
             val = Math.abs(val)
           }
@@ -943,7 +946,7 @@
                 // eslint-disable-next-line
                 _val = eval(_val)
               } catch (e) {
-                console.info(_val)
+                window.mkInfo(_val)
                 console.warn(e)
                 _val = 0
               }
@@ -957,6 +960,29 @@
           val = ''
         } else if (data) {
           let _val = card.formula
+
+          if (card.$keys && card.noValue === 'hide') { // 绌哄�奸殣钘�
+            let _data = {}
+            let empty = true
+
+            Object.keys(data).forEach(key => {
+              _data[key.toLowerCase()] = data[key]
+            })
+            _data.username = sessionStorage.getItem('User_Name') || ''
+            _data.fullname = sessionStorage.getItem('Full_Name') || ''
+            _data.bid = data.$$BID || ''
+
+            card.$keys.forEach(key => {
+              if (!_data.hasOwnProperty(key)) {
+                empty = false
+              } else if (_data[key] && !/^1949-10-01/.test(_data[key])) {
+                empty = false
+              }
+            })
+
+            if (empty) return null
+          }
+
           if (/@username@|@fullName@|@bid@/ig.test(_val)) {
             _val = _val.replace(/@username@/ig, sessionStorage.getItem('User_Name') || '').replace(/@fullName@/ig, sessionStorage.getItem('Full_Name') || '').replace(/@bid@/ig, data.$$BID || '')
           }
@@ -970,7 +996,7 @@
               // eslint-disable-next-line
               _val = eval(_val)
             } catch (e) {
-              console.info(_val)
+              window.mkInfo(_val)
               console.warn(e)
               _val = ''
             }
@@ -990,8 +1016,10 @@
   
         if (val !== '') {
           if (val && typeof(val) === 'string') {
-            val = val.replace(/\n/ig, '<br/>')
-            if (!/<(span|div|p|a|img)\s/g.test(val)) {
+            if (!card.evalchars || card.evalchars.includes('enter')) {
+              val = val.replace(/\n/ig, '<br/>')
+            }
+            if ((!card.evalchars || card.evalchars.includes('space')) && !/<(span|div|p|a|img)\s/g.test(val)) {
               val = val.replace(/\s/ig, '&nbsp;')
             }
 
@@ -1031,14 +1059,26 @@
           className = mark.signType
         }
 
-        contents.push(
-          <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
-            <div style={_style}>
-              {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>}
+        if (card.link && !data.$disabled) {
+          _style.cursor = 'pointer'
+          contents.push(
+            <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)}}>
+                {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>
             </div>
-          </div>
-        )
+          )
+        } else {
+          contents.push(
+            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+              <div style={_style}>
+                {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>
+            </div>
+          )
+        }
       } else if (card.eleType === 'tag') {
         let vals = ''
   
@@ -1220,6 +1260,7 @@
             name={name}
             BID={data.$$BID}
             LID={lid}
+            columns={cards.columns}
             BData={data.$$BData || ''}
             disabled={_disabled}
             selectedData={_data}
@@ -1282,6 +1323,7 @@
               disabled={_disabled}
               LID={lid}
               btn={card}
+              columns={cards.columns}
               selectedData={_data}
             />
           }
diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss
index e5cfb31..b13d11b 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.scss
+++ b/src/tabviews/custom/components/card/cardcellList/index.scss
@@ -54,7 +54,7 @@
       overflow: visible;
       text-align: center;
     }
-    span {
+    span, div {
       text-indent: 0px;
       font-style: inherit;
       font-weight: inherit;
@@ -117,7 +117,7 @@
       min-height: 28px;
       padding: 0;
       overflow: hidden;
-      text-align: inherit;
+      // text-align: inherit;
     }
     .ant-checkbox-wrapper:not(.square) {
       .ant-checkbox-inner, .ant-checkbox-checked::after {
diff --git a/src/tabviews/custom/components/card/data-card/index.jsx b/src/tabviews/custom/components/card/data-card/index.jsx
index f5d8dd2..2682bca 100644
--- a/src/tabviews/custom/components/card/data-card/index.jsx
+++ b/src/tabviews/custom/components/card/data-card/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, Empty, message, Row, Col, Pagination, Switch } from 'antd'
+import { Spin, Empty, message, Row, Col, Pagination, Switch, notification } from 'antd'
 import { DownOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -186,6 +186,23 @@
   
         window.GLOB.SyncData.delete(_config.dataName)
       }
+    }
+
+    if (_config.wrap.zHeight) {
+      if (_config.wrap.zHeight <= 100) {
+        if (_config.wrap.zHeight < 0) {
+          _config.wrap.zHeight = `calc(100vh - ${-_config.wrap.zHeight}px)`
+        } else {
+          _config.wrap.zHeight = _config.wrap.zHeight + 'vh'
+        }
+      }
+
+      if (_config.style) {
+        delete _config.style.height
+      }
+      _config.wrap.layout += ' fix-height'
+    } else {
+      _config.wrap.zHeight = 'none'
     }
 
     this.setState({
@@ -393,9 +410,7 @@
 
     if (config.$searchId !== searchId) return
     
-    this.setState({pageIndex: 1}, () => {
-      this.loadData()
-    })
+    this.reloadIndex()
   }
 
   /**
@@ -409,6 +424,7 @@
 
     if (config.uuid !== menuId) return
 
+    let _id = config.wrap.selected === 'always' ? id : ''
     if (config.supNodes) {
       if (['mainline', 'maingrid', 'popclose'].includes(position)) {
         let supNode = this.supModules[this.supModules.length - 1]
@@ -424,18 +440,18 @@
       } else {
         if (position === 'line' || position === 'line_grid') {
           if (lines && lines.length === 1) {
-            this.loadLinedata(lines[0].$$uuid, position)
+            if (config.forbidLine) {
+              this.loadData(lines[0].$$uuid, 'repage')
+            } else {
+              this.loadLinedata(lines[0].$$uuid, position)
+            }
           } else {
-            this.loadData(id)
+            this.loadData(_id, 'repage')
           }
-        } else if (!btn || btn.resetPageIndex !== 'false') {
-          this.setState({
-            pageIndex: 1
-          }, () => {
-            this.loadData(id)
-          })
+        } else if (btn.resetPageIndex !== 'false') {
+          this.reloadIndex()
         } else {
-          this.loadData(id)
+          this.loadData(_id, 'repage')
         }
       }
     } else {
@@ -443,20 +459,20 @@
 
       if (position === 'line' || position === 'line_grid') {
         if (lines && lines.length === 1) {
-          this.loadLinedata(lines[0].$$uuid, position)
+          if (config.forbidLine) {
+            this.loadData(lines[0].$$uuid, 'repage')
+          } else {
+            this.loadLinedata(lines[0].$$uuid, position)
+          }
         } else {
-          this.loadData(id)
+          this.loadData(_id, 'repage')
         }
       } else if (['mainline', 'maingrid', 'popclose'].includes(position) && supModule) {
         MKEmitter.emit('reloadData', supModule, position === 'maingrid' ? '' : BID)
-      } else if (!btn || btn.resetPageIndex !== 'false') {
-        this.setState({
-          pageIndex: 1
-        }, () => {
-          this.loadData(id)
-        })
+      } else if (btn.resetPageIndex !== 'false') {
+        this.reloadIndex()
       } else {
-        this.loadData(id)
+        this.loadData(_id, 'repage')
       }
     }
   }
@@ -478,13 +494,21 @@
     })
   }
 
+  reloadIndex = () => {
+    this.setState({
+      pageIndex: 1
+    }, () => {
+      this.loadData()
+    })
+  }
+
   prevCheck = (id) => {
     const { selected } = this.state
 
     if (selected === 'false' && !id) return
 
     setTimeout(() => {
-      this.checkTopLine(id)
+      this.checkTopLine(id, selected)
     }, 10)
 
     if (selected === 'init') {
@@ -492,59 +516,39 @@
     }
   }
 
-  checkTopLine = (id) => {
-    const { config, data, selected } = this.state
+  checkTopLine = (id, selected) => {
+    const { config, data } = this.state
 
-    if (data.length === 0) {
-      this.setState({
-        activeKey: '',
-        selectKeys: [],
-        selectedData: []
-      })
-  
-      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
-      if (config.setting.$hasSyncModule) {
-        MKEmitter.emit('syncBalconyData', config.uuid, [], false)
+    let index = -1
+    let keys = []
+    let items = []
+
+    if (data.length > 0) {
+      if (id) {
+        index = data.findIndex(item => item.$$uuid === id && !item.$disabled)
       }
-      return
-    }
-
-    if (selected === 'sign') {
-      let index = ''
-      let keys = []
-      let items = []
-      let last = ''
-      data.forEach((item, i) => {
-        if (!item.$disabled && item.selected === 'true') {
-          items.push(item)
-          keys.push(i)
-          index = i
-          last = item
+  
+      if (index !== -1) {
+        keys = [index]
+        items = [data[index]]
+      } else if (selected === 'sign') {
+        data.forEach((item, i) => {
+          if (!item.$disabled && item.selected === 'true') {
+            items.push(item)
+            keys.push(i)
+            index = i
+          }
+        })
+      } else if (selected !== 'false') {
+        if (!data[0].$disabled) {
+          index = 0
+          keys = [index]
+          items = [data[index]]
         }
-      })
-
-      this.setState({
-        activeKey: index,
-        selectKeys: keys,
-        selectedData: items
-      })
-  
-      MKEmitter.emit('resetSelectLine', config.uuid, last ? last.$$uuid : '', last)
-      if (config.setting.$hasSyncModule) {
-        MKEmitter.emit('syncBalconyData', config.uuid, items, data.length === keys.length)
-      }
-      return
-    }
-
-    let index = 0
-    if (id) {
-      index = data.findIndex(item => item.$$uuid === id)
-      if (index === -1) {
-        index = 0
       }
     }
 
-    if (data[index].$disabled) {
+    if (index === -1) {
       this.setState({
         activeKey: '',
         selectKeys: [],
@@ -557,16 +561,18 @@
       }
       return
     }
+
+    let item = items[items.length - 1]
 
     this.setState({
       activeKey: index,
-      selectKeys: [index],
-      selectedData: [data[index]]
+      selectKeys: keys,
+      selectedData: items
     })
 
-    MKEmitter.emit('resetSelectLine', config.uuid, data[index].$$uuid, data[index])
+    MKEmitter.emit('resetSelectLine', config.uuid, item.$$uuid, item)
     if (config.setting.$hasSyncModule) {
-      MKEmitter.emit('syncBalconyData', config.uuid, [data[index]], data.length === 1)
+      MKEmitter.emit('syncBalconyData', config.uuid, items, data.length === keys.length)
     }
   }
 
@@ -599,7 +605,7 @@
       MKEmitter.emit('resetSelectLine', config.uuid, last ? last.$$uuid : '', last)
       MKEmitter.emit('syncBalconyData', config.uuid, items, data.length > 0 && data.length === keys.length)
       if (items.length === 0) {
-        message.warning('鏈幏鍙栧埌鏁版嵁锛�')
+        message.warning(window.GLOB.dict['no_data'] || '鏈幏鍙栧埌鏁版嵁锛�')
       }
     } else {
       this.setState({
@@ -664,7 +670,9 @@
     if (config.uuid !== menuId) return
 
     if (!id) {
-      this.loadData()
+      this.reloadIndex()
+    } else if (config.forbidLine) {
+      this.loadData(id, 'repage')
     } else {
       this.loadLinedata(id)
     }
@@ -787,6 +795,11 @@
     if (result.status) {
       if (result.$requestId && this.requestId !== result.$requestId) return
 
+      if (type === 'repage' && result.data.length === 0 && pageIndex > 1) {
+        this.reloadIndex()
+        return
+      }
+
       let start = 1
       if (config.setting.laypage) {
         start = pageSize * (pageIndex - 1) + 1
@@ -797,7 +810,7 @@
         Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
-      if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
+      if (selected !== 'false' || id) {
         this.prevCheck(id)
       } else {
         MKEmitter.emit('resetSelectLine', config.uuid, '', '')
@@ -885,15 +898,6 @@
   async loadLinedata (id, position) {
     const { config, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
 
-    if (config.forbidLine) {
-      this.setState({
-        pageIndex: 1
-      }, () => {
-        this.loadData()
-      })
-      return
-    }
-
     let searches = fromJS(search).toJS()
     if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
       let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
@@ -915,7 +919,7 @@
     let result = await Api.genericInterface(param)
     if (result.status) {
       if (position === 'line_grid' && (!result.data || !result.data[0])) {
-        this.loadData()
+        this.reloadIndex()
         return
       }
 
@@ -929,6 +933,12 @@
         _data.$$uuid = _data[config.setting.primaryKey] || ''
         _data.$$BID = BID || ''
         _data.$$BData = BData || ''
+
+        if (config.wrap.controlField) {
+          if (config.wrap.controlVal.includes(_data[config.wrap.controlField] + '')) {
+            _data.$disabled = true
+          }
+        }
 
         data = data.map(item => {
           if (item.$$uuid === _data.$$uuid) {
@@ -1070,6 +1080,20 @@
   }
 
   refreshSearch = (list) => {
+    const { config, BID } = this.state
+
+    if (config.setting.supModule && !BID && config.wrap.supKey !== 'false') {
+      notification.warning({
+        top: 92,
+        message: window.GLOB.dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
+        duration: 5
+      })
+      this.setState({
+        search: list
+      })
+      return
+    }
+
     this.setState({
       search: list,
       pageIndex: 1
@@ -1205,10 +1229,10 @@
             selectedData={selectedData}
           /> : null
         }
-        {config.wrap.pickup === 'true' && this.state.data.length > 0 ? <div className="pickup-wrap"><Switch title="鏀惰捣" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /></div> : null}
+        {config.wrap.pickup === 'true' && this.state.data.length > 0 ? <div className="pickup-wrap"><Switch title="鏀惰捣" checkedChildren={window.GLOB.dict['open'] || '寮�'} unCheckedChildren={window.GLOB.dict['shut'] || '鍏�'} checked={pickup} onChange={this.pickupChange} /></div> : 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 ' + config.wrap.layout}>
+          <Row className={'card-row-list ' + config.wrap.layout} style={{maxHeight: config.wrap.zHeight}}>
             {precards.map((item, index) => (
               <Col key={'pre' + index} className="extend-card" style={item.wStyle} span={item.setting.width || 6}>
                 {item.setting.cardRole === 'header' ? <TableHeader card={item} data={extendData} refresh={this.refreshByHeader}>
@@ -1254,8 +1278,8 @@
           {switchable ? <div className={'prev-page ' + (total <= _total ? 'disabled' : '')} onClick={this.nextPage}><div><div><img src={nextImg} alt=""/></div></div></div> : null}
         </div>
         {config.$empty && data.length === 0 ? <Empty description={false}/> : null}
-        {config.wrap.pagestyle === 'page' ? <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.length > 0 ? <div className={'mk-more' + (pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
+        {config.wrap.pagestyle === 'page' ? <Pagination size="small" total={total} showTotal={(t, range) => total > 0 ? `${range[0]}-${range[1]} ${window.GLOB.dict['of'] || '鍏�'} ${total} ${window.GLOB.dict['items'] || '鏉�'}` : `${total} ${window.GLOB.dict['items'] || '鏉�'}`} pageSize={pageSize} showSizeChanger={true} pageSizeOptions={this.state.pageOptions} onChange={this.changePageIndex} onShowSizeChange={this.pageSizeChange} current={pageIndex}/> : null}
+        {config.wrap.pagestyle === 'more' && data.length > 0 ? <div className={'mk-more' + (pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>{window.GLOB.dict['view_more'] || '鏌ョ湅鏇村'}<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 e26e385..7a3eefc 100644
--- a/src/tabviews/custom/components/card/data-card/index.scss
+++ b/src/tabviews/custom/components/card/data-card/index.scss
@@ -8,6 +8,7 @@
 
   .pickup-wrap {
     float: right;
+    margin-bottom: 3px;
     button {
       margin-top: 3px;
     }
@@ -64,6 +65,25 @@
   .card-row-list {
     flex: 10;
     max-width: 100%;
+  }
+  .card-row-list.fix-height {
+    border: 1px solid #e8e8e8;
+    border-radius: 4px;
+    overflow-y: auto;
+    .extend-card:first-child {
+      position: sticky;
+      top: 0;
+      z-index: 1;
+      .card-item-box {
+        margin-top: 0!important;
+        margin-bottom: 0!important;
+      }
+    }
+    div:last-child {
+      .card-item-box {
+        border-bottom: none!important;
+      }
+    }
   }
   .card-row-list.flex-layout {
     display: flex;
@@ -275,16 +295,16 @@
     }
   }
 }
-.custom-data-card-box::-webkit-scrollbar {
+.custom-data-card-box::-webkit-scrollbar, .custom-data-card-box .card-row-list::-webkit-scrollbar {
   width: 7px;
   height: 7px;
 }
-.custom-data-card-box::-webkit-scrollbar-thumb {
+.custom-data-card-box::-webkit-scrollbar-thumb, .custom-data-card-box .card-row-list::-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);
 }
-.custom-data-card-box::-webkit-scrollbar-track {
+.custom-data-card-box::-webkit-scrollbar-track, .custom-data-card-box .card-row-list::-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);
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 4f56e58..8ee5097 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.jsx
+++ b/src/tabviews/custom/components/card/double-data-card/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, Empty, Row, Col, Pagination, Switch } from 'antd'
+import { Spin, Empty, Row, Col, Pagination, Switch, notification } from 'antd'
 import { DownOutlined, UpOutlined, PlusSquareOutlined, MinusSquareOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -129,6 +129,26 @@
 
     _config.wrap.wrapClass =  `${_config.wrap.selStyle} ${_config.wrap.cardType || ''}`
 
+    if (_config.wrap.zHeight || _config.wrap.minWidth) {
+      if (_config.wrap.zHeight) {
+        if (_config.wrap.zHeight <= 100) {
+          if (_config.wrap.zHeight < 0) {
+            _config.wrap.zHeight = `calc(100vh - ${-_config.wrap.zHeight}px)`
+          } else {
+            _config.wrap.zHeight = _config.wrap.zHeight + 'vh'
+          }
+        }
+        _config.wrap.wrapClass += ' fix-height'
+      }
+      _config.wrap.minWidth = _config.wrap.minWidth ? _config.wrap.minWidth + 'px' : '100%'
+      _config.wrap.zoomStyle = {
+        maxHeight: _config.wrap.zHeight || 'none',
+        '--mk-data-zoom-width': _config.wrap.minWidth
+      }
+    } else {
+      _config.wrap.zoomStyle = null
+    }
+
     if (_config.wrap.shifting === 'true') {
       _config.wrap.shifting = 'shifting'
     } else {
@@ -173,19 +193,6 @@
       if (_config.wrap.maxPageSize) {
         pageOptions = pageOptions.filter(item => item <= _config.wrap.maxPageSize)
       }
-    }
-
-    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({
@@ -351,9 +358,7 @@
 
     if (config.$searchId !== searchId) return
     
-    this.setState({pageIndex: 1}, () => {
-      this.loadData()
-    })
+    this.reloadIndex()
   }
 
   /**
@@ -366,22 +371,23 @@
 
     let supModule = config.setting.supModule
 
+    let _id = config.wrap.selected === 'always' ? id : ''
     if (position === 'line' || position === 'line_grid') {
       if (lines && lines.length === 1) {
-        this.loadLinedata(lines[0].$$parentId || lines[0].$$uuid, position)
+        if (config.forbidLine) {
+          this.loadData(lines[0].$$parentId || lines[0].$$uuid, 'repage')
+        } else {
+          this.loadLinedata(lines[0].$$parentId || lines[0].$$uuid, position)
+        }
       } else {
-        this.loadData(id)
+        this.loadData(_id, 'repage')
       }
     } else if (['mainline', 'maingrid', 'popclose'].includes(position) && supModule) {
       MKEmitter.emit('reloadData', supModule, position === 'maingrid' ? '' : BID)
-    } else if (!btn || btn.resetPageIndex !== 'false') {
-      this.setState({
-        pageIndex: 1
-      }, () => {
-        this.loadData(id)
-      })
+    } else if (btn.resetPageIndex !== 'false') {
+      this.reloadIndex()
     } else {
-      this.loadData(id)
+      this.loadData(_id, 'repage')
     }
   }
 
@@ -407,64 +413,40 @@
     })
   }
 
-  checkTopLine = (id) => {
-    const { config, data, selected, card } = this.state
+  checkTopLine = (id, selected) => {
+    const { config, data, card } = this.state
     let _opens = [...this.state.opens]
 
-    if (data.length === 0) {
-      this.setState({
-        activeKey: '',
-        selectKeys: [],
-        selectedData: []
-      })
-  
-      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
-      return
-    }
+    let index = -1
+    let keys = []
+    let items = []
 
-    if (selected === 'sign') {
-      let index = ''
-      let keys = []
-      let items = []
-      let last = ''
-
-      if (card.setting.display === 'collapse') {
-        _opens = []
+    if (data.length > 0) {
+      if (id) {
+        index = data.findIndex(item => item.$$uuid === id && !item.$disabled)
       }
 
-      data.forEach((item, i) => {
-        if (!item.$disabled && item.selected === 'true') {
-          items.push(item)
-          keys.push(i)
-          index = i
-          last = item
-
-          if (card.setting.display === 'collapse') {
-            _opens.push(i)
+      if (index !== -1) {
+        keys = [index]
+        items = [data[index]]
+      } else if (selected === 'sign') {
+        data.forEach((item, i) => {
+          if (!item.$disabled && item.selected === 'true') {
+            items.push(item)
+            keys.push(i)
+            index = i
           }
+        })
+      } else if (selected !== 'false') {
+        if (!data[0].$disabled) {
+          index = 0
+          keys = [index]
+          items = [data[index]]
         }
-      })
-
-      this.setState({
-        opens: _opens,
-        activeKey: index,
-        selectKeys: keys,
-        selectedData: items
-      })
-  
-      MKEmitter.emit('resetSelectLine', config.uuid, last ? last.$$uuid : '', last)
-      return
-    }
-
-    let index = 0
-    if (id) {
-      index = data.findIndex(item => item.$$uuid === id)
-      if (index === -1) {
-        index = 0
       }
     }
 
-    if (data[index].$disabled) {
+    if (index === -1) {
       this.setState({
         activeKey: '',
         selectKeys: [],
@@ -476,17 +458,19 @@
     }
 
     if (card.setting.display === 'collapse') {
-      _opens = [index]
+      _opens = keys
     }
+
+    let item = items[items.length - 1]
 
     this.setState({
       opens: _opens,
       activeKey: index,
-      selectKeys: [index],
-      selectedData: [data[index]]
+      selectKeys: keys,
+      selectedData: items
     })
 
-    MKEmitter.emit('resetSelectLine', config.uuid, data[index].$$uuid, data[index])
+    MKEmitter.emit('resetSelectLine', config.uuid, item.$$uuid, item)
   }
 
   checkAll = () => {
@@ -534,7 +518,9 @@
     if (config.uuid !== menuId) return
 
     if (!id) {
-      this.loadData()
+      this.reloadIndex()
+    } else if (config.forbidLine) {
+      this.loadData(id, 'repage')
     } else {
       this.loadLinedata(id)
     }
@@ -630,6 +616,11 @@
     if (result.status) {
       if (result.$requestId && this.requestId !== result.$requestId) return
 
+      if (type === 'repage' && result.data.length === 0 && pageIndex > 1) {
+        this.reloadIndex()
+        return
+      }
+
       let start = 1
       if (config.setting.laypage) {
         start = pageSize * (pageIndex - 1) + 1
@@ -640,13 +631,10 @@
         Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
-      if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
+      if (selected !== 'false' || id) {
         setTimeout(() => {
-          this.checkTopLine(id)
+          this.checkTopLine(id, selected)
         }, 10)
-        if (selected === 'init') {
-          this.setState({selected: 'false'})
-        }
       } else {
         MKEmitter.emit('resetSelectLine', config.uuid, '', '')
       }
@@ -756,6 +744,10 @@
         loading: false
       })
 
+      if (selected === 'init') {
+        this.setState({selected: 'false'})
+      }
+
       if (config.timer && config.clearField && result.data && result.data[0]) {
         let vals = (config.clearValue || '').split(',')
         if (vals.includes(result.data[0][config.clearField])) {
@@ -780,15 +772,6 @@
   async loadLinedata (id, position) {
     const { config, pageIndex, pageSize, search, BID, BData, orderBy } = this.state
 
-    if (config.forbidLine) {
-      this.setState({
-        pageIndex: 1
-      }, () => {
-        this.loadData()
-      })
-      return
-    }
-
     let searches = fromJS(search).toJS()
     if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
       let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
@@ -810,7 +793,7 @@
     let result = await Api.genericInterface(param)
     if (result.status) {
       if (position === 'line_grid' && (!result.data || !result.data[0])) {
-        this.loadData()
+        this.reloadIndex()
         return
       }
 
@@ -933,6 +916,14 @@
     }
   }
 
+  reloadIndex = () => {
+    this.setState({
+      pageIndex: 1
+    }, () => {
+      this.loadData()
+    })
+  }
+
   loadMore = () => {
     const { total, pageIndex, pageSize, loading } = this.state
 
@@ -956,6 +947,20 @@
   }
 
   refreshSearch = (list) => {
+    const { config, BID } = this.state
+
+    if (config.setting.supModule && !BID && config.wrap.supKey !== 'false') {
+      notification.warning({
+        top: 92,
+        message: window.GLOB.dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
+        duration: 5
+      })
+      this.setState({
+        search: list
+      })
+      return
+    }
+
     this.setState({
       search: list,
       pageIndex: 1
@@ -1152,10 +1157,10 @@
             selectedData={selectedData}
           /> : null
         }
-        {config.wrap.pickup === 'true' && this.state.data.length > 0 ? <div className="pickup-wrap"><Switch title="鏀惰捣" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /></div> : null}
+        {config.wrap.pickup === 'true' && this.state.data.length > 0 ? <div className="pickup-wrap"><Switch title="鏀惰捣" checkedChildren={window.GLOB.dict['open'] || '寮�'} unCheckedChildren={window.GLOB.dict['shut'] || '鍏�'} checked={pickup} onChange={this.pickupChange} /></div> : null}
         <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 '}>
+          <div className={`data-zoom ${config.wrap.wrapClass}`}>
+            <Row className="card-row-list">
               {precards.map((item, index) => (
                 <Col key={'pre' + index} className="extend-card" style={item.wStyle} span={item.setting.width || 6}>
                   {item.setting.cardRole === 'header' ? <TableHeader card={item} data={extendData} refresh={this.refreshByHeader}>
@@ -1232,8 +1237,8 @@
           </div>
           {config.$empty && data.length === 0 ? <Empty description={false}/> : null}
         </div>
-        {config.wrap.pagestyle === 'page' ? <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.length > 0 ? <div className={'mk-more' + (pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>鏌ョ湅鏇村<DownOutlined/></div> : null}
+        {config.wrap.pagestyle === 'page' ? <Pagination size="small" total={total} showTotal={(t, range) => total > 0 ? `${range[0]}-${range[1]} ${window.GLOB.dict['of'] || '鍏�'} ${total} ${window.GLOB.dict['items'] || '鏉�'}` : `${total} ${window.GLOB.dict['items'] || '鏉�'}`} pageSize={pageSize} showSizeChanger={true} pageSizeOptions={this.state.pageOptions} onChange={this.changePageIndex} onShowSizeChange={this.pageSizeChange} current={pageIndex}/> : null}
+        {config.wrap.pagestyle === 'more' && data.length > 0 ? <div className={'mk-more' + (pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>{window.GLOB.dict['view_more'] || '鏌ョ湅鏇村'}<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 3f19dd4..07c69b2 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.scss
+++ b/src/tabviews/custom/components/card/double-data-card/index.scss
@@ -8,6 +8,7 @@
 
   .pickup-wrap {
     float: right;
+    margin-bottom: 3px;
     button {
       margin-top: 3px;
     }
@@ -26,6 +27,7 @@
   .data-zoom {
     display: flex;
     position: relative;
+    min-width: var(--mk-data-zoom-width, 100%);
     .mk-disabled {
       >.card-item-box {
         cursor: not-allowed;
@@ -42,14 +44,6 @@
   .card-row-list {
     flex: 10;
     max-width: 100%;
-  }
-  .card-row-list.flex-layout {
-    display: flex;
-    width: 100%;
-    >.ant-col {
-      width: 5%;
-      flex: 1;
-    }
   }
   .card-item-box {
     position: relative;
@@ -279,19 +273,31 @@
     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;
+    .fix-height .card-row-list {
+      .extend-card:first-child {
+        position: sticky;
+        top: 0;
+        z-index: 1;
+        .card-item-box {
+          margin-top: 0!important;
+          margin-bottom: 0!important;
+        }
+      }
+      div:last-child {
+        .sub-card-wrap {
+          .card-item-box {
+            border-bottom: none!important;
+          }
+        }
+      }
     }
   }
   .data-zoom-box::-webkit-scrollbar {
     height: 9px;
-    width: 9px;
+    width: 7px;
   }
   .data-zoom-box::-webkit-scrollbar-thumb {
     border-radius: 5px;
@@ -322,16 +328,16 @@
     }
   }
 }
-.double-data-card-box::-webkit-scrollbar {
+.double-data-card-box::-webkit-scrollbar, .double-data-card-box .card-row-list::-webkit-scrollbar {
   width: 7px;
   height: 7px;
 }
-.double-data-card-box::-webkit-scrollbar-thumb {
+.double-data-card-box::-webkit-scrollbar-thumb, .double-data-card-box .card-row-list::-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);
 }
-.double-data-card-box::-webkit-scrollbar-track {
+.double-data-card-box::-webkit-scrollbar-track, .double-data-card-box .card-row-list::-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);
diff --git a/src/tabviews/custom/components/card/table-card/index.jsx b/src/tabviews/custom/components/card/table-card/index.jsx
index 5251e62..ef25ae7 100644
--- a/src/tabviews/custom/components/card/table-card/index.jsx
+++ b/src/tabviews/custom/components/card/table-card/index.jsx
@@ -612,7 +612,7 @@
           {data && data.length === 0 ? <Empty description={false}/> : null}
         </Row>
         {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}
+        {config.wrap.pagestyle === 'more' && data && data.length > 0 ? <div className={'mk-more' + (config.setting.pageSize * pageIndex >= total ? ' disabled' : '')} onClick={this.loadMore}>{window.GLOB.dict['view_more'] || '鏌ョ湅鏇村'}<DownOutlined/></div> : null}
       </div>
     )
   }
diff --git a/src/tabviews/custom/components/editor/braft-editor/index.jsx b/src/tabviews/custom/components/editor/braft-editor/index.jsx
index 0b6db75..d5a8cea 100644
--- a/src/tabviews/custom/components/editor/braft-editor/index.jsx
+++ b/src/tabviews/custom/components/editor/braft-editor/index.jsx
@@ -21,14 +21,14 @@
     BID: '',                   // 涓婄骇ID
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    data: {}                   // 鏁版嵁
+    data: []                   // 鏁版嵁
   }
 
   UNSAFE_componentWillMount () {
     const { config } = this.props
 
     let _config = fromJS(config).toJS()
-    let _data = { $$empty: true }
+    let _data = []
 
     let BID = ''
     let BData = ''
@@ -47,16 +47,25 @@
 
       if (_config.setting.sync === 'true' && window.GLOB.SyncData.has(_config.dataName)) {
         _data = window.GLOB.SyncData.get(_config.dataName) || []
-        _data = _data[0] || {$$empty: true}
-
         _config.setting.sync = 'false'
   
         window.GLOB.SyncData.delete(_config.dataName)
+      }
+    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.has(_config.wrap.publicId)) {
+      _data = window.GLOB.CacheData.get(_config.wrap.publicId)
+      _data = fromJS(_data).toJS()
+      if (_data.$$empty) {
+        _data = []
+      } else {
+        _data = [_data]
       }
     }
 
     if (_config.wrap.minHeight) {
       _config.style.minHeight = _config.wrap.minHeight
+    }
+    if (_config.wrap.firstTr === 'light') {
+      _config.wrap.tbStyle = 'th-light'
     }
 
     this.setState({
@@ -116,7 +125,6 @@
     if (config.$syncId !== syncId) return
 
     let _data = window.GLOB.SyncData.get(config.dataName) || []
-    _data = _data[0] || {$$empty: true}
 
     this.setState({data: _data})
 
@@ -140,6 +148,11 @@
 
     if (config.wrap.datatype === 'public' && config.wrap.publicId === publicId) {
       let _data = fromJS(data).toJS()
+      if (_data.$$empty) {
+        _data = []
+      } else {
+        _data = [_data]
+      }
 
       this.setState({data: _data})
     }
@@ -174,13 +187,13 @@
     
     if (config.wrap.datatype === 'static') {
       this.setState({
-        data: {$$empty: true},
+        data: [],
         loading: false
       })
       return
     } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
       this.setState({
-        data: {$$empty: true},
+        data: [],
         loading: false
       })
       return
@@ -204,11 +217,8 @@
 
     let result = await Api.genericInterface(param)
     if (result.status) {
-      let _data = result.data || []
-      _data = _data[0] || {$$empty: true}
-
       this.setState({
-        data: _data,
+        data: result.data || [],
         loading: false
       })
       
@@ -225,10 +235,10 @@
   render() {
     const { config, loading, data } = this.state
 
-    if (config.wrap.empty === 'hidden' && (!data || data.$$empty)) return null
+    if (config.wrap.empty === 'hidden' && (!data || data.length === 0)) return null
 
     return (
-      <div className={'custom-braft-editor-box ' + (config.wrap.firstTr || '')} id={'anchor' + config.uuid} style={config.style}>
+      <div className={'custom-braft-editor-box ' + (config.wrap.tbStyle || '')} id={'anchor' + config.uuid} style={config.style}>
         {loading ?
           <div className="loading-mask">
             <div className="ant-spin-blur"></div>
@@ -236,10 +246,14 @@
           </div> : null
         }
         <NormalHeader config={config}/>
-        <BraftContent
-          value={config.wrap.datatype !== 'static' ? (data[config.wrap.field] || '') : config.html}
-          encryption={config.wrap.datatype !== 'static' ? config.wrap.encryption : 'false'}
-        />
+        {config.wrap.datatype === 'static' ? <BraftContent
+          value={config.html}
+          encryption={'false'}
+        /> : data.map((item, index) => <BraftContent
+          key={index}
+          value={item[config.wrap.field] || ''}
+          encryption={config.wrap.encryption}
+        />)}
       </div>
     )
   }
diff --git a/src/tabviews/custom/components/editor/braft-editor/index.scss b/src/tabviews/custom/components/editor/braft-editor/index.scss
index 1829c88..e9e62b4 100644
--- a/src/tabviews/custom/components/editor/braft-editor/index.scss
+++ b/src/tabviews/custom/components/editor/braft-editor/index.scss
@@ -28,15 +28,34 @@
   }
 }
 
-.custom-braft-editor-box.light {
+.custom-braft-editor-box.th-light {
   .braft-content {
     table {
       tr:first-child {
-        background-color:#ffffff;
+        background-color: transparent;
       }
     }
   }
 }
+.custom-braft-editor-box.no-border {
+  .braft-content {
+    table {
+      td, th {
+        border: none!important;
+      }
+      tr td:first-child {
+        padding-left: 0px;
+      }
+    }
+  }
+}
+.custom-braft-editor-box.tb-flex {
+  .braft-content {
+    table {
+      table-layout: fixed;
+    }
+  }
+}
 
 .custom-braft-editor-box::after {
   content: ' ';
diff --git a/src/tabviews/custom/components/module/invoice/index.jsx b/src/tabviews/custom/components/module/invoice/index.jsx
index ad7b49b..5f130b2 100644
--- a/src/tabviews/custom/components/module/invoice/index.jsx
+++ b/src/tabviews/custom/components/module/invoice/index.jsx
@@ -85,6 +85,12 @@
     _config.buyer = this.formatSetting(_config.buyer, 'buyer')
     _config.detail = this.formatSetting(_config.detail, 'detail')
     _config.detail.uuid = _config.uuid
+    _config.buyer.setting.uuid = _config.uuid + 'buyer'
+    _config.detail.setting.uuid = _config.uuid + 'detail'
+    _config.billOutBtn.uuid = _config.uuid
+    _config.billSaveBtn.uuid = _config.uuid
+    _config.billOutBtn.logLabel = _config.$menuname + '-' + _config.billOutBtn.label
+    _config.billSaveBtn.logLabel = _config.$menuname + '-' + _config.billSaveBtn.label
 
     let book = null
     let pas = {}
@@ -233,7 +239,7 @@
     item.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
     item.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-    item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript)
+    item.setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(item.setting.dataresource + item.setting.customScript)
 
     return item
   }
@@ -487,18 +493,23 @@
 
     setTimeout(() => {
       this.getBillMsg().then(() => {
-        let sql = this.getPreSql(config.billSaveBtn)
-  
-        let param = {
-          func: 'sPC_TableData_InUpDe',
-          LText: sql,
-          exec_type: window.GLOB.execType || 'y',
-          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
-          BID: BID
+        let param = null
+        if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid + config.billSaveBtn.type)) {
+          param = this.getBackPreParam(config.billSaveBtn)
+        } else {
+          let sql = this.getPreSql(config.billSaveBtn)
+    
+          param = {
+            func: 'sPC_TableData_InUpDe',
+            LText: sql,
+            exec_type: window.GLOB.execType || 'y',
+            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
+            BID: BID
+          }
+    
+          param.secretkey = Utils.encrypt('', param.timestamp)
+          param.LText = Utils.formatOptions(param.LText, param.exec_type)
         }
-  
-        param.secretkey = Utils.encrypt('', param.timestamp)
-        param.LText = Utils.formatOptions(param.LText, param.exec_type)
 
         this.setState({
           saveType: 'bill'
@@ -510,7 +521,7 @@
           })
           if (res.status) {
             if (config.billSaveBtn.reTabId) {
-              MKEmitter.emit('reloadMenuView', config.billSaveBtn.reTabId, 'table')
+              MKEmitter.emit('reloadMenuView', config.billSaveBtn.reTabId)
             }
             if (config.billSaveBtn.syncComId) {
               MKEmitter.emit('reloadData', config.billSaveBtn.syncComId)
@@ -570,19 +581,24 @@
 
     setTimeout(() => {
       this.getBillMsg().then(() => {
-        let sql = this.getPreSql(config.billOutBtn)
-  
-        let param = {
-          func: 'sPC_TableData_InUpDe',
-          LText: sql,
-          script_type: 'Y',
-          exec_type: window.GLOB.execType || 'y',
-          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
-          BID: BID
+        let param = null
+        if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid + config.billOutBtn.type)) {
+          param = this.getBackPreParam(config.billOutBtn)
+        } else {
+          let sql = this.getPreSql(config.billOutBtn)
+    
+          param = {
+            func: 'sPC_TableData_InUpDe',
+            LText: sql,
+            script_type: 'Y',
+            exec_type: window.GLOB.execType || 'y',
+            timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
+            BID: BID
+          }
+    
+          param.secretkey = Utils.encrypt('', param.timestamp)
+          param.LText = Utils.formatOptions(param.LText, param.exec_type)
         }
-  
-        param.secretkey = Utils.encrypt('', param.timestamp)
-        param.LText = Utils.formatOptions(param.LText, param.exec_type)
 
         this.setState({
           saveType: 'out'
@@ -714,6 +730,7 @@
     sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
     sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
     sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+    sql = sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
     sql = sql.replace(/@typename@/ig, `'admin'`)
 
     if (window.GLOB.externalDatabase !== null) {
@@ -727,10 +744,202 @@
     }
 
     if (window.GLOB.debugger === true) {
-      console.info(sql.replace(/\n\s{6}/ig, '\n'))
+      window.mkInfo(sql.replace(/\n\s{6}/ig, '\n'))
     }
 
     return sql
+  }
+
+  getBackPreParam = (btn) => {
+    const { config, book, ID, BID, io, details, oriDetails, business_type, invoice_type, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, from_to_code, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee } = this.state
+    let ex = window.GLOB.CacheData.get('sql_' + btn.uuid + btn.type)
+    let exps = []
+
+    let values = {
+      time_id: Utils.getguid(),
+      roleid: sessionStorage.getItem('role_id') || '',
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      mk_nation: sessionStorage.getItem('nation') || '',
+      mk_province: sessionStorage.getItem('province') || '',
+      mk_city: sessionStorage.getItem('city') || '',
+      mk_district: sessionStorage.getItem('district') || '',
+      mk_address: sessionStorage.getItem('address') || '',
+      id: ID || '',
+      bid: BID || '',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    }
+
+    if (window.GLOB.externalDatabase !== null) {
+      values.db = window.GLOB.externalDatabase
+    }
+
+    let options = fromJS(oriDetails).toJS()
+    let price = 0
+    let tax = 0
+
+    let lines = []
+    details.forEach(line => {
+      if (!line.productcode) return
+
+      let vals = [line.productcode, line.productname, line.spec, line.unit, line.bill_count, line.unitprice, line.amount_line, line.tax_classify_code, line.tax_classify_name, line.tax_rate, line.tax_amount, line.free_tax_mark || '', line.vat_special_management || '', line.invoice_lp || '', line.tax_item, line.tax_method, line.uuid]
+      let data_type = 'add'
+
+      price += line.amount_line * 100
+      tax += line.tax_amount * 100
+
+      if (options.length) {
+        options = options.filter(option => {
+          if (option.uuid === line.uuid) {
+            data_type = 'upt'
+            return false
+          }
+          return true
+        })
+      }
+
+      vals.push(data_type)
+
+      lines.push(vals)
+    })
+
+    let _total = (price - tax) / 100
+    price = price / 100
+    tax = tax / 100
+
+    if (options.length) {
+      options.forEach(line => {
+        let vals = [line.productcode, line.productname, line.spec, line.unit, line.bill_count, line.unitprice, line.amount_line, line.tax_classify_code, line.tax_classify_name, line.tax_rate, line.tax_amount, line.free_tax_mark || '', line.vat_special_management || '', line.invoice_lp || '', line.tax_item, line.tax_method, line.uuid, 'del']
+        lines.push(vals)
+      })
+    }
+
+    ex.reps.forEach(n => {
+      let key = n.toLowerCase()
+      if (values.hasOwnProperty(key)) {
+        exps.push({
+          key: n,
+          value: values[key]
+        })
+      }
+    })
+
+    exps.push({
+      key: 'account_id',
+      value: book.account_id || ''
+    }, {
+      key: 'account_year_id',
+      value: book.account_year_id || ''
+    }, {
+      key: 'account_code',
+      value: book.account_code || ''
+    }, {
+      key: 'account_year_code',
+      value: book.account_year_code || ''
+    }, {
+      key: 'invoice_type',
+      value: invoice_type
+    }, {
+      key: 'from_to_name',
+      value: from_to_name
+    }, {
+      key: 'from_to_tax_no',
+      value: from_to_tax_no
+    }, {
+      key: 'from_to_addr',
+      value: from_to_addr
+    }, {
+      key: 'from_to_tel',
+      value: from_to_tel
+    }, {
+      key: 'from_to_bank_name',
+      value: from_to_bank_name
+    }, {
+      key: 'from_to_account_no',
+      value: from_to_account_no
+    }, {
+      key: 'from_to_mob',
+      value: from_to_mob
+    }, {
+      key: 'from_to_email',
+      value: from_to_email
+    }, {
+      key: 'from_to_code',
+      value: from_to_code
+    }, {
+      key: 'orgname',
+      value: orgname
+    }, {
+      key: 'tax_no',
+      value: tax_no
+    }, {
+      key: 'addr',
+      value: addr
+    }, {
+      key: 'tel',
+      value: tel
+    }, {
+      key: 'bank_name',
+      value: bank_name
+    }, {
+      key: 'account_no',
+      value: account_no
+    }, {
+      key: 'remark',
+      value: remark
+    }, {
+      key: 'payee',
+      value: payee
+    }, {
+      key: 'reviewer',
+      value: reviewer
+    }, {
+      key: 'drawer',
+      value: drawer
+    }, {
+      key: 'io',
+      value: io
+    }, {
+      key: 'orgcode',
+      value: book.orgcode || ''
+    }, {
+      key: 'total_net_amount',
+      value: _total
+    }, {
+      key: 'total_tax',
+      value: tax
+    }, {
+      key: 'total_amount',
+      value: price
+    }, {
+      key: 'business_type',
+      value: business_type || config.wrap.business_type || ''
+    })
+
+    exps.push({
+      key: 'mk_excel_data',
+      value: lines
+    })
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    return {
+      $backend: true,
+      $type: 's_TableData_InUpDe',
+      data: [{
+        id: ex.id,
+        menuname: btn.logLabel || '',
+        exps: exps,
+        md5_id: md5_id
+      }]
+    }
   }
 
   getBillMsg = () => {
@@ -843,141 +1052,153 @@
   callBackBill = (result) => {
     const { config, BID, ID } = this.state
 
-    let btn = config.billOutBtn
-    let lines = []
-    let pre = '@'
+    let param = null
 
-    let getDefaultSql = (obj, tb, bid, level) => {
-      let keys = []
-      let vals = []
-      let subObjs = []
-      let id = Utils.getuuid()
-      let tbName = pre + tb
-
-      delete obj.$$key
-
-      Object.keys(obj).forEach(key => {
-        let val = obj[key]
-        if (val === null || val === undefined) return
-        if (typeof(val) === 'object') {
-          if (Array.isArray(val)) {
-            val.forEach(item => {
-              if (typeof(item) !== 'object' || Array.isArray(item)) return
-              if (Object.keys(item).length > 0) {
+    if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid + 'billback')) {
+      param = this.getCallBackendParam(config.billOutBtn, result)
+    } else {
+      let btn = config.billOutBtn
+      let lines = []
+      let pre = '@'
+  
+      let getDefaultSql = (obj, tb, bid, level) => {
+        let keys = []
+        let vals = []
+        let subObjs = []
+        let id = Utils.getuuid()
+        let tbName = pre + tb
+  
+        delete obj.$$key
+  
+        Object.keys(obj).forEach(key => {
+          let val = obj[key]
+          if (val === null || val === undefined) return
+          if (typeof(val) === 'object') {
+            if (Array.isArray(val)) {
+              val.forEach(item => {
+                if (typeof(item) !== 'object' || Array.isArray(item)) return
+                if (Object.keys(item).length === 0) return
+  
+                Object.keys(item).forEach(k => {
+                  if (item[k] === null) {
+                    item[k] = ''
+                  }
+                })
                 item.$$key = tb + '_' + key
                 subObjs.push(item)
-              }
-            })
-          } else if (Object.keys(val).length > 0) {
-            val.$$key = tb + '_' + key
-            subObjs.push(val)
+              })
+            } else if (Object.keys(val).length > 0) {
+              val.$$key = tb + '_' + key
+              subObjs.push(val)
+            }
+          } else {
+            if (typeof(val) === 'string') {
+              val = val.replace(/'/ig, '"')
+            }
+            keys.push('[' + key + ']')
+            vals.push(`'${val}'`)
           }
-        } else {
-          if (typeof(val) === 'string') {
-            val = val.replace(/'/ig, '"')
-          }
-          keys.push('[' + key + ']')
-          vals.push(`'${val}'`)
-        }
-      })
-
-      keys = keys.join(',')
-      vals = vals.join(',')
-
-      lines.push({
-        table: md5(tb + keys),
-        insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
-        select: `Select ${keys ? vals + ',' : ''}'${level}','${id}','${bid}'`
-      })
-
-      subObjs.forEach(item => {
-        getDefaultSql(item, item.$$key, id, level + 1)
-      })
-    }
-    
-    getDefaultSql(result, btn.cbTable, '', 1)
-
-    let lineMap = new Map()
-    lines.forEach(line => {
-      if (lineMap.has(line.table)) {
-        let _line = lineMap.get(line.table)
-        _line.selects.push(line.select)
-        lineMap.set(line.table, _line)
-      } else {
-        lineMap.set(line.table, {
-          table: line.table,
-          insert: line.insert,
-          selects: [line.select]
+        })
+  
+        keys = keys.join(',')
+        vals = vals.join(',')
+  
+        lines.push({
+          table: md5(tb + keys),
+          insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
+          select: `Select ${keys ? vals + ',' : ''}'${level}','${id}','${bid}'`
+        })
+  
+        subObjs.forEach(item => {
+          getDefaultSql(item, item.$$key, id, level + 1)
         })
       }
-    })
-
-    let param = {
-      func: 'sPC_TableData_InUpDe',
-      BID: BID,
-      menuname: config.name + '(鍥炶皟)'
-    }
-
-    let callbacksql = this.getBackSql()
-    let _prevCustomScript = `${callbacksql}
-    `
-    let _backCustomScript = ''
-
-    btn.cbScripts.forEach(script => {
-      if (script.status === 'false') return
-
-      if (script.position === 'front') {
-        _prevCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${script.sql}
-      `
-      } else {
-        _backCustomScript += `
-      /* 鑷畾涔夎剼鏈� */
-      ${script.sql}
-      `
+      
+      getDefaultSql(result, btn.cbTable, '', 1)
+  
+      let lineMap = new Map()
+      lines.forEach(line => {
+        if (lineMap.has(line.table)) {
+          let _line = lineMap.get(line.table)
+          _line.selects.push(line.select)
+          lineMap.set(line.table, _line)
+        } else {
+          lineMap.set(line.table, {
+            table: line.table,
+            insert: line.insert,
+            selects: [line.select]
+          })
+        }
+      })
+  
+      param = {
+        func: 'sPC_TableData_InUpDe',
+        BID: BID,
+        menuname: config.name + '(鍥炶皟)'
       }
-    })
-
-    _backCustomScript += `
-      aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
-
-    let sql = [...lineMap.values()].map(item => (`
-      ${item.insert}
-      ${item.selects.join(` union all
-      `)}
-    `))
-    sql = sql.join('')
-    sql = _prevCustomScript + sql
-    sql = sql + _backCustomScript
-
-    sql = sql.replace(/@ID@/ig, `'${ID || ''}'`)
-    sql = sql.replace(/@BID@/ig, `'${BID || ''}'`)
-    sql = sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
-    sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
-    sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
-    sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
-    sql = sql.replace(/@typename@/ig, `'admin'`)
-
-    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-      sql = sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
-    } else {
-      sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
-    }
-
-    if (window.GLOB.debugger === true) {
-      console.info('%c' + config.name + '(鍥炶皟)', 'color: blue')
-      console.info(sql.replace(/\n\s{8}/ig, '\n'))
-    }
-
-    param.LText = sql
-    param.exec_type = window.GLOB.execType || 'y' // 鍚庡彴瑙g爜
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt('', param.timestamp)
-    param.LText = Utils.formatOptions(param.LText, param.exec_type)
-
-    if (window.GLOB.probation) {
-      param.s_debug_type = 'Y'
+  
+      let callbacksql = this.getBackSql()
+      let _prevCustomScript = `${callbacksql}
+      `
+      let _backCustomScript = ''
+  
+      btn.cbScripts.forEach(script => {
+        if (script.status === 'false') return
+  
+        if (script.position === 'front') {
+          _prevCustomScript += `
+        /* 鑷畾涔夎剼鏈� */
+        ${script.sql}
+        `
+        } else {
+          _backCustomScript += `
+        /* 鑷畾涔夎剼鏈� */
+        ${script.sql}
+        `
+        }
+      })
+  
+      _backCustomScript += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+  
+      let sql = [...lineMap.values()].map(item => (`
+        ${item.insert}
+        ${item.selects.join(` union all
+        `)}
+      `))
+      sql = sql.join('')
+      sql = _prevCustomScript + sql
+      sql = sql + _backCustomScript
+  
+      sql = sql.replace(/@ID@/ig, `'${ID || ''}'`)
+      sql = sql.replace(/@BID@/ig, `'${BID || ''}'`)
+      sql = sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
+      sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
+      sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
+      sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+      sql = sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
+      sql = sql.replace(/@typename@/ig, `'admin'`)
+  
+      if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+        sql = sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
+      } else {
+        sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
+      }
+  
+      if (window.GLOB.debugger === true) {
+        window.mkInfo('%c' + config.name + '(鍥炶皟)', 'color: blue')
+        window.mkInfo(sql.replace(/\n\s{8}/ig, '\n'))
+      }
+  
+      param.LText = sql
+      param.exec_type = window.GLOB.execType || 'y' // 鍚庡彴瑙g爜
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+      param.secretkey = Utils.encrypt('', param.timestamp)
+      param.LText = Utils.formatOptions(param.LText, param.exec_type)
+  
+      if (window.GLOB.probation) {
+        param.s_debug_type = 'Y'
+      }
     }
 
     Api.genericInterface(param).then(res => {
@@ -986,7 +1207,7 @@
       })
       if (res.status) {
         if (config.billOutBtn.reTabId) {
-          MKEmitter.emit('reloadMenuView', config.billOutBtn.reTabId, 'table')
+          MKEmitter.emit('reloadMenuView', config.billOutBtn.reTabId)
         }
         if (config.billOutBtn.syncComId) {
           MKEmitter.emit('reloadData', config.billOutBtn.syncComId)
@@ -1008,6 +1229,163 @@
     })
   }
 
+  getCallBackendParam = (btn, result) => {
+    const { book, BID, ID } = this.state
+
+    let lines = []
+    let tables = []
+
+    btn.verify.cbScripts.forEach(script => {
+      if (script.status === 'false') return
+
+      if (/\s#[a-z0-9_]+(\s|\()/ig.test(script.sql)) {
+        tables.push(...script.sql.match(/\s#[a-z0-9_]+(\s|\()/ig))
+      }
+    })
+
+    tables = tables.map(tb => tb.replace(/\s|\(/g, ''))
+
+    if (result.$ErrCode) {
+      delete result.$ErrCode
+      delete result.$ErrMesg
+    }
+
+    let getDefaultSql = (obj, tb, bid, level) => {
+      let vals = {}
+      let subObjs = []
+      let id = Utils.getuuid()
+
+      delete obj.$$key
+
+      Object.keys(obj).forEach(key => {
+        let val = obj[key]
+        if (val === null || val === undefined) return
+        if (typeof(val) === 'object') {
+          if (Array.isArray(val)) {
+            val.forEach(item => {
+              if (typeof(item) !== 'object' || Array.isArray(item)) return
+              if (Object.keys(item).length === 0) return
+
+              Object.keys(item).forEach(k => {
+                if (item[k] === null) {
+                  item[k] = ''
+                }
+              })
+              item.$$key = tb + '_' + key
+              subObjs.push(item)
+            })
+          } else if (Object.keys(val).length > 0) {
+            val.$$key = tb + '_' + key
+            subObjs.push(val)
+          }
+        } else {
+          if (typeof(val) === 'string') {
+            val = val.replace(/'/ig, '"')
+          } else {
+            val = val + ''
+          }
+          vals[key] = val
+        }
+      })
+
+      vals.mk_level = level
+      vals.mk_id = id
+      vals.mk_bid = bid
+
+      let isnew = true
+      lines.forEach(line => {
+        if (line.tb === tb) {
+          line.values.push(vals)
+          isnew = false
+        }
+      })
+      if (isnew) {
+        lines.push({
+          tb: tb,
+          type: tables.includes('#' + tb) ? '01' : '02',
+          values: [vals]
+        })
+      }
+
+      subObjs.forEach(item => {
+        getDefaultSql(item, item.$$key, id, level + 1)
+      })
+    }
+    
+    getDefaultSql(result, btn.cbTable, '', 1)
+
+    let ex = window.GLOB.CacheData.get('sql_' + btn.uuid + 'billback')
+    let exps = []
+
+    let values = {
+      time_id: Utils.getguid(),
+      roleid: sessionStorage.getItem('role_id') || '',
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      mk_nation: sessionStorage.getItem('nation') || '',
+      mk_province: sessionStorage.getItem('province') || '',
+      mk_city: sessionStorage.getItem('city') || '',
+      mk_district: sessionStorage.getItem('district') || '',
+      mk_address: sessionStorage.getItem('address') || '',
+      id: ID || '',
+      bid: BID || '',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    }
+
+    if (window.GLOB.externalDatabase !== null) {
+      values.db = window.GLOB.externalDatabase
+    }
+
+    ex.reps.forEach(n => {
+      let key = n.toLowerCase()
+      if (values.hasOwnProperty(key)) {
+        exps.push({
+          key: n,
+          value: values[key]
+        })
+      }
+    })
+
+    exps.push({
+      key: 'account_id',
+      value: book.account_id || ''
+    }, {
+      key: 'account_year_id',
+      value: book.account_year_id || ''
+    }, {
+      key: 'account_code',
+      value: book.account_code || ''
+    }, {
+      key: 'account_year_code',
+      value: book.account_year_code || ''
+    })
+
+    exps.push({
+      key: 'mk_outer_params',  // 鍥炶皟鑴氭湰鐨勬暟鎹浛鎹�
+      value: lines
+    })
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5('back_' + btn.uuid + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    return {
+      $backend: true,
+      $type: 's_TableData_InUpDe',
+      data: [{
+        id: ex.id,
+        menuname: btn.logLabel + '(鍥炶皟)',
+        exps: exps,
+        md5_id: md5_id
+      }]
+    }
+  }
+
   getBackSql = () => {
     const { book, BID } = this.state
 
diff --git a/src/tabviews/custom/components/module/invoice/index.scss b/src/tabviews/custom/components/module/invoice/index.scss
index 1ec31ae..dcae8ad 100644
--- a/src/tabviews/custom/components/module/invoice/index.scss
+++ b/src/tabviews/custom/components/module/invoice/index.scss
@@ -23,6 +23,8 @@
       margin-left: 0px;
       padding: 0px;
       box-shadow: none;
+      position: relative;
+      z-index: 1;
     }
     .mk-back::after {
       display: none;
diff --git a/src/tabviews/custom/components/module/voucher/index.jsx b/src/tabviews/custom/components/module/voucher/index.jsx
index 0fd7ac5..6e9f250 100644
--- a/src/tabviews/custom/components/module/voucher/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/index.jsx
@@ -492,11 +492,11 @@
     }
 
     if (tip) {
-      const _this = this
+      const that = this
       confirm({
         content: tip + '纭瑕佷繚瀛樺悧锛�',
         onOk() {
-          _this.voucherSave(list, t)
+          that.voucherSave(list, t)
         },
         onCancel() {}
       })
@@ -700,7 +700,7 @@
       }
 
       if (tabId) {
-        MKEmitter.emit('reloadMenuView', tabId, 'table')
+        MKEmitter.emit('reloadMenuView', tabId)
       }
     })
   }
@@ -953,7 +953,7 @@
       }
 
       if (tabId) {
-        MKEmitter.emit('reloadMenuView', tabId, 'table')
+        MKEmitter.emit('reloadMenuView', tabId)
       }
     })
   }
diff --git a/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/fileupload/index.jsx b/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/fileupload/index.jsx
index 627a699..03c3d0f 100644
--- a/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/fileupload/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/resetAttach/addAttach/fileupload/index.jsx
@@ -1,10 +1,9 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import moment from 'moment'
 import { Upload, Button, Progress, notification } from 'antd'
 import { UploadOutlined } from '@ant-design/icons'
-import SparkMD5 from 'spark-md5'
+
 import Api from '@/api'
 import './index.scss'
 
@@ -90,54 +89,6 @@
     })
   }
 
-  shardupload = (param, name) => {
-    let form = new FormData()
-
-    form.append('file', param.binary)
-    form.append('fileMd5', param.fileMd5)
-    form.append('shardingMd5', param.fileMd5)
-    form.append('baseDomain', window.GLOB.baseurl)
-    form.append('rootPath', 'Content/images/upload/')
-    form.append('fileName', param.fileName)
-    form.append('fileExt', param.fileType)
-    form.append('shardingCnt', 1)
-    form.append('shardingNo', 1)
-    form.append('LoginUID', sessionStorage.getItem('LoginUID') || '')
-    form.append('UserID', sessionStorage.getItem('UserID') || '')
-
-    Api.getLargeFileUpload(form).then(res => {
-      if (res.status) {
-        if (res.urlPath) {
-          this.onUpdate(res.urlPath, name)
-        } else {
-          this.onFail()
-        }
-        this.setState({
-          percent: 100
-        }, () => {
-          setTimeout(() => {
-            this.setState({
-              showprogress: false,
-              percent: 0
-            })
-          }, 200)
-        })
-      } else {
-        this.onFail(res.message)
-      }
-    })
-  }
-
-  getuuid = () => {
-    let uuid = []
-    let _options = '0123456789abcdefghigklmnopqrstuv'
-    for (let i = 0; i < 19; i++) {
-      uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
-    }
-    uuid = uuid.join('')
-    return uuid
-  }
-
   beforeUpload = (file) => {
     const { accepts, maxSize } = this.state
 
@@ -172,49 +123,31 @@
       percent: 0
     })
 
-    // 鍏煎鎬х殑澶勭悊
-    let spark = new SparkMD5.ArrayBuffer()         // 瀵筧rrayBuffer鏁版嵁杩涜md5鍔犲瘑锛屼骇鐢熶竴涓猰d5瀛楃涓�
-    let totalFileReader = new FileReader()         // 鐢ㄤ簬璁$畻鍑烘�绘枃浠剁殑fileMd5
-    let param = {}
+    let form = new FormData()
 
-    param.fileName = file.name.replace(/\.{1}[^.]*$/ig, '')  // 鏂囦欢鍚嶏紙鍘婚櫎鍚庣紑鍚嶏級
-    param.fileType = file.name.replace(/^.*\.{1}/ig, '')     // 鏂囦欢绫诲瀷
+    form.append('file', file)
 
-    if (!/^[A-Za-z0-9]+$/.test(param.fileName)) {            // 鏂囦欢鍚嶇О鍚湁鑻辨枃鍙婃暟瀛椾箣澶栧瓧绗︽椂锛屽悕绉扮郴缁熺敓鎴�
-      param.fileName = moment().format('YYYYMMDDHHmmss') + this.getuuid()
-    }
-
-    totalFileReader.readAsArrayBuffer(file)
-    totalFileReader.onload = (e) => {   // 瀵规暣涓猼otalFile鐢熸垚md5
-      spark.append(e.target.result)
-      param.fileMd5 = spark.end()       // 璁$畻鏁翠釜鏂囦欢鐨刦ileMd5
-      param.binary = file
-
-      let _param = new FormData()
-      _param.append('fileMd5', param.fileMd5)
-      
-      Api.getFilePreUpload(_param).then(res => {
-        if (res.status && res.urlPath) {
+    Api.getFileUpload(form).then(res => {
+      if (res.status) {
+        if (res.urlPath) {
           this.onUpdate(res.urlPath, file.name)
-          this.setState({
-            percent: 100
-          }, () => {
-            setTimeout(() => {
-              this.setState({
-                showprogress: false,
-                percent: 0
-              })
-            }, 200)
-          })
         } else {
-          this.shardupload(param, file.name)
+          this.onFail()
         }
-      })
-    }
-
-    totalFileReader.onerror = () => {
-      this.onFail('鏂囦欢璇诲彇澶辫触锛�')
-    }
+        this.setState({
+          percent: 100
+        }, () => {
+          setTimeout(() => {
+            this.setState({
+              showprogress: false,
+              percent: 0
+            })
+          }, 200)
+        })
+      } else {
+        this.onFail(res.message)
+      }
+    })
 
     return false
   }
diff --git a/src/tabviews/custom/components/share/braftContent/index.scss b/src/tabviews/custom/components/share/braftContent/index.scss
index f2f0d33..bf6b2f9 100644
--- a/src/tabviews/custom/components/share/braftContent/index.scss
+++ b/src/tabviews/custom/components/share/braftContent/index.scss
@@ -1,14 +1,32 @@
 .braft-content {
+  padding: 15px;
   .media-wrap {
     max-width: 100%;
   }
   img {
     max-width: 100%;
   }
+  p {
+    margin-bottom: 0px!important;
+    min-height: 18px;
+  }
+  br {
+    content: "";
+    display: block;
+    height: 18px;
+  }
+  hr {
+    height: 15px;
+    border-top: 1px solid rgba(0, 0, 0, 0.1);
+    margin-top: 15px;
+  }
   video {
     max-width: 100%;
     width: 100%;
   }
+  table + p, hr + p {
+    min-height: 0px;
+  }
   table {
     width: 100%;
     border-collapse: collapse;
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index a468ec1..b01e03d 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -236,6 +236,9 @@
         }
         if (col.format === 'percent') {
           content = content * 100
+          if (!col.round) {
+            content = +content.toFixed(2)
+          }
         } else if (col.format === 'abs') {
           content = Math.abs(content)
         }
@@ -428,7 +431,7 @@
               content = ''
             }
           } catch (e) {
-            console.info(content)
+            window.mkInfo(content)
             console.warn(e)
             content = ''
           }
@@ -446,7 +449,12 @@
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       } else if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
-        content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        if (!col.evalchars || col.evalchars.includes('enter')) {
+          content = content.replace(/\n/ig, '<br/>')
+        }
+        if (!col.evalchars || col.evalchars.includes('space')) {
+          content = content.replace(/\s/ig, '&nbsp;')
+        }
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       }
 
@@ -806,15 +814,27 @@
     this.props.refreshdata({pageIndex})
   }
 
-  mkCheckTopLine = (menuId, id, type) => {
+  mkCheckTopLine = (menuId, id, selected) => {
     const { MenuID, data, setting } = this.props
 
-    if (MenuID !== menuId || !data || data.length === 0) return
+    if (MenuID !== menuId) return
+    if (!data || data.length === 0) {
+      MKEmitter.emit('resetSelectLine', menuId, '', '')
+      return
+    }
 
-    if (type === 'sign') {
-      let index = ''
-      let keys = []
-      let items = []
+    let index = -1
+    let keys = []
+    let items = []
+
+    if (id) {
+      index = data.findIndex(item => item.$$uuid === id && !item.$disabled)
+    }
+    
+    if (index !== -1) {
+      keys = [index]
+      items = [data[index]]
+    } else if (selected === 'sign') {
       data.forEach((item, i) => {
         if (!item.$disabled && item.selected === 'true') {
           items.push(item)
@@ -822,33 +842,25 @@
           index = i
         }
       })
-  
-      this.changedata(index)
-      this.setState({ selectedRowKeys: keys, activeIndex: index })
-      this.props.chgSelectData(items)
-
-      if (setting.$hasSyncModule) {
-        MKEmitter.emit('syncBalconyData', MenuID, items, data.length === keys.length)
+    } else if (selected !== 'false') {
+      if (!data[0].$disabled) {
+        index = 0
+        keys = [index]
+        items = [data[index]]
       }
+    }
+
+    if (index === -1) {
+      MKEmitter.emit('resetSelectLine', menuId, '', '')
       return
     }
 
-    let index = 0
-    if (id) {
-      index = data.findIndex(item => item.$$uuid === id)
-      if (index === -1) {
-        index = 0
-      }
-    }
-
-    if (data[index].$disabled) return
-
     this.changedata(index)
-    this.setState({ selectedRowKeys: [index], activeIndex: index })
-    this.props.chgSelectData([data[index]])
+    this.setState({ selectedRowKeys: keys, activeIndex: index })
+    this.props.chgSelectData(items)
 
     if (setting.$hasSyncModule) {
-      MKEmitter.emit('syncBalconyData', MenuID, [data[index]], data.length === 1)
+      MKEmitter.emit('syncBalconyData', MenuID, items, data.length === keys.length)
     }
   }
 
@@ -868,7 +880,7 @@
       MKEmitter.emit('resetSelectLine', MenuID, '', '')
       MKEmitter.emit('syncBalconyData', MenuID, data, data.length > 0)
       if (data.length === 0) {
-        message.warning('鏈幏鍙栧埌鏁版嵁锛�')
+        message.warning(window.GLOB.dict['no_data'] || '鏈幏鍙栧埌鏁版嵁锛�')
       }
     } else {
       this.setState({
@@ -1023,22 +1035,9 @@
       if (setting.$hasSyncModule) {
         MKEmitter.emit('syncBalconyData', MenuID, selects, data.length === selects.length)
       }
-    } else if (type === 'false') {
-      this.setState({
-        selectedRowKeys: [],
-        activeIndex: null,
-        pickup: false
-      })
-    } else if (type === 'repage') {
-      this.setState({
-        pageIndex: Index,
-        selectedRowKeys: [],
-        activeIndex: null,
-        pickup: false
-      })
     } else {
       this.setState({
-        pageIndex: 1,
+        pageIndex: type === 'false' ? this.state.pageIndex : 1,
         selectedRowKeys: [],
         activeIndex: null,
         pickup: false
@@ -1158,7 +1157,7 @@
         pageSizeOptions: pageOptions,
         showSizeChanger: true,
         total: this.props.total || 0,
-        showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
+        showTotal: (total, range) => `${range[0]}-${range[1]} ${window.GLOB.dict['of'] || '鍏�'} ${total} ${window.GLOB.dict['items'] || '鏉�'}`
       }
     }
 
@@ -1169,8 +1168,14 @@
     }
 
     let height = setting.height || false
-    if (height && height <= 100) {
-      height = height + 'vh'
+    if (height) {
+      if (height <= 100) {
+        if (height < 0) {
+          height = `calc(100vh - ${-height}px)`
+        } else {
+          height = height + 'vh'
+        }
+      }
     }
     let loading = this.props.loading
     if (setting.mask === 'hidden') {
@@ -1195,9 +1200,9 @@
     }
 
     return (
-      <div className={`normal-custom-table ${setting.tableHeader || ''} ${setting.parity === 'true' ? 'mk-parity' : ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || 'middle'} table-col-${columns.length} ${fixed}`} style={style}>
+      <div className={`normal-custom-table ${setting.tableHeader || ''} ${setting.parity === 'true' ? 'mk-parity' : ''} ${height ? 'fixed-table-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || 'middle'} table-col-${columns.length} ${fixed}`} style={style}>
         {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 ?
-          <Switch title="鏀惰捣" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /> : null
+          <Switch title="鏀惰捣" className="main-pickup" checkedChildren={window.GLOB.dict['open'] || '寮�'} unCheckedChildren={window.GLOB.dict['shut'] || '鍏�'} checked={pickup} onChange={this.pickupChange} /> : null
         }
         <Table
           components={components}
diff --git a/src/tabviews/custom/components/share/normalTable/index.scss b/src/tabviews/custom/components/share/normalTable/index.scss
index a7688af..b41bf8b 100644
--- a/src/tabviews/custom/components/share/normalTable/index.scss
+++ b/src/tabviews/custom/components/share/normalTable/index.scss
@@ -154,21 +154,6 @@
       // }
     }
   }
-  // .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);
-  // }
   .fix-header {
     .ant-table-body {
       min-height: unset
@@ -218,7 +203,7 @@
     background-color: #fafafa!important;
   }
 }
-.normal-custom-table:not(.fixed-height) {
+.normal-custom-table:not(.fixed-table-height) {
   .ant-table-body::-webkit-scrollbar {
     width: 8px;
     height: 10px;
@@ -233,14 +218,6 @@
     border-radius: 3px;
     border: 1px solid rgba(0, 0, 0, 0.07);
     background: rgba(0, 0, 0, 0);
-  }
-}
-.normal-custom-table.fixed-height {
-  .ant-table-body {
-    border-bottom: 1px solid rgba(0, 0, 0, .05);
-    .ant-table-fixed {
-      border-bottom: 0;
-    }
   }
 }
 .normal-custom-table.hidden {
diff --git a/src/tabviews/custom/components/share/tabtransfer/index.jsx b/src/tabviews/custom/components/share/tabtransfer/index.jsx
index 34289a8..0a67c42 100644
--- a/src/tabviews/custom/components/share/tabtransfer/index.jsx
+++ b/src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -50,9 +50,16 @@
   UNSAFE_componentWillMount () {
     let _config = fromJS(this.props.config).toJS()
 
+    let BID = ''
+    let BData = window.GLOB.CacheData.get(_config.$pageId)
+
+    if (BData) {
+      BID = BData.$BID || ''
+    }
+
     let params = []
     if (_config.type !== 'group') {
-      _config.components = this.formatSetting(_config.components, params)
+      _config.components = this.formatSetting(_config.components, params, BID)
     } else {
       let delay = 110
       _config.components.forEach(item => {
@@ -68,17 +75,17 @@
       config: _config
     }, () => {
       if (params.length > 0) {
-        this.loadmaindata(params)
+        this.loadmaindata(params, BID)
       }
     })
   }
 
-  formatSetting = (components, params) => {
+  formatSetting = (components, params, BID) => {
     let delay = 110
     return components.map(item => {
       if (item.type === 'tabs') return item
       if (item.type === 'group') {
-        item.components = this.formatSetting(item.components, params)
+        item.components = this.formatSetting(item.components, params, BID)
         return item
       }
 
@@ -102,7 +109,18 @@
           item.setting.sync = 'false'
           item.setting.onload = 'false'
         } else {
-          params.push(getStructDefaultParam(item, searchlist, params.length === 0))
+          let backend = false
+          if (window.backend && params.length === 0 && window.GLOB.CacheData.has('sql_' + item.uuid)) {
+            backend = true
+          } else if (window.backend && params[0] && params[0].exps) {
+            backend = true
+          }
+
+          if (backend && !window.GLOB.CacheData.has('sql_' + item.uuid)) {
+            item.setting.sync = 'false'
+          } else {
+            params.push(getStructDefaultParam(item, searchlist, params.length === 0, BID))
+          }
         }
       }
       
@@ -116,19 +134,17 @@
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
    */ 
-  loadmaindata = (params) => {
+  loadmaindata = (params, BID) => {
     const { config } = this.state
-    let BID = ''
-    let BData = window.GLOB.CacheData.get(config.$pageId)
-
-    if (BData) {
-      BID = BData.$BID || ''
-    }
 
     let param = getStructuredParams(params, config, BID)
 
     if (config.$cache && config.$time) {
-      Api.getLCacheConfig(params[0].uuid, config.$time, BID).then(res => {
+      let uuid = params[0].uuid || ''
+      if (params[0].id) {
+        uuid = window.GLOB.CacheData.get('first_' + params[0].id) || ''
+      }
+      Api.getLCacheConfig(uuid, config.$time, BID).then(res => {
         if (!res.valid) {
           this.getMainData(param, params, config.uuid)
         }
@@ -156,11 +172,11 @@
         }
 
         params.forEach((item) => {
-          let _data = result[item.name] || ''
+          let _data = result[item.dataName] || ''
           if (_data && !Array.isArray(_data)) {
             _data = [_data]
           }
-          window.GLOB.SyncData.set(item.name, _data)
+          window.GLOB.SyncData.set(item.dataName, _data)
         })
 
         MKEmitter.emit('transferSyncData', tabId)
@@ -386,7 +402,7 @@
     }
 
     return (
-      <Row className="component-wrap" id={'anchor' + config.uuid} gutter={8}>{this.getComponents(config.components)}</Row>
+      <Row className="component-wrap" id={'anchor' + config.uuid}>{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 10d0453..5b5f0f3 100644
--- a/src/tabviews/custom/components/table/base-table/index.jsx
+++ b/src/tabviews/custom/components/table/base-table/index.jsx
@@ -67,8 +67,6 @@
 
     if (setting.selected !== 'always' && setting.selected !== 'init' && setting.selected !== 'sign') {
       setting.selected = 'false'
-    } else {
-      setting.orisel = true
     }
 
     _config.style = _config.style || {}
@@ -85,7 +83,7 @@
     }, () => {
       if (_config.setting.onload === 'true') {
         setTimeout(() => {
-          this.loadmaindata()
+          this.loadData()
           this.getStatFieldsValue()
         }, _config.setting.delay || 0)
       }
@@ -94,10 +92,8 @@
 
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
-   * @param { Boolean } reset  琛ㄦ牸鏄惁閲嶇疆
-   * @param { String }  repage 琛ㄦ牸鏄惁閲嶇疆椤电爜
    */
-  async loadmaindata (reset, repage, id) {
+  async loadData (reset, repage, id) {
     const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
     if (setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
@@ -110,9 +106,6 @@
       
       MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲
       reset && MKEmitter.emit('resetTable', config.uuid, 'true') // 鍒楄〃閲嶇疆
-      // if (setting.$hasSyncModule) {
-      //   MKEmitter.emit('syncBalconyData', config.uuid, [], false)
-      // }
 
       this.requestId = ''
       return
@@ -147,38 +140,12 @@
     if (result.status) {
       if (result.$requestId && this.requestId !== result.$requestId) return
 
-      if (repage === 'false' && result.data && result.data.length === 0 && result.total > 0 && pageIndex > 1) {
-        let _pageIndex = Math.ceil(result.total / pageSize)
-
-        if (_pageIndex < pageIndex) {
-          MKEmitter.emit('resetTable', config.uuid, 'repage', _pageIndex)
-          this.setState({
-            pageIndex: _pageIndex,
-            data: [],
-            selectedData: [],
-            total: result.total
-          }, () => {
-            this.loadmaindata()
-          })
-          return
-        }
+      if (repage === 'false' && result.data.length === 0 && pageIndex > 1) {
+        this.reloadIndex()
+        return
       }
 
-      if ((setting.selected !== 'false' || (setting.orisel && id)) && result.data && result.data.length > 0) {
-        setTimeout(() => {
-          MKEmitter.emit('mkCheckTopLine', config.uuid, id, setting.selected)
-        }, 200)
-        if (setting.selected === 'init') {
-          this.setState({setting: {...setting, selected: 'false'}})
-        }
-      } else {
-        MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲
-        // if (setting.$hasSyncModule) {
-        //   MKEmitter.emit('syncBalconyData', config.uuid, [], false)
-        // }
-      }
-      
-      reset && MKEmitter.emit('resetTable', config.uuid, repage) // 鍒楄〃閲嶇疆
+      reset && MKEmitter.emit('resetTable', config.uuid, repage || '') // 鍒楄〃閲嶇疆
 
       let start = 1
       if (setting.laypage) {
@@ -214,12 +181,24 @@
         total = data[data.length - 1].mk_total || 0
       }
 
+      if (data.length && (id || setting.selected !== 'false')) {
+        setTimeout(() => {
+          MKEmitter.emit('mkCheckTopLine', config.uuid, id, setting.selected)
+        }, 200)
+      } else {
+        MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲
+      }
+
       this.setState({
         data: data,
         selectedData: [],
         total: total,
         loading: false
       })
+
+      if (setting.selected === 'init') {
+        this.setState({setting: {...setting, selected: 'false'}})
+      }
 
       if (config.autoMatic) {
         if (result.data && result.data.length > 0) {
@@ -249,11 +228,6 @@
   async loadLinedata (id, position) {
     const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
-    if (config.forbidLine) {
-      this.reloadtable()
-      return
-    }
-
     let searches = fromJS(search).toJS()
     if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
       let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
@@ -275,7 +249,7 @@
     let result = await Api.genericInterface(param)
     if (result.status) {
       if (position === 'line_grid' && (!result.data || !result.data[0])) {
-        this.loadmaindata(true, 'false')
+        this.reloadIndex()
         return
       }
 
@@ -287,6 +261,12 @@
         _data.$$uuid = _data[setting.primaryKey] || ''
         _data.$$BID = BID || ''
         _data.$$BData = BData || ''
+
+        if (setting.controlField) {
+          if (setting.controlVal.includes(_data[setting.controlField] + '')) {
+            _data.$disabled = true
+          }
+        }
 
         if (config.absFields) {
           config.absFields.forEach(f => {
@@ -439,13 +419,25 @@
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
   refreshbysearch = (searches) => {
-    const { config} = this.state
+    const { config, BID } = this.state
+
+    if (config.setting.supModule && !BID) {
+      notification.warning({
+        top: 92,
+        message: window.GLOB.dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
+        duration: 5
+      })
+      this.setState({
+        search: searches
+      })
+      return
+    }
 
     this.setState({
       pageIndex: 1,
       search: searches
     }, () => {
-      this.loadmaindata(true, 'true')
+      this.loadData(true, 'true')
       this.getStatFieldsValue()
     })
 
@@ -463,7 +455,7 @@
       this.setState({
         pageIndex: pagination.pageIndex
       }, () => {
-        this.loadmaindata()
+        this.loadData()
       })
     } else {
       if (sorter.order) {
@@ -479,25 +471,8 @@
         pageSize: pagination.pageSize,
         orderBy: (sorter.field && sorter.order) ? `${sorter.field} ${sorter.order}` : ''
       }, () => {
-        this.loadmaindata()
+        this.loadData()
       })
-    }
-  }
-
-  /**
-   * @description 琛ㄦ牸鍒锋柊
-   */
-  reloadtable = (btn, id) => {
-    if (!btn || btn.resetPageIndex !== 'false') {
-      this.setState({
-        pageIndex: 1
-      }, () => {
-        this.loadmaindata(true, 'true', id)
-        this.getStatFieldsValue()
-      })
-    } else {
-      this.loadmaindata(true, 'false', id)
-      this.getStatFieldsValue()
     }
   }
 
@@ -532,7 +507,10 @@
     if (config.uuid !== menuId) return
 
     if (!id) {
-      this.reloadtable()
+      this.reloadIndex()
+    } else if (config.forbidLine) {
+      this.loadData(true, 'false', id)
+      this.getStatFieldsValue()
     } else {
       this.loadLinedata(id)
     }
@@ -549,7 +527,7 @@
         BData: data
       }, () => {
         if (!setting.checkBid) {
-          this.loadmaindata(true, 'true')
+          this.loadData(true, 'true')
           this.getStatFieldsValue()
         }
       })
@@ -558,25 +536,32 @@
 
   /**
    * @description 鎸夐挳鎵ц瀹屾垚鍚庨〉闈㈠埛鏂�
-   * @param {*} menuId     // 鑿滃崟Id
-   * @param {*} position   // 鍒锋柊浣嶇疆
-   * @param {*} btn        // 鎵ц鐨勬寜閽�
    */
   refreshByButtonResult = (menuId, position, btn, id, lines) => {
     const { config, BID } = this.state
 
     if (config.uuid !== menuId) return
 
+    let _id = config.wrap.selected === 'always' ? (id || '') : ''
     if (position === 'line' || position === 'line_grid') {
       if (lines && lines.length === 1) {
-        this.loadLinedata(lines[0].$$uuid, position)
+        if (config.forbidLine) {
+          this.loadData(true, 'false', lines[0].$$uuid)
+          this.getStatFieldsValue()
+        } else {
+          this.loadLinedata(lines[0].$$uuid, position)
+        }
       } else {
-        this.reloadtable(btn, id)
+        this.loadData(true, 'false', _id)
+        this.getStatFieldsValue()
       }
     } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
       MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
+    } else if (btn.resetPageIndex !== 'false') {
+      this.reloadIndex()
     } else {
-      this.reloadtable(btn, id)
+      this.loadData(true, 'false', _id)
+      this.getStatFieldsValue()
     }
   }
 
@@ -584,9 +569,16 @@
     const { config } = this.state
 
     if (config.$searchId !== searchId) return
-    
-    this.setState({pageIndex: 1}, () => {
-      this.reloadtable()
+
+    this.reloadIndex()
+  }
+
+  reloadIndex = () => {
+    this.setState({
+      pageIndex: 1
+    }, () => {
+      this.loadData(true, 'true')
+      this.getStatFieldsValue()
     })
   }
 
diff --git a/src/tabviews/custom/components/table/edit-table/index.jsx b/src/tabviews/custom/components/table/edit-table/index.jsx
index ffd5efc..c3cdecd 100644
--- a/src/tabviews/custom/components/table/edit-table/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/index.jsx
@@ -1,6 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
+import { notification } from 'antd'
 import moment from 'moment'
 
 import Api from '@/api'
@@ -224,7 +225,7 @@
     }, () => {
       if (_config.setting.onload === 'true') {
         setTimeout(() => {
-          this.loadmaindata()
+          this.loadData()
         }, _config.setting.delay || 0)
       }
     })
@@ -251,6 +252,7 @@
     config.dataSource = config.dataSource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
     config.dataSource = config.dataSource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
     config.dataSource = config.dataSource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+    config.dataSource = config.dataSource.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
 
     if (/\s/.test(config.dataSource)) { // 鎷兼帴鍒悕
       config.dataSource = '(' + config.dataSource + ') tb'
@@ -419,10 +421,8 @@
 
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
-   * @param { Boolean } reset  琛ㄦ牸鏄惁閲嶇疆
-   * @param { String }  repage 琛ㄦ牸鏄惁閲嶇疆椤电爜
    */
-  async loadmaindata (reset, repage) {
+  async loadData (reset, repage) {
     const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
     if (setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
@@ -528,11 +528,6 @@
    */ 
   async loadLinedata (id, position) {
     const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
-
-    if (config.forbidLine) {
-      this.reloadtable()
-      return
-    }
     
     let searches = fromJS(search).toJS()
     if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
@@ -555,7 +550,7 @@
     let result = await Api.genericInterface(param)
     if (result.status) {
       if (position === 'line_grid' && (!result.data || !result.data[0])) {
-        this.loadmaindata(true, 'false')
+        this.reloadIndex()
         return
       }
 
@@ -632,11 +627,25 @@
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
   refreshbysearch = (searches) => {
+    const { setting, BID } = this.state
+
+    if (setting.supModule && !BID) {
+      notification.warning({
+        top: 92,
+        message: window.GLOB.dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
+        duration: 5
+      })
+      this.setState({
+        search: searches
+      })
+      return
+    }
+
     this.setState({
       pageIndex: 1,
       search: searches
     }, () => {
-      this.loadmaindata(true, 'true')
+      this.loadData(true, 'true')
     })
   }
 
@@ -657,23 +666,19 @@
       pageSize: pagination.pageSize,
       orderBy: (sorter.field && sorter.order) ? `${sorter.field} ${sorter.order}` : ''
     }, () => {
-      this.loadmaindata()
+      this.loadData()
     })
   }
 
   /**
    * @description 琛ㄦ牸鍒锋柊
    */
-  reloadtable = (btn) => {
-    if (!btn || btn.resetPageIndex !== 'false') {
-      this.setState({
-        pageIndex: 1
-      }, () => {
-        this.loadmaindata(true, 'true')
-      })
-    } else {
-      this.loadmaindata(true, 'false')
-    }
+  reloadIndex = () => {
+    this.setState({
+      pageIndex: 1
+    }, () => {
+      this.loadData(true, 'true')
+    })
   }
 
   /**
@@ -707,7 +712,9 @@
     if (config.uuid !== menuId) return
 
     if (!id) {
-      this.reloadtable()
+      this.reloadIndex()
+    } else if (config.forbidLine) {
+      this.loadData(true, 'false')
     } else {
       this.loadLinedata(id)
     }
@@ -729,7 +736,7 @@
       }, () => {
         if (!setting.checkBid) {
           setTimeout(() => {
-            this.loadmaindata(true, 'true')
+            this.loadData(true, 'true')
           }, setting.delay || 0)
         }
       })
@@ -749,14 +756,20 @@
 
     if (position === 'line' || position === 'line_grid') {
       if (lines && lines.length === 1) {
-        this.loadLinedata(lines[0].$$uuid, position)
+        if (config.forbidLine) {
+          this.loadData(true, 'false')
+        } else {
+          this.loadLinedata(lines[0].$$uuid, position)
+        }
       } else {
-        this.reloadtable(btn)
+        this.loadData(true, 'false')
       }
     } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
       MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
+    } else if (btn.resetPageIndex !== 'false') {
+      this.reloadIndex()
     } else {
-      this.reloadtable(btn)
+      this.loadData(true, 'false')
     }
   }
 
@@ -789,9 +802,7 @@
 
     if (config.$searchId !== searchId) return
     
-    this.setState({pageIndex: 1}, () => {
-      this.reloadtable()
-    })
+    this.reloadIndex()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
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 762b303..03add13 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -586,19 +586,34 @@
     const { config } = this.props
     const { value, err } = this.state
 
-    return (
-      <InputNumber
-        title={err}
-        className={err ? 'has-error' : ''}
-        ref={ref => this.node = ref}
-        precision={config.decimal || 0}
-        value={value}
-        onChange={(value) => this.onChange(value)}
-        onPressEnter={this.enterPress}
-        onFocus={this.onFocus}
-        onBlur={this.onBlur}
-      />
-    )
+    if (!config.decimal && config.decimal !== 0) {
+      return (
+        <InputNumber
+          title={err}
+          className={err ? 'has-error' : ''}
+          ref={ref => this.node = ref}
+          value={value}
+          onChange={(value) => this.onChange(value)}
+          onPressEnter={this.enterPress}
+          onFocus={this.onFocus}
+          onBlur={this.onBlur}
+        />
+      )
+    } else {
+      return (
+        <InputNumber
+          title={err}
+          className={err ? 'has-error' : ''}
+          ref={ref => this.node = ref}
+          precision={config.decimal}
+          value={value}
+          onChange={(value) => this.onChange(value)}
+          onPressEnter={this.enterPress}
+          onFocus={this.onFocus}
+          onBlur={this.onBlur}
+        />
+      )
+    }
   }
 }
 
@@ -862,6 +877,9 @@
         }
         if (col.format === 'percent') {
           content = content * 100
+          if (!col.round) {
+            content = +content.toFixed(2)
+          }
         } else if (col.format === 'abs') {
           content = Math.abs(content)
         }
@@ -956,7 +974,7 @@
             // eslint-disable-next-line
             content = eval(content)
           } catch (e) {
-            console.info(content)
+            window.mkInfo(content)
             console.warn(e)
             content = ''
           }
@@ -978,7 +996,12 @@
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       } else if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
-        content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        if (!col.evalchars || col.evalchars.includes('enter')) {
+          content = content.replace(/\n/ig, '<br/>')
+        }
+        if (!col.evalchars || col.evalchars.includes('space')) {
+          content = content.replace(/\s/ig, '&nbsp;')
+        }
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       }
 
@@ -1187,6 +1210,9 @@
           }
           if (col.format === 'percent') {
             content = content * 100
+            if (!col.round) {
+              content = +content.toFixed(2)
+            }
           } else if (col.format === 'abs') {
             content = Math.abs(content)
           }
@@ -1270,7 +1296,7 @@
             // eslint-disable-next-line
             content = eval(content)
           } catch (e) {
-            console.info(content)
+            window.mkInfo(content)
             console.warn(e)
             content = ''
           }
@@ -1292,7 +1318,12 @@
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       } else if (content !== '') {
         content = `${col.prefix || ''}${content}${col.postfix || ''}`
-        content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+        if (!col.evalchars || col.evalchars.includes('enter')) {
+          content = content.replace(/\n/ig, '<br/>')
+        }
+        if (!col.evalchars || col.evalchars.includes('space')) {
+          content = content.replace(/\s/ig, '&nbsp;')
+        }
         content = <span dangerouslySetInnerHTML={{__html: content}}></span>
       }
 
@@ -1373,7 +1404,8 @@
     allColumns: null,
     checkForms: [],
     allForms: [],
-    reseting: false
+    reseting: false,
+    dict: window.GLOB.dict
   }
 
   timer = null
@@ -1459,6 +1491,9 @@
         } else {
           _item.datatype = item.datatype
         }
+        if (_item.type === 'number' && item.type === 'number') {
+          _item.decimal = item.decimal || 0
+        }
 
         forms.push(_item)
       } else {
@@ -1504,7 +1539,11 @@
       deForms: hasBid ? deForms : null
     }, () => {
       if (deForms.length > 0 && (!hasBid || BID)) {
-        this.improveActionForm(deForms, BID)
+        if (window.backend && window.GLOB.CacheData.has('sql_' + deForms[0].uuid)) {
+          this.improveBackActionForm(deForms, BID)
+        } else {
+          this.improveActionForm(deForms, BID)
+        }
       }
     })
   }
@@ -1518,7 +1557,11 @@
     const { deForms } = this.state
 
     if (deForms && nextProps.BID !== BID) {
-      this.improveActionForm(deForms, nextProps.BID)
+      if (window.backend && window.GLOB.CacheData.has('sql_' + deForms[0].uuid)) {
+        this.improveBackActionForm(deForms, nextProps.BID)
+      } else {
+        this.improveActionForm(deForms, nextProps.BID)
+      }
     }
     if (parCtrl && !is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
       let getColumns = (cols, sk) => {
@@ -1615,7 +1658,7 @@
   }
 
   checkLine = () => {
-    const { edData, forms, checkForms } = this.state
+    const { edData, forms, checkForms, dict } = this.state
 
     let data = edData.filter(item => item.$$uuid === this.blurId)[0]
 
@@ -1658,7 +1701,7 @@
       if (col.type === 'text') {
         let val = record[col.field] !== undefined ? (record[col.field] + '') : ''
         if (col.required === 'true' && !val) {
-          err = `${col.label}涓嶅彲涓虹┖`
+          err = `${col.label}${dict['not_empty'] || '涓嶅彲涓虹┖'}`
         } else if (col.datatype === 'datetime' && !val) {
           val = '1949-10-01'
         }
@@ -1667,27 +1710,27 @@
         let val = record[col.field]
 
         if (col.required === 'true' && !val) {
-          err = `${col.label}涓嶅彲涓�${col.noValue === 'hide' ? '绌�' : '0'}`
+          err = `${col.label}${col.noValue === 'hide' ? (dict['not_empty'] || '涓嶅彲涓虹┖') : dict['not_zero'] || '涓嶅彲涓�0'}`
         } else if (col.noValue === 'hide' && !val) {
           if (col.clearField && checkForms.includes(col.clearField) && !record[col.clearField]) {
-            err = `璇峰~鍐� ${col.label} 鎴� ${col.clearName}`
+            err = `${dict['input_tip'] || '璇峰~鍐� '}${col.label} ${dict['or'] || '鎴�'} ${col.clearName}`
           }
           val = 0
         } else if (!val && val !== 0) {
-          err = `${col.label}涓嶅彲涓虹┖`
+          err = `${col.label}${dict['not_empty'] || '涓嶅彲涓虹┖'}`
         } else {
           val = +val
           if (isNaN(val)) {
-            err = `${col.label}鏁版嵁鏍煎紡閿欒`
+            err = `${col.label} ${dict['data_format'] || '鏁版嵁鏍煎紡閿欒'}`
             return
           }
   
           val = +val.toFixed(col.decimal || 0)
           
           if (typeof(col.max) === 'number' && val > col.max) {
-            err = `${col.label}涓嶅彲澶т簬${col.max}`
+            err = `${col.label}${dict['max_limit'] || ' 涓嶅彲澶т簬 '}${col.max}`
           } else if (typeof(col.min) === 'number' && val < col.min) {
-            err = `${col.label}涓嶅彲灏忎簬${col.min}`
+            err = `${col.label}${dict['less_limit'] || ' 涓嶅彲灏忎簬 '}${col.min}`
           }
         }
 
@@ -1881,7 +1924,7 @@
         sql = sql.replace(/@BID@/ig, `'${BID}'`)
 
         if (debug) {
-          console.info(sql)
+          window.mkInfo(sql)
         }
 
         sql = sql.replace(/%/ig, ' mpercent ')
@@ -1894,7 +1937,7 @@
         sql = sql.replace(/@BID@/ig, `'${BID}'`)
 
         if (debug) {
-          console.info(sql)
+          window.mkInfo(sql)
         }
 
         sql = sql.replace(/%/ig, ' mpercent ')
@@ -1976,6 +2019,100 @@
         })
       )
     }
+
+    Promise.all(deffers).then(response => {
+      let result = {...response[0], ...(response[1] || {})}
+
+      delete result.ErrCode
+      delete result.ErrMesg
+      delete result.message
+      delete result.status
+
+      this.resetFormList(result)
+    })
+  }
+
+  improveBackActionForm = (deForms, BID) => {
+    let sysvals = {
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      bid: BID || '',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
+    }
+    if (window.GLOB.externalDatabase !== null) {
+      sysvals.db = window.GLOB.externalDatabase
+    }
+
+    let deffers = []
+    let mainItems = []  // 浜戠鎴栧崟鐐规暟鎹�
+    let localItems = [] // 鏈湴鏁版嵁
+
+    deForms.forEach(item => {
+      let ex = window.GLOB.CacheData.get('sql_' + item.uuid)
+      
+      if (!ex) return
+      
+      let exps = []
+      ex.reps.forEach(n => {
+        let key = n.toLowerCase()
+        if (sysvals.hasOwnProperty(key)) {
+          exps.push({
+            key: n,
+            value: sysvals[key]
+          })
+        }
+      })
+
+      let cell = {
+        id: ex.id,
+        menuname: item.label + '锛堣〃鍗曪級',
+        exps: exps,
+        md5_id: ''
+      }
+
+      if (item.database === 'sso' && window.GLOB.mainSystemApi) {
+        mainItems.push(cell)
+      } else {
+        localItems.push(cell)
+      }
+    })
+
+    if (localItems.length) {
+      deffers.push({
+        $backend: true,
+        $type: 's_Get_SelectedList',
+        data: localItems
+      })
+    }
+
+    if (mainItems.length) {
+      deffers.push({
+        $backend: true,
+        $type: 's_Get_SelectedList',
+        data: mainItems,
+        rduri: window.GLOB.mainSystemApi
+      })
+    }
+
+    if (!deffers.length) return
+
+    deffers = deffers.map(item => {
+      return new Promise(resolve => {
+        Api.getSystemCacheConfig(item, false).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+          }
+          resolve(res)
+        })
+      })
+    })
 
     Promise.all(deffers).then(response => {
       let result = {...response[0], ...(response[1] || {})}
@@ -2220,7 +2357,7 @@
 
   checkData = () => {
     const { setting } = this.props
-    const { edData, forms, checkForms, selectedRowKeys } = this.state
+    const { edData, forms, checkForms, selectedRowKeys, dict } = this.state
 
     let data = fromJS(edData).toJS()
 
@@ -2234,7 +2371,7 @@
       if (data.length === 0) {
         notification.warning({
           top: 92,
-          message: '璇烽�夋嫨闇�瑕佹彁浜ょ殑鏁版嵁锛�',
+          message: dict['select_row'] || '璇烽�夋嫨闇�瑕佹彁浜ょ殑鏁版嵁锛�',
           duration: 5
         })
         return null
@@ -2244,7 +2381,7 @@
     if (data.length === 0) {
       notification.warning({
         top: 92,
-        message: '鏁版嵁鏈慨鏀癸紝涓嶅彲鎻愪氦锛�',
+        message: dict['un_modified'] || '鏁版嵁鏈慨鏀癸紝涓嶅彲鎻愪氦锛�',
         duration: 5
       })
       return null
@@ -2278,7 +2415,7 @@
         if (col.type === 'text') {
           let val = item[col.field] !== undefined ? (item[col.field] + '') : ''
           if (col.required === 'true' && !val) {
-            line.push(`${col.label}涓嶅彲涓虹┖`)
+            line.push(`${col.label}${dict['not_empty'] || '涓嶅彲涓虹┖'}`)
           } else if (col.datatype === 'datetime' && !val) {
             val = '1949-10-01'
           }
@@ -2286,31 +2423,31 @@
         } else if (col.type === 'number') {
           let val = item[col.field]
           if (col.required === 'true' && !val) {
-            err = `${col.label}涓嶅彲涓�${col.noValue === 'hide' ? '绌�' : '0'}`
+            err = `${col.label}${col.noValue === 'hide' ? (dict['not_empty'] || '涓嶅彲涓虹┖') : dict['not_zero'] || '涓嶅彲涓�0'}`
           } else if (col.noValue === 'hide' && !val) {
             if (col.clearField && checkForms.includes(col.clearField) && !item[col.clearField]) {
-              let msg = `璇峰~鍐� ${col.label} 鎴� ${col.clearName}`
+              let msg = `${dict['input_tip'] || '璇峰~鍐� '}${col.label} ${dict['or'] || '鎴�'} ${col.clearName}`
               if (!line.includes(msg)) {
                 line.push(msg)
               }
             }
             val = 0
           } else if (!val && val !== 0) {
-            line.push(`${col.label}涓嶅彲涓虹┖`)
+            line.push(`${col.label}${dict['not_empty'] || '涓嶅彲涓虹┖'}`)
             return
           } else {
             val = +val
             if (isNaN(val)) {
-              line.push(`${col.label}鏁版嵁鏍煎紡閿欒`)
+              line.push(`${col.label} ${dict['data_format'] || '鏁版嵁鏍煎紡閿欒'}`)
               return
             }
   
             val = +val.toFixed(col.decimal || 0)
             
             if (typeof(col.max) === 'number' && val > col.max) {
-              line.push(`${col.label}涓嶅彲澶т簬${col.max}`)
+              line.push(`${col.label}${dict['max_limit'] || ' 涓嶅彲澶т簬 '}${col.max}`)
             } else if (typeof(col.min) === 'number' && val < col.min) {
-              line.push(`${col.label}涓嶅彲灏忎簬${col.min}`)
+              line.push(`${col.label}${dict['less_limit'] || ' 涓嶅彲灏忎簬 '}${col.min}`)
             }
           }
 
@@ -2319,7 +2456,7 @@
       })
 
       if (line.length > 0) {
-        err += `绗�${Index}琛岋細` + line.join('锛�') + '锛�'
+        err += (dict['line'] ? `${dict['line']} ${Index}锛歚 : `绗�${Index}琛岋細`) + line.join('锛�') + '锛�'
       }
       if (!item.$deleted) {
         Index++
@@ -2343,14 +2480,14 @@
 
   submit = (record) => {
     const { submit, BID, setting } = this.props
-    const { forms } = this.state
+    const { forms, dict } = this.state
 
     this.setState({visible: false, midData: null})
 
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
+        message: dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
 
@@ -2366,22 +2503,32 @@
 
     if (!data) return
 
-    let result = getEditTableSql(submit, data, forms)
-
-    let param = {
-      excel_in: result.lines,
-      BID: BID || ''
-    }
-
     this.setState({
       loading: true
     })
 
-    if (submit.intertype === 'system') { // 绯荤粺瀛樺偍杩囩▼
-      param.func = 'sPC_TableData_InUpDe'
-      
-      delete param.excel_in
+    if (submit.intertype === 'system' && window.backend && window.GLOB.CacheData.has('sql_submit_' + submit.$menuId)) {
+      let ex = window.GLOB.CacheData.get('sql_submit_' + submit.$menuId)
+      let param = this.getExps(ex, submit, data, forms)
 
+      Api.genericInterface(param).then((res) => {
+        if (res.status) {
+          this.execSuccess(res, record)
+        } else {
+          this.execError(res, record)
+        }
+      }, (error) => {
+        if (error && error.ErrCode === 'LoginError') return
+
+        this.execError({})
+      })
+    } else if (submit.intertype === 'system') { // 绯荤粺瀛樺偍杩囩▼
+      let result = getEditTableSql(submit, data, forms)
+      let param = {}
+
+      param.func = 'sPC_TableData_InUpDe'
+      param.BID = BID || ''
+      
       param.exec_type = window.GLOB.execType || 'y'
       param.LText = Utils.formatOptions(result.sql, param.exec_type)
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -2405,7 +2552,12 @@
         this.execError({})
       })
     } else if (submit.intertype === 'inner' && submit.innerFunc) { // 鑷畾涔夊瓨鍌ㄨ繃绋�
+      let result = getEditTableSql(submit, data, forms)
+      let param = {}
+
       param.func = submit.innerFunc
+      param.BID = BID || ''
+      param.excel_in = result.lines
 
       if (submit.recordUser === 'true') {
         param.username = sessionStorage.getItem('User_Name') || ''
@@ -2426,19 +2578,92 @@
     }
   }
 
+  getExps = (ex, btn, data, forms) => {
+    const { BID } = this.props
+
+    let exps = []
+    let values = {
+      time_id: Utils.getguid(),
+      roleid: sessionStorage.getItem('role_id') || '',
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      mk_nation: sessionStorage.getItem('nation') || '',
+      mk_province: sessionStorage.getItem('province') || '',
+      mk_city: sessionStorage.getItem('city') || '',
+      mk_district: sessionStorage.getItem('district') || '',
+      mk_address: sessionStorage.getItem('address') || '',
+      bid: BID || '',
+      typename: 'admin',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    }
+
+    if (window.GLOB.externalDatabase !== null) {
+      values.db = window.GLOB.externalDatabase
+    }
+
+    let lines = data.map(item => {
+      let vals = []
+      forms.forEach(col => {
+        vals.push(item[col.field])
+      })
+  
+      vals.push(item.$$uuid)
+      vals.push(item.$type || 'upt')
+      vals.push(BID)
+  
+      return vals
+    })
+
+    ex.reps.forEach(n => {
+      let key = n.toLowerCase()
+      if (values.hasOwnProperty(key)) {
+        exps.push({
+          key: n,
+          value: values[key]
+        })
+      }
+    })
+
+    exps.push({
+      key: 'mk_excel_data',
+      value: lines
+    })
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    return {
+      $backend: true,
+      $type: 's_TableData_InUpDe',
+      data: [{
+        id: ex.id,
+        menuname: btn.logLabel || '',
+        exps: exps,
+        md5_id: md5_id
+      }]
+    }
+  }
+
   execSuccess = (res, record) => {
     const { submit } = this.props
-    const { edData } = this.state
+    const { edData, dict } = this.state
 
     if (res && res.ErrCode === 'S') { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.message || '鎵ц鎴愬姛',
+        message: res.message || dict['exc_success'] || '鎵ц鎴愬姛',
         duration: submit.stime ? submit.stime : 2
       })
     } else if (res && res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.message || '鎵ц鎴愬姛'
+        title: res.message || dict['exc_success'] || '鎵ц鎴愬姛',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res && res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
@@ -2484,26 +2709,28 @@
 
   execError = (res, record) => {
     const { submit } = this.props
+    const { dict } = this.state
 
     if (res.ErrCode === 'E') {
       Modal.error({
-        title: res.message || '鎵ц澶辫触锛�',
+        title: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: submit.ntime ? submit.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: submit.ftime ? submit.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || '鎵ц澶辫触锛�')
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     }
     
     this.setState({
@@ -2617,7 +2844,7 @@
 
   render() {
     const { setting, lineMarks, submit } = this.props
-    const { edData, columns, loading, pageOptions, selectedRowKeys, visible, midData, reseting } = this.state
+    const { edData, columns, loading, pageOptions, selectedRowKeys, visible, midData, reseting, dict } = this.state
 
     if (reseting) return null
 
@@ -2648,13 +2875,19 @@
         pageSizeOptions: pageOptions,
         showSizeChanger: true,
         total: this.props.total || 0,
-        showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
+        showTotal: (total, range) => `${range[0]}-${range[1]} ${dict['of'] || '鍏�'} ${total} ${dict['items'] || '鏉�'}`
       }
     }
 
     let height = setting.height || false
-    if (height && height <= 100) {
-      height = height + 'vh'
+    if (height) {
+      if (height <= 100) {
+        if (height < 0) {
+          height = `calc(100vh - ${-height}px)`
+        } else {
+          height = height + 'vh'
+        }
+      }
     }
 
     let style = {
@@ -2667,9 +2900,9 @@
     return (
       <>
         {setting.hasSubmit && edData.length > 0 ? <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>
+          <Button style={submit.style} onClick={() => setTimeout(() => {this.submit()}, 10)} loading={loading} className="submit-table" type="link">{dict['submit'] || '鎻愪氦'}</Button>
         </div> : null}
-        <div className={`edit-custom-table ${setting.tableHeader || ''} ${setting.parity === 'true' ? 'mk-parity' : ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || ''} mk-edit-${setting.editType || 'simple'}`} style={style}>
+        <div className={`edit-custom-table ${setting.tableHeader || ''} ${setting.parity === 'true' ? 'mk-parity' : ''} ${height ? 'fixed-table-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || ''} mk-edit-${setting.editType || 'simple'}`} style={style}>
           <Table
             rowKey="$$uuid"
             components={components}
@@ -2691,7 +2924,7 @@
             onChange={this.changeTable}
             pagination={_pagination}
           />
-          {setting.hasSubmit && _data.length > 10 ? <Button style={submit.style} onClick={() => setTimeout(() => {this.submit()}, 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">{dict['submit'] || '鎻愪氦'}</Button> : null}
         </div>
         <Modal
           className="mk-user-confirm"
@@ -2700,13 +2933,13 @@
           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>
+            <Button key="cancel" onClick={() => { this.setState({ visible: false, midData: null }) }}>{dict['cancel'] || '鍙栨秷'}</Button>,
+            <Button key="refresh" className="table-refresh" onClick={() => { midData && this.updateMutil(midData) }}>{dict['refresh'] || '鍒锋柊琛ㄦ牸'}</Button>,
+            <Button key="confirm" type="primary" onClick={() => setTimeout(() => {this.submit()}, 10)}>{dict['submit'] || '鎻愪氦鏁版嵁'}</Button>
           ]}
           destroyOnClose
         >
-          <div><QuestionCircleOutlined />琛ㄦ牸涓湁鏁版嵁灏氭湭鎻愪氦</div>
+          <div><QuestionCircleOutlined />{dict['data_not_sub'] || '琛ㄦ牸涓湁鏁版嵁灏氭湭鎻愪氦'}</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 52f01f0..62322be 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
@@ -294,7 +294,7 @@
     background-color: #fafafa!important;
   }
 }
-.edit-custom-table:not(.fixed-height) {
+.edit-custom-table:not(.fixed-table-height) {
   .ant-table-body::-webkit-scrollbar {
     width: 8px;
     height: 10px;
@@ -309,14 +309,6 @@
     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 {
diff --git a/src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx b/src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx
index d74157b..df74eed 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx
@@ -41,61 +41,128 @@
       loading: true
     })
 
-    let param = {
-      func: 'sPC_Get_TableData',
-      obj_name: 'data',
-      exec_type: window.GLOB.execType || 'y',
-      arr_field: config.arr_field,
-      default_sql: 'true',
-      custom_script: '',
-      menuname: config.label
-    }
+    let param = null
+    if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid)) {
+      let ex = window.GLOB.CacheData.get('sql_' + config.uuid)
+      let sysvals = {
+        time_id: Utils.getguid(),
+        mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+        mk_organization: sessionStorage.getItem('organization') || '',
+        mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+        id: ID || '',
+        bid: BID || '',
+        datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        orderby: orderBy || config.order || '',
+        pagesize: config.laypage === 'true' ? pageSize : '9999',
+        pageindex: pageIndex
+      }
+      if (window.GLOB.externalDatabase !== null) {
+        sysvals.db = window.GLOB.externalDatabase
+      }
 
-    let sql = ''
-    let DateCount = ''
-    let _search = ''
-    let _orderBy = orderBy || config.order || ''
-    let _datasource = config.dataSource
+      let exps = []
 
-    if (config.searchKey && searchKey) {
-      let fields = config.searchKey.split(',').map(field => field + ` like '%${searchKey}%'`)
-      _search = 'where ' + fields.join(' OR ')
-    }
+      if (config.searchKey) {
+        if (!searchKey) {
+          exps.push({
+            key: 'mk_search',
+            value: []
+          })
+        } else {
+          exps.push({
+            key: 'mk_search',
+            value: [{
+              key: config.searchKey,
+              match: '01',
+              type: /,/.test(config.searchKey) ? 'text_or' : 'text',
+              value: searchKey
+            }]
+          })
+        }
+        config.searchKey.split(',').forEach(key => {
+          sysvals[key.toLowerCase()] = searchKey || ''
+        })
+      }
 
-    _datasource = _datasource.replace(/@BID@/ig, `'${BID || ''}'`)
-    _datasource = _datasource.replace(/@ID@/ig, `'${ID || ''}'`)
-
-    if (config.laypage === 'true') {
-      sql = `/*system_query*/select top ${pageSize} ${config.arr_field} from (select ${config.arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
-      DateCount = `/*system_query*/select count(1) as total from ${_datasource} ${_search}`
-    } else if (_orderBy) {
-      sql = `/*system_query*/select ${config.arr_field} from (select ${config.arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
-    } else {
-      sql = `/*system_query*/select ${config.arr_field} from ${_datasource} ${_search}  `
-    }
-
-    let departmentcode = sessionStorage.getItem('departmentcode') || ''
-    let organization = sessionStorage.getItem('organization') || ''
-    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
+      ex.reps.forEach(n => {
+        let key = n.toLowerCase()
+        if (sysvals.hasOwnProperty(key)) {
+          exps.push({
+            key: n,
+            value: sysvals[key]
+          })
+        }
+      })
     
-    sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-      Select @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}'
-      ${sql}`
-
-    // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true) {
-      console.info(`/*${config.label} 鏁版嵁婧�*/\n` + sql.replace(/\n\s{6}/ig, '\n'))
-      DateCount && console.info(`/*${config.label} 鎬绘暟鏌ヨ*/\n` + DateCount.replace(/\n\s{6}/ig, '\n'))
+      param = {
+        $backend: true,
+        $type: 's_Get_TableData',
+        data: [{
+          id: ex.id,
+          menuname: config.label || '',
+          exps: exps,
+          md5_id: ''
+        }]
+      }
+    } else {
+      param = {
+        func: 'sPC_Get_TableData',
+        obj_name: 'data',
+        exec_type: window.GLOB.execType || 'y',
+        arr_field: config.arr_field,
+        default_sql: 'true',
+        custom_script: '',
+        menuname: config.label
+      }
+  
+      let sql = ''
+      let DateCount = ''
+      let _search = ''
+      let _orderBy = orderBy || config.order || ''
+      let _datasource = config.dataSource
+  
+      if (config.searchKey && searchKey) {
+        let fields = config.searchKey.split(',').map(field => field + ` like '%${searchKey}%'`)
+        _search = 'where ' + fields.join(' OR ')
+      }
+  
+      _datasource = _datasource.replace(/@BID@/ig, `'${BID || ''}'`)
+      _datasource = _datasource.replace(/@ID@/ig, `'${ID || ''}'`)
+  
+      if (config.laypage === 'true') {
+        sql = `/*system_query*/select top ${pageSize} ${config.arr_field} from (select ${config.arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
+        DateCount = `/*system_query*/select count(1) as total from ${_datasource} ${_search}`
+      } else if (_orderBy) {
+        sql = `/*system_query*/select ${config.arr_field} from (select ${config.arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
+      } else {
+        sql = `/*system_query*/select ${config.arr_field} from ${_datasource} ${_search}  `
+      }
+  
+      let departmentcode = sessionStorage.getItem('departmentcode') || ''
+      let organization = sessionStorage.getItem('organization') || ''
+      let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
+      
+      sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+        Select @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}'
+        ${sql}`
+  
+      // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
+      if (window.GLOB.debugger === true) {
+        window.mkInfo(`/*${config.label} 鏁版嵁婧�*/\n` + sql.replace(/\n\s{6}/ig, '\n'))
+        DateCount && window.mkInfo(`/*${config.label} 鎬绘暟鏌ヨ*/\n` + DateCount.replace(/\n\s{6}/ig, '\n'))
+      }
+  
+      param.LText = Utils.formatOptions(sql, param.exec_type)
+      param.DateCount = Utils.formatOptions(DateCount, param.exec_type)
+  
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+      param.secretkey = Utils.encrypt('', param.timestamp)
+  
+      param.username = sessionStorage.getItem('User_Name') || ''
+      param.fullname = sessionStorage.getItem('Full_Name') || ''
     }
-
-    param.LText = Utils.formatOptions(sql, param.exec_type)
-    param.DateCount = Utils.formatOptions(DateCount, param.exec_type)
-
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt('', param.timestamp)
-
-    param.username = sessionStorage.getItem('User_Name') || ''
-    param.fullname = sessionStorage.getItem('Full_Name') || ''
 
     Api.getSystemCacheConfig(param, config.cache === 'true').then(result => {
       if (result.status) {
diff --git a/src/tabviews/custom/components/table/normal-table/index.jsx b/src/tabviews/custom/components/table/normal-table/index.jsx
index a5e10c5..ae15927 100644
--- a/src/tabviews/custom/components/table/normal-table/index.jsx
+++ b/src/tabviews/custom/components/table/normal-table/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Collapse } from 'antd'
+import { Collapse, notification } from 'antd'
 import moment from 'moment'
 
 import Api from '@/api'
@@ -79,8 +79,6 @@
 
     if (setting.selected !== 'always' && setting.selected !== 'init' && setting.selected !== 'sign') {
       setting.selected = 'false'
-    } else {
-      setting.orisel = true
     }
 
     if (_config.setting.sync === 'true') {
@@ -200,7 +198,7 @@
         this.setState({
           pageIndex: 1
         }, () => {
-          this.loadmaindata(true, 'true', '', 'timer')
+          this.loadData(true, 'true', '', 'timer')
         })
       })
     }
@@ -237,7 +235,7 @@
           Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => {
             if (!res.valid && config.setting.onload === 'true') {
               setTimeout(() => {
-                this.loadmaindata(false, 'true', '', 'init')
+                this.loadData(false, 'true', '', 'init')
               }, config.setting.delay || 0)
             }
   
@@ -299,13 +297,13 @@
 
         if (config.setting.onload === 'true') {
           setTimeout(() => {
-            this.loadmaindata(false, 'true', '', 'init')
+            this.loadData(false, 'true', '', 'init')
           }, config.setting.delay || 0)
         }
       }
     } else if (config.setting.onload === 'true') {
       setTimeout(() => {
-        this.loadmaindata()
+        this.loadData()
       }, config.setting.delay || 0)
     }
   }
@@ -511,10 +509,8 @@
 
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
-   * @param { Boolean } reset  琛ㄦ牸鏄惁閲嶇疆
-   * @param { String }  repage 琛ㄦ牸鏄惁閲嶇疆椤电爜
    */
-  async loadmaindata (reset, repage, id, type) {
+  async loadData (reset, repage, id, type) {
     const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
     if (setting.supModule && !BID && setting.supKey !== 'false') { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
@@ -575,35 +571,9 @@
         Api.writeCacheConfig(config.uuid, result.data || [], BID)
       }
 
-      if (repage === 'false' && result.data && result.data.length === 0 && result.total > 0 && pageIndex > 1) {
-        let _pageIndex = Math.ceil(result.total / pageSize)
-
-        if (_pageIndex < pageIndex) {
-          MKEmitter.emit('resetTable', config.uuid, 'repage', _pageIndex)
-          this.setState({
-            pageIndex: _pageIndex,
-            data: [],
-            selectedData: [],
-            total: result.total
-          }, () => {
-            this.loadmaindata()
-          })
-          return
-        }
-      }
-      
-      if ((setting.selected !== 'false' || (setting.orisel && id)) && result.data && result.data.length > 0) {
-        setTimeout(() => {
-          MKEmitter.emit('mkCheckTopLine', config.uuid, id, setting.selected)
-        }, 200)
-        if (setting.selected === 'init') {
-          this.setState({setting: {...setting, selected: 'false'}})
-        }
-      } else {
-        MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲
-        if (setting.$hasSyncModule) {
-          MKEmitter.emit('syncBalconyData', config.uuid, [], false)
-        }
+      if (repage === 'false' && result.data.length === 0 && pageIndex > 1) {
+        this.reloadIndex()
+        return
       }
       
       reset && MKEmitter.emit('resetTable', config.uuid, repage) // 鍒楄〃閲嶇疆
@@ -649,6 +619,17 @@
         allSearch.push(...searches)
       }
 
+      if (data.length && (id || setting.selected !== 'false')) {
+        setTimeout(() => {
+          MKEmitter.emit('mkCheckTopLine', config.uuid, id, setting.selected)
+        }, 200)
+      } else {
+        MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲
+        if (setting.$hasSyncModule) {
+          MKEmitter.emit('syncBalconyData', config.uuid, [], false)
+        }
+      }
+
       this.setState({
         data: data,
         selectedData: [],
@@ -656,6 +637,10 @@
         total: total,
         loading: false
       })
+
+      if (setting.selected === 'init') {
+        this.setState({setting: {...setting, selected: 'false'}})
+      }
 
       if (config.$hasTopModule) {
         window.GLOB.CacheData.set(config.uuid + 'tb', data[0] || { $$empty: true, $$uuid: '' })
@@ -686,11 +671,6 @@
   async loadLinedata (id, position) {
     const { setting, config, search, orderBy, BID, pageIndex, pageSize, BData } = this.state
 
-    if (config.forbidLine) {
-      this.reloadtable()
-      return
-    }
-
     let searches = fromJS(search).toJS()
     if (config.setting.useMSearch) { // 涓昏〃鎼滅储鏉′欢
       let mainSearch = window.GLOB.SearchBox.get(config.$searchId) || []
@@ -712,7 +692,7 @@
     let result = await Api.genericInterface(param)
     if (result.status) {
       if (position === 'line_grid' && (!result.data || !result.data[0])) {
-        this.loadmaindata(true, 'false')
+        this.reloadIndex()
         return
       }
       
@@ -724,6 +704,12 @@
         _data.$$uuid = _data[setting.primaryKey] || ''
         _data.$$BID = BID || ''
         _data.$$BData = BData || ''
+
+        if (setting.controlField) {
+          if (setting.controlVal.includes(_data[setting.controlField] + '')) {
+            _data.$disabled = true
+          }
+        }
   
         if (config.absFields) {
           config.absFields.forEach(f => {
@@ -812,11 +798,25 @@
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
   refreshbysearch = (searches) => {
+    const { setting, BID } = this.state
+
+    if (setting.supModule && !BID && setting.supKey !== 'false') {
+      notification.warning({
+        top: 92,
+        message: window.GLOB.dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
+        duration: 5
+      })
+      this.setState({
+        search: searches
+      })
+      return
+    }
+
     this.setState({
       pageIndex: 1,
       search: searches
     }, () => {
-      this.loadmaindata(true, 'true')
+      this.loadData(true, 'true')
     })
   }
 
@@ -837,23 +837,19 @@
       pageSize: pagination.pageSize,
       orderBy: (sorter.field && sorter.order) ? `${sorter.field} ${sorter.order}` : ''
     }, () => {
-      this.loadmaindata()
+      this.loadData()
     })
   }
 
   /**
    * @description 琛ㄦ牸鍒锋柊
    */
-  reloadtable = (btn, id) => {
-    if (!btn || btn.resetPageIndex !== 'false') {
-      this.setState({
-        pageIndex: 1
-      }, () => {
-        this.loadmaindata(true, 'true', id)
-      })
-    } else {
-      this.loadmaindata(true, 'false', id)
-    }
+  reloadIndex = () => {
+    this.setState({
+      pageIndex: 1
+    }, () => {
+      this.loadData(true, 'true')
+    })
   }
 
   /**
@@ -887,7 +883,9 @@
     if (config.uuid !== menuId) return
 
     if (!id) {
-      this.reloadtable()
+      this.reloadIndex()
+    } else if (config.forbidLine) {
+      this.loadData(true, 'false', id)
     } else {
       this.loadLinedata(id)
     }
@@ -912,7 +910,7 @@
 
       if (bid !== this.state.BID || bid !== '') {
         this.setState({ BID: bid, BData: _data, pageIndex: 1 }, () => {
-          this.loadmaindata(true, 'true')
+          this.loadData(true, 'true')
         })
       }
     } else {
@@ -928,7 +926,7 @@
           BData: data
         }, () => {
           if (!setting.checkBid) {
-            this.loadmaindata(true, 'true')
+            this.loadData(true, 'true')
           }
         })
       }
@@ -937,15 +935,13 @@
 
   /**
    * @description 鎸夐挳鎵ц瀹屾垚鍚庨〉闈㈠埛鏂�
-   * @param {*} menuId     // 鑿滃崟Id
-   * @param {*} position   // 鍒锋柊浣嶇疆
-   * @param {*} btn        // 鎵ц鐨勬寜閽�
    */
   refreshByButtonResult = (menuId, position, btn, id, lines) => {
     const { config, BID } = this.state
 
     if (config.uuid !== menuId) return
 
+    let _id = config.wrap.selected === 'always' ? (id || '') : ''
     if (config.supNodes) {
       if (['mainline', 'maingrid', 'popclose'].includes(position)) {
         let supNode = this.supModules[this.supModules.length - 1]
@@ -961,25 +957,37 @@
       } else {
         if (position === 'line' || position === 'line_grid') {
           if (lines && lines.length === 1) {
-            this.loadLinedata(lines[0].$$uuid, position)
+            if (config.forbidLine) {
+              this.loadData(true, 'false', lines[0].$$uuid)
+            } else {
+              this.loadLinedata(lines[0].$$uuid, position)
+            }
           } else {
-            this.reloadtable(btn, id)
+            this.loadData(true, 'false', _id)
           }
+        } else if (btn.resetPageIndex !== 'false') {
+          this.reloadIndex()
         } else {
-          this.reloadtable(btn, id)
+          this.loadData(true, 'false', _id)
         }
       }
     } else {
       if (position === 'line' || position === 'line_grid') {
         if (lines && lines.length === 1) {
-          this.loadLinedata(lines[0].$$uuid, position)
+          if (config.forbidLine) {
+            this.loadData(true, 'false', lines[0].$$uuid)
+          } else {
+            this.loadLinedata(lines[0].$$uuid, position)
+          }
         } else {
-          this.reloadtable(btn, id)
+          this.loadData(true, 'false', _id)
         }
       } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
         MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
+      } else if (btn.resetPageIndex !== 'false') {
+        this.reloadIndex()
       } else {
-        this.reloadtable(btn, id)
+        this.loadData(true, 'false', _id)
       }
     }
   }
@@ -1013,9 +1021,7 @@
 
     if (config.$searchId !== searchId) return
     
-    this.setState({pageIndex: 1}, () => {
-      this.reloadtable()
-    })
+    this.reloadIndex()
   }
 
   render() {
diff --git a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
index 2701fbb..ea63ca4 100644
--- a/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
+++ b/src/tabviews/custom/components/tabs/antv-tabs/index.jsx
@@ -146,10 +146,10 @@
     if (!tabs.subtabs.length) return null
 
     return (
-      <div className={`menu-antv-tabs-wrap ${tabs.setting.tabLabel || ''} ${tabs.setting.cusClass || ''}`} id={'anchor' + tabs.uuid} style={tabs.style}>
+      <div className={`menu-antv-tabs-wrap ${tabs.setting.tabLabel || ''} ${tabs.setting.cusClass || ''} align-${tabs.setting.tabAlign || ''}`} 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}>
+            <TabPane tab={<span className={tab.taType || ''} id={'tab' + tab.uuid}>{tab.icon ? <MkIcon type={tab.icon} /> : null}{tab.label}</span>} style={{backgroundColor: tab.backgroundColor || 'transparent'}} key={tab.uuid}>
               <TabTransfer config={tab}/>
             </TabPane>
           ))}
diff --git a/src/tabviews/custom/components/tabs/antv-tabs/index.scss b/src/tabviews/custom/components/tabs/antv-tabs/index.scss
index 42c4140..21a134e 100644
--- a/src/tabviews/custom/components/tabs/antv-tabs/index.scss
+++ b/src/tabviews/custom/components/tabs/antv-tabs/index.scss
@@ -23,6 +23,10 @@
   .ant-tabs-bottom-bar {
     margin-top: 0;
   }
+
+  .ant-tabs-tab .only-icon .anticon {
+    margin-right: 0px;
+  }
 }
 
 .menu-antv-tabs-wrap.hide >.ant-tabs >.ant-tabs-bar{
@@ -59,4 +63,10 @@
   .ant-tabs-nav-scroll {
     text-align: right;
   }
+}
+.menu-antv-tabs-wrap.align-right >.ant-tabs >.ant-tabs-bar .ant-tabs-nav-scroll {
+  text-align: right;
+}
+.menu-antv-tabs-wrap.align-center >.ant-tabs >.ant-tabs-bar .ant-tabs-nav-scroll {
+  text-align: center;
 }
\ No newline at end of file
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index 9d8a16c..8e29805 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -3,6 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Row, Col, Modal } from 'antd'
 import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -219,6 +220,21 @@
 
       window.GLOB.CacheData.set(MenuID, urlparam)
 
+      if (window.backend && config.allSqls) {
+        let keys = Object.keys(urlparam)
+        config.allSqls.forEach(item => {
+          item.id = md5(window.GLOB.appkey + item.v_id)
+          if (item.type === 'datasource' || item.type === 'excelOut') {
+            item.urlkeys = keys
+            item.urlparam = urlparam
+            if (config.flow_code) {
+              item.works_flow_code = config.flow_code
+            }
+          }
+          window.GLOB.CacheData.set('sql_' + item.uuid, item)
+        })
+      }
+
       let userName = sessionStorage.getItem('User_Name') || ''
       let fullName = sessionStorage.getItem('Full_Name') || ''
 
@@ -285,7 +301,7 @@
         }
       })
 
-      config.components = this.formatSetting(config.components, params, inherit, config.interfaces, balMap, tbMap)
+      config.components = this.formatSetting(config.components, params, inherit, config.interfaces, balMap, tbMap, BID)
 
       if (initInters.length > 0) {
         this.stepInter = {
@@ -680,6 +696,7 @@
 
         if (item.hasExtend) {
           item.setting.hasExtend = true
+          item.setting.sync = 'false'
           item.setting.tableMode = 'compatible'
           item.setting.extendTime = moment().format('YYYY-MM-DD HH:mm:ss')
           item.colsCtrls = null
@@ -698,6 +715,9 @@
           }
         }
       } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+        if (item.wrap.datatype === 'public') {
+          balMap.set(item.wrap.publicId + 'public', true)
+        }
         item.subcards && item.subcards.forEach(card => {
           if (card.style.boxShadow) {
             delete card.style.hShadow
@@ -791,6 +811,9 @@
           return cell.eleType !== 'button' || pass || permAction[cell.uuid] || cell.permission === 'false'
         })
       } else if (item.type === 'form') {
+        if (item.wrap.datatype === 'public') {
+          balMap.set(item.wrap.publicId + 'public', true)
+        }
         item.subcards = item.subcards.map(group => {
           group.subButton.uuid = group.uuid
           group.subButton.OpenType = 'formSubmit'
@@ -897,7 +920,7 @@
           item.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
           item.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-          item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript)
+          item.setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(item.setting.dataresource + item.setting.customScript)
 
           if (!item.setting.execute || item.setting.custompage) {
             item.forbidLine = true
@@ -905,7 +928,7 @@
 
           if (item.setting.sync === 'true') {
             // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
-            if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true') {
+            if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && !_tailScript) {
 
             } else {
               item.setting.sync = 'false'
@@ -953,25 +976,18 @@
 
     if (cell.OpenType === 'excelOut') { // 瀵煎嚭
       cell.$menuName = item.$menuname
-
-      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
-        cell.errorType = 'error1'
-      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom') {
-        if (item.setting.interType !== 'system') {
-          cell.errorType = 'error2'
-        } else if (item.type === 'balcony' || item.subtype === 'propcard') {
-          cell.errorType = 'error2'
-        }
+    } else if (cell.OpenType === 'pop' && cell.modal) {
+      if (item.$cache && item.$time) {
+        cell.modal.$cache = item.$cache
+        cell.modal.$time = item.$time
       }
-    } else if (cell.OpenType === 'pop' && item.$cache && item.$time && cell.modal) {
-      cell.modal.$cache = item.$cache
-      cell.modal.$time = item.$time
-      cell.modal.uuid = cell.uuid + 'pop'
+      cell.modal.uuid = cell.uuid + '_pop'
     }
 
     if (cell.verify) {
+      let isStatic = item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')
       if (cell.verify.invalid === 'true') {
-        if (item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')) {
+        if (isStatic) {
           cell.verify.invalid = 'false'
         } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
           cell.verify.invalid = 'false'
@@ -982,6 +998,9 @@
         } else if (cell.Ot === 'notRequired') {
           cell.verify.invalid = 'false'
         }
+      }
+      if (cell.verify.uniques && cell.verify.uniques.length > 0 && cell.Ot === 'requiredOnce' && isStatic) {
+        cell.verify.uniques = []
       }
 
       if (cell.verify.linkEnable === 'true' && /@/.test(cell.verify.linkUrl)) {
@@ -1127,18 +1146,18 @@
   }
 
   // 鏍煎紡鍖栭粯璁よ缃�
-  formatSetting = (components, params, inherit, interfaces, balMap, tbMap) => {
+  formatSetting = (components, params, inherit, interfaces, balMap, tbMap, BID) => {
     let delay = 20
     return components.map(component => {
       if (component.type === 'tabs') {
         component.subtabs = component.subtabs.map(tab => {
-          tab.components = this.formatSetting(tab.components, null, inherit, interfaces, balMap, tbMap)
+          tab.components = this.formatSetting(tab.components, null, inherit, interfaces, balMap, tbMap, BID)
           tab = {...tab, ...inherit}
           return tab
         })
         return component
       } else if (component.type === 'group') {
-        component.components = this.formatSetting(component.components, params, null, interfaces, balMap, tbMap)
+        component.components = this.formatSetting(component.components, params, null, interfaces, balMap, tbMap, BID)
         return component
       }
 
@@ -1213,6 +1232,8 @@
 
       if (component.setting.interType !== 'system') return component
 
+      component.setting.uuid = component.uuid
+
       // dataName 绯荤粺鐢熸垚鐨勬暟鎹簮鍚嶇О
       if (component.setting.sync === 'true') {
         component.dataName = 'mk' + component.uuid.slice(-18)
@@ -1234,12 +1255,22 @@
             component.setting.sync = 'false'
             component.setting.onload = 'false'
           } else {
-            params.push(getStructDefaultParam(component, searchlist, params.length === 0))
+            let backend = false
+            if (window.backend && params.length === 0 && window.GLOB.CacheData.has('sql_' + component.uuid)) {
+              backend = true
+            } else if (window.backend && params[0] && params[0].exps) {
+              backend = true
+            }
+            if (backend && !window.GLOB.CacheData.has('sql_' + component.uuid)) {
+              component.setting.sync = 'false'
+            } else {
+              params.push(getStructDefaultParam(component, searchlist, params.length === 0, BID))
+            }
           }
         }
       }
       
-      component.setting.delay = delay
+      component.setting.delay = delay + (component.setting.delay || 0)
       delay += 20
 
       return component
@@ -1265,7 +1296,7 @@
     let delay = 15
     return interfaces.map(inter => {
       inter.MenuID = MenuID
-      inter.setting.delay = delay
+      inter.setting.delay = delay + (inter.setting.delay || 0)
       inter.$searchId = MenuID
       delay += 15
 
@@ -1288,6 +1319,8 @@
       inter.setting.arr_field = inter.columns.map(col => col.field).join(',')
 
       if (inter.setting.interType !== 'system') return inter
+
+      inter.setting.uuid = inter.uuid
 
       let _customScript = ''
       let _tailScript = ''
@@ -1334,7 +1367,7 @@
       inter.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
       inter.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-      inter.setting.custompage = /@pageSize@|@orderBy@/i.test(inter.setting.dataresource + inter.setting.customScript)
+      inter.setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(inter.setting.dataresource + inter.setting.customScript)
 
       return inter
     })
@@ -1350,7 +1383,11 @@
     this.setState({loading: true, loadingview: false})
 
     if (config.$cache && config.$time) {
-      Api.getLCacheConfig(params[0].uuid, config.$time, BID).then(res => {
+      let uuid = params[0].uuid || ''
+      if (params[0].id) {
+        uuid = window.GLOB.CacheData.get('first_' + params[0].id) || ''
+      }
+      Api.getLCacheConfig(uuid, config.$time, BID).then(res => {
         if (!res.valid) {
           this.getMainData(param, params, config.MenuID)
         } else {
@@ -1386,11 +1423,11 @@
         }
 
         params.forEach((item) => {
-          let _data = result[item.name] || ''
+          let _data = result[item.dataName] || ''
           if (_data && !Array.isArray(_data)) {
             _data = [_data]
           }
-          window.GLOB.SyncData.set(item.name, _data)
+          window.GLOB.SyncData.set(item.dataName, _data)
         })
 
         MKEmitter.emit('transferSyncData', MenuID)
diff --git a/src/tabviews/custom/popview/index.jsx b/src/tabviews/custom/popview/index.jsx
index ff072e0..71b9453 100644
--- a/src/tabviews/custom/popview/index.jsx
+++ b/src/tabviews/custom/popview/index.jsx
@@ -156,7 +156,7 @@
     let params = []
     let BID = urlparam.$BID || ''
 
-    config.components = this.formatSetting(config.components, params, balMap, tbMap)
+    config.components = this.formatSetting(config.components, params, balMap, tbMap, BID)
 
     this.setState({
       BID: BID,
@@ -414,6 +414,7 @@
 
         if (item.hasExtend) {
           item.setting.hasExtend = true
+          item.setting.sync = 'false'
           item.setting.tableMode = 'compatible'
           item.setting.extendTime = moment().format('YYYY-MM-DD HH:mm:ss')
           item.colsCtrls = null
@@ -432,6 +433,9 @@
           }
         }
       } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+        if (item.wrap.datatype === 'public') {
+          balMap.set(item.wrap.publicId + 'public', true)
+        }
         item.subcards && item.subcards.forEach(card => {
           if (card.style.boxShadow) {
             delete card.style.hShadow
@@ -513,6 +517,9 @@
           return true
         })
       } else if (item.type === 'form') {
+        if (item.wrap.datatype === 'public') {
+          balMap.set(item.wrap.publicId + 'public', true)
+        }
         item.subcards = item.subcards.map(group => {
           group.subButton.uuid = group.uuid
           group.subButton.OpenType = 'formSubmit'
@@ -609,7 +616,7 @@
           item.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
           item.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-          item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript)
+          item.setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(item.setting.dataresource + item.setting.customScript)
 
           if (!item.setting.execute || item.setting.custompage) {
             item.forbidLine = true
@@ -617,7 +624,7 @@
 
           if (item.setting.sync === 'true') {
             // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
-            if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true') {
+            if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && !_tailScript) {
 
             } else {
               item.setting.sync = 'false'
@@ -664,21 +671,14 @@
 
     if (cell.OpenType === 'excelOut') { // 瀵煎嚭
       cell.$menuName = item.$menuname
-
-      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
-        cell.errorType = 'error1'
-      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom') {
-        if (item.setting.interType !== 'system') {
-          cell.errorType = 'error2'
-        } else if (item.type === 'balcony' || item.subtype === 'propcard') {
-          cell.errorType = 'error2'
-        }
-      }
+    } else if (cell.OpenType === 'pop' && cell.modal) {
+      cell.modal.uuid = cell.uuid + '_pop'
     }
 
     if (cell.verify) {
+      let isStatic = item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')
       if (cell.verify.invalid === 'true') {
-        if (item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')) {
+        if (isStatic) {
           cell.verify.invalid = 'false'
         } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
           cell.verify.invalid = 'false'
@@ -689,6 +689,10 @@
         } else if (cell.Ot === 'notRequired') {
           cell.verify.invalid = 'false'
         }
+      }
+
+      if (cell.verify.uniques && cell.verify.uniques.length > 0 && cell.Ot === 'requiredOnce' && isStatic) {
+        cell.verify.uniques = []
       }
 
       if (cell.verify.linkEnable === 'true' && /@/.test(cell.verify.linkUrl)) {
@@ -814,17 +818,17 @@
   }
 
   // 鏍煎紡鍖栭粯璁よ缃�
-  formatSetting = (components, params, balMap, tbMap) => {
+  formatSetting = (components, params, balMap, tbMap, BID) => {
     let delay = 20
     return components.map(component => {
       if (component.type === 'tabs') {
         component.subtabs = component.subtabs.map(tab => {
-          tab.components = this.formatSetting(tab.components, null, balMap, tbMap)
+          tab.components = this.formatSetting(tab.components, null, balMap, tbMap, BID)
           return tab
         })
         return component
       } else if (component.type === 'group') {
-        component.components = this.formatSetting(component.components, params, balMap, tbMap)
+        component.components = this.formatSetting(component.components, params, balMap, tbMap, BID)
         return component
       }
 
@@ -891,6 +895,8 @@
 
       if (component.setting.interType !== 'system') return component
 
+      component.setting.uuid = component.uuid
+      
       // dataName 绯荤粺鐢熸垚鐨勬暟鎹簮鍚嶇О
       if (component.setting.sync === 'true') {
         component.dataName = 'mk' + component.uuid.slice(-18)
@@ -912,12 +918,23 @@
             component.setting.sync = 'false'
             component.setting.onload = 'false'
           } else {
-            params.push(getStructDefaultParam(component, searchlist, params.length === 0))
+            let backend = false
+            if (window.backend && params.length === 0 && window.GLOB.CacheData.has('sql_' + component.uuid)) {
+              backend = true
+            } else if (window.backend && params[0] && params[0].exps) {
+              backend = true
+            }
+
+            if (backend && !window.GLOB.CacheData.has('sql_' + component.uuid)) {
+              component.setting.sync = 'false'
+            } else {
+              params.push(getStructDefaultParam(component, searchlist, params.length === 0, BID))
+            }
           }
         }
       }
 
-      component.setting.delay = delay
+      component.setting.delay = delay + (component.setting.delay || 0)
       delay += 20
 
       return component
@@ -955,11 +972,11 @@
         }
 
         params.forEach((item) => {
-          let _data = result[item.name] || ''
+          let _data = result[item.dataName] || ''
           if (_data && !Array.isArray(_data)) {
             _data = [_data]
           }
-          window.GLOB.SyncData.set(item.name, _data)
+          window.GLOB.SyncData.set(item.dataName, _data)
         })
 
         MKEmitter.emit('transferSyncData', Tab.uuid)
diff --git a/src/tabviews/home/index.jsx b/src/tabviews/home/index.jsx
index d8b8d6c..5dafb3f 100644
--- a/src/tabviews/home/index.jsx
+++ b/src/tabviews/home/index.jsx
@@ -43,7 +43,7 @@
       this.setState({
         waiting: false
       })
-    } else {
+    } else if (!window.GLOB.$error) {
       setTimeout(() => {
         this.check(times)
       }, 200)
diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx
index 39cbb1d..4dd6804 100644
--- a/src/tabviews/subtable/index.jsx
+++ b/src/tabviews/subtable/index.jsx
@@ -230,12 +230,6 @@
 
         if (item.OpenType === 'excelOut') { // 瀵煎嚭
           item.$menuName = Tab.label
-    
-          if (!item.verify || !item.verify.columns || item.verify.columns.length === 0) {
-            item.errorType = 'error1'
-          } else if (item.intertype === 'system' && item.verify.dataType !== 'custom' && config.setting.interType !== 'system') {
-            item.errorType = 'error2'
-          }
         }
 
         if (item.verify && item.verify.invalid === 'true') {
diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx
index bc3c2db..888ef15 100644
--- a/src/tabviews/subtabtable/index.jsx
+++ b/src/tabviews/subtabtable/index.jsx
@@ -203,12 +203,6 @@
 
         if (item.OpenType === 'excelOut') { // 瀵煎嚭
           item.$menuName = Tab.label
-    
-          if (!item.verify || !item.verify.columns || item.verify.columns.length === 0) {
-            item.errorType = 'error1'
-          } else if (item.intertype === 'system' && item.verify.dataType !== 'custom' && config.setting.interType !== 'system') {
-            item.errorType = 'error2'
-          }
         }
 
         if (item.verify && item.verify.invalid === 'true') {
diff --git a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
index a85c8a0..4886b6f 100644
--- a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
@@ -114,7 +114,7 @@
       MKEmitter.emit('closeTabView', MenuID || btn.$MenuID)
 
       if (btn.refreshTab && btn.refreshTab.length > 0) {
-        MKEmitter.emit('reloadMenuView', btn.refreshTab[btn.refreshTab.length - 1], 'table')
+        MKEmitter.emit('reloadMenuView', btn.refreshTab[btn.refreshTab.length - 1])
       }
       return
     }
@@ -125,7 +125,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: window.GLOB.dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -142,7 +142,7 @@
    */
   changeUser = (primaryId) => {
     const { setting, btn } = this.props
-    let _this = this
+    let that = this
 
     let param = {
       func: 'webapi_ChangeUser',
@@ -162,7 +162,9 @@
     param[setting.primaryKey] = primaryId
 
     confirm({
-      title: '纭畾瑕佹墽琛屽悧?',
+      title: window.GLOB.dict['exec_sure'] || '纭畾瑕佹墽琛屽悧?',
+      okText: window.GLOB.dict['ok'] || '纭畾',
+      cancelText: window.GLOB.dict['cancel'] || '鍙栨秷',
       onOk() {
         return new Promise(resolve => {
           Api.genericInterface(param).then(res => {
@@ -206,16 +208,16 @@
                 message: res.message || '鎵ц澶辫触锛�',
                 duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
               })
-              _this.setState({loading: false})
+              that.setState({loading: false})
             }
           }, () => {
             resolve()
-            _this.setState({loading: false})
+            that.setState({loading: false})
           })
         })
       },
       onCancel() {
-        _this.setState({loading: false})
+        that.setState({loading: false})
       }
     })
   }
diff --git a/src/tabviews/zshare/actionList/excelInbutton/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
index ab1cc80..513cdc5 100644
--- a/src/tabviews/zshare/actionList/excelInbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -3,6 +3,7 @@
 import moment from 'moment'
 import { is, fromJS } from 'immutable'
 import { Button, Modal, notification, message } from 'antd'
+import md5 from 'md5'
 
 import ExcelIn from './excelin'
 import Utils, { getExcelInSql } from '@/utils/utils.js'
@@ -29,6 +30,7 @@
     disabled: false,
     hidden: false,
     primaryId: '',
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -108,7 +110,7 @@
    */
   actionTrigger = (triggerId, record, type, lid) => {
     const { setting, BID, btn, selectedData, LID } = this.props
-    const { loading, disabled } = this.state
+    const { loading, disabled, dict } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -119,20 +121,14 @@
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
+        message: dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
     } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
-        duration: 5
-      })
-    } else if (!btn.verify || !btn.verify.sheet || !btn.verify.columns || btn.verify.columns.length === 0) {
-      notification.warning({
-        top: 92,
-        message: 'excel瀵煎叆楠岃瘉淇℃伅鏈缃紒',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
     } else {
@@ -148,7 +144,7 @@
         this.refs.excelIn.exceltrigger()
       })
   
-      if (window.GLOB.systemType === 'production') {
+      if (window.GLOB.systemType === 'production') { // positecgroup
         MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '瀵煎叆Excel'})
       }
     }
@@ -164,16 +160,18 @@
    */
   execSuccess = (res = {}) => {
     const { btn } = this.props
+    const { dict } = this.state
 
     if (res.ErrCode === 'S' || !res.ErrCode) { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.message || '鎵ц鎴愬姛锛�',
+        message: res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�',
         duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
       })
     } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.message || '鎵ц鎴愬姛锛�'
+        title: res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�',
       })
     } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
@@ -182,6 +180,16 @@
     this.setState({
       loading: false
     })
+
+    let tabId = ''
+    if (btn.refreshTab && btn.refreshTab.length > 0) {
+      tabId = btn.refreshTab[btn.refreshTab.length - 1]
+    }
+
+    if (tabId && btn.$MenuID === tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃讹紝鍋滄鍏朵粬鎿嶄綔
+      MKEmitter.emit('reloadMenuView', tabId)
+      return
+    }
 
     if (btn.execSuccess === 'closepoptab') {
       MKEmitter.emit('popclose')
@@ -207,6 +215,10 @@
       }
     }
 
+    if (tabId) {
+      MKEmitter.emit('reloadMenuView', tabId)
+    }
+
     if (btn.switchTab && btn.switchTab.length > 0) {
       let id = btn.switchTab[btn.switchTab.length - 1]
       let node = document.getElementById('tab' + id)
@@ -226,6 +238,7 @@
    */
   execError = (res = {}) => {
     const { btn } = this.props
+    const { dict } = this.state
 
     if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
       res.ErrCode = 'E'
@@ -233,23 +246,24 @@
 
     if (res.ErrCode === 'E') {
       Modal.error({
-        title: res.message || '鎵ц澶辫触锛�',
+        title: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || '鎵ц澶辫触锛�')
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     }
     
     this.setState({
@@ -259,7 +273,38 @@
     if (btn.execError === 'closepoptab') {
       MKEmitter.emit('popclose')
     } else if (btn.execError !== 'never') {
+      let tabId = ''
+      if (btn.refreshTab && btn.refreshTab.length > 0) {
+        tabId = btn.refreshTab[btn.refreshTab.length - 1]
+      }
+      if (tabId && btn.$MenuID === tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃讹紝鍋滄鍏朵粬鎿嶄綔
+        MKEmitter.emit('reloadMenuView', tabId, 'table')
+        return
+      }
+
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', this.state.selines)
+
+      if (btn.syncComponentId) {
+        if (btn.syncComponentId === 'multiComponent') {
+          btn.syncComponentIds.forEach((id, i) => {
+            setTimeout(() => {
+              if (/\$focus/.test(id)) {
+                MKEmitter.emit('reloadData', id.split('$')[0], id.split('$')[1])
+              } else {
+                MKEmitter.emit('reloadData', id)
+              }
+            }, 20 * i)
+          })
+        } else if (/\$focus/.test(btn.syncComponentId)) {
+          MKEmitter.emit('reloadData', btn.syncComponentId.split('$')[0], btn.syncComponentId.split('$')[1])
+        } else {
+          MKEmitter.emit('reloadData', btn.syncComponentId)
+        }
+      }
+
+      if (tabId) {
+        MKEmitter.emit('reloadMenuView', tabId)
+      }
     }
 
     if (btn.execError === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
@@ -292,88 +337,66 @@
       })
     }
 
-    let result = getExcelInSql(btn, data, (BID || ''), this.state.primaryId)
+    if (btn.intertype === 'system' && window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
+      let ex = window.GLOB.CacheData.get('sql_' + btn.uuid)
+      let param = this.getExps(ex, data)
 
-    if (result.errors) {
-      notification.warning({
-        top: 92,
-        message: result.errors,
-        duration: 5
-      })
-      this.setState({ loading: false })
-      return
-    }
-
-    let param = {
-      ID: this.state.primaryId,
-      excel_in: result.lines
-    }
-
-    if (BID) {
-      param.BID = BID
-    }
-
-    if (btn.intertype === 'system') { // 绯荤粺瀛樺偍杩囩▼
-      param.func = 'sPC_TableData_InUpDe'
-
-      delete param.excel_in
-
-      // param.excel_in_type = 'true'
-      param.exec_type = window.GLOB.execType || 'y'
-      param.LText = result.sql
-      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+      if (param.errors) {
+        notification.warning({
+          top: 92,
+          message: param.errors,
+          duration: 5
+        })
+        this.setState({ loading: false })
+        return
+      }
 
       let unCheckParam = null
 
-      if (/\$check@|@check\$/ig.test(param.LText)) {
+      if (ex.reps.includes('mk_check_begin')) {
         unCheckParam = fromJS(param).toJS()
-        param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
-      }
 
-      param.LText = Utils.formatOptions(param.LText, param.exec_type)
-      param.secretkey = Utils.encrypt('', param.timestamp)
-      if (window.GLOB.mkHS) { // 浜戠楠岃瘉
-        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
-      }
-
-      param.menuname = btn.logLabel
-      
-      if (window.GLOB.probation) {
-        param.s_debug_type = 'Y'
+        param.data[0].exps.push({
+          key: 'mk_check_begin',
+          value: ''
+        }, {
+          key: 'mk_check_end',
+          value: ''
+        })
+        unCheckParam.data[0].exps.push({
+          key: 'mk_check_begin',
+          value: 'Y'
+        }, {
+          key: 'mk_check_end',
+          value: 'Y'
+        })
       }
 
       if (unCheckParam) {
-        unCheckParam.LText = unCheckParam.LText.replace(/\$check@/ig, '/*').replace(/@check\$/ig, '*/')
-        unCheckParam.LText = Utils.formatOptions(unCheckParam.LText, unCheckParam.exec_type)
-        unCheckParam.secretkey = Utils.encrypt('', unCheckParam.timestamp)
-        unCheckParam.menuname = btn.logLabel
-
-        if (window.GLOB.probation) {
-          unCheckParam.s_debug_type = 'Y'
-        }
-
         Api.genericInterface(param).then(res => {
           if (res.status) {
             this.execSuccess(res)
           } else if (res.ErrCode === 'C') {
-            const _this = this
+            const that = this
             confirm({
-              title: '璇风‘璁�',
+              title: window.GLOB.dict['exec_sure'] || '璇风‘璁�',
               content: res.message,
+              okText: window.GLOB.dict['ok'] || '纭畾',
+              cancelText: window.GLOB.dict['cancel'] || '鍙栨秷',
               onOk() {
                 return new Promise(resolve => {
                   Api.genericInterface(unCheckParam).then(result => {
                     if (result.status) {
-                      _this.execSuccess(result)
+                      that.execSuccess(result)
                     } else {
-                      _this.execError(result)
+                      that.execError(result)
                     }
                     resolve()
                   })
                 })
               },
               onCancel() {
-                _this.execError(res)
+                that.execError(res)
               }
             })
           } else {
@@ -395,132 +418,455 @@
           this.execError({})
         })
       }
-    } else if (btn.intertype === 'inner' && btn.innerFunc) { // 鑷畾涔夊瓨鍌ㄨ繃绋�
-      param.func = btn.innerFunc
-
-      if (btn.recordUser === 'true') {
-        param.username = sessionStorage.getItem('User_Name') || ''
-        param.fullname = sessionStorage.getItem('Full_Name') || ''
+    } else {
+      let result = getExcelInSql(btn, data, (BID || ''), this.state.primaryId)
+  
+      if (result.errors) {
+        notification.warning({
+          top: 92,
+          message: result.errors,
+          duration: 5
+        })
+        this.setState({ loading: false })
+        return
       }
-      if (btn.dataM === 'true') {
-        param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
+  
+      let param = {
+        ID: this.state.primaryId,
+        excel_in: result.lines
       }
-
-      Api.genericInterface(param).then((res) => {
-        if (res.status) {
-          this.execSuccess(res)
-        } else {
-          this.execError(res)
+  
+      if (BID) {
+        param.BID = BID
+      }
+  
+      if (btn.intertype === 'system') { // 绯荤粺瀛樺偍杩囩▼
+        param.func = 'sPC_TableData_InUpDe'
+  
+        delete param.excel_in
+  
+        // param.excel_in_type = 'true'
+        param.exec_type = window.GLOB.execType || 'y'
+        param.LText = result.sql
+        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+  
+        let unCheckParam = null
+  
+        if (/\$check@|@check\$/ig.test(param.LText)) {
+          unCheckParam = fromJS(param).toJS()
+          param.LText = param.LText.replace(/\$check@|@check\$/ig, '')
         }
-      }, (error) => {
-        if (error && error.ErrCode === 'LoginError') return
-        this.execError({})
-      })
-    } else if (btn.intertype === 'outer') { // 澶栭儴鎺ュ彛
-      let _outParam = null
-      let ver_token = false
-
-      new Promise(resolve => {
-        // 鍐呴儴璇锋眰
-        if (btn.innerFunc) {
-          param.func = btn.innerFunc
-          // 瀛樺湪鍐呴儴鍑芥暟鏃讹紝鏁版嵁棰勫鐞�
+  
+        param.LText = Utils.formatOptions(param.LText, param.exec_type)
+        param.secretkey = Utils.encrypt('', param.timestamp)
+        if (window.GLOB.mkHS) { // 浜戠楠岃瘉
+          param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+        }
+  
+        if (btn.database === 'sso' && window.GLOB.mainSystemApi) {
+          param.rduri = window.GLOB.mainSystemApi
+        }
+  
+        param.menuname = btn.logLabel
+        
+        if (window.GLOB.probation) {
+          param.s_debug_type = 'Y'
+        }
+  
+        if (unCheckParam) {
+          unCheckParam.LText = unCheckParam.LText.replace(/\$check@/ig, '/*').replace(/@check\$/ig, '*/')
+          unCheckParam.LText = Utils.formatOptions(unCheckParam.LText, unCheckParam.exec_type)
+          unCheckParam.secretkey = Utils.encrypt('', unCheckParam.timestamp)
+          unCheckParam.menuname = btn.logLabel
+  
+          if (window.GLOB.probation) {
+            unCheckParam.s_debug_type = 'Y'
+          }
+  
           Api.genericInterface(param).then(res => {
             if (res.status) {
-              delete res.ErrCode
-              delete res.ErrMesg
-              delete res.message
-              delete res.status
-
-              // 浣跨敤澶勭悊鍚庣殑鏁版嵁璋冪敤澶栭儴鎺ュ彛
-              let keys = Object.keys(res) // 鎻愪氦澶栭儴鎺ュ彛鍓嶏紝娣诲姞BID
-              if (this.props.BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
-                res.BID = this.props.BID
-              }
-              resolve(res)
+              this.execSuccess(res)
+            } else if (res.ErrCode === 'C') {
+              const that = this
+              confirm({
+                title: window.GLOB.dict['exec_sure'] || '璇风‘璁�',
+                content: res.message,
+                okText: window.GLOB.dict['ok'] || '纭畾',
+                cancelText: window.GLOB.dict['cancel'] || '鍙栨秷',
+                onOk() {
+                  return new Promise(resolve => {
+                    Api.genericInterface(unCheckParam).then(result => {
+                      if (result.status) {
+                        that.execSuccess(result)
+                      } else {
+                        that.execError(result)
+                      }
+                      resolve()
+                    })
+                  })
+                },
+                onCancel() {
+                  that.execError(res)
+                }
+              })
             } else {
               this.execError(res)
-              resolve(false)
             }
           }, (error) => {
             if (error && error.ErrCode === 'LoginError') return
             this.execError({})
           })
         } else {
-          resolve(param)
+          Api.genericInterface(param).then((res) => {
+            if (res.status) {
+              this.execSuccess(res)
+            } else {
+              this.execError(res)
+            }
+          }, (error) => {
+            if (error && error.ErrCode === 'LoginError') return
+            this.execError({})
+          })
         }
-      }).then(res => {
-        if (!res) return
-        // 澶栭儴璇锋眰
-        _outParam = fromJS(res).toJS()
-
-        if (btn.sysInterface === 'true') {
-          if (window.GLOB.mainSystemApi) {
-            param.rduri = window.GLOB.mainSystemApi
-          }
-        } else if (btn.sysInterface === 'external') {
-          if (window.GLOB.systemType === 'production') {
-            param.$token = btn.exProInterface || ''
+      } else if (btn.intertype === 'inner' && btn.innerFunc) { // 鑷畾涔夊瓨鍌ㄨ繃绋�
+        param.func = btn.innerFunc
+  
+        if (btn.recordUser === 'true') {
+          param.username = sessionStorage.getItem('User_Name') || ''
+          param.fullname = sessionStorage.getItem('Full_Name') || ''
+        }
+        if (btn.dataM === 'true') {
+          param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
+        }
+  
+        Api.genericInterface(param).then((res) => {
+          if (res.status) {
+            this.execSuccess(res)
           } else {
-            param.$token = btn.exInterface || ''
+            this.execError(res)
           }
-          ver_token = true
-        } else {
-          if (window.GLOB.systemType === 'production' && btn.proInterface) {
-            param.rduri = btn.proInterface
+        }, (error) => {
+          if (error && error.ErrCode === 'LoginError') return
+          this.execError({})
+        })
+      } else if (btn.intertype === 'outer') { // 澶栭儴鎺ュ彛
+        let _outParam = null
+        let ver_token = false
+  
+        new Promise(resolve => {
+          // 鍐呴儴璇锋眰
+          if (btn.innerFunc) {
+            param.func = btn.innerFunc
+            // 瀛樺湪鍐呴儴鍑芥暟鏃讹紝鏁版嵁棰勫鐞�
+            Api.genericInterface(param).then(res => {
+              if (res.status) {
+                delete res.ErrCode
+                delete res.ErrMesg
+                delete res.message
+                delete res.status
+  
+                // 浣跨敤澶勭悊鍚庣殑鏁版嵁璋冪敤澶栭儴鎺ュ彛
+                let keys = Object.keys(res) // 鎻愪氦澶栭儴鎺ュ彛鍓嶏紝娣诲姞BID
+                if (this.props.BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
+                  res.BID = this.props.BID
+                }
+                resolve(res)
+              } else {
+                this.execError(res)
+                resolve(false)
+              }
+            }, (error) => {
+              if (error && error.ErrCode === 'LoginError') return
+              this.execError({})
+            })
           } else {
-            param.rduri = btn.interface
+            resolve(param)
           }
-          let host = window.GLOB.baseurl.replace(/http(s):\/\//, '')
-          if (param.rduri.indexOf(host) === -1 && /\/dostars/.test(param.rduri)) {
-            param.$login = true
-          }
-        }
-
-        if (btn.outerFunc) {
-          res.func = btn.outerFunc
-        }
-        
-        if (window.GLOB.mkHS && res.func === 's_sDataDictb_excelIn') { // s_sDataDictb_excelIn 浜戠楠岃瘉
-          let sql = `Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)`
-          param.LText = Utils.formatOptions(sql)
-          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-          param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-          param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
-        }
-
-        return Api.genericInterface(res)
-      }).then(response => {
-        if (!response || response.ErrCode === 'LoginError') return
-        // 鍥炶皟璇锋眰
-        if (ver_token && response.ErrCode === 'token_error') {
-          response.ErrCode = 'E'
-          this.execError(response)
-        } else if (btn.callbackFunc ) {
-          // 瀛樺湪鍥炶皟鍑芥暟鏃讹紝璋冪敤
-          delete response.message
-          delete response.status
-
-          response.func = btn.callbackFunc
-
-          let _callbackparam = {..._outParam, ...response}
-          return Api.genericInterface(_callbackparam)
-        } else {
-          if (response.status) {
-            this.execSuccess(response)
+        }).then(res => {
+          if (!res) return
+          // 澶栭儴璇锋眰
+          _outParam = fromJS(res).toJS()
+  
+          if (btn.sysInterface === 'true') {
+            if (window.GLOB.mainSystemApi) {
+              param.rduri = window.GLOB.mainSystemApi
+            }
+          } else if (btn.sysInterface === 'external') {
+            if (window.GLOB.systemType === 'production') {
+              param.$token = btn.exProInterface || ''
+            } else {
+              param.$token = btn.exInterface || ''
+            }
+            ver_token = true
           } else {
+            if (window.GLOB.systemType === 'production' && btn.proInterface) {
+              param.rduri = btn.proInterface
+            } else {
+              param.rduri = btn.interface
+            }
+            let host = window.GLOB.baseurl.replace(/http(s):\/\//, '')
+            if (param.rduri.indexOf(host) === -1 && /\/dostars/.test(param.rduri)) {
+              param.$login = true
+            }
+          }
+  
+          if (btn.outerFunc) {
+            res.func = btn.outerFunc
+          }
+          
+          if (window.GLOB.mkHS && res.func === 's_sDataDictb_excelIn') { // s_sDataDictb_excelIn 浜戠楠岃瘉
+            let sql = `Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)`
+            param.LText = Utils.formatOptions(sql)
+            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+            param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+            param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+          }
+  
+          return Api.genericInterface(res)
+        }).then(response => {
+          if (!response || response.ErrCode === 'LoginError') return
+          // 鍥炶皟璇锋眰
+          if (ver_token && response.ErrCode === 'token_error') {
+            response.ErrCode = 'E'
             this.execError(response)
+          } else if (btn.callbackFunc ) {
+            // 瀛樺湪鍥炶皟鍑芥暟鏃讹紝璋冪敤
+            delete response.message
+            delete response.status
+  
+            response.func = btn.callbackFunc
+  
+            let _callbackparam = {..._outParam, ...response}
+            return Api.genericInterface(_callbackparam)
+          } else {
+            if (response.status) {
+              this.execSuccess(response)
+            } else {
+              this.execError(response)
+            }
+          }
+        }).then(res => {
+          if (!res || res.ErrCode === 'LoginError') return
+  
+          if (res.status) {
+            this.execSuccess(res)
+          } else {
+            this.execError(res)
+          }
+        })
+      }
+    }
+  }
+
+  getExps = (ex, data) => {
+    const { BID, btn } = this.props
+    const { primaryId } = this.state
+
+    let exps = []
+    let values = {
+      time_id: Utils.getguid(),
+      roleid: sessionStorage.getItem('role_id') || '',
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      mk_nation: sessionStorage.getItem('nation') || '',
+      mk_province: sessionStorage.getItem('province') || '',
+      mk_city: sessionStorage.getItem('city') || '',
+      mk_district: sessionStorage.getItem('district') || '',
+      mk_address: sessionStorage.getItem('address') || '',
+      id: primaryId || '',
+      bid: BID || '',
+      typename: 'admin',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      // mk_check_begin: '',
+      // mk_check_end: ''
+    }
+
+    if (window.GLOB.externalDatabase !== null) {
+      values.db = window.GLOB.externalDatabase
+    }
+
+    let keys = ['delete', 'drop', 'insert', 'truncate', 'update']
+    let errors = []
+    let _topline = btn.verify.range || 0
+    let cols = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
+    for (let i = 0; i < 26; i++) {
+      cols.push('A' + cols[i])
+    }
+
+    let lines = data.map((item, lindex) => {
+      let vals = []
+      btn.verify.columns.forEach((col, cindex) => {
+        if (col.import === 'false') return
+
+        let val = item[col.Column] !== undefined ? item[col.Column] : ''
+        let _colindex = cols[cindex] || (cindex + 1)
+        let _position = (_topline + lindex + 1) + '琛� ' + _colindex + '鍒� '
+
+        if (col.import === 'init') {
+          if (/^Nvarchar/ig.test(col.type)) {
+            val = ''
+          } else if (/^Decimal/ig.test(col.type) || /^int/ig.test(col.type)) {
+            val = 0
+          } else if (col.type === 'date') {
+            val = '1949-10-01'
+          } else if (col.type === 'datetime') {
+            val = '1949-10-01 00:00:00'
+          }
+        } else if (/^Nvarchar/ig.test(col.type)) {
+          val = val + ''
+
+          if (/'/.test(val)) {
+            val = val.replace(/'/ig, '"')
+          }
+
+          val = val.replace(/(^\s+$)|\t+|\v+/ig, '')
+
+          if (!val && col.required === 'true') {            // 蹇呭~鏍¢獙
+            errors.push(_position + '鍐呭涓嶅彲涓虹┖')
+          } else if (col.limit && val.length > col.limit) { // 闀垮害鏍¢獙
+            errors.push(_position + '鍐呭瓒呴暱')
+          } else {                                          // 鍏抽敭瀛楁牎楠�
+            keys.forEach(key => {
+              let _patten = new RegExp('(^' + key + '\\s+)|(\\s+' + key + '\\s+)', 'ig')
+              if (_patten.test(val)) {
+                errors.push(_position + '鍚湁鍏抽敭瀛�' + key)
+              }
+            })
+          }
+        } else if (/^Decimal/ig.test(col.type) || /^int/ig.test(col.type)) {
+          if (col.required === 'false') {
+            if (!val || isNaN(val)) {
+              val = 0
+            }
+          } else if (!val && val !== 0) {
+            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' || col.type === 'datetime') {
+          if (typeof(val) === 'number') {
+            if (val > 2958465 || val <= 0) {                 // 鏃堕棿杩囧ぇ鎴栧皬浜庣瓑浜�0
+              errors.push(_position + '鏃堕棿涓鸿礋鍊兼垨澶ぇ')
+            } else {                                         // 鏃堕棿鏍煎紡鍖�
+              if (val < 60) {                                // 1900-2-29锛宔xcel涓瓨鍦紝瀹為檯涓嶅瓨鍦�
+                val++
+              }
+              if (col.type === 'datetime') {
+                val = val - 2
+                let day = Math.floor(val)
+                let seconds = Math.round((val - day) * 24 * 60 * 60)
+                val = moment('19000101', 'YYYYMMDD').add(day, 'days').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss')
+              } else {
+                val = moment('19000101', 'YYYYMMDD').add(Math.floor(val - 2), 'days').format('YYYY-MM-DD')
+              }
+            }
+          } else if (typeof(val) === 'string') {
+            val = val.replace(/(^\s+$)|\t+|\v+/ig, '')
+            if (!val) {
+              if (col.required === 'true') {         // 鏃堕棿蹇呭~鏍¢獙
+                errors.push(_position + '鍐呭涓嶅彲涓虹┖')
+              } else if (col.type === 'date') {
+                val = '1949-10-01'
+              } else if (col.type === 'datetime') {
+                val = '1949-10-01 00:00:00'
+              }
+            } else if (!/^[1-9][0-9]{3}/.test(val)) { // 鏃堕棿姝e垯鏍¢獙
+              errors.push(_position + '鏃堕棿鏍煎紡閿欒')
+            }
+          } else {                                    // 鏃堕棿鏍煎紡閿欒
+            errors.push(_position + '鏃堕棿鏍煎紡閿欒')
           }
         }
-      }).then(res => {
-        if (!res || res.ErrCode === 'LoginError') return
 
-        if (res.status) {
-          this.execSuccess(res)
-        } else {
-          this.execError(res)
-        }
+        vals.push(val)
       })
+
+      let _lineIndex = '0000' + (lindex + 1) + '0'
+      _lineIndex = _lineIndex.substring(_lineIndex.length - 6)
+
+      vals.push(Utils.getguid() + _lineIndex)
+      vals.push(BID)
+
+      return vals
+    })
+
+    if (errors.length) return {errors: errors.join('; ')}
+
+    ex.reps.forEach(n => {
+      let key = n.toLowerCase()
+      if (values.hasOwnProperty(key)) {
+        exps.push({
+          key: n,
+          value: values[key]
+        })
+      }
+    })
+
+    exps.push({
+      key: 'mk_excel_data',
+      value: lines
+    })
+
+    if (btn.$process && btn.verify.workFlow === 'true') {
+      let flow = window.GLOB.UserCacheMap.get(btn.$flowId)
+      let target = flow ? flow.cells.filter(cell => cell.mknode === 'start')[0] : ''
+      
+      let error = ''
+      let msg = ''
+      let status = 0
+      let statusName = ''
+      let detailId = ''
+  
+      if (target) {
+        detailId = target.id
+        status = target.mkdata.status
+        statusName = target.mkdata.statusName
+
+        let label = target.attrs && target.attrs.text && target.attrs.text.text ? target.attrs.text.text : ''
+        msg = {...target.mkdata, label: label, id: target.id, checkIds: [], checkUsers: []}
+        msg = window.btoa(window.encodeURIComponent(JSON.stringify(msg)))
+      } else {
+        status = 0
+        statusName = '寮傚父'
+        error = '宸ヤ綔娴佹棤寮�濮嬭妭鐐�'
+      }
+
+      exps.push(
+        { key: 'works_flow_error', value: error },
+        { key: 'works_flow_code', value: flow ? flow.flow_code : '' },
+        { key: 'works_flow_name', value: flow ? flow.flow_name : '' },
+        { key: 'works_flow_param', value: msg },
+        { key: 'works_flow_detail_id', value: detailId },
+        { key: 'status', value: status },
+        { key: 'statusname', value: statusName },
+        { key: 'work_group', value: sessionStorage.getItem('work_group') || '' },
+        { key: 'work_grade', value: sessionStorage.getItem('work_grade') || 0 },
+        // { key: 'start_type', value: '寮�濮�' },
+      )
+    }
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    return {
+      $backend: true,
+      $type: 's_TableData_InUpDe',
+      data: [{
+        id: ex.id,
+        menuname: btn.logLabel || '',
+        exps: exps,
+        md5_id: md5_id
+      }]
     }
   }
 
diff --git a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
index 0317ad6..3dddc9d 100644
--- a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -23,9 +23,10 @@
   }
 
   state = {
-    loading: false, // 瀵煎嚭涓�
+    loading: false,
     hidden: false,
-    disabled: false
+    disabled: false,
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -92,7 +93,7 @@
    */
   actionTrigger = (triggerId, _, type, lid) => {
     const { setting, BID, btn, LID } = this.props
-    const { loading, disabled } = this.state
+    const { loading, disabled, dict } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -101,24 +102,12 @@
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
-        duration: 5
-      })
-    } else if (btn.errorType === 'error1') {
-      notification.warning({
-        top: 92,
-        message: '璇疯缃鍑哄垪锛�',
-        duration: 5
-      })
-    } else if (btn.errorType === 'error2') {
-      notification.warning({
-        top: 92,
-        message: '鎸夐挳闇�鑷畾涔夊鍑烘暟鎹簮锛�',
+        message: dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
     } else {
       MKEmitter.emit('queryModuleParam', btn.$menuId, this.triggerExcelout)
-      if (window.GLOB.systemType === 'production') {
+      if (window.GLOB.systemType === 'production') { // positecgroup
         MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '瀵煎嚭Excel'})
       }
     }
@@ -145,7 +134,7 @@
       if (!valid) {
         notification.warning({
           top: 92,
-          message: '鎼滅储鏉′欢涓嶅彲涓虹┖锛�',
+          message: window.GLOB.dict['miss_search'] || '鎼滅储鏉′欢涓嶅彲涓虹┖锛�',
           duration: 5
         })
         return
@@ -159,7 +148,9 @@
     if (btn.pagination !== 'true') {
       if (btn.intertype === 'system') { // 浣跨敤绯荤粺鍑芥暟
         let param = this.getExcelDefaultParam(viewParam.orderBy, viewParam.search)
-
+        if (btn.database === 'sso' && window.GLOB.mainSystemApi) {
+          param.rduri = window.GLOB.mainSystemApi
+        }
         Api.genericInterface(param).then(result => {
           if (result.status) {
             this.exportExcel(result.data, result.ErrCode, result.message, viewParam.search)
@@ -343,7 +334,7 @@
         Api.genericInterface(res).then(result => {
           if (result.status) {
             if (!result.data) {
-              this.execError({ErrCode: 'N', message: '鏈幏鍙栧埌鏁版嵁淇℃伅锛�'})
+              this.execError({ErrCode: 'N', message: window.GLOB.dict['no_data'] || '鏈幏鍙栧埌鏁版嵁淇℃伅锛�'})
             } else if (result.data.length >= pageSize) {
               data = data.concat(result.data)
               pageIndex++
@@ -376,6 +367,9 @@
     let param = null
     if (btn.intertype === 'system') { // 浣跨敤绯荤粺鍑芥暟
       param = this.getExcelDefaultParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
+      if (btn.database === 'sso' && window.GLOB.mainSystemApi) {
+        param.rduri = window.GLOB.mainSystemApi
+      }
     } else if (btn.intertype === 'inner') { // 浣跨敤鍐呴儴鍑芥暟
       param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
       param.func = btn.innerFunc
@@ -387,7 +381,6 @@
       if (btn.dataM === 'true') {
         param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
       }
-
     } else if (btn.intertype === 'outer' && !btn.innerFunc) { // 浣跨敤澶栭儴鍑芥暟
       param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
 
@@ -422,7 +415,7 @@
     Api.genericInterface(param).then(result => {
       if (result.status) {
         if (!result.data) {
-          this.execError({ErrCode: 'N', message: '鏈幏鍙栧埌鏁版嵁淇℃伅锛�'})
+          this.execError({ErrCode: 'N', message: window.GLOB.dict['no_data'] || '鏈幏鍙栧埌鏁版嵁淇℃伅锛�'})
         } else if (result.data.length >= pageSize) {
           data = data.concat(result.data)
           pageIndex++
@@ -445,6 +438,7 @@
    */
   exportExcel = (data = [], ErrCode, msg, search) => {
     const { btn } = this.props
+    const { dict } = this.state
     
     let imgCol = false
     let merge = false
@@ -518,7 +512,7 @@
       if (errors.length) {
         notification.error({
           top: 92,
-          message: '鏁版嵁涓己灏戝瓧娈碉細' + errors.join('銆�'),
+          message: (dict['miss_field'] || '鏁版嵁涓己灏戝瓧娈�') + '锛�' + errors.join('銆�'),
           duration: 5
         })
 
@@ -535,7 +529,7 @@
         // eslint-disable-next-line
         let func = new Function('XLSX', 'data', 'columns', 'searches', 'callback', btn.verify.excel_func)
         func(XLSX, data, columns, search, (res) => {
-          res = res || {ErrCode: ErrCode || 'S', message: msg || '瀵煎嚭鎴愬姛锛�'}
+          res = res || {ErrCode: ErrCode || 'S', message: msg || dict['exc_success'] || '瀵煎嚭鎴愬姛锛�'}
           this.execSuccess(res)
         })
       } else if (imgCol) {
@@ -616,7 +610,7 @@
 
         this.table2excel(column, table)
 
-        this.execSuccess({ErrCode: ErrCode || 'S', message: msg || '瀵煎嚭鎴愬姛锛�'})
+        this.execSuccess({ErrCode: ErrCode || 'S', message: msg || dict['exc_success'] || '瀵煎嚭鎴愬姛锛�'})
       } else {
         let table = []
         let _header = []
@@ -776,7 +770,7 @@
   
         XLSX.writeFile(wb, `${btn.verify.excelName || btn.$menuName || ''}${moment().format('YYYYMMDDHHmmss')}.xlsx`)
   
-        this.execSuccess({ErrCode: ErrCode || 'S', message: msg || '瀵煎嚭鎴愬姛锛�'})
+        this.execSuccess({ErrCode: ErrCode || 'S', message: msg || dict['exc_success'] || '瀵煎嚭鎴愬姛锛�'})
       }
     } catch (e) {
       console.warn(e)
@@ -868,7 +862,10 @@
 
     let _setting = {}
     let _orderBy = orderBy || ''
+
     if (btn.verify.dataType === 'custom') {
+      _setting.uuid = btn.uuid
+      _setting.interType = 'system'
       _setting.arr_field = []
 
       btn.verify.columns.forEach(col => {
@@ -914,11 +911,18 @@
         _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
       }
 
+      if (btn.$flowId && window.GLOB.UserCacheMap.has(btn.$flowId)) {
+        let flow = window.GLOB.UserCacheMap.get(btn.$flowId)
+        _setting.dataresource = _setting.dataresource.replace(/@works_flow_code@/ig, `'${flow.flow_code}'`)
+        _customScript = _customScript.replace(/@works_flow_code@/ig, `'${flow.flow_code}'`)
+        _tailScript = _tailScript.replace(/@works_flow_code@/ig, `'${flow.flow_code}'`)
+      }
+
       _setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
       _setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
       _setting.laypage = pagination
-      _setting.custompage = /@pageSize@|@orderBy@/i.test(_setting.dataresource + _setting.customScript)
+      _setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(_setting.dataresource + _setting.customScript)
 
       _setting.queryType = btn.verify.queryType
       _setting.$name = btn.logLabel
@@ -930,6 +934,10 @@
       _setting.laypage = pagination
       _setting.arr_field = _setting.all_field || _setting.arr_field
 
+      if (setting.sub_field) {
+        _setting.uuid = btn.uuid
+      }
+
       delete _setting.sub_field
     }
 
@@ -939,17 +947,9 @@
       primaryId = primaryId ? 'excel:' + primaryId : ''
     }
 
-    let param = UtilsDM.getDefaultQueryParam(_setting, search, _orderBy, pageIndex, pageSize, primaryId, BID)
+    let param = UtilsDM.getQueryDataParams(_setting, search, _orderBy, pageIndex, pageSize, BID, primaryId)
     
-    param.DateCount = ''
-
-    // 鏁版嵁绠$悊鏉冮檺
-    if (sessionStorage.getItem('dataM') === 'true') {
-      param.dataM = 'Y'
-    }
-    if (BID) {
-      param.BID = BID
-    }
+    delete param.DateCount
 
     return param
   }
@@ -973,7 +973,8 @@
       })
     } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.message
+        title: res.message,
+        okText: window.GLOB.dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
@@ -982,6 +983,16 @@
     this.setState({
       loading: false
     })
+
+    let tabId = ''
+    if (btn.refreshTab && btn.refreshTab.length > 0) {
+      tabId = btn.refreshTab[btn.refreshTab.length - 1]
+    }
+
+    if (tabId && btn.$MenuID === tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃讹紝鍋滄鍏朵粬鎿嶄綔
+      MKEmitter.emit('reloadMenuView', tabId)
+      return
+    }
 
     if (btn.execSuccess === 'closepoptab') {
       MKEmitter.emit('popclose')
@@ -1006,6 +1017,10 @@
         MKEmitter.emit('reloadData', btn.syncComponentId)
       }
     }
+
+    if (tabId) {
+      MKEmitter.emit('reloadMenuView', tabId)
+    }
     
     if (btn.switchTab && btn.switchTab.length > 0) {
       let id = btn.switchTab[btn.switchTab.length - 1]
@@ -1026,6 +1041,7 @@
    */
   execError = (res = {}) => {
     const { btn } = this.props
+    const { dict } = this.state
 
     if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
       res.ErrCode = 'E'
@@ -1033,23 +1049,24 @@
 
     if (res.ErrCode === 'E') {
       Modal.error({
-        title: res.message || '鎵ц澶辫触锛�',
+        title: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || '鎵ц澶辫触锛�')
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     }
     
     this.setState({
@@ -1059,7 +1076,38 @@
     if (btn.execError === 'closepoptab') {
       MKEmitter.emit('popclose')
     } else if (btn.execError !== 'never') {
+      let tabId = ''
+      if (btn.refreshTab && btn.refreshTab.length > 0) {
+        tabId = btn.refreshTab[btn.refreshTab.length - 1]
+      }
+      if (tabId && btn.$MenuID === tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃讹紝鍋滄鍏朵粬鎿嶄綔
+        MKEmitter.emit('reloadMenuView', tabId)
+        return
+      }
+
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', [])
+
+      if (btn.syncComponentId) {
+        if (btn.syncComponentId === 'multiComponent') {
+          btn.syncComponentIds.forEach((id, i) => {
+            setTimeout(() => {
+              if (/\$focus/.test(id)) {
+                MKEmitter.emit('reloadData', id.split('$')[0], id.split('$')[1])
+              } else {
+                MKEmitter.emit('reloadData', id)
+              }
+            }, 20 * i)
+          })
+        } else if (/\$focus/.test(btn.syncComponentId)) {
+          MKEmitter.emit('reloadData', btn.syncComponentId.split('$')[0], btn.syncComponentId.split('$')[1])
+        } else {
+          MKEmitter.emit('reloadData', btn.syncComponentId)
+        }
+      }
+
+      if (tabId) {
+        MKEmitter.emit('reloadMenuView', tabId)
+      }
     }
 
     if (btn.execError === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
diff --git a/src/tabviews/zshare/actionList/funcbutton/index.jsx b/src/tabviews/zshare/actionList/funcbutton/index.jsx
index cf887d2..43430ed 100644
--- a/src/tabviews/zshare/actionList/funcbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/funcbutton/index.jsx
@@ -2,9 +2,11 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Button, notification, message, Modal } from 'antd'
+import moment from 'moment'
 import md5 from 'md5'
 
 import Api from '@/api'
+import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 
@@ -23,6 +25,7 @@
     loading: false,
     disabled: false,
     hidden: false,
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -102,7 +105,7 @@
    */
   actionTrigger = (triggerId, record, type, lid) => {
     const { btn, BID, selectedData, LID } = this.props
-    const { loading } = this.state
+    const { loading, dict } = this.state
 
     if (loading) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -112,14 +115,14 @@
     let error = ''
 
     if (btn.funcType === 'shareLink' && window.GLOB.systemType === 'production' && !btn.shareProUrl) {
-      error = '灏氭湭璁剧疆姝e紡绯荤粺閾炬帴鍦板潃锛�'
+      error = dict['no_prod_link'] || '灏氭湭璁剧疆姝e紡绯荤粺閾炬帴鍦板潃锛�'
     } else if (btn.funcType === 'refund') {
       if (data.length === 0) {
-        error = '璇烽�夋嫨琛岋紒'
+        error = dict['select_row'] || '璇烽�夋嫨琛岋紒'
       } else if (data.length !== 1) {
-        error = '璇烽�夋嫨鍗曡鏁版嵁锛�'
+        error = dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�'
       } else if (!data[0].$$uuid) {
-        error = '鏈幏鍙栧埌璁㈠崟缂栧彿锛�'
+        error = dict['no_ordercode'] || '鏈幏鍙栧埌璁㈠崟缂栧彿锛�'
       }
     }
 
@@ -160,23 +163,276 @@
       const that = this
 
       confirm({
-        title: btn.tipTitle || '纭畾瑕佹墽琛屽悧?',
+        title: btn.tipTitle || dict['exec_sure'] || '纭畾瑕佹墽琛屽悧?',
+        okText: dict['ok'] || '纭畾',
+        cancelText: dict['cancel'] || '鍙栨秷',
         onOk() {
-          that.execRefund(orderId)
+          that.execRefund(orderId, data[0])
         },
         onCancel() {}
       })
     }
   }
 
-  execRefund = (orderId) => {
-    Api.setRefund(orderId).then(res => {
-      if (!res.status) {
-        this.execError({ErrCode: 'E', message: '鎵ц澶辫触锛�', ...res})
-      } else {
-        this.execSuccess({ErrCode: 'S', ...res})
+  execRefund = (orderId, data) => {
+    const { btn, BID } = this.props
+
+    let param = null
+    if (btn.payMode === 'inner') {
+      param = {
+        func: btn.innerFunc || '',
+        BID: BID || '',
+        username: sessionStorage.getItem('User_Name') || '',
+        fullname: sessionStorage.getItem('Full_Name') || '',
+        dataM: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        ID: orderId
+      }
+    } else if (window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
+      param = this.getbackParam(orderId, data)
+    } else if (btn.payMode === 'system') {
+      let sql = this.getSysDeclareSql(orderId, data)
+
+      param = {
+        func: 'sPC_TableData_InUpDe',
+        BID: BID || '',
+        exec_type: window.GLOB.execType || 'y',
+        timestamp: moment().format('YYYY-MM-DD HH:mm:ss')
+      }
+
+      param.secretkey = Utils.encrypt('', param.timestamp)
+      param.LText = Utils.formatOptions(sql, param.exec_type)
+
+      if (btn.output) {
+        param.key_back_type = 'Y'
+      }
+
+      if (window.GLOB.mkHS) { // 鍑芥暟 sPC_TableData_InUpDe 浜戠楠岃瘉
+        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+      }
+
+      param.menuname = btn.logLabel
+
+      if (window.GLOB.probation) {
+        param.s_debug_type = 'Y'
+      }
+    }
+
+    this.setState({loading: true})
+
+    if (param) {
+      Api.genericInterface(param).then(res => {
+        if (res.status) {
+          let id = orderId
+          if (btn.output) {
+            id = res.mk_b_id || res[btn.output] || orderId
+          }
+
+          Api.setRefund({out_biz_no: id}).then(res => {
+            if (!res.status) {
+              this.execError({ErrCode: 'E', message: res.message || window.GLOB.dict['exc_fail'] || '鎵ц澶辫触锛�', ...res})
+            } else {
+              this.execSuccess({ErrCode: 'S', ...res})
+            }
+          })
+        } else {
+          this.execError(res)
+        }
+      })
+    } else {
+      Api.setRefund({out_biz_no: orderId}).then(res => {
+        if (!res.status) {
+          this.execError({ErrCode: 'E', message: res.message || window.GLOB.dict['exc_fail'] || '鎵ц澶辫触锛�', ...res})
+        } else {
+          this.execSuccess({ErrCode: 'S', ...res})
+        }
+      })
+    }
+  }
+
+  getbackParam = (ID, data) => {
+    const { columns, btn, BID } = this.props
+
+    let ex = window.GLOB.CacheData.get('sql_' + btn.uuid)
+    let exps = []
+    let values = {
+      time_id: Utils.getguid(),
+      roleid: sessionStorage.getItem('role_id') || '',
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      mk_nation: sessionStorage.getItem('nation') || '',
+      mk_province: sessionStorage.getItem('province') || '',
+      mk_city: sessionStorage.getItem('city') || '',
+      mk_district: sessionStorage.getItem('district') || '',
+      mk_address: sessionStorage.getItem('address') || '',
+      id: ID || '',
+      bid: BID || '',
+      typename: 'admin',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    }
+  
+    if (window.GLOB.externalDatabase !== null) {
+      values.db = window.GLOB.externalDatabase
+    }
+
+    ex.reps.forEach(n => {
+      let key = n.toLowerCase()
+      if (values.hasOwnProperty(key)) {
+        exps.push({
+          key: n,
+          value: values[key]
+        })
       }
     })
+
+    let _data = {}
+    Object.keys(data).forEach(key => {
+      _data[key.toLowerCase()] = data[key]
+    })
+  
+    columns.forEach(col => {
+      if (!ex.reps.includes(col.field)) return
+      if (!col.datatype) return
+
+      let _key = col.field.toLowerCase()
+      let _val = _data.hasOwnProperty(_key) ? _data[_key] : ''
+
+      if (/^date/ig.test(col.datatype) && !_val) {
+        _val = '1949-10-01'
+      }
+
+      exps.push({
+        key: 'mk_' + col.field + '_mk',
+        value: _val
+      })
+    })
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    return {
+      $backend: true,
+      $type: 's_TableData_InUpDe',
+      data: [{
+        id: ex.id,
+        menuname: btn.logLabel || '',
+        exps: exps,
+        md5_id: md5_id
+      }]
+    }
+  }
+
+  getSysDeclareSql = (ID, data) => {
+    const { columns, btn, BID } = this.props
+
+    // 绯荤粺鍙橀噺
+    let _vars = ['tbid', 'errorcode', 'retmsg', 'username', 'fullname', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
+    let _declare = []
+    let _initVal = []
+  
+    let _data = {}
+    Object.keys(data).forEach(key => {
+      _data[key.toLowerCase()] = data[key]
+    })
+  
+    columns.forEach(col => {
+      let _key = col.field.toLowerCase()
+
+      if (_vars.includes(_key)) return
+
+      _declare.push(`@${_key} ${col.datatype}`)
+
+      let _val = _data.hasOwnProperty(_key) ? _data[_key] : ''
+
+      if (/^date/ig.test(col.datatype) && !_val) {
+        _val = '1949-10-01'
+      }
+
+      if (/'/.test(_val)) {
+        _val = _val.replace(/'/ig, '"')
+      }
+
+      _initVal.push(`@${_key}='${_val}'`)
+    })
+  
+    // 鍙橀噺澹版槑
+    _declare = _declare.join(',')
+    if (_declare) {
+      _declare = ',' + _declare
+    }
+
+    let _sql = `/* 绯荤粺鐢熸垚 */
+      Declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000), @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@bid nvarchar(50),@tbid nvarchar(50)${_declare}
+    `
+  
+    let userName = sessionStorage.getItem('User_Name') || ''
+    let fullName = sessionStorage.getItem('Full_Name') || ''
+    let RoleID = sessionStorage.getItem('role_id') || ''
+    let departmentcode = sessionStorage.getItem('departmentcode') || ''
+    let organization = sessionStorage.getItem('organization') || ''
+    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
+    let nation = sessionStorage.getItem('nation') || ''
+    let province = sessionStorage.getItem('province') || ''
+    let city = sessionStorage.getItem('city') || ''
+    let district = sessionStorage.getItem('district') || ''
+    let address = sessionStorage.getItem('address') || ''
+  
+    // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
+    _sql += `
+      /* 鐢ㄦ埛淇℃伅鍒濆鍖栬祴鍊� */
+      select @ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @bid='${BID}'
+    `
+    _sql += `
+      /* 鏄剧ず鍒楀彉閲忚祴鍊� */
+      select ${_initVal.join(',')}
+    `
+
+    btn.verify.scripts.forEach(item => {
+      if (item.status === 'false') return
+
+      _sql += `
+      ${item.sql}
+      `
+    })
+
+    if (btn.output) {
+      _sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
+    } else {
+      _sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    }
+
+    _sql = _sql.replace(/@ID@/ig, `'${ID || ''}'`)
+    _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
+    _sql = _sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
+    _sql = _sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
+    _sql = _sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
+    _sql = _sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+    _sql = _sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
+    _sql = _sql.replace(/@typename@/ig, `'admin'`)
+
+    if (window.GLOB.externalDatabase !== null) {
+      _sql = _sql.replace(/@db@/ig, window.GLOB.externalDatabase)
+    }
+
+    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+      _sql = _sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
+    } else {
+      _sql = _sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
+    }
+
+    if (window.GLOB.debugger === true) {
+      window.mkInfo('%c' + btn.logLabel, 'color: blue')
+      window.mkInfo(_sql)
+    }
+
+    return _sql
   }
 
   getShortUrl = (url) => {
@@ -243,22 +499,24 @@
         title: btn.shareTip
       })
     } else {
-      message.success('宸插鍒跺埌鍓垏鏉裤��')
+      message.success(window.GLOB.dict['copied'] || '宸插鍒跺埌鍓垏鏉裤��')
     }
   }
 
   execSuccess = (res = {}) => {
     const { btn } = this.props
+    const { dict } = this.state
 
     if (res.ErrCode === 'S' || !res.ErrCode) { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.message || '鎵ц鎴愬姛锛�',
+        message: res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�',
         duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
       })
     } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.message || '鎵ц鎴愬姛锛�'
+        title: res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
@@ -275,6 +533,7 @@
 
   execError = (res) => {
     const { btn } = this.props
+    const { dict } = this.state
 
     if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
       res.ErrCode = 'E'
@@ -282,23 +541,24 @@
 
     if (res.ErrCode === 'E') {
       Modal.error({
-        title: res.message || '鎵ц澶辫触锛�',
+        title: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || '鎵ц澶辫触锛�')
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     }
     
     this.setState({
diff --git a/src/tabviews/zshare/actionList/funczip/index.jsx b/src/tabviews/zshare/actionList/funczip/index.jsx
index 5181920..9bee41a 100644
--- a/src/tabviews/zshare/actionList/funczip/index.jsx
+++ b/src/tabviews/zshare/actionList/funczip/index.jsx
@@ -22,6 +22,7 @@
     loading: false,
     disabled: false,
     hidden: false,
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -101,7 +102,7 @@
    */
   actionTrigger = (triggerId, record, type, lid) => {
     const { BID, btn, selectedData, setting, LID } = this.props
-    const { loading, disabled } = this.state
+    const { loading, disabled, dict } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -112,21 +113,21 @@
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
+        message: dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
       return
     } else if (btn.Ot !== 'notRequired' && data.length === 0) {
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨琛岋紒',
+        message: dict['select_row'] || '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return
     } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -351,43 +352,47 @@
    */
   execError = (res) => {
     const { btn } = this.props
+    const { dict } = this.state
 
     this.setState({
       loading: false
     })
 
     if (res.ErrCode === '01') {
-      message.error('鏈幏鍙栧埌涓嬭浇鏂囦欢銆�')
+      message.error(dict['exc_fail'] || '鏈幏鍙栧埌涓嬭浇鏂囦欢銆�')
       return
     } else if (res.ErrCode === '02') {
       Modal.error({
-        title: '閮ㄥ垎鏂囦欢涓嬭浇澶辫触锛�1銆佽妫�鏌ユ枃浠惰矾寰勬槸鍚︽纭紝2銆佽妫�鏌ユ枃浠舵槸鍚﹁法鍩熴��',
+        title: dict['exc_fail'] || '閮ㄥ垎鏂囦欢涓嬭浇澶辫触锛�1銆佽妫�鏌ユ枃浠惰矾寰勬槸鍚︽纭紝2銆佽妫�鏌ユ枃浠舵槸鍚﹁法鍩熴��',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
       return
     } else if (res.ErrCode === '03') {
       Modal.error({
-        title: '鏂囦欢涓嬭浇澶辫触锛�1銆佽妫�鏌ユ枃浠惰矾寰勬槸鍚︽纭紝2銆佽妫�鏌ユ枃浠舵槸鍚﹁法鍩熴��',
+        title: dict['exc_fail'] || '鏂囦欢涓嬭浇澶辫触锛�1銆佽妫�鏌ユ枃浠惰矾寰勬槸鍚︽纭紝2銆佽妫�鏌ユ枃浠舵槸鍚﹁法鍩熴��',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
       return
     } else if (res.ErrCode === 'E') {
       Modal.error({
-        title: res.message || '鎵ц澶辫触锛�',
+        title: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || '鎵ц澶辫触锛�')
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     }
 
     if (btn.execError !== 'never') {
diff --git a/src/tabviews/zshare/actionList/index.jsx b/src/tabviews/zshare/actionList/index.jsx
index 8e213d8..c0945f5 100644
--- a/src/tabviews/zshare/actionList/index.jsx
+++ b/src/tabviews/zshare/actionList/index.jsx
@@ -134,6 +134,7 @@
             BID={BID}
             btn={item}
             BData={BData}
+            columns={columns}
             selectedData={selectedData}
           />
         )
@@ -205,18 +206,19 @@
             btn={item}
             selectedData={selectedData}
             />
-            )
-          }
+          )
         } else {
           return (
             <FuncButton
               key={item.uuid}
               BID={BID}
               btn={item}
+              columns={columns}
               selectedData={selectedData}
             />
           )
         }
+      }
       return null
     })
   }
@@ -231,7 +233,7 @@
           <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>
+              <div className="mk-button-more">{window.GLOB.dict['more'] || '鏇村'}<DownOutlined/></div>
             </Dropdown> : null}
           </div>
         </Affix>
@@ -241,7 +243,7 @@
         <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>
+            <div className="mk-button-more">{window.GLOB.dict['more'] || '鏇村'}<DownOutlined/></div>
           </Dropdown> : null}
         </div>
       )
diff --git a/src/tabviews/zshare/actionList/index.scss b/src/tabviews/zshare/actionList/index.scss
index 700f589..3419db2 100644
--- a/src/tabviews/zshare/actionList/index.scss
+++ b/src/tabviews/zshare/actionList/index.scss
@@ -16,6 +16,9 @@
     width: auto;
     padding: 0 15px;
   }
+  .ant-btn.ant-btn-link {
+    border-color: #d9d9d9;
+  }
 
   .ant-btn.mk-btn-hover-bg:not([disabled]):hover {
     opacity: 1!important;
diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
index 5a78f3e..6721fb5 100644
--- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx
+++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -1,8 +1,12 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Button, notification, Modal } from 'antd'
+import { Button, notification, Modal, message } from 'antd'
+import moment from 'moment'
+import md5 from 'md5'
 
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 import './index.scss'
@@ -21,8 +25,10 @@
 
   state = {
     disabled: false,
+    loading: false,
     hidden: false,
-    visible: false
+    visible: false,
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -102,7 +108,7 @@
    */
   actionTrigger = (triggerId, record, type, lid) => {
     const { btn, selectedData, BID, LID } = this.props
-    const { disabled } = this.state
+    const { disabled, dict } = this.state
 
     if (disabled) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -114,7 +120,7 @@
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨琛岋紒',
+        message: dict['select_row'] || '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return
@@ -122,14 +128,14 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
     } else if (btn.pageTemplate === 'custom' && window.GLOB.systemType === 'production' && !btn.proUrl) {
       notification.warning({
         top: 92,
-        message: '灏氭湭璁剧疆姝e紡绯荤粺閾炬帴鍦板潃锛�',
+        message: dict['no_prod_link'] || '灏氭湭璁剧疆姝e紡绯荤粺閾炬帴鍦板潃锛�',
         duration: 5
       })
       return
@@ -145,18 +151,15 @@
     let Id = ''
     let name = ''
     let MenuNo = ''
-    let Remark = ''
+    let lang = ''
     if (btn.Ot === 'requiredSgl' && data[0]) {
       Id = data[0].$$uuid || ''
       name = data[0].PrintTempName || ''
       MenuNo = data[0].PrintTempNO || ''
-      Remark = data[0].Remark || ''
+      lang = data[0].lang_s || ''
     }
 
-    let _name = '鏂伴〉闈�'
-
     if (btn.pageTemplate === 'billprint') {
-      _name = '鍗曟嵁鎵撳嵃'
       if (btn.preHandle === 'true' && btn.pre_func) {
         MKEmitter.emit('queryModuleParam', btn.$menuId, (res) => {
           let searches = {}
@@ -215,46 +218,104 @@
       } else {
         if (btn.Ot === 'required') {
           data.forEach(item => {
-            let _id = item.$$uuid || ''
-            let url = '#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: _id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') })))
+            let _param = { id: item.$$uuid || '', tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
+
+            Object.keys(item).forEach(key => {
+              if (/^\$/.test(key)) return
+              if (typeof(item[key]) !== 'string' && typeof(item[key]) !== 'number') return
+              if (typeof(item[key]) === 'string' && item[key].length > 50) return
+              if (['id', 'tempid', 'pageid', 'datam'].includes(key.toLowerCase())) return
+
+              _param[key.toLowerCase()] = item[key]
+            })
+
+            let url = '#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
             window.open(url)
           })
         } else if (btn.Ot === 'requiredOnce') {
           Id = data.map(item => item.$$uuid).filter(Boolean).join(',')
+          let _param = { id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
+          let item = data[0]
+
+          Object.keys(item).forEach(key => {
+            if (/^\$/.test(key)) return
+            if (typeof(item[key]) !== 'string' && typeof(item[key]) !== 'number') return
+            if (typeof(item[key]) === 'string' && item[key].length > 50) return
+            if (['id', 'tempid', 'pageid', 'datam'].includes(key.toLowerCase())) return
+
+            _param[key.toLowerCase()] = item[key]
+          })
   
-          window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
+          window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify(_param))))
         } else {
-          window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
+          let _param = { id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
+          let item = data[0]
+
+          Object.keys(item).forEach(key => {
+            if (/^\$/.test(key)) return
+            if (typeof(item[key]) !== 'string' && typeof(item[key]) !== 'number') return
+            if (typeof(item[key]) === 'string' && item[key].length > 50) return
+            if (['id', 'tempid', 'pageid', 'datam'].includes(key.toLowerCase())) return
+
+            _param[key.toLowerCase()] = item[key]
+          })
+
+          window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify(_param))))
         }
       }
     } else if (btn.pageTemplate === 'billprintTemp') {
-      let src = '#/menudesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'billPrint', MenuId: Id, MenuNo: MenuNo, MenuName: name || '鎵撳嵃', Remark: Remark })))
+      let src = '#/menudesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'billPrint', MenuId: Id, MenuNo: MenuNo, MenuName: name || '鎵撳嵃', lang })))
       window.open(src)
     } else if (btn.pageTemplate === 'print') {
-      let cloudmsg = '&cuid=' + (sessionStorage.getItem('CloudUserID') || '') + '&clid=' + (sessionStorage.getItem('CloudLoginUID') || '') + '&cun=' + (sessionStorage.getItem('CloudUserName') || '')
-      let msg = '&uid=' + sessionStorage.getItem('UserID') + '&lid=' + sessionStorage.getItem('LoginUID') + '&un=' + sessionStorage.getItem('User_Name')
-      let src = '#/print/' + window.btoa('ID=' + Id + msg + cloudmsg)
+      let src = '#/print/' + window.btoa(window.encodeURIComponent(JSON.stringify({ ID: Id, lang })))
       window.open(src)
     } else if (btn.pageTemplate === 'pay') {
-      let _p = `ID=${Id}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID')}&logo=${window.GLOB.doclogo}&name=${sessionStorage.getItem('Full_Name')}&icp=${window.GLOB.ICP}&copyRight=${window.GLOB.copyRight}`
-      let url = '#/pay/' +  window.btoa(window.encodeURIComponent(_p))
-      _name = '鏀粯'
-      
-      confirm({
-        title: '璇峰湪浠樻椤甸潰瀹屾垚璁㈠崟鏀粯銆�',
-        content: '',
-        className: 'pay-query',
-        okText: '鏀粯鎴愬姛',
-        cancelText: '鏀粯閬囧埌闂',
-        onOk() {
-          // 鏀粯鍚庡埛鏂扮晫闈�
-          MKEmitter.emit('reloadMenuView', btn.$MenuID)
-        },
-        onCancel() {
-          MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
-        },
-      })
-      window.open(url)
+      let appId = ''
+      let merchId = ''
+
+      if (btn.wxApp) {
+        appId = btn.wxApp
+        if (!window.GLOB.WXApps || window.GLOB.WXApps.findIndex(item => item.appId === btn.wxApp) === -1) {
+          notification.warning({
+            top: 92,
+            message: '鎸夐挳鍏宠仈搴旂敤涓嶅湪鍙敤鍒楄〃涓紝璇烽噸鏂颁繚瀛樻寜閽厤缃紒',
+            duration: 5
+          })
+          return
+        }
+      }
+      if (btn.wxMerch) {
+        merchId = btn.wxMerch
+        if (!window.GLOB.WXApps || window.GLOB.WXApps.findIndex(item => item.appId === btn.wxMerch) === -1) {
+          notification.warning({
+            top: 92,
+            message: '鎸夐挳鍏宠仈鍟嗘埛涓嶅湪鍙敤鍒楄〃涓紝璇烽噸鏂颁繚瀛樻寜閽厤缃紒',
+            duration: 5
+          })
+          return
+        }
+      }
+
+      if (btn.payMode === 'system' || btn.payMode === 'inner') {
+        this.prequest(Id, data[0] || {}, appId, merchId)
+      } else {
+        confirm({
+          title: '璇峰湪浠樻椤甸潰瀹屾垚璁㈠崟鏀粯銆�',
+          content: '',
+          className: 'pay-query',
+          okText: '鏀粯鎴愬姛',
+          cancelText: '鏀粯閬囧埌闂',
+          onOk() {
+            // 鏀粯鍚庡埛鏂扮晫闈�
+            MKEmitter.emit('reloadMenuView', btn.$MenuID)
+          },
+          onCancel() {
+            MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
+          },
+        })
+
+        window.open('#/pay/' + window.btoa(window.encodeURIComponent(JSON.stringify({ ID: Id, appId, merchId }))))
+      }
     } else if (btn.pageTemplate === 'custom') {
       let url = btn.url
       if (window.GLOB.systemType === 'production') {
@@ -306,14 +367,305 @@
       window.open(url)
     }
 
-    if (window.GLOB.systemType === 'production') {
-      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: _name})
+    if (window.GLOB.systemType === 'production') { // positecgroup
+      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: btn.label})
+    }
+  }
+
+  prequest = (ID, data, appId, merchId) => {
+    const { btn, BID } = this.props
+
+    let param = null
+    if (btn.payMode === 'inner') {
+      param = {
+        func: btn.innerFunc || '',
+        BID: BID || '',
+        username: sessionStorage.getItem('User_Name') || '',
+        fullname: sessionStorage.getItem('Full_Name') || '',
+        dataM: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        ID: ID
+      }
+    } else if (window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
+      param = this.getbackParam(ID, data)
+    } else {
+      let sql = this.getSysDeclareSql(ID, data)
+
+      param = {
+        func: 'sPC_TableData_InUpDe',
+        BID: BID || '',
+        exec_type: window.GLOB.execType || 'y',
+        timestamp: moment().format('YYYY-MM-DD HH:mm:ss')
+      }
+
+      param.secretkey = Utils.encrypt('', param.timestamp)
+      param.LText = Utils.formatOptions(sql, param.exec_type)
+
+      if (btn.output) {
+        param.key_back_type = 'Y'
+      }
+
+      if (window.GLOB.mkHS) { // 鍑芥暟 sPC_TableData_InUpDe 浜戠楠岃瘉
+        param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+      }
+
+      param.menuname = btn.logLabel
+
+      if (window.GLOB.probation) {
+        param.s_debug_type = 'Y'
+      }
+    }
+
+    this.setState({loading: true})
+    Api.genericInterface(param).then(res => {
+      this.setState({loading: false})
+      if (res.status) {
+        let id = ID
+        if (btn.output) {
+          id = res.mk_b_id || res[btn.output] || ID
+        }
+
+        confirm({
+          title: '璇峰湪浠樻椤甸潰瀹屾垚璁㈠崟鏀粯銆�',
+          content: '',
+          className: 'pay-query',
+          okText: '鏀粯鎴愬姛',
+          cancelText: '鏀粯閬囧埌闂',
+          onOk() {
+            // 鏀粯鍚庡埛鏂扮晫闈�
+            MKEmitter.emit('reloadMenuView', btn.$MenuID)
+          },
+          onCancel() {
+            MKEmitter.emit('refreshByButtonResult', btn.$menuId, 'grid', btn)
+          },
+        })
+
+        window.open('#/pay/' + window.btoa(window.encodeURIComponent(JSON.stringify({ ID: id, appId, merchId }))))
+      } else {
+        this.execError(res)
+      }
+    })
+  }
+
+  getbackParam = (ID, data) => {
+    const { columns, btn, BID } = this.props
+
+    let ex = window.GLOB.CacheData.get('sql_' + btn.uuid)
+    let exps = []
+    let values = {
+      time_id: Utils.getguid(),
+      roleid: sessionStorage.getItem('role_id') || '',
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      mk_nation: sessionStorage.getItem('nation') || '',
+      mk_province: sessionStorage.getItem('province') || '',
+      mk_city: sessionStorage.getItem('city') || '',
+      mk_district: sessionStorage.getItem('district') || '',
+      mk_address: sessionStorage.getItem('address') || '',
+      id: ID || '',
+      bid: BID || '',
+      typename: 'admin',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    }
+  
+    if (window.GLOB.externalDatabase !== null) {
+      values.db = window.GLOB.externalDatabase
+    }
+
+    ex.reps.forEach(n => {
+      let key = n.toLowerCase()
+      if (values.hasOwnProperty(key)) {
+        exps.push({
+          key: n,
+          value: values[key]
+        })
+      }
+    })
+
+    let _data = {}
+    Object.keys(data).forEach(key => {
+      _data[key.toLowerCase()] = data[key]
+    })
+  
+    columns.forEach(col => {
+      if (!ex.reps.includes(col.field)) return
+      if (!col.datatype) return
+
+      let _key = col.field.toLowerCase()
+      let _val = _data.hasOwnProperty(_key) ? _data[_key] : ''
+
+      if (/^date/ig.test(col.datatype) && !_val) {
+        _val = '1949-10-01'
+      }
+
+      exps.push({
+        key: 'mk_' + col.field + '_mk',
+        value: _val
+      })
+    })
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    return {
+      $backend: true,
+      $type: 's_TableData_InUpDe',
+      data: [{
+        id: ex.id,
+        menuname: btn.logLabel || '',
+        exps: exps,
+        md5_id: md5_id
+      }]
+    }
+  }
+
+  getSysDeclareSql = (ID, data) => {
+    const { columns, btn, BID } = this.props
+
+    // 绯荤粺鍙橀噺
+    let _vars = ['tbid', 'errorcode', 'retmsg', 'username', 'fullname', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
+    let _declare = []
+    let _initVal = []
+  
+    let _data = {}
+    Object.keys(data).forEach(key => {
+      _data[key.toLowerCase()] = data[key]
+    })
+  
+    columns.forEach(col => {
+      let _key = col.field.toLowerCase()
+
+      if (_vars.includes(_key)) return
+
+      _declare.push(`@${_key} ${col.datatype}`)
+
+      let _val = _data.hasOwnProperty(_key) ? _data[_key] : ''
+
+      if (/^date/ig.test(col.datatype) && !_val) {
+        _val = '1949-10-01'
+      }
+
+      if (/'/.test(_val)) {
+        _val = _val.replace(/'/ig, '"')
+      }
+
+      _initVal.push(`@${_key}='${_val}'`)
+    })
+  
+    // 鍙橀噺澹版槑
+    _declare = _declare.join(',')
+    if (_declare) {
+      _declare = ',' + _declare
+    }
+
+    let _sql = `/* 绯荤粺鐢熸垚 */
+      Declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000), @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@bid nvarchar(50),@tbid nvarchar(50)${_declare}
+    `
+  
+    let userName = sessionStorage.getItem('User_Name') || ''
+    let fullName = sessionStorage.getItem('Full_Name') || ''
+    let RoleID = sessionStorage.getItem('role_id') || ''
+    let departmentcode = sessionStorage.getItem('departmentcode') || ''
+    let organization = sessionStorage.getItem('organization') || ''
+    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
+    let nation = sessionStorage.getItem('nation') || ''
+    let province = sessionStorage.getItem('province') || ''
+    let city = sessionStorage.getItem('city') || ''
+    let district = sessionStorage.getItem('district') || ''
+    let address = sessionStorage.getItem('address') || ''
+  
+    // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
+    _sql += `
+      /* 鐢ㄦ埛淇℃伅鍒濆鍖栬祴鍊� */
+      select @ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @bid='${BID}'
+    `
+    _sql += `
+      /* 鏄剧ず鍒楀彉閲忚祴鍊� */
+      select ${_initVal.join(',')}
+    `
+
+    btn.verify.scripts.forEach(item => {
+      if (item.status === 'false') return
+
+      _sql += `
+      ${item.sql}
+      `
+    })
+
+    if (btn.output) {
+      _sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
+    } else {
+      _sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    }
+
+    _sql = _sql.replace(/@ID@/ig, `'${ID || ''}'`)
+    _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
+    _sql = _sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
+    _sql = _sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
+    _sql = _sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
+    _sql = _sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+    _sql = _sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
+    _sql = _sql.replace(/@typename@/ig, `'admin'`)
+
+    if (window.GLOB.externalDatabase !== null) {
+      _sql = _sql.replace(/@db@/ig, window.GLOB.externalDatabase)
+    }
+
+    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+      _sql = _sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
+    } else {
+      _sql = _sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
+    }
+
+    if (window.GLOB.debugger === true) {
+      window.mkInfo('%c' + btn.logLabel, 'color: blue')
+      window.mkInfo(_sql)
+    }
+
+    return _sql
+  }
+
+  execError = (res) => {
+    const { btn } = this.props
+    const { dict } = this.state
+
+    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
+      res.ErrCode = 'E'
+    }
+
+    if (res.ErrCode === 'E') {
+      Modal.error({
+        title: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
+      })
+    } else if (res.ErrCode === 'N') {
+      notification.error({
+        top: 92,
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
+      })
+    } else if (res.ErrCode === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
+      })
+    } else if (res.ErrCode === 'NM') {
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     }
   }
 
   render() {
     const { btn, name } = this.props
-    const { disabled, hidden } = this.state
+    const { disabled, hidden, loading } = this.state
 
     if (hidden) return null
 
@@ -333,6 +685,7 @@
         id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         style={btn.style || null}
+        loading={loading}
         disabled={disabled}
         className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index bcf9a4f..ed8e372 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -44,10 +44,10 @@
     hidden: false,
     autoMatic: false,
     check: false,
-    count: 0
+    count: 0,
+    dict: window.GLOB.dict
   }
 
-  moduleParams = null
   preCallback = null
 
   UNSAFE_componentWillMount () {
@@ -206,7 +206,7 @@
    */
   actionTrigger = (triggerId, record, type, lid, callback) => {
     const { btn, selectedData, LID } = this.props
-    const { loading, disabled } = this.state
+    const { loading, disabled, dict } = this.state
 
     if (type === 'preButton') {
       if (btn.uuid !== triggerId) return
@@ -224,7 +224,7 @@
 
     this.setState({autoMatic: type === 'autoMatic'})
 
-    let _this = this
+    let that = this
     let data = record || selectedData || []
 
     let valid = this.checkBtnData(data)
@@ -242,14 +242,16 @@
     } else if (btn.OpenType === 'prompt') {
       this.setState({loading: true})
       confirm({
-        title: btn.tipTitle || '纭畾瑕佹墽琛屽悧?',
+        title: btn.tipTitle || dict['exec_sure'] || '纭畾瑕佹墽琛屽悧?',
+        okText: dict['ok'] || '纭畾',
+        cancelText: dict['cancel'] || '鍙栨秷',
         onOk() {
           return new Promise(resolve => {
-            _this.execSubmit(data, resolve)
+            that.execSubmit(data, resolve)
           })
         },
         onCancel() {
-          _this.setState({loading: false})
+          that.setState({loading: false})
         }
       })
     } else if (btn.OpenType === 'exec') {
@@ -305,7 +307,7 @@
       }
     }
 
-    if (window.GLOB.systemType === 'production') {
+    if (window.GLOB.systemType === 'production') { // positecgroup
       let _change = {
         prompt: '鎻愮ず妗�',
         exec: '鐩存帴鎵ц',
@@ -319,7 +321,7 @@
 
   preTrigger = (callback) => {
     const { btn, selectedData } = this.props
-    const { loading, disabled } = this.state
+    const { loading, disabled, dict } = this.state
 
     if (loading || disabled) {
       callback()
@@ -329,7 +331,7 @@
       return
     }
 
-    let _this = this
+    let that = this
     let data = selectedData || []
 
     let valid = this.checkBtnData(data)
@@ -352,15 +354,17 @@
     } else if (btn.OpenType === 'prompt') {
       this.setState({loading: true})
       confirm({
-        title: btn.tipTitle || '纭畾瑕佹墽琛屽悧?',
+        title: btn.tipTitle || dict['exec_sure'] || '纭畾瑕佹墽琛屽悧?',
+        okText: dict['ok'] || '纭畾',
+        cancelText: dict['cancel'] || '鍙栨秷',
         onOk() {
           return new Promise(resolve => {
-            _this.execSubmit(data, resolve)
+            that.execSubmit(data, resolve)
           })
         },
         onCancel() {
           callback()
-          _this.setState({loading: false})
+          that.setState({loading: false})
         }
       })
     } else if (btn.OpenType === 'exec') {
@@ -402,11 +406,12 @@
 
   checkBtnData = (data) => {
     const { BID, btn, setting } = this.props
+    const { dict } = this.state
 
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
+        message: dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
       return false
@@ -414,7 +419,7 @@
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨琛岋紒',
+        message: dict['select_row'] || '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return false
@@ -422,42 +427,17 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return false
-    } else if (btn.intertype === 'system') {
-      if (data.length === 0 && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤鍒涘缓鍑瘉鍑芥暟锛岄渶瑕侀�夋嫨琛岋紒',
-          duration: 5
-        })
-        return false
-      }
-    } else if (btn.intertype === 'custom' || btn.intertype === 'outer') {
-      if (btn.callbackType === 'script' && (!btn.verify || !btn.verify.cbScripts || !btn.verify.cbScripts.filter(item => item.status !== 'false').length === 0)) {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤鑷畾涔夎剼鏈洖璋冩椂锛屽洖璋冭剼鏈笉鍙负绌猴紒',
-          duration: 5
-        })
-        return false
-      } else if (btn.procMode === 'system' && data.length === 0 && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤鍒涘缓鍑瘉鍑芥暟锛岄渶瑕侀�夋嫨琛岋紒',
-          duration: 5
-        })
-        return false
-      } else if (btn.intertype === 'custom' && window.GLOB.systemType === 'production' && !btn.proInterface) {
-        notification.warning({
-          top: 92,
-          message: '灏氭湭璁剧疆姝e紡绯荤粺鎺ュ彛鍦板潃锛�',
-          duration: 5
-        })
-        return false
-      }
+    } else if (btn.intertype === 'custom' && window.GLOB.systemType === 'production' && !btn.proInterface) {
+      notification.warning({
+        top: 92,
+        message: dict['no_prod_link'] || '灏氭湭璁剧疆姝e紡绯荤粺鎺ュ彛鍦板潃锛�',
+        duration: 5
+      })
+      return false
     }
 
     return true
@@ -478,8 +458,8 @@
       
       let primaryId = ''
 
-      if ((btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') && setting.primaryKey) {
-        let ids = data.map(d => { return d[setting.primaryKey] || ''})
+      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
+        let ids = data.map(d => d.$$uuid)
         ids = ids.filter(Boolean)
         primaryId = ids.join(',')
       }
@@ -488,11 +468,11 @@
         param.ID = primaryId
 
         if (retmsg) {
-          const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, retmsg, this.moduleParams) // 鏁版嵁婧�
+          const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, retmsg) // 鏁版嵁婧�
           param.LText = sql
           param.$callbacksql = callbacksql
         } else {
-          param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, false, this.moduleParams) // 鏁版嵁婧�
+          param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, false) // 鏁版嵁婧�
           if (btn.output) {
             param.key_back_type = 'Y'
           }
@@ -512,23 +492,14 @@
         param.LText = Utils.formatOptions(param.LText, param.exec_type)
       } else if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit' || btn.OpenType === 'form') { // 琛ㄥ崟
         if (btn.sqlType === 'insert') { // 绯荤粺鍑芥暟娣诲姞鏃讹紝鐢熸垚uuid
-          primaryId = ''
-
-          if (formdata && setting.primaryKey) { // 琛ㄥ崟涓瓨鍦ㄤ富閿瓧娈碉紝涓婚敭鍊间互琛ㄥ崟涓殑鍊间负鍑�
-            let _form = formdata.filter(_form => _form.key === setting.primaryKey)[0]
-            if (_form) {
-              primaryId = _form.value
-            }
-          }
-
-          param.ID = primaryId || Utils.getguid()
+          param.ID = Utils.getguid()
 
           if (retmsg) {
-            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg, this.moduleParams) // 鏁版嵁婧�
+            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg) // 鏁版嵁婧�
             param.LText = sql
             param.$callbacksql = callbacksql
           } else {
-            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false, this.moduleParams) // 鏁版嵁婧�
+            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false) // 鏁版嵁婧�
             if (btn.output) {
               param.key_back_type = 'Y'
             }
@@ -550,11 +521,11 @@
           param.ID = primaryId
 
           if (retmsg) {
-            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg, this.moduleParams) // 鏁版嵁婧�
+            const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, retmsg) // 鏁版嵁婧�
             param.LText = sql
             param.$callbacksql = callbacksql
           } else {
-            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false, this.moduleParams) // 鏁版嵁婧�
+            param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, false) // 鏁版嵁婧�
             if (btn.output) {
               param.key_back_type = 'Y'
             }
@@ -616,11 +587,11 @@
           param.ID = primaryId
 
           if (retmsg) {
-            const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, retmsg, this.moduleParams) // 鏁版嵁婧�
+            const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, retmsg) // 鏁版嵁婧�
             param.LText = sql
             param.$callbacksql = callbacksql
           } else {
-            param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, false, this.moduleParams) // 鏁版嵁婧�
+            param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, false) // 鏁版嵁婧�
             if (btn.output) {
               param.key_back_type = 'Y'
             }
@@ -656,11 +627,11 @@
             param.ID = Utils.getguid()
 
             if (retmsg) {
-              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg, this.moduleParams) // 鏁版嵁婧�
+              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg) // 鏁版嵁婧�
               param.LText = sql
               param.$callbacksql = callbacksql
             } else {
-              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false, this.moduleParams) // 鏁版嵁婧�
+              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false) // 鏁版嵁婧�
               if (btn.output) {
                 param.key_back_type = 'Y'
               }
@@ -682,11 +653,11 @@
             param.ID = primaryId
 
             if (retmsg) {
-              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg, this.moduleParams) // 鏁版嵁婧�
+              const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, retmsg) // 鏁版嵁婧�
               param.LText = sql
               param.$callbacksql = callbacksql
             } else {
-              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false, this.moduleParams) // 鏁版嵁婧�
+              param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, false) // 鏁版嵁婧�
               if (btn.output) {
                 param.key_back_type = 'Y'
               }
@@ -737,6 +708,464 @@
     return _params
   }
 
+  getBackSystemParam = (data, formdata) => {
+    const { btn } = this.props
+
+    let ex = window.GLOB.CacheData.get('sql_' + btn.uuid)
+    let _params = []
+
+    if (btn.Ot === 'notRequired' || btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
+      let primaryId = ''
+      let cell = null
+
+      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
+        primaryId = data.map(d => d.$$uuid).filter(Boolean).join(',')
+        cell = data[0]
+      }
+
+      if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit' || btn.OpenType === 'form') { // 琛ㄥ崟
+        if (btn.sqlType === 'insert') { // 绯荤粺鍑芥暟娣诲姞鏃讹紝鐢熸垚uuid
+          primaryId = Utils.getguid()
+        }
+      }
+
+      let exp = this.getExps(ex, formdata, cell, primaryId, btn.$process)
+
+      if (ex.reps.includes('mk_check_begin')) {
+        exp.$unCheckParam = fromJS(exp).toJS()
+
+        exp.data[0].exps.push({
+          key: 'mk_check_begin',
+          value: ''
+        }, {
+          key: 'mk_check_end',
+          value: ''
+        })
+        exp.$unCheckParam.data[0].exps.push({
+          key: 'mk_check_begin',
+          value: 'Y'
+        }, {
+          key: 'mk_check_end',
+          value: 'Y'
+        })
+      } else if (btn.procMode === 'system' && btn.callbackType === 'script') {
+        let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
+        exp.$backParam = this.getExps(_backex, formdata, cell, primaryId)
+      }
+
+      _params.push(exp)
+    } else if (btn.Ot === 'required') {
+      _params = data.map((cell, index) => {
+        let primaryId = cell.$$uuid || ''
+
+        if (btn.OpenType === 'pop') { // 琛ㄥ崟
+          if (index !== 0) {
+            let _cell = {}
+            Object.keys(cell).forEach(key => {
+              _cell[key.toLowerCase()] = cell[key]
+            })
+            formdata = formdata.map(_data => {
+              if (_data.readin && _cell.hasOwnProperty(_data.key.toLowerCase())) {
+                _data.value = _cell[_data.key.toLowerCase()]
+              }
+              return _data
+            })
+          }
+
+          if (btn.sqlType === 'insert') { // 绯荤粺鍑芥暟娣诲姞鏃讹紝鐢熸垚uuid
+            primaryId = Utils.getguid()
+          }
+        }
+        let exp = this.getExps(ex, formdata, cell, primaryId, btn.$process)
+        if (ex.reps.includes('mk_check_begin')) {
+          exp.$unCheckParam = fromJS(exp).toJS()
+  
+          exp.data[0].exps.push({
+            key: 'mk_check_begin',
+            value: ''
+          }, {
+            key: 'mk_check_end',
+            value: ''
+          })
+          exp.$unCheckParam.data[0].exps.push({
+            key: 'mk_check_begin',
+            value: 'Y'
+          }, {
+            key: 'mk_check_end',
+            value: 'Y'
+          })
+        } else if (btn.procMode === 'system' && btn.callbackType === 'script') {
+          let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
+          exp.$backParam = this.getExps(_backex, formdata, cell, primaryId)
+        }
+
+        return exp
+      })
+    }
+
+    return _params
+  }
+
+  getExps = (ex, formdata, cell, id, process) => {
+    const { columns, BID, btn } = this.props
+    let exps = []
+    let values = {
+      time_id: Utils.getguid(),
+      roleid: sessionStorage.getItem('role_id') || '',
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      mk_nation: sessionStorage.getItem('nation') || '',
+      mk_province: sessionStorage.getItem('province') || '',
+      mk_city: sessionStorage.getItem('city') || '',
+      mk_district: sessionStorage.getItem('district') || '',
+      mk_address: sessionStorage.getItem('address') || '',
+      id: id || '',
+      bid: BID || '',
+      typename: 'admin',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      // mk_check_begin: '',
+      // mk_check_end: ''
+    }
+
+    if (window.GLOB.externalDatabase !== null) {
+      values.db = window.GLOB.externalDatabase
+    }
+
+    let formkeys = []
+    formdata && formdata.forEach(form => {
+      // if (!ex.reps.includes(form.key)) return
+
+      formkeys.push(form.key)
+
+      let val = form.value
+      if (form.type === 'number' || form.type === 'rate') {
+        if (isNaN(val)) {
+          val = 0
+        }
+      } else if (['date', 'datemonth'].includes(form.type)) {
+        val = val || '1949-10-01'
+      }
+
+      exps.push({
+        key: 'mk_' + form.key + '_mk',
+        value: val
+      })
+    })
+
+    if (cell && columns && columns.length > 0) {
+      let datavars = {}
+
+      Object.keys(cell).forEach(key => {
+        datavars[key.toLowerCase()] = cell[key]
+      })
+  
+      columns.forEach(col => {
+        if (!ex.reps.includes(col.field) || formkeys.includes(col.field)) return
+        if (!col.datatype) return
+
+        let _key = col.field.toLowerCase()
+        let _val = datavars.hasOwnProperty(_key) ? datavars[_key] : ''
+
+        if (/^date/ig.test(col.datatype) && !_val) {
+          _val = '1949-10-01'
+        }
+
+        exps.push({
+          key: 'mk_' + col.field + '_mk',
+          value: _val
+        })
+      })
+    }
+
+    ex.reps.forEach(n => {
+      let key = n.toLowerCase()
+      if (values.hasOwnProperty(key)) {
+        exps.push({
+          key: n,
+          value: values[key]
+        })
+      }
+    })
+
+    if (process && btn.verify.workFlow === 'true') {
+      let flow = window.GLOB.UserCacheMap.get(btn.$flowId)
+      let node = null
+      let line = null
+      let target = null
+      let status = 0
+      let statusName = ''
+      let detailId = ''
+      let sign = ''
+      let error = ''
+      let userid = sessionStorage.getItem('UserID') || ''
+      let checkIds = []
+      let checkUsers = []
+      let noticeIds = []
+      let work_grade = sessionStorage.getItem('work_grade') || 0
+      let departmentcode = sessionStorage.getItem('departmentcode') || ''
+      let _data = cell || {}
+      let msg = ''
+  
+      if (btn.verify.flowType === 'start') {
+        target = flow ? flow.cells.filter(cell => cell.mknode === 'start')[0] : ''
+  
+        if (target) {
+          detailId = target.id
+          status = target.mkdata.status
+          statusName = target.mkdata.statusName
+        } else {
+          error = '宸ヤ綔娴佹棤寮�濮嬭妭鐐�'
+        }
+      } else if (_data.works_flow_param) {
+        try {
+          node = JSON.parse(window.decodeURIComponent(window.atob(_data.works_flow_param)))
+        } catch (e) {
+          node = null
+        }
+  
+        if (node) {
+          let lines = flow ? flow.cells.filter(cell => cell.shape === 'edge' && cell.source.cell === node.id) : []
+          if (btn.verify.flowType === 'reject') {
+            line = lines.filter(cell => cell.mkdata.flowType === 'reject' || cell.mknode === 'startEdge')[0]
+          } else {
+            lines = lines.filter(cell => cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge')
+  
+            if (lines.length === 0) {
+              error = '鏃犲彲鎵ц鐨勬祦绋嬪垎鏀�'
+            } else {
+              let branchKey = btn.verify.flowBranch ? btn.verify.flowBranch.toLowerCase() : ''
+  
+              formdata && formdata.forEach(form => {
+                let _key = form.key.toLowerCase()
+                _data[_key] = form.value
+              })
+  
+              if (!branchKey) {
+                lines.forEach(line => {
+                  if (line.mkdata.execCondition === 'open') {
+                    error = '鎸夐挳鏈缃祦绋嬫帶鍒跺瓧娈点��'
+                  }
+                })
+                if (!error) {
+                  lines = lines.filter(cell => {
+                    if (cell.mkdata.seniorCondition === 'open' && !line) {
+                      cell.mkdata.seniorbers && cell.mkdata.seniorbers.forEach(per => {
+                        if (per.worker_id === userid) {
+                          line = cell
+                        }
+                      })
+                      return false
+                    }
+                    return true
+                  })
+
+                  if (!line) {
+                    line = lines[0]
+                  }
+                }
+              } else if (!_data.hasOwnProperty(branchKey)) {
+                error = '淇℃伅涓棤娴佺▼鎺у埗瀛楁銆�'
+              } else {
+                let _def_lines = []
+                let _equ_lines = []
+                let _unequ_lines = []
+                let _or_lines = []
+                let branchVal = _data[branchKey]
+  
+                if (branchVal && typeof(branchVal) === 'string' && !isNaN(branchVal)) {
+                  branchVal = +branchVal
+                }
+  
+                lines.forEach(item => {
+                  if (item.mkdata.execCondition !== 'open') {
+                    _def_lines.push(item)
+                  } else {
+                    if (item.mkdata.match === '=') {
+                      if (item.mkdata.matchVal === branchVal + '') {
+                        _equ_lines.push(item)
+                      }
+                    } else if (item.mkdata.match === '!=') {
+                      if (item.mkdata.matchVal !== branchVal + '') {
+                        _unequ_lines.push(item)
+                      }
+                    } else {
+                      if (item.mkdata.match === '<') {
+                        if (item.mkdata.matchVal < branchVal) {
+                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                        }
+                      } else if (item.mkdata.match === '>') {
+                        if (item.mkdata.matchVal > branchVal) {
+                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                        }
+                      } else if (item.mkdata.match === '<=') {
+                        if (item.mkdata.matchVal <= branchVal) {
+                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                        }
+                      } else if (item.mkdata.match === '>=') {
+                        if (item.mkdata.matchVal >= branchVal) {
+                          _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                        }
+                      }
+                    }
+                  }
+                })
+  
+                _or_lines.sort((a, b) => a.dist - b.dist)
+  
+                let _lines = [..._equ_lines, ..._or_lines, ..._unequ_lines, ..._def_lines]
+  
+                _lines = _lines.filter(cell => {
+                  if (cell.mkdata.seniorCondition === 'open' && !line) {
+                    cell.mkdata.seniorbers && cell.mkdata.seniorbers.forEach(per => {
+                      if (per.worker_id === userid) {
+                        line = cell
+                      }
+                    })
+                    return false
+                  }
+                  return true
+                })
+                
+                if (!line) {
+                  line = _lines[0]
+                }
+              }
+            }
+          }
+        } else {
+          error = '琛屼俊鎭腑宸ヤ綔娴佸弬鏁版棤娉曡В鏋�'
+        }
+        
+        if (line) {
+          detailId = line.id
+          status = line.mkdata.status
+          statusName = line.mkdata.statusName
+          sign = line.mkdata.seniorSign || ''
+          target = flow.cells.filter(cell => cell.id === line.target.cell)[0]
+  
+          line.mkdata.members && line.mkdata.members.forEach(item => {
+            if (line.mkdata.approver === 'departmentManager') {
+              if (item.job_type === 'manage' && departmentcode === item.parentIds[1]) {
+                checkIds.push(item.worker_id)
+                checkUsers.push(item)
+              }
+            } else if (line.mkdata.approver === 'directManager') {
+              if (departmentcode === item.parentIds[1] && item.work_grade > work_grade) {
+                checkIds.push(item.worker_id)
+                checkUsers.push(item)
+              }
+            } else {
+              checkIds.push(item.worker_id)
+              checkUsers.push(item)
+            }
+          })
+          line.mkdata.copys && line.mkdata.copys.forEach(item => {
+            noticeIds.push(item.worker_id)
+          })
+  
+          if (!target) {
+            error = '鏈煡璇㈠埌宸ヤ綔娴佺洰鏍囪妭鐐�'
+          } else if (checkIds.length === 0 && !['startEdge', 'endEdge', 'throughEdge'].includes(line.mknode)) {
+            error = '鏈幏鍙栧埌涓嬩竴姝ュ鎵逛汉'
+          } else if (line.approvalMethod === 'countersign' && (!node.checkIds || !node.checkIds.includes(userid))) {
+            error = '褰撳墠鐢ㄦ埛涓嶅湪瀹℃壒浜哄垪琛ㄤ腑'
+          }
+        } else if (!error) {
+          error = '宸ヤ綔娴佷腑鏃犲搴旀祦绋�'
+        }
+      } else {
+        error = '琛屼俊鎭腑鏃犲伐浣滄祦鍙傛暟'
+      }
+
+      if (error) {
+        status = 0
+        statusName = '寮傚父'
+      } else if (target) {
+        let label = target.attrs && target.attrs.text && target.attrs.text.text ? target.attrs.text.text : ''
+        msg = {...target.mkdata, label: label, id: target.id, checkIds: [], checkUsers: []}
+        msg = window.btoa(window.encodeURIComponent(JSON.stringify(msg)))
+      }
+  
+      if (btn.verify.flowType === 'start') {
+        exps.push(
+          { key: 'works_flow_error', value: error },
+          { key: 'works_flow_code', value: flow ? flow.flow_code : '' },
+          { key: 'works_flow_name', value: flow ? flow.flow_name : '' },
+          { key: 'works_flow_param', value: msg },
+          { key: 'works_flow_detail_id', value: detailId },
+          { key: 'status', value: status },
+          { key: 'statusname', value: statusName },
+          { key: 'work_group', value: sessionStorage.getItem('work_group') || '' },
+          { key: 'work_grade', value: sessionStorage.getItem('work_grade') || 0 },
+          // { key: 'start_type', value: '寮�濮�' },
+        )
+      } else {
+        let works_flow_countersign = ''
+        let works_flow_sign_values = ''
+        let works_flow_sign_field = ''
+        let works_flow_sign_label = ''
+        let works_begin_branch = ''
+        if (line.approvalMethod === 'countersign' && node.checkIds.length > 1) {
+          works_flow_countersign = 'Y'
+          let mark = line.mark || '宸插鏍�'
+          let fields = ['statuscharone', 'statuschartwo', 'statuscharthree', 'statuscharfour', 'statuscharfive']
+          node.checkUsers.forEach((user, index) => {
+            if (user.worker_id === userid) {
+              works_flow_sign_field = fields[index]
+              works_flow_sign_label = `${user.parentNames[2] || ''}${user.workername || ''}${mark}`
+            } else {
+              works_flow_sign_values += `${user.parentNames[2] || ''}${user.workername || ''}${mark}`
+            }
+          })
+        } else {
+          works_begin_branch = line.mknode === 'startEdge' ? 'Y' : ''
+        }
+
+        exps.push(
+          { key: 'works_flow_error', value: error },
+          { key: 'works_flow_countersign', value: works_flow_countersign },
+          { key: 'works_flow_sign_values', value: works_flow_sign_values },
+          { key: 'works_begin_branch', value: works_begin_branch },
+          { key: 'works_flow_sign_field', value: works_flow_sign_field },
+          { key: 'works_flow_sign_label', value: works_flow_sign_label },
+          { key: 'works_flow_code', value: flow ? flow.flow_code : '' },
+          { key: 'works_flow_name', value: flow ? flow.flow_name : '' },
+          { key: 'works_flow_param', value: msg },
+          { key: 'works_flow_detail_id', value: detailId },
+          { key: 'status', value: status },
+          { key: 'statusname', value: statusName },
+          { key: 'work_group', value: sessionStorage.getItem('work_group') || '' },
+          { key: 'work_grade', value: sessionStorage.getItem('work_grade') || 0 },
+          // { key: 'check_type', value: btn.verify.flowType === 'reject' ? '椹冲洖' : '瀹℃牳' },
+          // { key: 'notice_type', value: '鎶勯��' },
+          { key: 'check_userids', value: checkIds.join(',') },
+          { key: 'notice_userids', value: noticeIds.join(',') },
+          { key: 'works_flow_sign', value: sign },
+        )
+      }
+    }
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5(ex.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    return {
+      $backend: true,
+      $type: 's_TableData_InUpDe',
+      data: [{
+        id: ex.id,
+        menuname: btn.logLabel || '',
+        exps: exps,
+        md5_id: md5_id
+      }]
+    }
+  }
+
   getInnerParam = (data, formdata, retmsg) => {
     const { setting, btn, columns } = this.props
     let _params = []
@@ -763,7 +1192,7 @@
       let primaryId = ''
 
       if ((btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') && setting.primaryKey) {
-        let ids = data.map(d => { return d[setting.primaryKey] || ''})
+        let ids = data.map(d => d.$$uuid)
         ids = ids.filter(Boolean)
         primaryId = ids.join(',')
 
@@ -782,7 +1211,10 @@
         param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
       }
 
-      if (retmsg) {
+      if (btn.callbackType === 'script' && window.backend && window.GLOB.CacheData.has('sql_back_' + btn.uuid)) {
+        let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
+        param.$backParam = this.getExps(_backex, formdata, data[0], primaryId)
+      } else if (retmsg) {
         param.$callbacksql = this.getSysDeclareSql(btn, formdata, data[0], columns, this.props.BID)
       }
 
@@ -805,7 +1237,7 @@
           param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
         }
 
-        let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
+        let primaryId = cell.$$uuid || ''
 
         if (btn.OpenType === 'pop') { // 琛ㄥ崟
           if (index !== 0) {
@@ -835,7 +1267,10 @@
           param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
         }
 
-        if (retmsg) {
+        if (btn.callbackType === 'script' && window.backend && window.GLOB.CacheData.has('sql_back_' + btn.uuid)) {
+          let _backex = window.GLOB.CacheData.get('sql_back_' + btn.uuid)
+          param.$backParam = this.getExps(_backex, formdata, cell, primaryId)
+        } else if (retmsg) {
           param.$callbacksql = this.getSysDeclareSql(btn, formdata, cell, columns, this.props.BID)
         }
 
@@ -1025,53 +1460,10 @@
    * @description 鎸夐挳鎻愪氦鎵ц
    */
   execSubmit = (data, _resolve, formdata, force) => {
-    const { setting, btn } = this.props
-    this.moduleParams = null
+    const { btn } = this.props
 
     if (btn.preButton && !force) {
       this.trigger(btn.preButton, data, _resolve, formdata, 0)
-    } else if (btn.verify && btn.verify.invalid === 'true' && setting.dataresource) {
-      MKEmitter.emit('queryModuleParam', btn.$menuId, (param) => {
-        let datasource = setting.dataresource
-        let customScript = setting.customScript || ''
-        let allSearch = Utils.getAllSearchOptions(param.search)
-
-        let regoptions = allSearch.map(item => {
-          return {
-            reg: new RegExp('@' + item.key + '@', 'ig'),
-            value: `'${item.value}'`
-          }
-        })
-
-        regoptions.push({
-          reg: new RegExp('@userName@', 'ig'),
-          value: `'${sessionStorage.getItem('User_Name') || ''}'`
-        }, {
-          reg: new RegExp('@fullName@', 'ig'),
-          value: `'${sessionStorage.getItem('Full_Name') || ''}'`
-        }, {
-          reg: new RegExp('@orderBy@', 'ig'),
-          value: setting.order
-        }, {
-          reg: new RegExp('@pageSize@', 'ig'),
-          value: 10
-        }, {
-          reg: new RegExp('@pageIndex@', 'ig'),
-          value: 1
-        })
-
-        regoptions.forEach(item => {
-          datasource = datasource.replace(item.reg, item.value)
-          customScript = customScript.replace(item.reg, item.value)
-        })
-
-        this.moduleParams = {
-          datasource,
-          customScript
-        }
-
-        this.execRealSubmit(data, _resolve, formdata)
-      })
     } else {
       this.execRealSubmit(data, _resolve, formdata)
     }
@@ -1081,7 +1473,7 @@
     if (times > 50) {
       notification.warning({
         top: 92,
-        message: '鍓嶇疆鎸夐挳鍔犺浇澶辫触锛�',
+        message: window.GLOB.dict['pre_btn_failed'] || '鍓嶇疆鎸夐挳鍔犺浇澶辫触锛�',
         duration: 5
       })
       this.setState({loading: false})
@@ -1119,7 +1511,7 @@
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
+        message: window.GLOB.dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
       _resolve()
@@ -1129,11 +1521,19 @@
     if (btn.intertype === 'system' || btn.intertype === 'inner') { // 绯荤粺鎺ュ彛
       let params = []
 
-      if (btn.intertype === 'system') {
+      if (btn.intertype === 'system' && window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
+        params = this.getBackSystemParam(data, formdata)
+      } else if (btn.intertype === 'system') {
         params = this.getSystemParam(data, formdata)
         if (btn.returnValue === 'true') {
           params = params.map(item => {
             item.script_type = 'Y'
+            return item
+          })
+        }
+        if (btn.database === 'sso' && window.GLOB.mainSystemApi) {
+          params = params.map(item => {
+            item.rduri = window.GLOB.mainSystemApi
             return item
           })
         }
@@ -1183,6 +1583,14 @@
           _resolve()
         })
       } else if (params.length <= 20 && btn.execType !== 'single') {
+        if (window.backend && params[0].$backend && (!btn.verify || (btn.verify.printEnable !== 'true' && !btn.output))) {
+          params = [{
+            $backend: true,
+            $type: 's_TableData_InUpDe',
+            data: params.map(item => item.data[0])
+          }]
+        }
+
         let deffers = params.map((param, i) => {
           return new Promise(resolve => {
             setTimeout(() => {
@@ -1230,7 +1638,9 @@
       /** *********************璋冪敤澶栭儴鎺ュ彛************************* */
       let _params = [] // 璇锋眰鍙傛暟鏁扮粍
 
-      if (btn.procMode === 'system') {
+      if (btn.procMode === 'system' && window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
+        _params = this.getBackSystemParam(data, formdata)
+      } else if (btn.procMode === 'system') {
         _params = this.getSystemParam(data, formdata, true)
         _params = _params.map(item => {
           item.script_type = 'Y'
@@ -1251,7 +1661,9 @@
     } else if (btn.intertype === 'custom') { // 绯荤粺鎺ュ彛
       let params = []
 
-      if (btn.procMode === 'system') {
+      if (btn.procMode === 'system' && window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
+        params = this.getBackSystemParam(data, formdata)
+      } else if (btn.procMode === 'system') {
         params = this.getSystemParam(data, formdata, true)
         params = params.map(item => {
           item.script_type = 'Y'
@@ -1287,13 +1699,15 @@
       BID: param.BID || '',
       ID: param.ID || '',
       callbacksql: param.$callbacksql || '',
-      mk_api_key: ''
+      mk_api_key: '',
+      backParam: param.$backParam || ''
     }
 
     if (!record.ID && btn.Ot !== 'notRequired' && param[setting.primaryKey]) {
       record.ID = param[setting.primaryKey]
     }
 
+    delete param.$backParam
     delete param.$callbacksql
 
     if (param.$pice) {
@@ -1303,7 +1717,7 @@
 
       this.customOuterRequest(params, param, record, _resolve)
       return
-    } else if (!param.func) {
+    } else if (!param.func && !param.$backend) {
       this.customOuterRequest(params, param, record, _resolve)
       return
     }
@@ -1357,7 +1771,7 @@
   // Api.directRequest('http://localhost:3001/test.xml', 'get', null, 'true').then(res => {
   //   let $x2js = new x2js()
   //   let jsonObj = $x2js.xml2js(res);
-  //   console.info(jsonObj)
+  //   window.mkInfo(jsonObj)
   // })
 
   /**
@@ -1399,7 +1813,21 @@
       method: btn.method || 'post'
     }
 
-    if (btn.cross === 'true') {
+    if (btn.ContentType) {
+      _params.headers = {
+        'Content-Type': btn.ContentType
+      }
+    }
+
+    if (btn.$outerScript) {
+      if (JSON.stringify(param) !== '{}') {
+        if (btn.stringify === 'qs') {
+          _params.data = qs.stringify(param)
+        } else {
+          _params.data = param
+        }
+      }
+    } else if (btn.cross === 'true') {
       if (JSON.stringify(param) !== '{}') {
         if (btn.stringify === 'qs') {
           _params.data = qs.stringify(param)
@@ -1433,13 +1861,7 @@
       _params.method = 'post'
     }
 
-    if (btn.ContentType) {
-      _params.headers = {
-        'Content-Type': btn.ContentType
-      }
-    }
-
-    Api.directRequest(_params).then(res => {
+    Api.directRequest(_params, btn.$outerScript, 'outer').then(res => {
       if (typeof(res) !== 'object') {
         let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒'
 
@@ -1506,6 +1928,8 @@
         _resolve()
       }
       return
+    } else if (btn.callbackType === 'script' && record.backParam) {
+      param = this.getCallBackendParam(result, record)
     } else if (btn.callbackType === 'script' || btn.callbackType === 'default') {
       param = this.getCallBackSql(result, record)
     } else if (btn.callbackType === 'func') {
@@ -1569,6 +1993,108 @@
     })
   }
 
+  getCallBackendParam = (result, record) => {
+    const { btn } = this.props
+    let lines = []
+    let tables = []
+    let param = fromJS(record.backParam).toJS()
+
+    btn.verify.cbScripts.forEach(script => {
+      if (script.status === 'false') return
+
+      if (/\s#[a-z0-9_]+(\s|\()/ig.test(script.sql)) {
+        tables.push(...script.sql.match(/\s#[a-z0-9_]+(\s|\()/ig))
+      }
+    })
+
+    tables = tables.map(tb => tb.replace(/\s|\(/g, ''))
+
+    if (result.$ErrCode) {
+      delete result.$ErrCode
+      delete result.$ErrMesg
+    }
+
+    let getDefaultSql = (obj, tb, bid, level) => {
+      let vals = {}
+      let subObjs = []
+      let id = Utils.getuuid()
+
+      delete obj.$$key
+
+      Object.keys(obj).forEach(key => {
+        let val = obj[key]
+        if (val === null || val === undefined) return
+        if (typeof(val) === 'object') {
+          if (Array.isArray(val)) {
+            val.forEach(item => {
+              if (typeof(item) !== 'object' || Array.isArray(item)) return
+              if (Object.keys(item).length === 0) return
+
+              Object.keys(item).forEach(k => {
+                if (item[k] === null) {
+                  item[k] = ''
+                }
+              })
+              item.$$key = tb + '_' + key
+              subObjs.push(item)
+            })
+          } else if (Object.keys(val).length > 0) {
+            val.$$key = tb + '_' + key
+            subObjs.push(val)
+          }
+        } else {
+          if (typeof(val) === 'string') {
+            val = val.replace(/'/ig, '"')
+          } else {
+            val = val + ''
+          }
+          vals[key] = val
+        }
+      })
+
+      vals.mk_level = level
+      vals.mk_id = id
+      vals.mk_bid = bid
+
+      let isnew = true
+      lines.forEach(line => {
+        if (line.tb === tb) {
+          line.values.push(vals)
+          isnew = false
+        }
+      })
+      if (isnew) {
+        lines.push({
+          tb: tb,
+          type: tables.includes('#' + tb) ? '01' : '02',
+          values: [vals]
+        })
+      }
+
+      subObjs.forEach(item => {
+        getDefaultSql(item, item.$$key, id, level + 1)
+      })
+    }
+    
+    getDefaultSql(result, btn.cbTable, '', 1)
+
+    param.data[0].exps.push({
+      key: 'mk_outer_params',  // 鍥炶皟鑴氭湰鐨勬暟鎹浛鎹�
+      value: lines
+    })
+
+    let md5_id = ''
+    if (window.GLOB.probation) {
+      md5_id = md5('back_' + btn.uuid + JSON.stringify(param.data[0].exps) + Math.floor(new Date().getTime() / 600000))
+      md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+    }
+
+    param.data[0].md5_id = md5_id
+    param.data[0].menuname = btn.logLabel + '(鍥炶皟)'
+
+    return param
+  }
+
   getCallBackSql = (result, record) => {
     const { btn } = this.props
     let lines = []
@@ -1619,10 +2145,15 @@
           if (Array.isArray(val)) {
             val.forEach(item => {
               if (typeof(item) !== 'object' || Array.isArray(item)) return
-              if (Object.keys(item).length > 0) {
-                item.$$key = tb + '_' + key
-                subObjs.push(item)
-              }
+              if (Object.keys(item).length === 0) return
+
+              Object.keys(item).forEach(k => {
+                if (item[k] === null) {
+                  item[k] = ''
+                }
+              })
+              item.$$key = tb + '_' + key
+              subObjs.push(item)
             })
           } else if (Object.keys(val).length > 0) {
             val.$$key = tb + '_' + key
@@ -1726,6 +2257,7 @@
       sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
       sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
       sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+      sql = sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
       sql = sql.replace(/@typename@/ig, `'admin'`)
 
       if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
@@ -1735,8 +2267,8 @@
       }
 
       if (window.GLOB.debugger === true) {
-        console.info('%c' + btn.logLabel + '(鍥炶皟)', 'color: blue')
-        console.info(sql.replace(/\n\s{8}/ig, '\n'))
+        window.mkInfo('%c' + btn.logLabel + '(鍥炶皟)', 'color: blue')
+        window.mkInfo(sql.replace(/\n\s{8}/ig, '\n'))
       }
 
       param.LText = sql
@@ -1770,7 +2302,7 @@
           `)}
         `))
         sql = sql.join('')
-        console.info(sql.replace(/\n\s{10}/ig, '\n'))
+        window.mkInfo(sql.replace(/\n\s{10}/ig, '\n'))
       }
     }
 
@@ -1837,24 +2369,26 @@
           msg = msg.replace(/\n|\r/ig, '<br/>')
           msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
         }
-        const _this = this
+        const that = this
         confirm({
-          title: '璇风‘璁�',
+          title: window.GLOB.dict['exec_sure'] || '璇风‘璁�',
           content: msg,
+          okText: window.GLOB.dict['ok'] || '纭畾',
+          cancelText: window.GLOB.dict['cancel'] || '鍙栨秷',
           onOk() {
             return new Promise(resolve => {
               Api.genericInterface(unCheckParam).then(result => {
                 if (result.status) {
-                  _this.triggerNote(result, param.ID) // 娑堟伅
+                  that.triggerNote(result, param.ID) // 娑堟伅
           
                   if (params.length === 0) {
-                    _this.execSuccess(result)
+                    that.execSuccess(result)
                     _resolve()
                   } else {
-                    _this.checkLoopRequest(params, _resolve)
+                    that.checkLoopRequest(params, _resolve)
                   }
                 } else {
-                  _this.execError(result)
+                  that.execError(result)
                   _resolve()
                 }
                 resolve()
@@ -1862,7 +2396,7 @@
             })
           },
           onCancel() {
-            _this.execError(res)
+            that.execError(res)
             _resolve()
           }
         })
@@ -1892,16 +2426,18 @@
     let record = {
       BID: param.BID || '',
       ID: param.ID || '',
-      callbacksql: param.$callbacksql || ''
+      callbacksql: param.$callbacksql || '',
+      backParam: param.$backParam || ''
     }
 
     if (!record.ID && btn.Ot !== 'notRequired' && param[setting.primaryKey]) {
       record.ID = param[setting.primaryKey]
     }
 
+    delete param.$backParam
     delete param.$callbacksql
 
-    if (!param.func) {
+    if (!param.func && !param.$backend) {
       this.outerOuterRequest(params, param, record, _resolve)
       return
     }
@@ -2055,6 +2591,8 @@
         _resolve()
       }
       return
+    } else if (btn.callbackType === 'script' && record.backParam) {
+      param = this.getCallBackendParam(result, record)
     } else if (btn.callbackType === 'script' || btn.callbackType === 'default') {
       param = this.getCallBackSql(result, record)
     } else if (btn.callbackType === 'func' || btn.callbackFunc) {
@@ -2180,6 +2718,7 @@
               _resolve()
             } else {
               if (params.length === 0) {
+                this.clearBackCache()
                 this.execSuccess(res)
                 _resolve()
               } else {
@@ -2201,6 +2740,7 @@
               _resolve()
             } else {
               if (params.length === 0) {
+                this.clearBackCache()
                 this.execSuccess(res)
                 _resolve()
               } else {
@@ -2217,6 +2757,7 @@
           _resolve()
         } else {
           if (params.length === 0) {
+            this.clearBackCache()
             this.execSuccess(re)
             _resolve()
           } else {
@@ -2225,6 +2766,34 @@
         }
       })
     }
+  }
+
+  clearBackCache = () => {
+    if (!window.GLOB.backend) return
+
+    Api.cacheInterface({userid: sessionStorage.getItem('UserID') || '', LoginUID: sessionStorage.getItem('LoginUID') || ''}).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message || '缂撳瓨娓呯┖澶辫触锛�',
+          duration: 5
+        })
+      } else if (window.GLOB.localSystemApi) {
+        Api.cacheInterface({
+          userid: sessionStorage.getItem('LocalUserID') || sessionStorage.getItem('UserID') || '',
+          LoginUID: sessionStorage.getItem('LocalLoginUID') || sessionStorage.getItem('LoginUID') || '',
+          rduri: window.GLOB.localSystemApi.replace('dostars', 'excache')
+        }).then(result => {
+          if (!result.status) {
+            notification.warning({
+              top: 92,
+              message: result.message || '缂撳瓨娓呯┖澶辫触锛�',
+              duration: 5
+            })
+          }
+        })
+      }
+    })
   }
 
   /**
@@ -2237,7 +2806,7 @@
    */
   execSuccess = (res = {}) => {
     const { btn } = this.props
-    const { autoMatic } = this.state
+    const { autoMatic, dict } = this.state
 
     if (btn.resetForms) {
       let data = {}
@@ -2272,6 +2841,17 @@
     }
 
     let sign = ''
+    let focusField = ''
+
+    if (/@focus:[a-z0-9_]+@/i.test(res.message)) {
+      let val = res.message.match(/@focus:[a-z0-9_]+@/i)
+      res.message = res.message.replace(/@focus:[a-z0-9_]+@/i, '')
+      focusField = val ? val[0].replace(/@focus:|@/ig, '') : ''
+
+      if (!res.message) {
+        res.ErrCode = '-1'
+      }
+    }
     if (/^@speak@/i.test(res.message)) {
       res.message = res.message.replace(/^@speak@/i, '')
       let val = res.message.match(/<<.*>>/)
@@ -2287,9 +2867,10 @@
       if (!res.message) {
         res.ErrCode = '-1'
       }
-    } else if (/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i.test(res.message)) {
-      sign = res.message.match(/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i)[0].toLowerCase()
-      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@|@no_target_menu@/i, '')
+    }
+    if (/@close_tab@|@close_popup@|@goback@|@no_target_menu@|@open_target_menu@/i.test(res.message)) {
+      sign = res.message.match(/@close_tab@|@close_popup@|@goback@|@no_target_menu@|@open_target_menu@/i)[0].toLowerCase()
+      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@|@no_target_menu@|@open_target_menu@/i, '')
     }
 
     let id = ''
@@ -2307,20 +2888,21 @@
       if (btn.formType !== 'counter' || res.message) {
         notification.success({
           top: 92,
-          message: res.message || '鎵ц鎴愬姛锛�',
+          message: res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�',
           duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
         })
       }
     } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
-      let msg = res.message || '鎵ц鎴愬姛锛�'
+      let msg = res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�'
       if (/\n|\r/.test(msg)) {
         msg = msg.replace(/\n|\r/ig, '<br/>')
         msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
       }
       Modal.success({
         title: msg,
+        okText: dict['got_it'] || '鐭ラ亾浜�',
         onOk: () => {
-          this.successContinue(sign, id, res)
+          this.successContinue(sign, id, res, focusField)
         }
       })
       return
@@ -2328,12 +2910,16 @@
 
     }
 
-    this.successContinue(sign, id, res)
+    this.successContinue(sign, id, res, focusField)
   }
 
-  successContinue = (sign, id, res) => {
+  successContinue = (sign, id, res, focusField) => {
     const { btn } = this.props
     const { btnconfig } = this.state
+
+    if (focusField) {
+      MKEmitter.emit('resetFocus', btn.uuid, focusField)
+    }
 
     this.setState({
       loadingNumber: '',
@@ -2352,12 +2938,8 @@
       tabId = btn.refreshTab[btn.refreshTab.length - 1]
     }
 
-    // if (btn.formCache === 'clear') { // 娓呴櫎琛ㄥ崟缂撳瓨
-    //   window.GLOB.CacheMap = new Map()
-    // }
-
     if (tabId && btn.$MenuID === tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃讹紝鍋滄鍏朵粬鎿嶄綔
-      MKEmitter.emit('reloadMenuView', tabId, 'table')
+      MKEmitter.emit('reloadMenuView', tabId)
       return
     }
 
@@ -2399,7 +2981,7 @@
     }
 
     if (tabId) {
-      MKEmitter.emit('reloadMenuView', tabId, 'table')
+      MKEmitter.emit('reloadMenuView', tabId)
     }
     
     if (btn.switchTab && btn.switchTab.length > 0) {
@@ -2444,7 +3026,7 @@
         if (!url) {
           notification.warning({
             top: 92,
-            message: '灏氭湭娣诲姞姝e紡绯荤粺閾炬帴鍦板潃锛�',
+            message: window.GLOB.dict['no_prod_link'] || '灏氭湭璁剧疆姝e紡绯荤粺閾炬帴鍦板潃锛�',
             duration: 5
           })
           return
@@ -2545,10 +3127,30 @@
   }
 
   sendWxMessage = (verify, id) => {
-    if (!window.GLOB.nginx) {
+    let domain = window.GLOB.baseurl
+    let appId = window.GLOB.WXAppID || ''
+
+    if (verify.wxAppId && verify.wxAppId !== appId) {
+      appId = verify.wxAppId
+      if (!window.GLOB.WXApps || window.GLOB.WXApps.findIndex(item => item.appId === verify.wxAppId) === -1) {
+        notification.warning({
+          top: 92,
+          message: '鎸夐挳鍏宠仈鍏紬鍙蜂笉鍦ㄥ彲鐢ㄥ垪琛ㄤ腑锛岃閲嶆柊淇濆瓨鎸夐挳閰嶇疆锛�',
+          duration: 5
+        })
+        return
+      }
+    }
+    
+    if (['8IFltwzyKcu15iA8fqSyb6m-pMa88a3ZTu0No3vDHgo', 'LOB-bbt9jVncGh7IOAUdESh1Sgzcbt62UwOqSqcK9ok'].includes(verify.wxTemplateId) && window.GLOB.sysType !== 'cloud') {
+      domain = 'https://cloud.mk9h.cn/'
+      appId = 'wx4d8a34c8d4494872'
+    }
+
+    if (!appId) {
       notification.warning({
         top: 92,
-        message: 'nginx鏈嶅姟灏氭湭寮�鍚紝涓嶅彲鍙戦�佹ā鏉挎秷鎭��',
+        message: '灏氭湭娣诲姞鍏紬鍙稩D锛屼笉鍙彂閫佹ā鏉挎秷鎭��',
         duration: 5
       })
       return
@@ -2562,13 +3164,6 @@
     param.LText = Utils.getuuid()
     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) && window.GLOB.sysType !== 'cloud') {
-      domain1 = 'https://cloud.mk9h.cn/'
-      domain2 = 'https://cloud.mk9h.cn:8443/'
-    }
 
     Api.genericInterface(param).then(res => {
       // res.send_data = [{openid: 'o2E7gvoSFvQRG7I8_gZxf4y3ONkQ', send_id: Utils.getuuid(), p1: '010000000001', p2: '鏄庣', p3: 'dddd', p4: '椤洪', p5: '鎴愬姛'}]
@@ -2632,62 +3227,63 @@
         return m
       })
 
-      Api.wxAccessToken(domain1).then(res => {
-        if (!res.oa_access_token) return
-  
-        params.forEach(n => {
-          Api.wxNginxRequest(`${domain2}cgi-bin/message/template/send?access_token=${res.oa_access_token}`, 'post', JSON.stringify(n)).then(re => {
-            if (verify.wxNoteCallback === 'true') {
-              let msg = re.errmsg || ''
+      // cgi-bin/message/template/send
+      params.forEach(n => {
+        Api.directRequest({
+          url: domain + 'wechat/send?appid=' + appId,
+          method: 'post',
+          data: JSON.stringify(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: msg
-              }
-
-              _p.LText = Utils.getuuid()
-              _p.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-              _p.secretkey = Utils.encrypt(_p.LText, _p.timestamp)
-
-              Api.genericInterface(_p).then(result => {
-                if (!result.status) {
-                  notification.warning({
-                    top: 92,
-                    message: result.message,
-                    duration: 5
-                  })
-                }
-              })
-            } else if (re.errcode !== 0 && re.errmsg) {
-              let msgs = [
-                {errcode: -1, errmsg: '绯荤粺绻佸繖锛岃绋嶅�欏啀璇�'},
-                {errcode: 40001, errmsg: 'access_token 鏃犳晥'},
-                {errcode: 40003, errmsg: '涓嶅悎娉曠殑 OpenID'},
-                {errcode: 40014, errmsg: '涓嶅悎娉曠殑 access_token'},
-                {errcode: 40033, errmsg: '涓嶅悎娉曠殑璇锋眰瀛楃'},
-                {errcode: 43004, errmsg: '闇�瑕佹帴鏀惰�呭叧娉�'},
-                {errcode: 43019, errmsg: '闇�瑕佸皢鎺ユ敹鑰呬粠榛戝悕鍗曚腑绉婚櫎'},
-                {errcode: 50005, errmsg: '鐢ㄦ埛鏈叧娉ㄥ叕浼楀彿'}
-              ]
-
-              let msg = msgs.filter(m => m.errcode === re.errcode)[0]
-              msg = msg || re
-
-              notification.warning({
-                top: 92,
-                message: msg.errmsg,
-                duration: 5
-              })
+            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: msg
+            }
+
+            _p.LText = Utils.getuuid()
+            _p.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+            _p.secretkey = Utils.encrypt(_p.LText, _p.timestamp)
+
+            Api.genericInterface(_p).then(result => {
+              if (!result.status) {
+                notification.warning({
+                  top: 92,
+                  message: result.message,
+                  duration: 5
+                })
+              }
+            })
+          } else if (re.errcode !== 0 && re.errmsg) {
+            let msgs = [
+              {errcode: -1, errmsg: '绯荤粺绻佸繖锛岃绋嶅�欏啀璇�'},
+              {errcode: 40001, errmsg: 'access_token 鏃犳晥'},
+              {errcode: 40003, errmsg: '涓嶅悎娉曠殑 OpenID'},
+              {errcode: 40014, errmsg: '涓嶅悎娉曠殑 access_token'},
+              {errcode: 40033, errmsg: '涓嶅悎娉曠殑璇锋眰瀛楃'},
+              {errcode: 43004, errmsg: '闇�瑕佹帴鏀惰�呭叧娉�'},
+              {errcode: 43019, errmsg: '闇�瑕佸皢鎺ユ敹鑰呬粠榛戝悕鍗曚腑绉婚櫎'},
+              {errcode: 50005, errmsg: '鐢ㄦ埛鏈叧娉ㄥ叕浼楀彿'}
+            ]
+
+            let msg = msgs.filter(m => m.errcode === re.errcode)[0]
+            msg = msg || re
+
+            notification.warning({
+              top: 92,
+              message: msg.errmsg,
+              duration: 5
+            })
+          }
         })
       })
     })
@@ -2963,7 +3559,7 @@
    */
   execError = (res = {}) => {
     const { btn } = this.props
-    const { autoMatic } = this.state
+    const { autoMatic, dict } = this.state
 
     if (this.preCallback) {
       this.setState({
@@ -2975,7 +3571,7 @@
     } else if (autoMatic) {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: 10
       })
 
@@ -3009,19 +3605,20 @@
       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, '')
+    } else if (/@close_tab@|@close_popup@|@goback@|@open_target_menu@/i.test(res.message)) {
+      sign = res.message.match(/@close_tab@|@close_popup@|@goback@|@open_target_menu@/i)[0].toLowerCase()
+      res.message = res.message.replace(/@close_tab@|@close_popup@|@goback@|@open_target_menu@/i, '')
     }
 
     if (res.ErrCode === 'E') {
-      let msg = res.message || '鎵ц澶辫触锛�'
+      let msg = res.message || dict['exc_fail'] || '鎵ц澶辫触锛�'
       if (/\n|\r/.test(msg)) {
         msg = msg.replace(/\n|\r/ig, '<br/>')
         msg = <span dangerouslySetInnerHTML={{__html: msg}}></span>
       }
       Modal.error({
         title: msg,
+        okText: dict['got_it'] || '鐭ラ亾浜�',
         onOk: () => {
           this.errorContinue(sign)
         }
@@ -3030,18 +3627,18 @@
     } else if (res.ErrCode === 'N') {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || '鎵ц澶辫触锛�')
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     } else if (res.ErrCode === '-2') {
       this.setState({
         loadingNumber: '',
@@ -3078,8 +3675,47 @@
     } else if (btn.execError === 'closepoptab' || sign === '@close_popup@') {
       MKEmitter.emit('popclose')
     } else if (btn.execError !== 'never') {
+      let tabId = ''
+      if (btn.refreshTab && btn.refreshTab.length > 0) {
+        tabId = btn.refreshTab[btn.refreshTab.length - 1]
+      }
+      if (tabId && btn.$MenuID === tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃讹紝鍋滄鍏朵粬鎿嶄綔
+        MKEmitter.emit('reloadMenuView', tabId)
+        return
+      }
+
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn, '', this.state.selines)
+
+      if (btn.syncComponentId) {
+        if (btn.syncComponentId === 'multiComponent') {
+          btn.syncComponentIds.forEach((id, i) => {
+            setTimeout(() => {
+              if (/\$focus/.test(id)) {
+                MKEmitter.emit('reloadData', id.split('$')[0], id.split('$')[1])
+              } else {
+                MKEmitter.emit('reloadData', id)
+              }
+            }, 20 * i)
+          })
+        } else if (/\$focus/.test(btn.syncComponentId)) {
+          MKEmitter.emit('reloadData', btn.syncComponentId.split('$')[0], btn.syncComponentId.split('$')[1])
+        } else {
+          if (btn.syncDelay) {
+            this.delayTimer && clearTimeout(this.delayTimer)
+            this.delayTimer = setTimeout(() => {
+              MKEmitter.emit('reloadData', btn.syncComponentId)
+            }, btn.syncDelay)
+          } else {
+            MKEmitter.emit('reloadData', btn.syncComponentId)
+          }
+        }
+      }
+
+      if (tabId) {
+        MKEmitter.emit('reloadMenuView', tabId)
+      }
     }
+
     if (btn.OpenType === 'form') {
       let data = this.props.selectedData && this.props.selectedData[0] ? this.props.selectedData[0] : null
 
@@ -3100,6 +3736,35 @@
 
     if (window.GLOB.breakpoint) {
       MKEmitter.emit('refreshDebugTable')
+    }
+
+    if (sign === '@open_target_menu@' && btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0) {
+      let id = ''
+      if (this.state.selines && this.state.selines.length > 0 && btn.Ot !== 'notRequired') {
+        if (btn.Ot === 'requiredOnce') {
+          id = this.state.selines.map(d => d.$$uuid).filter(Boolean).join(',')
+        } else {
+          id = this.state.selines[0].$$uuid
+        }
+      }
+
+      let menuId = btn.openmenu.slice(-1)[0]
+      let menu = null
+
+      if (window.GLOB.mkThdMenus.has(menuId)) {
+        menu = {...window.GLOB.mkThdMenus.get(menuId), param: { $BID: id || '' }}
+      } else if (btn.MenuID) {
+        menu = {
+          MenuID: btn.MenuID,
+          MenuName: btn.MenuName,
+          type: btn.tabType,
+          param: { $BID: id || '' }
+        }
+      }
+
+      if (menu) {
+        MKEmitter.emit('modifyTabs', menu, true)
+      }
     }
 
     if (btn.execError === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
@@ -3235,8 +3900,8 @@
 
   modelconfirm = () => {
     const { BID } = this.props
-    const { btnconfig, selines } = this.state
-    let _this = this
+    const { btnconfig, selines, dict } = this.state
+    let that = this
 
     let result = []
     let _data = {}
@@ -3379,15 +4044,17 @@
       this.execSubmit(selines, () => {}, result)
     } else {
       confirm({
-        title: btnconfig.setting.tipTitle || '纭畾瑕佹墽琛屽悧?',
+        title: btnconfig.setting.tipTitle || dict['exec_sure'] || '纭畾瑕佹墽琛屽悧?',
+        okText: dict['ok'] || '纭畾',
+        cancelText: dict['cancel'] || '鍙栨秷',
         onOk() {
           return new Promise(resolve => {
-            _this.execSubmit(selines, resolve, result)
+            that.execSubmit(selines, resolve, result)
           })
         },
         onCancel() {
-          _this.preCallback && _this.preCallback()
-          _this.setState({ loading: false })
+          that.preCallback && that.preCallback()
+          that.setState({ loading: false })
         }
       })
     }
@@ -3398,7 +4065,7 @@
    */
   getModels = () => {
     const { BID, btn, BData } = this.props
-    const { btnconfig, visible } = this.state
+    const { btnconfig, visible, dict } = this.state
 
     if (!btnconfig || !btnconfig.setting) return null
 
@@ -3434,10 +4101,10 @@
           />
           <div className="ant-drawer-footer" style={{ position: 'absolute', zIndex: 1, right: 0, bottom: 0, width: '100%', borderTop: '1px solid #e9e9e9', padding: '10px 16px', background: '#fff', textAlign: 'right'}}>
             <Button onClick={this.handleCancel} style={{ marginRight: 8 }}>
-              {btnconfig.setting.formType !== 'check' ? '鍙栨秷' : '鍏抽棴'}
+              {btnconfig.setting.formType !== 'check' ? dict['cancel'] || '鍙栨秷' : dict['close'] || '鍏抽棴'}
             </Button>
             {btnconfig.setting.formType !== 'check' ? <Button onClick={this.handleOk} loading={this.state.confirmLoading} type="primary">
-              纭畾
+              {dict['ok'] || '纭畾'}
             </Button> : null}
           </div>
         </Drawer>
@@ -3465,6 +4132,8 @@
           wrapClassName={'action-modal' + (btnconfig.setting.moveable === 'true' ? ' moveable-modal modal-' + btn.uuid : '')}
           visible={visible}
           width={width}
+          okText={dict['ok'] || '纭畾'}
+          cancelText={dict['cancel'] || '鍙栨秷'}
           onOk={this.handleOk}
           maskStyle={btnconfig.setting.moveable === 'true' ?  {backgroundColor: 'rgba(0, 0, 0, 0.15)'} : null}
           confirmLoading={this.state.confirmLoading}
@@ -3529,7 +4198,7 @@
 
   changeLineCount = (count) => {
     const { btn, selectedData } = this.props
-    const { disabled } = this.state
+    const { disabled, dict } = this.state
 
     if (disabled) return
 
@@ -3539,7 +4208,7 @@
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨琛岋紒',
+        message: dict['select_row'] || '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return
@@ -3547,7 +4216,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
diff --git a/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx b/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx
index 05fb8a7..f3e36e6 100644
--- a/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/mkcounter/index.jsx
@@ -35,10 +35,10 @@
     let val = count - 1
 
     if (btn.min !== '' && val < btn.min) {
-      message.warning(`涓嶅彲灏忎簬${btn.min}!`)
+      message.warning(`${window.GLOB.dict['less_limit'] || '涓嶅彲灏忎簬'}${btn.min}!`)
       return
     } else if (btn.max !== '' && val > btn.max) {
-      message.warning(`涓嶅彲澶т簬${btn.max}!`)
+      message.warning(`${window.GLOB.dict['max_limit'] || '涓嶅彲澶т簬'}${btn.max}!`)
       return
     }
 
@@ -58,10 +58,10 @@
     let val = count + 1
 
     if (btn.min !== '' && val < btn.min) {
-      message.warning(`涓嶅彲灏忎簬${btn.min}!`)
+      message.warning(`${window.GLOB.dict['less_limit'] || '涓嶅彲灏忎簬'}${btn.min}!`)
       return
     } else if (btn.max !== '' && val > btn.max) {
-      message.warning(`涓嶅彲澶т簬${btn.max}!`)
+      message.warning(`${window.GLOB.dict['max_limit'] || '涓嶅彲澶т簬'}${btn.max}!`)
       return
     }
 
@@ -79,14 +79,14 @@
     const { count, orival } = this.state
 
     if (count === '') {
-      message.warning(`涓嶅彲涓虹┖!`)
+      message.warning(window.GLOB.dict['not_empty'] || '涓嶅彲涓虹┖锛�')
       this.setState({count: 0})
       return
     } else if (btn.min !== '' && count < btn.min) {
-      message.warning(`涓嶅彲灏忎簬${btn.min}!`)
+      message.warning(`${window.GLOB.dict['less_limit'] || '涓嶅彲灏忎簬'}${btn.min}!`)
       return
     } else if (btn.max !== '' && count > btn.max) {
-      message.warning(`涓嶅彲澶т簬${btn.max}!`)
+      message.warning(`${window.GLOB.dict['max_limit'] || '涓嶅彲澶т簬'}${btn.max}!`)
       return
     }
 
diff --git a/src/tabviews/zshare/actionList/popupbutton/index.jsx b/src/tabviews/zshare/actionList/popupbutton/index.jsx
index dce034b..8ef0d17 100644
--- a/src/tabviews/zshare/actionList/popupbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/popupbutton/index.jsx
@@ -30,6 +30,7 @@
     disabled: false,
     hidden: false,
     loading: false,
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -143,7 +144,7 @@
    */
   actionTrigger = (triggerId, record, type, lid) => {
     const { setting, BID, btn, selectedData, LID } = this.props
-    const { loading, disabled } = this.state
+    const { loading, disabled, dict } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -154,7 +155,7 @@
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
+        message: dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
       return
@@ -162,7 +163,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: data.length === 0 ? '璇烽�夋嫨琛岋紒' : '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: data.length === 0 ? dict['select_row'] || '璇烽�夋嫨琛岋紒' : dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -183,7 +184,7 @@
       visible: true
     })
 
-    if (window.GLOB.systemType === 'production') {
+    if (window.GLOB.systemType === 'production') { // positecgroup
       MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '寮圭獥锛堟爣绛撅級'})
     }
   }
@@ -230,7 +231,7 @@
 
   getPop = () => {
     const { btn } = this.props
-    const { popData, primaryId, visible } = this.state
+    const { popData, primaryId, visible, dict } = this.state
 
     let ratio = btn.ratio || 85
 
@@ -248,7 +249,7 @@
         visible={visible}
         onCancel={this.popclose}
         footer={[
-          <Button key="close" onClick={this.popclose}>鍏抽棴</Button>
+          <Button key="close" onClick={this.popclose}>{dict['close'] || '鍏抽棴'}</Button>
         ]}
         destroyOnClose
       >
@@ -292,7 +293,7 @@
           {btn.$view === 'popview' ? <PopView Tab={btn} param={{$BID: (popData ? primaryId : this.props.BID), ...(popData || this.props.BData || {})}} /> : null}
           <div className="close-drawer">
             <Button onClick={this.popclose}>
-              鍏抽棴
+              {dict['close'] || '鍏抽棴'}
             </Button>
           </div>
         </Drawer>
diff --git a/src/tabviews/zshare/actionList/printbutton/index.jsx b/src/tabviews/zshare/actionList/printbutton/index.jsx
index 8373813..fd2771a 100644
--- a/src/tabviews/zshare/actionList/printbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -8,6 +8,7 @@
 import Utils from '@/utils/utils.js'
 import asyncSpinComponent from '@/utils/asyncSpinComponent'
 import { updateForm } from '@/utils/utils-update.js'
+import UtilsDM from '@/utils/utils-datamanage.js'
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
 // import './index.scss'
@@ -37,7 +38,8 @@
     loading: false,
     disabled: false,
     hidden: false,
-    autoMatic: false
+    autoMatic: false,
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -132,7 +134,7 @@
    */
   actionTrigger = (triggerId, record, type, lid) => {
     const { BID, btn, selectedData, setting, LID } = this.props
-    const { loading, disabled } = this.state
+    const { loading, disabled, dict } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -141,7 +143,7 @@
     if (setting.supModule && !BID) {
       notification.warning({
         top: 92,
-        message: '闇�瑕佷笂绾т富閿�硷紒',
+        message: dict['sup_key_req'] || '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
       return
@@ -149,14 +151,14 @@
 
     this.setState({autoMatic: type === 'autoMatic'})
 
-    let _this = this
+    let that = this
     let data = record || selectedData || []
 
     if (btn.Ot !== 'notRequired' && data.length === 0) {
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨琛岋紒',
+        message: dict['select_row'] || '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return
@@ -164,21 +166,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
-        duration: 5
-      })
-      return
-    } else if (!btn.verify || !btn.verify.printMode) {
-      notification.warning({
-        top: 92,
-        message: '璇峰畬鍠勬墦鍗伴獙璇佷俊鎭紒',
-        duration: 5
-      })
-      return
-    } else if (btn.intertype === 'system' && btn.verify.dataType === 'custom' && (!btn.verify.setting || btn.verify.columns.length === 0)) {
-      notification.warning({
-        top: 92,
-        message: '鑷畾涔夋墦鍗版暟鎹璁剧疆鏁版嵁婧愶紒',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -203,19 +191,21 @@
     } else if (btn.execMode === 'prompt') {
       this.setState({ loading: true })
       confirm({
-        title: '纭畾瑕佹墽琛屽悧?',
+        title: dict['exec_sure'] || '纭畾瑕佹墽琛屽悧?',
+        okText: dict['ok'] || '纭畾',
+        cancelText: dict['cancel'] || '鍙栨秷',
         onOk() {
-          _this.triggerPrint(data)
+          that.triggerPrint(data)
         },
         onCancel() {
-          _this.setState({ loading: false })
+          that.setState({ loading: false })
         }
       })
     } else {
       this.triggerPrint(data)
     }
 
-    if (window.GLOB.systemType === 'production') {
+    if (window.GLOB.systemType === 'production') { // positecgroup
       MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '鏍囩鎵撳嵃'})
     }
   }
@@ -507,7 +497,7 @@
       if (list.length === 0) {
         notification.warning({
           top: 92,
-          message: '鏈幏鍙栧埌鎵撳嵃鏁版嵁锛�',
+          message: window.GLOB.dict['no_data'] || '鏈幏鍙栧埌鎵撳嵃鏁版嵁锛�',
           duration: 5
         })
         return false
@@ -534,7 +524,7 @@
       if (!result.ConfigParam) {
         notification.warning({
           top: 92,
-          message: '鏈幏鍙栧埌鎵撳嵃妯℃澘淇℃伅锛�',
+          message: window.GLOB.dict['no_print_temp'] || '鏈幏鍙栧埌鎵撳嵃妯℃澘淇℃伅锛�',
           duration: 5
         })
         this.setState({ loading: false })
@@ -785,7 +775,7 @@
 
       notification.warning({
         top: 92,
-        message: '鑷畾涔夊嚱鏁版墽琛岄敊璇紒',
+        message: window.GLOB.dict['func_error'] || '鑷畾涔夊嚱鏁版墽琛岄敊璇紒',
         duration: 5
       })
     }
@@ -933,7 +923,7 @@
           Promise.all(deffers).then(result => {
             let errorMsg = ''
             result.forEach(res => {
-              if (!res.status) {
+              if (!res.status && !errorMsg) {
                 errorMsg = res
               }
             })
@@ -958,6 +948,65 @@
    */
   getDefaultSql = (formlist, data, ID) => {
     const { BID, btn, columns } = this.props
+
+    if (window.backend && window.GLOB.CacheData.has('sql_' + btn.uuid)) {
+      let setting = {...btn.verify.setting}
+      setting.interType = 'system'
+      setting.uuid = btn.uuid
+
+      let _param = UtilsDM.getQueryDataParams(setting, [], setting.order, 1, 9999, BID, ID)
+      let item = window.GLOB.CacheData.get('sql_' + btn.uuid)
+
+      _param.data[0].exps = _param.data[0].exps.filter(n => n.key !== 'mk_search')
+      let formkeys = []
+
+      formlist.forEach(form => {
+        if (!item.reps.includes(form.key)) return
+
+        formkeys.push(form.key)
+
+        let val = form.value
+        if (form.type === 'number' || form.type === 'rate') {
+          if (isNaN(val)) {
+            val = 0
+          }
+        } else if (['date', 'datemonth'].includes(form.type)) {
+          val = val || '1949-10-01'
+        }
+
+        _param.data[0].exps.push({
+          key: 'mk_' + form.key + '_mk',
+          value: val
+        })
+      })
+
+      if (data && columns && columns.length > 0) {
+        let datavars = {}
+  
+        Object.keys(data).forEach(key => {
+          datavars[key.toLowerCase()] = data[key]
+        })
+    
+        columns.forEach(col => {
+          if (!item.reps.includes(col.field) || formkeys.includes(col.field)) return
+          if (!col.datatype) return
+  
+          let _key = col.field.toLowerCase()
+          let _val = datavars.hasOwnProperty(_key) ? datavars[_key] : ''
+  
+          if (/^date/ig.test(col.datatype) && !_val) {
+            _val = '1949-10-01'
+          }
+
+          _param.data[0].exps.push({
+            key: 'mk_' + col.field + '_mk',
+            value: _val
+          })
+        })
+      }
+
+      return _param
+    }
 
     let arrFields = btn.verify.columns.map(col => col.field).join(',')
 
@@ -1009,7 +1058,7 @@
     }
 
     let isDataM = sessionStorage.getItem('dataM') === 'true'
-    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript + _tailScript)
+    let custompage = /@pageSize@|@orderBy@|@mk_total/i.test(_dataresource + _customScript + _tailScript)
     let regoptions = [
       { reg: /@orderBy@/ig, value: btn.verify.setting.order },
       { reg: /@pageSize@/ig, value: '9999' },
@@ -1020,6 +1069,7 @@
       { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
       { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
       { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      { reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
       { reg: /@typename@/ig, value: `'admin'`},
       { reg: /\$@/ig, value: isDataM ? '/*' : ''},
       { reg: /@\$/ig, value: isDataM ? '*/' : ''},
@@ -1046,8 +1096,6 @@
     // 鑾峰彇瀛楁閿�煎
     formlist.forEach(form => {
       let _key = form.key.toLowerCase()
-
-      if (_vars.includes(_key)) return
 
       _vars.push(_key)
 
@@ -1170,8 +1218,8 @@
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
     if (window.GLOB.debugger === true) {
-      _customScript && console.info(`${btn.logLabel ? `/*${btn.logLabel} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
-      LText && console.info(`${btn.logLabel ? `/*${btn.logLabel} 鏁版嵁婧�*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
+      _customScript && window.mkInfo(`${btn.logLabel ? `/*${btn.logLabel} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
+      LText && window.mkInfo(`${btn.logLabel ? `/*${btn.logLabel} 鏁版嵁婧�*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
     }
 
     if (btn.logLabel) {
@@ -1344,7 +1392,7 @@
     let imgs = []
 
     if (!res.ConfigParam) {
-      error = '鏈幏鍙栧埌鎵撳嵃妯℃澘淇℃伅锛�'
+      error = window.GLOB.dict['no_print_temp'] || '鏈幏鍙栧埌鎵撳嵃妯℃澘淇℃伅锛�'
     } else {
       try {
         configParam = JSON.parse(window.decodeURIComponent(window.atob(res.ConfigParam)))
@@ -1445,8 +1493,13 @@
           if (item.Field) {
             fields.push(item.Field)
             // 鏉$爜浜岀淮鐮佸瓧娈典笉鍙负绌�
-            if (item.Type === 'qrcode' || item.Type === 'barcode') {
+            if (item.Type === 'barcode') {
               nonEFields.push(item.Field)
+            }
+          } else if (!item.Value) {
+            // 鏉$爜浜岀淮鐮佸唴瀹逛笉鍙负绌�
+            if (item.Type === 'barcode') {
+              error = '妯℃澘涓潯鐮�/浜岀淮鐮佸唴瀹逛笉鍙负绌猴紒'
             }
           }
 
@@ -1501,7 +1554,7 @@
     if (list.length === 0) {
       notification.warning({
         top: 92,
-        message: '鏈幏鍙栧埌鎵撳嵃鏁版嵁锛�',
+        message: window.GLOB.dict['no_data'] || '鏈幏鍙栧埌鎵撳嵃鏁版嵁锛�',
         duration: 5
       })
       this.setState({ loading: false })
@@ -1620,7 +1673,7 @@
     Api.postekPrint(param).then(res => {
       if (res.retval === '0') {
         if (params.length === 0) {
-          this.execSuccess({ ErrCode: 'S', message: '鎵撳嵃璇锋眰宸插彂鍑恒��', status: true })
+          this.execSuccess({ ErrCode: 'S', message: window.GLOB.dict['print_out'] || '鎵撳嵃璇锋眰宸插彂鍑恒��', status: true })
         } else {
           setTimeout(() => {
             this.loopRFIDPrint(params)
@@ -1638,6 +1691,8 @@
 
   execPrint = (list, template) => {
     const { btn } = this.props
+    const { dict } = this.state
+
     let _errors = []
 
     let defaultPrinter = btn.verify.defaultPrinter || 'lackprinter'
@@ -1738,13 +1793,13 @@
       if (btn.verify.emptyTip === 'false') {
         this.execSuccess({
           ErrCode: '-1',
-          message: '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
+          message: dict['no_data'] || '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
           status: true
         })
       } else {
         this.execError({
           ErrCode: 'N',
-          message: '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
+          message: dict['no_data'] || '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
           status: false
         })
       }
@@ -1758,7 +1813,7 @@
           lackerror.push(`鏁版嵁涓湭鑾峰彇鍒版ā鏉匡紙${err.title}锛�${err.lacks.join('銆�')} 瀛楁`)
         }
         if (err.emptys.length > 0) {
-          emptyerror.push(`鏁版嵁涓ā鏉匡紙${err.title}锛� ${err.emptys.join('銆�')} 瀛楁涓嶅彲涓虹┖`)
+          emptyerror.push(dict['not_empty'] ? `${err.title}: ${err.emptys.join('銆�')} ${dict['not_empty']}` : `鏁版嵁涓ā鏉匡紙${err.title}锛� ${err.emptys.join('銆�')} 瀛楁涓嶅彲涓虹┖`)
         }
       })
 
@@ -1782,7 +1837,7 @@
     if (printerList.length === 0) {
       this.execSuccess({
         ErrCode: '-1',
-        message: '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
+        message: dict['no_data'] || '鏈幏鍙栧埌鎵撳嵃淇℃伅锛�',
         status: true
       })
       return
@@ -1794,7 +1849,7 @@
       this.syncMessageSend(printerList, () => {
         this.execSuccess({
           ErrCode: 'S',
-          message: '鎵撳嵃璇锋眰宸插彂鍑恒��',
+          message: dict['print_out'] || '鎵撳嵃璇锋眰宸插彂鍑恒��',
           status: true
         })
       })
@@ -1805,7 +1860,7 @@
       this.syncMessageSend(printerList, () => {
         this.execSuccess({
           ErrCode: 'S',
-          message: '鎵撳嵃璇锋眰宸插彂鍑恒��',
+          message: dict['print_out'] || '鎵撳嵃璇锋眰宸插彂鍑恒��',
           status: true
         })
       })
@@ -1856,7 +1911,7 @@
     socket.onerror = () => {
       this.execError({
         ErrCode: 'N',
-        message: '鏃犳硶杩炴帴鍒�:' + btn.verify.linkUrl,
+        message: (dict['un_connect'] || '鏃犳硶杩炴帴鍒�') + ':' + btn.verify.linkUrl,
         status: false
       })
     }
@@ -1892,17 +1947,18 @@
    */
   execSuccess = (res = {}) => {
     const { btn } = this.props
-    const { autoMatic, btnconfig } = this.state
+    const { autoMatic, btnconfig, dict } = this.state
 
     if ((res.ErrCode === 'S' || !res.ErrCode) || autoMatic) { // 鎵ц鎴愬姛
       notification.success({
         top: 92,
-        message: res.message || '鎵ц鎴愬姛锛�',
+        message: res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�',
         duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
       })
     } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
       Modal.success({
-        title: res.message || '鎵ц鎴愬姛锛�'
+        title: res.message || dict['exc_success'] || '鎵ц鎴愬姛锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
@@ -1941,7 +1997,7 @@
    */
   execError = (res) => {
     const { btn } = this.props
-    const { btnconfig, autoMatic } = this.state
+    const { btnconfig, autoMatic, dict } = this.state
 
     if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
       res.ErrCode = 'E'
@@ -1949,23 +2005,24 @@
 
     if (res.ErrCode === 'E' && !autoMatic) {
       Modal.error({
-        title: res.message || '鎵ц澶辫触锛�',
+        title: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
+        okText: dict['got_it'] || '鐭ラ亾浜�'
       })
     } else if (res.ErrCode === 'N' || autoMatic) {
       notification.error({
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
       })
     } else if (res.ErrCode === 'F') {
       notification.error({
         className: 'notification-custom-error',
         top: 92,
-        message: res.message || '鎵ц澶辫触锛�',
+        message: res.message || dict['exc_fail'] || '鎵ц澶辫触锛�',
         duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
       })
     } else if (res.ErrCode === 'NM') {
-      message.error(res.message || '鎵ц澶辫触锛�')
+      message.error(res.message || dict['exc_fail'] || '鎵ц澶辫触锛�')
     }
     
     this.setState({
@@ -2113,8 +2170,8 @@
   }
 
   modelconfirm = () => {
-    const { btnconfig, selines } = this.state
-    let _this = this
+    const { btnconfig, selines, dict } = this.state
+    let that = this
     let result = []
     let _data = {}
     let BData = {}
@@ -2256,12 +2313,14 @@
       this.execSubmit(selines, () => {}, result)
     } else {
       confirm({
-        title: '纭畾瑕佹墽琛屽悧?',
+        title: dict['exec_sure'] || '纭畾瑕佹墽琛屽悧?',
+        okText: dict['ok'] || '纭畾',
+        cancelText: dict['cancel'] || '鍙栨秷',
         onOk() {
-          _this.triggerPrint(selines, result)
+          that.triggerPrint(selines, result)
         },
         onCancel() {
-          _this.setState({ loading: false })
+          that.setState({ loading: false })
         }
       })
     }
@@ -2272,7 +2331,7 @@
    */
   getModels = () => {
     const { BID, btn } = this.props
-    const { btnconfig } = this.state
+    const { btnconfig, dict } = this.state
 
     if (!this.state.visible || !btnconfig || !btnconfig.setting) return null
 
@@ -2306,6 +2365,8 @@
         visible={this.state.visible}
         confirmLoading={this.state.confirmLoading}
         width={width}
+        okText={dict['ok'] || '纭畾'}
+        cancelText={dict['cancel'] || '鍙栨秷'}
         maskStyle={btnconfig.setting.moveable === 'true' ?  {backgroundColor: 'rgba(0, 0, 0, 0.15)'} : null}
         onOk={this.handleOk}
         onCancel={this.handleCancel}
diff --git a/src/tabviews/zshare/actionList/tabbutton/index.jsx b/src/tabviews/zshare/actionList/tabbutton/index.jsx
index d96f206..e6c76ac 100644
--- a/src/tabviews/zshare/actionList/tabbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -22,7 +22,8 @@
   state = {
     disabled: false,
     hidden: false,
-    primaryId: ''
+    primaryId: '',
+    dict: window.GLOB.dict
   }
 
   UNSAFE_componentWillMount () {
@@ -102,7 +103,7 @@
    */
   actionTrigger = (triggerId, record, type, lid) => {
     const { btn, selectedData, BID, LID } = this.props
-    const { disabled } = this.state
+    const { disabled, dict } = this.state
 
     if (disabled || btn.multiMenus) return
     if (triggerId && btn.uuid !== triggerId) return
@@ -114,7 +115,7 @@
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨琛岋紒',
+        message: dict['select_row'] || '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return false
@@ -122,7 +123,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -187,7 +188,7 @@
       if (!menu) {
         notification.warning({
           top: 92,
-          message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
+          message: dict['no_perm'] || '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
           duration: 5
         })
         return
@@ -212,13 +213,14 @@
       MKEmitter.emit('openNewTab')
     }
 
-    if (window.GLOB.systemType === 'production') {
+    if (window.GLOB.systemType === 'production') { // positecgroup
       MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '鏍囩椤�'})
     }
   }
 
   triggerMenu = (tab) => {
     const { btn, selectedData, BID } = this.props
+    const { dict } = this.state
 
     let data = selectedData || []
 
@@ -226,7 +228,7 @@
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨琛岋紒',
+        message: dict['select_row'] || '璇烽�夋嫨琛岋紒',
         duration: 5
       })
       return false
@@ -234,7 +236,7 @@
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
-        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        message: dict['select_single_row'] || '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
       return
@@ -283,7 +285,7 @@
     if (!menu) {
       notification.warning({
         top: 92,
-        message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
+        message: dict['no_perm'] || '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
         duration: 5
       })
       return
@@ -298,7 +300,7 @@
       MKEmitter.emit('openNewTab')
     }
 
-    if (window.GLOB.systemType === 'production') {
+    if (window.GLOB.systemType === 'production') { // positecgroup
       MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '鏍囩椤�'})
     }
   }
diff --git a/src/tabviews/zshare/fileupload/index.jsx b/src/tabviews/zshare/fileupload/index.jsx
index ebf75f0..e061bd3 100644
--- a/src/tabviews/zshare/fileupload/index.jsx
+++ b/src/tabviews/zshare/fileupload/index.jsx
@@ -1,10 +1,8 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import moment from 'moment'
 import { Upload, Button, Progress, notification } from 'antd'
 import { UploadOutlined } from '@ant-design/icons'
-import SparkMD5 from 'spark-md5'
 
 import Api from '@/api'
 import MKEmitter from '@/utils/events.js'
@@ -195,44 +193,6 @@
     })
   }
 
-  shardupload = (param, file_name) => {
-    let form = new FormData()
-
-    form.append('file', param.binary)
-    form.append('fileMd5', param.fileMd5)
-    form.append('shardingMd5', param.fileMd5)
-    form.append('baseDomain', window.GLOB.baseurl)
-    form.append('rootPath', 'Content/images/upload/')
-    form.append('fileName', param.fileName)
-    form.append('fileExt', param.fileType)
-    form.append('shardingCnt', 1)
-    form.append('shardingNo', 1)
-    form.append('LoginUID', sessionStorage.getItem('LoginUID') || '')
-    form.append('UserID', sessionStorage.getItem('UserID') || '')
-
-    Api.getLargeFileUpload(form).then(res => {
-      if (res.status) {
-        if (res.urlPath) {
-          this.onUpdate(res.urlPath, file_name)
-        } else {
-          this.onFail()
-        }
-        this.setState({
-          percent: 100
-        }, () => {
-          setTimeout(() => {
-            this.setState({
-              showprogress: false,
-              percent: 0
-            })
-          }, 200)
-        })
-      } else {
-        this.onFail(res.message)
-      }
-    })
-  }
-
   getuuid = () => {
     let uuid = []
     let _options = '0123456789abcdefghigklmnopqrstuv'
@@ -406,49 +366,31 @@
       return false
     }
 
-    // 鍏煎鎬х殑澶勭悊
-    let spark = new SparkMD5.ArrayBuffer()         // 瀵筧rrayBuffer鏁版嵁杩涜md5鍔犲瘑锛屼骇鐢熶竴涓猰d5瀛楃涓�
-    let totalFileReader = new FileReader()         // 鐢ㄤ簬璁$畻鍑烘�绘枃浠剁殑fileMd5
-    let param = {}
+    let form = new FormData()
 
-    param.fileName = file.name.replace(/\.{1}[^.]*$/ig, '')  // 鏂囦欢鍚嶏紙鍘婚櫎鍚庣紑鍚嶏級
-    param.fileType = file.name.replace(/^.*\.{1}/ig, '')     // 鏂囦欢绫诲瀷
+    form.append('file', file)
 
-    if (!/^[A-Za-z0-9]+$/.test(param.fileName)) {            // 鏂囦欢鍚嶇О鍚湁鑻辨枃鍙婃暟瀛椾箣澶栧瓧绗︽椂锛屽悕绉扮郴缁熺敓鎴�
-      param.fileName = moment().format('YYYYMMDDHHmmss') + this.getuuid()
-    }
-
-    totalFileReader.readAsArrayBuffer(file)
-    totalFileReader.onload = (e) => {   // 瀵规暣涓猼otalFile鐢熸垚md5
-      spark.append(e.target.result)
-      param.fileMd5 = spark.end()       // 璁$畻鏁翠釜鏂囦欢鐨刦ileMd5
-      param.binary = file
-
-      let _param = new FormData()
-      _param.append('fileMd5', param.fileMd5)
-      
-      Api.getFilePreUpload(_param).then(res => {
-        if (res.status && res.urlPath) {
+    Api.getFileUpload(form).then(res => {
+      if (res.status) {
+        if (res.urlPath) {
           this.onUpdate(res.urlPath, file_name)
-          this.setState({
-            percent: 100
-          }, () => {
-            setTimeout(() => {
-              this.setState({
-                showprogress: false,
-                percent: 0
-              })
-            }, 200)
-          })
         } else {
-          this.shardupload(param, file_name)
+          this.onFail()
         }
-      })
-    }
-
-    totalFileReader.onerror = () => {
-      this.onFail('鏂囦欢璇诲彇澶辫触锛�')
-    }
+        this.setState({
+          percent: 100
+        }, () => {
+          setTimeout(() => {
+            this.setState({
+              showprogress: false,
+              percent: 0
+            })
+          }, 200)
+        })
+      } else {
+        this.onFail(res.message)
+      }
+    })
 
     return false
   }
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index f82ecc8..5d4e1e1 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -4,9 +4,9 @@
 import { Form, Row, Col, notification, Tooltip, Rate } from 'antd'
 import { QuestionCircleOutlined, StarFilled } from '@ant-design/icons'
 import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
-import { formRule } from '@/utils/option.js'
 import Utils from '@/utils/utils.js'
 import asyncComponent from '@/utils/asyncComponent'
 import MKEmitter from '@/utils/events.js'
@@ -48,7 +48,8 @@
     timestamp: '',
     n_id: '',
     focusId: '',
-    reFocusId: ''
+    reFocusId: '',
+    dict: window.GLOB.dict
   }
 
   record = {}
@@ -56,6 +57,7 @@
 
   componentDidMount () {
     const { action, unload } = this.props
+    const { dict } = this.state
 
     let data = {}
     let BData = {}
@@ -68,11 +70,18 @@
     let fieldMap = new Map()
     let check = action.setting.formType === 'check'
 
-    if (this.props.data) {
+    if (this.props.data && !this.props.data.$$empty) {
       Object.keys(this.props.data).forEach(key => {
         data[key.toLowerCase()] = this.props.data[key]
       })
+    } else if (action.uuid && sessionStorage.getItem('local_' + action.uuid)) {
+      let _data = JSON.parse(sessionStorage.getItem('local_' + action.uuid))
+
+      Object.keys(_data).forEach(key => {
+        data[key.toLowerCase()] = _data[key]
+      })
     }
+
     if (this.props.BData) {
       Object.keys(this.props.BData).forEach(key => {
         BData[key.toLowerCase()] = this.props.BData[key]
@@ -132,6 +141,8 @@
       } else if (item.type === 'datetime') {
         item.type = 'date'
         item.precision = 'second'
+      } else if (item.type === 'fileupload') {
+        item.fieldlength = item.fieldlength || 512
       }
 
       if (!item.field || !['text', 'number', 'switch', 'check', 'rate', 'select', 'popSelect', 'link', 'cascader', 'linkMain', 'funcvar', 'date', 'datemonth', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color', 'vercode'].includes(item.type)) return false
@@ -145,6 +156,7 @@
 
       // 鏁版嵁鑷姩濉厖
       let readin = item.readin !== 'false'
+      item.local = item.readin === 'local'
       item.readin = item.readin !== 'false' && item.readin !== 'top'
       item.readonly = check || item.readonly === 'true'
       item.writein = item.writein !== 'false'
@@ -326,14 +338,14 @@
         if (item.required === 'true') {
           item.rules.push({
             required: true,
-            message: item.label + '涓嶅彲涓虹┖!'
+            message: item.label + (dict['not_empty'] || '涓嶅彲涓虹┖锛�')
           })
         }
 
         item.rules.push({
           validator: (rule, value, callback) => {
             if (/'/.test(value)) {
-              callback('涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒')
+              callback(dict['single_quot'] || '涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒')
             // } else if (/--/.test(value)) {
             //   callback('涓嶅彲浣跨敤 -- 锛�')
             } else {
@@ -345,7 +357,7 @@
         if (!item.lenControl || item.lenControl === 'limit') {
           item.rules.push({
             max: item.fieldlength,
-            message: formRule.input.formMessage.replace('@max', item.fieldlength)
+            message: (dict['max_char'] || '鏈�澶欯max涓瓧绗�').replace('@max', item.fieldlength)
           })
         }
 
@@ -357,7 +369,7 @@
             }
             item.rules.push({
               pattern: reg,
-              message: item.regularText || formRule.input.numbermsg
+              message: item.regularText || dict['enter_num'] || '璇疯緭鍏ユ暟瀛楋紒'
             })
           } else if (item.regular === 'letter') {
             let reg = /^[a-zA-Z]*$/
@@ -366,7 +378,7 @@
             }
             item.rules.push({
               pattern: reg,
-              message: item.regularText || formRule.input.lettermsg
+              message: item.regularText || dict['enter_letter'] || '璇疯緭鍏ュ瓧姣嶏紒'
             })
           } else if (item.regular === 'letter_number') {
             let reg = /^[a-zA-Z0-9]*$/
@@ -375,7 +387,7 @@
             }
             item.rules.push({
               pattern: reg,
-              message: item.regularText || '璇疯緭鍏ユ暟瀛楁垨瀛楁瘝'
+              message: item.regularText || dict['enter_num_letter'] || '璇疯緭鍏ユ暟瀛楁垨瀛楁瘝'
             })
           } else if (item.regular === 'letter&number') {
             let reg = /^[a-zA-Z0-9@_.]*$/
@@ -384,24 +396,24 @@
             }
             item.rules.push({
               pattern: reg,
-              message: item.regularText || '璇疯緭鍏ユ暟瀛椼�佸瓧姣嶄互鍙夽_.'
+              message: item.regularText || dict['enter_num_letter_char'] || '璇疯緭鍏ユ暟瀛椼�佸瓧姣嶄互鍙夽_.'
             })
           } else if (item.regular === 'phone') {
             item.rules.push({
               pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
-              message: item.regularText || '璇锋纭緭鍏ユ墜鏈哄彿'
+              message: item.regularText || dict['phone_error'] || '璇锋纭緭鍏ユ墜鏈哄彿'
             })
           } else if (item.regular === 'email') {
             item.rules.push({
               pattern: /^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/,
-              message: item.regularText || '璇锋纭緭鍏ラ偖绠卞湴鍧�'
+              message: item.regularText || dict['email_error'] || '璇锋纭緭鍏ラ偖绠卞湴鍧�'
             })
           }
         }
       } else if (item.type === 'number') {
         item.rules = [{
           required: true,
-          message: item.label + '涓嶅彲涓虹┖!'
+          message: item.label + (dict['not_empty'] || '涓嶅彲涓虹┖锛�')
         }]
 
         if (typeof(item.min) === 'number' || typeof(item.max) === 'number' || item.notZero === 'true') {
@@ -410,9 +422,9 @@
               if (isNaN(value)) {
                 callback()
               } else if (item.notZero === 'true' && value === 0) {
-                callback(item.label + '涓嶅彲涓�0')
+                callback(item.label + (dict['not_zero'] || '涓嶅彲涓�0'))
               } else if (typeof(item.min) === 'number' && value < item.min) {
-                if (item.min < 1e-6) {
+                if (item.min > 0 && item.min < 1e-6) {
                   if (item.min === 1e-6) {
                     callback(item.label + '鏈�灏忓�间负 0.000001')
                   } else if (item.min === 1e-7) {
@@ -426,13 +438,13 @@
                   } else if (item.min === 1e-11) {
                     callback(item.label + '鏈�灏忓�间负 0.00000000001')
                   } else {
-                    callback(item.label + '鏈�灏忓�间负 ' + item.min)
+                    callback(item.label + (dict['less_limit'] || '鏈�灏忓�间负 ') + item.min)
                   }
                 } else {
-                  callback(item.label + '鏈�灏忓�间负 ' + item.min)
+                  callback(item.label + (dict['less_limit'] || '鏈�灏忓�间负 ') + item.min)
                 }
               } else if (typeof(item.max) === 'number' && value > item.max) {
-                callback(item.label + '鏈�澶у�间负 ' + item.max)
+                callback(item.label + (dict['max_limit'] || '鏈�澶у�间负 ') + item.max)
               } else {
                 callback()
               }
@@ -443,14 +455,14 @@
         if (item.required === 'true') {
           item.rules.push({
             required: true,
-            message: item.label + '涓嶅彲涓虹┖!'
+            message: item.label + (dict['not_empty'] || '涓嶅彲涓虹┖锛�')
           })
         }
 
         item.rules.push({
           validator: (rule, value, callback) => {
             if (/'/.test(value)) {
-              callback('涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒')
+              callback(dict['single_quot'] || '涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒')
             // } else if (/--/.test(value)) {
             //   callback('涓嶅彲浣跨敤 -- 锛�')
             } else {
@@ -459,38 +471,38 @@
           }
         }, {
           max: item.fieldlength,
-          message: formRule.input.formMessage.replace('@max', item.fieldlength)
+          message: (dict['max_char'] || '鏈�澶欯max涓瓧绗�').replace('@max', item.fieldlength)
         })
       } else if (item.type === 'brafteditor') {
         if (item.required === 'true') {
           item.rules.push({
             required: true,
-            message: item.label + '涓嶅彲涓虹┖!'
+            message: item.label + (dict['not_empty'] || '涓嶅彲涓虹┖锛�')
           })
         }
 
         item.rules.push({
           max: item.fieldlength,
-          message: formRule.input.formMessage.replace('@max', item.fieldlength)
+          message: (dict['max_char'] || '鏈�澶欯max涓瓧绗�').replace('@max', item.fieldlength)
         })
       } else if (item.type === 'linkMain' || item.type === 'vercode') {
         if (item.required === 'true') {
           item.rules.push({
             required: true,
-            message: item.label + '涓嶅彲涓虹┖!'
+            message: item.label + (dict['not_empty'] || '涓嶅彲涓虹┖锛�')
           })
         }
       } else {
         if (item.required === 'true') {
           item.rules.push({
             required: true,
-            message: '璇烽�夋嫨' + item.label + '!'
+            message: (dict['select_tip'] || '璇烽�夋嫨') + item.label + '!'
           })
         }
         if (['cascader', 'checkbox', 'checkcard', 'fileupload', 'multiselect'].includes(item.type) && item.fieldlength) {
           item.rules.push({
             max: item.fieldlength,
-            message: formRule.input.formMessage.replace('@max', item.fieldlength)
+            message: (dict['max_char'] || '鏈�澶欯max涓瓧绗�').replace('@max', item.fieldlength)
           })
         }
       }
@@ -759,6 +771,7 @@
     if (action.subButton && action.subButton.resetForms) {
       MKEmitter.addListener('resetForms', this.resetForms)
     }
+    MKEmitter.addListener('resetFocus', this.resetFocus)
   }
 
   componentWillUnmount () {
@@ -766,6 +779,27 @@
       return
     }
     MKEmitter.removeListener('resetForms', this.resetForms)
+    MKEmitter.removeListener('resetFocus', this.resetFocus)
+  }
+
+  resetFocus = (id, field) => {
+    const { action } = this.props
+
+    if (id !== action.uuid.replace(/_pop$/, '')) return
+
+    let focusId = ''
+
+    this.state.formlist.forEach(item => {
+      if (item.field === field) {
+        focusId = item.uuid
+      }
+    })
+
+    if (!focusId) return
+
+    setTimeout(() => {
+      MKEmitter.emit('mkFC', 'focus', focusId)
+    }, 20)
   }
 
   resetForms = (id, data) => {
@@ -820,7 +854,9 @@
   }
 
   getFormData = (deForms) => {
-    if (deForms.length === 1) {
+    if (window.backend && window.GLOB.CacheData.has('sql_' + md5(this.props.action.uuid.replace(/_pop$/, '') + deForms[0].uuid))) {
+      this.improveBackActionForm(deForms)
+    } else if (deForms.length === 1) {
       this.improveSimpleActionForm(deForms)
     } else if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
       this.improveSimpleActionForm(deForms)
@@ -829,6 +865,115 @@
     }
   }
 
+  /**
+   * @description 鑾峰彇涓嬫媺琛ㄥ崟閫夐」淇℃伅
+   */
+  improveBackActionForm = (deForms) => {
+    const { BID, action } = this.props
+
+    let sysvals = {
+      mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+      mk_organization: sessionStorage.getItem('organization') || '',
+      mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+      id: this.state.ID || '',
+      bid: BID || '',
+      datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
+    }
+    if (window.GLOB.externalDatabase !== null) {
+      sysvals.db = window.GLOB.externalDatabase
+    }
+
+    let deffers = []
+    let mainItems = []  // 浜戠鎴栧崟鐐规暟鎹�
+    let localItems = [] // 鏈湴鏁版嵁
+    let cache = action.setting.cache !== 'false' && !action.$cache
+    let skip = false
+
+    deForms.forEach(item => {
+      let ex = window.GLOB.CacheData.get('sql_' + md5(action.uuid.replace(/_pop$/, '') + item.uuid))
+      
+      if (!ex) {
+        notification.warning({
+          top: 92,
+          message: '琛ㄥ崟锛�' + item.label + '锛夋棤鍙墽琛岃剼鏈��',
+          duration: 5
+        })
+        return
+      }
+      
+      let exps = []
+      ex.reps.forEach(n => {
+        let key = n.toLowerCase()
+        if (sysvals.hasOwnProperty(key)) {
+          exps.push({
+            key: n,
+            value: sysvals[key]
+          })
+        }
+      })
+
+      let cell = {
+        id: ex.id,
+        menuname: item.label + '锛堣〃鍗曪級',
+        exps: exps,
+        md5_id: ''
+      }
+
+      if (item.database === 'sso' && window.GLOB.mainSystemApi) {
+        mainItems.push(cell)
+      } else {
+        localItems.push(cell)
+      }
+    })
+
+    if (localItems.length) {
+      deffers.push({
+        $backend: true,
+        $type: 's_Get_SelectedList',
+        data: localItems
+      })
+    }
+
+    if (mainItems.length) {
+      deffers.push({
+        $backend: true,
+        $type: 's_Get_SelectedList',
+        data: mainItems,
+        rduri: window.GLOB.mainSystemApi
+      })
+    }
+
+    if (!deffers.length) return
+
+    deffers = deffers.map(item => {
+      return new Promise(resolve => {
+        Api.getSystemCacheConfig(item, cache).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+            skip = true
+          }
+          resolve(res)
+        })
+      })
+    })
+
+    Promise.all(deffers).then(response => {
+      let result = {...response[0], ...(response[1] || {})}
+
+      delete result.ErrCode
+      delete result.ErrMesg
+      delete result.message
+      delete result.status
+
+      this.resetFormList(result, skip)
+    })
+  }
   /**
    * @description 鑾峰彇涓嬫媺琛ㄥ崟閫夐」淇℃伅
    */
@@ -853,7 +998,7 @@
         sql = sql.replace(/@BID@/ig, `'${BID}'`)
 
         if (window.GLOB.debugger === true) {
-          console.info(sql)
+          window.mkInfo(sql)
         }
 
         sql = sql.replace(/%/ig, ' mpercent ')
@@ -867,7 +1012,7 @@
         sql = sql.replace(/@BID@/ig, `'${BID}'`)
 
         if (window.GLOB.debugger === true) {
-          console.info(sql)
+          window.mkInfo(sql)
         }
 
         sql = sql.replace(/%/ig, ' mpercent ')
@@ -991,7 +1136,7 @@
       param.LText = param.LText.replace(/@BID@/ig, `'${this.props.BID || ''}'`)
 
       if (window.GLOB.debugger) {
-        console.info(param.LText)
+        window.mkInfo(param.LText)
       }
 
       if (window.GLOB.execType === 'x') {
@@ -1356,6 +1501,7 @@
   }
 
   handleConfirm = (formId) => {
+    const { action } = this.props
     const { formlist, send_type, timestamp, n_id } = this.state
 
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
@@ -1367,6 +1513,7 @@
         }
         let forms = []
         let record = {...this.record, ...values}
+        let locals = null
 
         formlist.forEach(item => {
           if (!item.field || ['hint', 'split', 'formula'].includes(item.type)) return
@@ -1463,12 +1610,21 @@
               value: n_id || ''
             })
           }
+
+          if (item.local) {
+            locals = locals || {}
+            locals[item.field] = _item.value
+          }
     
           forms.push(_item)
         })
 
         this.submitId = formId || ''
 
+        if (locals) {
+          sessionStorage.setItem('local_' + action.uuid, JSON.stringify(locals))
+        }
+
         resolve(forms)
       })
     })
diff --git a/src/tabviews/zshare/mutilform/index.scss b/src/tabviews/zshare/mutilform/index.scss
index baebc0a..0f49c85 100644
--- a/src/tabviews/zshare/mutilform/index.scss
+++ b/src/tabviews/zshare/mutilform/index.scss
@@ -104,11 +104,6 @@
       min-width: 100px;
     }
   }
-  .normal-braft-editor {
-    border: 1px solid #d9d9d9;
-    border-radius: 4px;
-    overflow-x: hidden;
-  }
   p {
     color: #1890ff;
     font-size: 15px;
diff --git a/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx b/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
index a7dc070..a73b13c 100644
--- a/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
@@ -28,6 +28,8 @@
       selectKeys = config.initval ? config.initval.split(',') : []
       initlength = selectKeys.length
       selectKeys = this.filterVals(config.options, selectKeys)
+    } else if (config.options[0] && typeof(config.options[0].$value) === 'number' && /^([0-9]|[1-9]\d{0,2})$/.test(config.initval)) {
+      selectKeys = +config.initval
     }
 
     if (!config.selectStyle && config.backgroundColor) {
diff --git a/src/tabviews/zshare/mutilform/mkInput/index.jsx b/src/tabviews/zshare/mutilform/mkInput/index.jsx
index cad739c..9bdbbcf 100644
--- a/src/tabviews/zshare/mutilform/mkInput/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkInput/index.jsx
@@ -85,7 +85,9 @@
     let val = e.target.value
     let submit = /\n/g.test(val)
 
-    val = val.replace(/\n/g, '')
+    if (submit) {
+      val = val.replace(/\n|'/g, '')
+    }
 
     if (submit && /^\s+$/.test(val)) {
       submit = false
diff --git a/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx b/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
index 7b76860..4b967e2 100644
--- a/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
@@ -39,6 +39,7 @@
     config.dataSource = config.dataSource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
     config.dataSource = config.dataSource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
     config.dataSource = config.dataSource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+    config.dataSource = config.dataSource.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
 
     if (/\s/.test(config.dataSource)) { // 鎷兼帴鍒悕
       config.dataSource = '(' + config.dataSource + ') tb'
@@ -120,61 +121,128 @@
       loading: true
     })
 
-    let param = {
-      func: 'sPC_Get_TableData',
-      obj_name: 'data',
-      exec_type: window.GLOB.execType || 'y',
-      arr_field: arr_field,
-      default_sql: 'true',
-      custom_script: '',
-      menuname: config.label
-    }
+    let param = null
+    if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid)) {
+      let ex = window.GLOB.CacheData.get('sql_' + config.uuid)
+      let sysvals = {
+        time_id: Utils.getguid(),
+        mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+        mk_organization: sessionStorage.getItem('organization') || '',
+        mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+        id: ID || '',
+        bid: BID || '',
+        datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        orderby: orderBy || config.order || '',
+        pagesize: config.laypage === 'true' ? pageSize : '9999',
+        pageindex: pageIndex
+      }
+      if (window.GLOB.externalDatabase !== null) {
+        sysvals.db = window.GLOB.externalDatabase
+      }
 
-    let sql = ''
-    let DateCount = ''
-    let _search = ''
-    let _orderBy = orderBy || config.order || ''
-    let _datasource = config.dataSource
+      let exps = []
 
-    if (config.searchKey && searchKey) {
-      let fields = config.searchKey.split(',').map(field => field + ` like '%${searchKey}%'`)
-      _search = 'where ' + fields.join(' OR ')
-    }
+      if (config.searchKey) {
+        if (!searchKey) {
+          exps.push({
+            key: 'mk_search',
+            value: []
+          })
+        } else {
+          exps.push({
+            key: 'mk_search',
+            value: [{
+              key: config.searchKey,
+              match: '01',
+              type: /,/.test(config.searchKey) ? 'text_or' : 'text',
+              value: searchKey
+            }]
+          })
+        }
+        config.searchKey.split(',').forEach(key => {
+          sysvals[key.toLowerCase()] = searchKey || ''
+        })
+      }
 
-    _datasource = _datasource.replace(/@BID@/ig, `'${BID || ''}'`)
-    _datasource = _datasource.replace(/@ID@/ig, `'${ID || ''}'`)
-
-    if (config.laypage === 'true') {
-      sql = `/*system_query*/select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
-      DateCount = `/*system_query*/select count(1) as total from ${_datasource} ${_search}`
-    } else if (_orderBy) {
-      sql = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
-    } else {
-      sql = `/*system_query*/select ${arr_field} from ${_datasource} ${_search}  `
-    }
-
-    let departmentcode = sessionStorage.getItem('departmentcode') || ''
-    let organization = sessionStorage.getItem('organization') || ''
-    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
+      ex.reps.forEach(n => {
+        let key = n.toLowerCase()
+        if (sysvals.hasOwnProperty(key)) {
+          exps.push({
+            key: n,
+            value: sysvals[key]
+          })
+        }
+      })
     
-    sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-      Select @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}'
-      ${sql}`
-
-    // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (window.GLOB.debugger === true) {
-      console.info(`/*${config.label} 鏁版嵁婧�*/\n` + sql.replace(/\n\s{6}/ig, '\n'))
-      DateCount && console.info(`/*${config.label} 鎬绘暟鏌ヨ*/\n` + DateCount.replace(/\n\s{6}/ig, '\n'))
+      param = {
+        $backend: true,
+        $type: 's_Get_TableData',
+        data: [{
+          id: ex.id,
+          menuname: config.label || '',
+          exps: exps,
+          md5_id: ''
+        }]
+      }
+    } else {
+      param = {
+        func: 'sPC_Get_TableData',
+        obj_name: 'data',
+        exec_type: window.GLOB.execType || 'y',
+        arr_field: arr_field,
+        default_sql: 'true',
+        custom_script: '',
+        menuname: config.label
+      }
+  
+      let sql = ''
+      let DateCount = ''
+      let _search = ''
+      let _orderBy = orderBy || config.order || ''
+      let _datasource = config.dataSource
+  
+      if (config.searchKey && searchKey) {
+        let fields = config.searchKey.split(',').map(field => field + ` like '%${searchKey}%'`)
+        _search = 'where ' + fields.join(' OR ')
+      }
+  
+      _datasource = _datasource.replace(/@BID@/ig, `'${BID || ''}'`)
+      _datasource = _datasource.replace(/@ID@/ig, `'${ID || ''}'`)
+  
+      if (config.laypage === 'true') {
+        sql = `/*system_query*/select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
+        DateCount = `/*system_query*/select count(1) as total from ${_datasource} ${_search}`
+      } else if (_orderBy) {
+        sql = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
+      } else {
+        sql = `/*system_query*/select ${arr_field} from ${_datasource} ${_search}  `
+      }
+  
+      let departmentcode = sessionStorage.getItem('departmentcode') || ''
+      let organization = sessionStorage.getItem('organization') || ''
+      let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
+      
+      sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+        Select @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}'
+        ${sql}`
+  
+      // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
+      if (window.GLOB.debugger === true) {
+        window.mkInfo(`/*${config.label} 鏁版嵁婧�*/\n` + sql.replace(/\n\s{6}/ig, '\n'))
+        DateCount && window.mkInfo(`/*${config.label} 鎬绘暟鏌ヨ*/\n` + DateCount.replace(/\n\s{6}/ig, '\n'))
+      }
+  
+      param.LText = Utils.formatOptions(sql, param.exec_type)
+      param.DateCount = Utils.formatOptions(DateCount, param.exec_type)
+  
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+      param.secretkey = Utils.encrypt('', param.timestamp)
+  
+      param.username = sessionStorage.getItem('User_Name') || ''
+      param.fullname = sessionStorage.getItem('Full_Name') || ''
     }
-
-    param.LText = Utils.formatOptions(sql, param.exec_type)
-    param.DateCount = Utils.formatOptions(DateCount, param.exec_type)
-
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt('', param.timestamp)
-
-    param.username = sessionStorage.getItem('User_Name') || ''
-    param.fullname = sessionStorage.getItem('Full_Name') || ''
 
     Api.genericInterface(param).then(result => {
       if (result.status) {
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index 8439a3a..691422b 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -1283,7 +1283,7 @@
     }
 
     return (
-      <div className={'normal-data-table mingke-table ' + (height ? 'fixed-height' : '') + ` table-col-${columns.length}`}>
+      <div className={'normal-data-table mingke-table ' + (height ? 'fixed-table-height' : '') + ` table-col-${columns.length}`}>
         <Table
           components={components}
           size={setting.size || 'middle'}
diff --git a/src/tabviews/zshare/normalTable/index.scss b/src/tabviews/zshare/normalTable/index.scss
index c65a3ae..563a668 100644
--- a/src/tabviews/zshare/normalTable/index.scss
+++ b/src/tabviews/zshare/normalTable/index.scss
@@ -249,7 +249,7 @@
     }
   }
 }
-.normal-data-table:not(.fixed-height) {
+.normal-data-table:not(.fixed-table-height) {
   .ant-table-body::-webkit-scrollbar {
     width: 8px;
     height: 10px;
@@ -264,13 +264,5 @@
     border-radius: 3px;
     border: 1px solid rgba(0, 0, 0, 0.07);
     background: rgba(0, 0, 0, 0);
-  }
-}
-.normal-data-table.fixed-height {
-  .ant-table-body {
-    border-bottom: 1px solid rgba(0, 0, 0, .05);
-    .ant-table-fixed {
-      border-bottom: 0;
-    }
   }
 }
\ No newline at end of file
diff --git a/src/tabviews/zshare/settingcomponent/index.jsx b/src/tabviews/zshare/settingcomponent/index.jsx
index 77e2230..dd87d2c 100644
--- a/src/tabviews/zshare/settingcomponent/index.jsx
+++ b/src/tabviews/zshare/settingcomponent/index.jsx
@@ -316,9 +316,14 @@
         })
       } else if (!links.includes(item.verify.linkUrl)) {
         links.push(item.verify.linkUrl)
+      }
+    })
 
-        let socket = null
-        socket = new WebSocket('ws://' + item.verify.linkUrl)
+    if (links.length === 0) return
+
+    let defers = links.map(link => {
+      return new Promise((resolve) => {
+        let socket = new WebSocket('ws://' + link)
         // 鎵撳紑Socket
         socket.onopen = () =>{
           let request  = {
@@ -360,29 +365,39 @@
               })
             }
 
-            window.GLOB.UserCacheMap.set(item.verify.linkUrl, _printers)
-          } else if (data && data.cmd === 'getPrinters') {
-            notification.warning({
-              top: 92,
-              message: data.message,
-              duration: 5
-            })
+            resolve({status: true, printers: _printers})
+          } else if (data && data.cmd === 'getPrinters' && data.message) {
+            resolve({status: false, printers: null, message: data.message})
           }
         }
 
         socket.onerror = () => {
-          let tool = item.verify.linkUrl
-          if (item.verify.linkUrl === '127.0.0.1:13529') {
+          let tool = link
+
+          if (link === '127.0.0.1:13529') {
             tool = '鏄庣閫氳缁勪欢'
-          } else if (item.verify.linkUrl === '127.0.0.1:13528') {
+          } else if (link === '127.0.0.1:13528') {
             tool = 'CAINIAO鎵撳嵃缁勪欢'
           }
-          notification.warning({
-            top: 92,
-            message: '鏃犳硶杩炴帴鍒�: ' + tool,
-            duration: 5
-          })
+
+          resolve({status: false, printers: null, message: '鏃犳硶杩炴帴鍒�: ' + tool})
+          
         }
+      })
+    })
+
+    Promise.all(defers).then(results => {
+      let res = results.filter(item => item.status)[0]
+      if (res) {
+        links.forEach(link => {
+          window.GLOB.UserCacheMap.set(link, res.printers)
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: results[0].message,
+          duration: 5
+        })
       }
     })
   }
diff --git a/src/tabviews/zshare/topSearch/index.jsx b/src/tabviews/zshare/topSearch/index.jsx
index 0e1c29d..8d6fe6d 100644
--- a/src/tabviews/zshare/topSearch/index.jsx
+++ b/src/tabviews/zshare/topSearch/index.jsx
@@ -48,6 +48,8 @@
     let fieldMap = new Map()
     let mainItems = []  // 浜戠鎴栧崟鐐规暟鎹�
     let localItems = [] // 鏈湴鏁版嵁
+    let backMItems = [] // 浜戠鎴栧崟鐐规暟鎹�
+    let backLItems = [] // 鏈湴鏁版嵁
     let deForms = []    // 娴嬭瘯绯荤粺锛屽崟涓姹�
     let advanceValues = []
     let linkFields = {}
@@ -55,6 +57,22 @@
     let forbid = false // header涓笉璁剧疆楂樼骇鎼滅储
     let _setting = {showAdv: false, show: false, style: null}
     let BID = this.props.BID
+    let sysvals = {}
+
+    if (window.backend) {
+      sysvals = {
+        mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+        mk_organization: sessionStorage.getItem('organization') || '',
+        mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+        bid: BID || '',
+        datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+        datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+      }
+      if (window.GLOB.externalDatabase !== null) {
+        sysvals.db = window.GLOB.externalDatabase
+      }
+    }
     
     if (config.wrap) {
       _setting.show = config.wrap.show !== 'false'
@@ -67,6 +85,7 @@
       _setting.wrapperCol = {style: {width: (100 - _setting.labelwidth) + '%'}}
       _setting.borderRadius = config.wrap.borderRadius
       _setting.resetContrl = config.wrap.resetContrl || 'init'
+      _setting.size = config.wrap.searchSize || ''
 
       if (config.wrap.searchBtn === 'show') {
         _setting.showBtn = true
@@ -187,43 +206,77 @@
 
         // 鏁版嵁婧愭煡璇㈣鍙�
         if (item.resourceType === '1' && item.dataSource) {
-          let _option = Utils.getSelectQueryOptions(item)
-          let _declare = `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`
+          if (window.backend && window.GLOB.CacheData.has('sql_' + item.uuid)) {
+            let ex = window.GLOB.CacheData.get('sql_' + item.uuid)
+            let exps = []
 
-          let exec = true
-          if (item.checkBid) {
-            item.sql = _declare + _option.sql
-            item.arr_field = _option.field
+            ex.reps.forEach(n => {
+              let key = n.toLowerCase()
+              if (sysvals.hasOwnProperty(key)) {
+                exps.push({
+                  key: n,
+                  value: sysvals[key]
+                })
+              }
+            })
 
-            exec = !!BID
-          }
+            let cell = {
+              id: ex.id,
+              exps: exps,
+              menuname: item.label + '锛堟悳绱級',
+              md5_id: ''
+            }
+            if (item.checkBid) {
+              item.sqlId = ex.id
+              item.exps = exps
+            }
 
-          if (exec) {
-            let _sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
+            if (item.checkBid && !BID) {
+
+            } else if (item.database === 'sso' && window.GLOB.mainSystemApi) {
+              backMItems.push(cell)
+            } else {
+              backLItems.push(cell)
+            }
+          } else {
+            let _option = Utils.getSelectQueryOptions(item)
+            let _declare = `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`
   
-            if (window.GLOB.debugger === true) {
-              console.info(_declare + _sql)
+            let exec = true
+            if (item.checkBid) {
+              item.sql = _declare + _option.sql
+              item.arr_field = _option.field
+  
+              exec = !!BID
             }
   
-            // 娴嬭瘯绯荤粺鍗曚釜璇锋眰
-            if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && !window.GLOB.systemType) {
-              deForms.push({
-                ...item,
-                arr_field: _option.field,
-                data_sql: Utils.formatOptions(_declare + _sql, window.GLOB.execType)
-              })
-            } else { // 鍚堝苟璇锋眰锛屽尯鍒嗘湰鍦板強绯荤粺
-              _sql = _sql.replace(/%/ig, ' mpercent ')
-              if (item.database === 'sso') {
-                if (mainItems.length === 0) {
-                  _sql = _declare + _sql
+            if (exec) {
+              let _sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
+    
+              if (window.GLOB.debugger === true) {
+                window.mkInfo(_declare + _sql)
+              }
+    
+              // 娴嬭瘯绯荤粺鍗曚釜璇锋眰
+              if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && !window.GLOB.systemType) {
+                deForms.push({
+                  ...item,
+                  arr_field: _option.field,
+                  data_sql: Utils.formatOptions(_declare + _sql, window.GLOB.execType)
+                })
+              } else { // 鍚堝苟璇锋眰锛屽尯鍒嗘湰鍦板強绯荤粺
+                _sql = _sql.replace(/%/ig, ' mpercent ')
+                if (item.database === 'sso') {
+                  if (mainItems.length === 0) {
+                    _sql = _declare + _sql
+                  }
+                  mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_sql))}' as LText`)
+                } else {
+                  if (localItems.length === 0) {
+                    _sql = _declare + _sql
+                  }
+                  localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_sql))}' as LText`)
                 }
-                mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_sql))}' as LText`)
-              } else {
-                if (localItems.length === 0) {
-                  _sql = _declare + _sql
-                }
-                localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_sql))}' as LText`)
               }
             }
           }
@@ -295,7 +348,9 @@
       advanceValues,
       searchlist: _list
     }, () => {
-      if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
+      if (window.backend && (backMItems.length > 0 || backLItems.length > 0)) {
+        this.improveBackSearch(backMItems, backLItems, false)
+      } else if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
         this.improveSimpleSearch(deForms, false, null, BID)
       } else if (mainItems.length > 0 || localItems.length > 0) {
         this.improveSearch(mainItems, localItems, BID)
@@ -336,19 +391,41 @@
 
   resetOptions = (BID) => {
     let deForms = []
+    let backMItems = [] // 浜戠鎴栧崟鐐规暟鎹�
+    let backLItems = [] // 鏈湴鏁版嵁
     let searchlist = fromJS(this.state.searchlist).toJS().map(item => {
       if (item.checkBid) {
-        let sql = item.sql.replace(/@BID@/ig, `'${BID || ''}'`)
-  
-        if (window.GLOB.debugger === true) {
-          console.info(sql)
-        }
+        if (window.backend && item.sqlId) {
+          let cell = {
+            id: item.sqlId,
+            menuname: item.label + '锛堟悳绱級',
+            md5_id: '',
+            exps: item.exps.map(n => {
+              if (n.key === 'BID') {
+                n.value = BID
+              }
+              return n
+            })
+          }
 
-        deForms.push({
-          ...item,
-          arr_field: item.arr_field,
-          data_sql: Utils.formatOptions(sql, window.GLOB.execType)
-        })
+          if (item.database === 'sso' && window.GLOB.mainSystemApi) {
+            backMItems.push(cell)
+          } else {
+            backLItems.push(cell)
+          }
+        } else {
+          let sql = item.sql.replace(/@BID@/ig, `'${BID || ''}'`)
+    
+          if (window.GLOB.debugger === true) {
+            window.mkInfo(sql)
+          }
+  
+          deForms.push({
+            ...item,
+            arr_field: item.arr_field,
+            data_sql: Utils.formatOptions(sql, window.GLOB.execType)
+          })
+        }
       } else if (item.checkShift) {
         let d = ''
         if (window.GLOB.CacheData.has(item.$supId)) {
@@ -386,7 +463,9 @@
       return item
     })
 
-    if (deForms.length > 0) {
+    if (window.backend && (backMItems.length > 0 || backLItems.length > 0)) {
+      this.improveBackSearch(backMItems, backLItems, true, searchlist)
+    } else if (deForms.length > 0) {
       this.improveSimpleSearch(deForms, true, searchlist, BID)
     } else {
       this.setState({
@@ -531,6 +610,54 @@
       delete result.status
 
       this.resetSearch(result, false)
+    })
+  }
+
+  // 鏌ヨ涓嬫媺鑿滃崟
+  improveBackSearch = (mainItems, localItems, trigger, searchlist) => {
+    let deffers = []
+    
+    if (localItems.length) {
+      deffers.push({
+        $backend: true,
+        $type: 's_Get_SelectedList',
+        data: localItems
+      })
+    }
+
+    if (mainItems.length) {
+      deffers.push({
+        $backend: true,
+        $type: 's_Get_SelectedList',
+        data: mainItems,
+        rduri: window.GLOB.mainSystemApi
+      })
+    }
+
+    deffers = deffers.map(item => {
+      return new Promise(resolve => {
+        Api.getSystemCacheConfig(item).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+          }
+          resolve(res)
+        })
+      })
+    })
+
+    Promise.all(deffers).then(response => {
+      let result = {...response[0], ...(response[1] || {})}
+
+      delete result.ErrCode
+      delete result.ErrMesg
+      delete result.message
+      delete result.status
+
+      this.resetSearch(result, trigger, searchlist)
     })
   }
 
@@ -729,7 +856,7 @@
       const _rules = [
         {
           required: item.required,
-          message: item.label + '涓嶅彲涓虹┖!'
+          message: item.label + (window.GLOB.dict['not_empty'] || '涓嶅彲涓虹┖锛�')
         }
       ]
 
@@ -790,13 +917,13 @@
             wrapperCol={setting.wrapperCol}
           >
             {setting.show ? <Button style={style} type="primary" onClick={this.handleSubmit}>
-              鎼滅储
+              {window.GLOB.dict['search'] || '鎼滅储'}
             </Button> : null}
             {setting.show ? <Button style={{ marginLeft: 8, ...style }} onClick={this.handleReset}>
-              閲嶇疆
+              {window.GLOB.dict['reset'] || '閲嶇疆'}
             </Button> : null}
             {setting.showAdv ? <Button className={visible ? 'visible' : ''} type="link" onClick={this.handleAdvance}>
-              楂樼骇{setting.advanceType === 'pulldown' ? <DownOutlined /> : null}
+              {window.GLOB.dict['senior'] || '楂樼骇'}{setting.advanceType === 'pulldown' ? <DownOutlined /> : null}
             </Button> : null}
           </Form.Item>
         </Col>
@@ -806,7 +933,7 @@
         <Col className="mk-search-col search-button" key="actions">
           <Form.Item>
             <Button type="primary" onClick={this.handleSubmit}>
-              鎼滅储
+              {window.GLOB.dict['search'] || '鎼滅储'}
             </Button>
           </Form.Item>
         </Col>
@@ -892,7 +1019,7 @@
       
             notification.warning({
               top: 92,
-              message: '璇疯緭鍏�' + labels.join('銆�') + ' !',
+              message: (window.GLOB.dict['input_tip'] || '璇疯緭鍏�') + labels.join('銆�') + ' !',
               duration: 3
             })
             return
@@ -1048,7 +1175,7 @@
         }
 
         if (typeof(val) === 'string') {
-          val = val.replace(/(^\s*|\s*$)/ig, '')
+          val = val.replace(/(^\s+|\s+$)/ig, '').replace(/\t+|\v+/g, '')
         }
 
         search.push({
@@ -1124,7 +1251,7 @@
 
     return (
       <>
-        <Form {...formItemLayout} className={`mk-search-wrap mk-float-${setting.float}`} style={setting.style}>
+        <Form {...formItemLayout} className={`mk-search-wrap mk-float-${setting.float} mk-size-${setting.size}`} 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">
@@ -1140,7 +1267,7 @@
           </Row> : null}
         </Form>
         {setting.advanceType === 'modal' ? <Modal
-          title="楂樼骇鎼滅储"
+          title={window.GLOB.dict['adv_search'] || '楂樼骇鎼滅储'}
           maskClosable={false}
           visible={visible}
           width={setting.advWidth}
@@ -1156,7 +1283,7 @@
           />
         </Modal> : null}
         {setting.advanceType === 'drawer' ? <Drawer
-          title="楂樼骇鎼滅储"
+          title={window.GLOB.dict['adv_search'] || '楂樼骇鎼滅储'}
           className="mk-search-drawer"
           width={setting.advWidth}
           height={setting.advHeight}
diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss
index bf4590a..021510b 100644
--- a/src/tabviews/zshare/topSearch/index.scss
+++ b/src/tabviews/zshare/topSearch/index.scss
@@ -132,6 +132,11 @@
     text-align: right;
   }
 }
+.mk-search-wrap.mk-size-small {
+  .ant-form-item, .search-button {
+    min-height: 45px;
+  }
+}
 .mk-search-drawer {
   .ant-drawer-wrapper-body {
     position: relative;
diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx
index fc3b441..4768e78 100644
--- a/src/templates/comtableconfig/index.jsx
+++ b/src/templates/comtableconfig/index.jsx
@@ -689,13 +689,13 @@
   cancelConfig = () => {
     // const { config, originMenu } = this.state
 
-    // let _this = this
+    // let that = this
 
     // if (config.isAdd) {
     //   confirm({
     //     content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
     //     onOk() {
-    //       _this.props.handleView()
+    //       that.props.handleView()
     //     },
     //     onCancel() {}
     //   })
diff --git a/src/templates/comtableconfig/updatetable/index.jsx b/src/templates/comtableconfig/updatetable/index.jsx
index ed03667..f61593a 100644
--- a/src/templates/comtableconfig/updatetable/index.jsx
+++ b/src/templates/comtableconfig/updatetable/index.jsx
@@ -29,7 +29,7 @@
 
   trigger = () => {
     const { config } = this.props
-    const _this = this
+    const that = this
 
     if (!config.enabled) {
       notification.warning({
@@ -45,7 +45,7 @@
       content: '',
       onOk() {
         return new Promise(resolve => {
-          _this.execUpdate(resolve)
+          that.execUpdate(resolve)
         })
       },
       onCancel() {}
@@ -429,6 +429,40 @@
   
                 if (_LongParam) {
                   _LongParam.uuid = item.uuid
+
+                  if (_LongParam.fields && _LongParam.fields.length === 0 && _LongParam.groups && _LongParam.groups.length > 0) {
+                    _LongParam.groups.forEach(group => {
+                      if (group.sublist && group.sublist.length > 0) {
+                        _LongParam.fields.push({
+                          uuid: Utils.getuuid(),
+                          label: group.label,
+                          field: '',
+                          type: 'split'
+                        })
+                        _LongParam.fields.push(...group.sublist)
+                      }
+                    })
+                  }
+
+                  let span = _LongParam.setting && _LongParam.setting.cols ? (24 / _LongParam.setting.cols) : 12
+                  if (![24, 12, 8].includes(span)) {
+                    span = 12
+                  }
+
+                  if (_LongParam.fields) {
+                    _LongParam.fields = _LongParam.fields.map(n => {
+                      if (!n.span && n.type !== 'split') {
+                        if (['textarea', 'hint', 'checkcard', 'brafteditor'].includes(n.type)) {
+                          n.span = 24
+                        } else {
+                          n.span = span
+                        }
+                      }
+
+                      return n
+                    })
+                  }
+
                   resolve(_LongParam)
                 } else {
                   resolve({uuid: item.uuid, $empty: true})
@@ -577,7 +611,7 @@
 
   saveConfig = (_resolve, _config, errors) => {
     let err = errors.join('锛�')
-    let _this = this
+    let that = this
 
     if (err) {
       _resolve()
@@ -586,7 +620,7 @@
         content: '',
         onOk() {
           return new Promise(resolve => {
-            _this.saveNewMenu(resolve, _config)
+            that.saveNewMenu(resolve, _config)
           })
         },
         onCancel() {}
diff --git a/src/templates/modalconfig/dragelement/card.jsx b/src/templates/modalconfig/dragelement/card.jsx
index da672eb..7e46955 100644
--- a/src/templates/modalconfig/dragelement/card.jsx
+++ b/src/templates/modalconfig/dragelement/card.jsx
@@ -101,7 +101,7 @@
   } else if (card.type === 'textarea') {
     formItem = (<TextArea value={card.initval} placeholder={card.placeholder || ''} autoSize={{ minRows: 2, maxRows: 6 }} />)
   } else if (card.type === 'brafteditor') {
-    formItem = (<Editor />)
+    formItem = (<Editor config={{contHeidht: card.contHeidht}}/>)
   } else if (card.type === 'fileupload') {
     formItem = (<Button style={{marginTop: '3px'}}><UploadOutlined /> 鐐瑰嚮涓婁紶 </Button>)
   } else if (card.type === 'funcvar') {
diff --git a/src/templates/modalconfig/dragelement/index.jsx b/src/templates/modalconfig/dragelement/index.jsx
index 4798f28..6d6c0c5 100644
--- a/src/templates/modalconfig/dragelement/index.jsx
+++ b/src/templates/modalconfig/dragelement/index.jsx
@@ -66,7 +66,7 @@
 
     delete val.$srcId
     
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
diff --git a/src/templates/modalconfig/dragelement/index.scss b/src/templates/modalconfig/dragelement/index.scss
index e19cce3..3106857 100644
--- a/src/templates/modalconfig/dragelement/index.scss
+++ b/src/templates/modalconfig/dragelement/index.scss
@@ -113,10 +113,6 @@
           min-width: 100px;
         }
       }
-      .normal-braft-editor {
-        border: 1px solid #d9d9d9;
-        border-radius: 4px;
-      }
     }
     .ant-form-item-control-wrapper::after {
       content: '';
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index cabfc7d..bbe3611 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -280,15 +280,15 @@
    * @description 琛ㄥ崟鍒犻櫎骞跺埛鏂�
    */
   closeForm = (card) => {
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎${card.label ? `<<${card.label}>>` : ''}鍚楋紵`,
       onOk() {
-        let _config = fromJS(_this.state.config).toJS()
+        let _config = fromJS(that.state.config).toJS()
         _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid))
 
-        _this.setState({
+        that.setState({
           config: _config,
         })
       },
@@ -379,14 +379,14 @@
 
   cancelConfig = () => {
     // const { config, originConfig } = this.state
-    // let _this = this
+    // let that = this
 
     // let isOrigin = config.fields.filter(item => item.origin).length > 0
     // if (isOrigin) {
     //   confirm({
     //     content: '灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
     //     onOk() {
-    //       _this.handleViewBack()
+    //       that.handleViewBack()
     //     },
     //     onCancel() {}
     //   })
@@ -455,7 +455,7 @@
 
   changecols = (type) => {
     let config = fromJS(this.state.config).toJS()
-    let _this = this
+    let that = this
 
     config.fields = config.fields.map(item => {
       item.labelwidth = 33.3
@@ -481,7 +481,7 @@
     confirm({
       content: `纭畾鍒囨崲涓�${type}鍒楀悧锛焋,
       onOk() {
-        _this.setState({config})
+        that.setState({config})
       },
       onCancel() {}
     })
@@ -557,13 +557,13 @@
   }
 
   clearConfig = () => {
-    const _this = this
+    const that = this
     let _config = {...this.state.config, fields: []}
 
     confirm({
       content: '纭畾娓呯┖琛ㄥ崟鍚楋紵',
       onOk() {
-        _this.setState({ config: _config })
+        that.setState({ config: _config })
       },
       onCancel() {}
     })
diff --git a/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx b/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx
index 5de06eb..c0076ff 100644
--- a/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx
@@ -70,7 +70,7 @@
       }
       delete _val.$srcId
     
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         _val.$srcId = srcid
       }
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index 96961c4..62be8b1 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -280,12 +280,12 @@
    */
   deleteElement = (card) => {
     const { config } = this.props
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 - ${card.label} 锛焋,
       onOk() {
-        let _actionlist = fromJS(_this.state.actionlist).toJS()
+        let _actionlist = fromJS(that.state.actionlist).toJS()
 
         _actionlist = _actionlist.filter(item => item.uuid !== card.uuid)
 
@@ -313,10 +313,10 @@
           card: card
         }
 
-        _this.setState({
+        that.setState({
           actionlist: _actionlist
         }, () => {
-          _this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, '', delcard)
+          that.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, '', delcard)
         })
       },
       onCancel() {}
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
index ab01815..bfc57cb 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react'
+import React, { Component } from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select, Switch } from 'antd'
@@ -22,8 +22,7 @@
     editItem: null,
     usefulfields: null,
     loading: false,
-    skip: false,
-    verifySql: ''
+    skip: false
   }
 
   UNSAFE_componentWillMount () {
@@ -37,26 +36,12 @@
   }
 
   resetfield = (columns) => {
-    const { btn } = this.props
     columns = columns.filter(item => item.import !== 'false')
     let fields = columns.map(item => item.Column)
 
     fields.push('jskey')
-
-    let _dec = columns.map(item => item.Column + ' ' + item.type).join(',')
-    let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
-
-    if (_dec) {
-      _dec += ','
-    }
-
-    let _sql = `create table #${sheet} (${_dec}jskey nvarchar(50),BID nvarchar(50) )
-      Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50), @retmsg nvarchar(4000),@tbid Nvarchar(512)
-      Select @ErrorCode='', @retmsg=''
-    `
     
     this.setState({
-      verifySql: _sql,
       usefulfields: fields.join(', ')
     })
   }
@@ -81,7 +66,7 @@
   }
 
   handleConfirm = () => {
-    const { type, btn, workFlow } = this.props
+    const { type, btn, workFlow, usefulfields } = this.props
     const { editItem, skip } = this.state
 
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
@@ -115,12 +100,6 @@
         let pass = checkSQL(values.sql, 'customscript')
 
         if (!pass) return
-
-        let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
-        let tail = `
-          drop table #${sheet}
-          aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg
-        `
 
         let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
         let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
@@ -165,8 +144,71 @@
             `
           }
         }
+        
+        let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
+        let fields = []
+        let _dec = []
+        let vals = []
 
-        let sql = this.state.verifySql + _initCustomScript + _prevCustomScript + _backCustomScript + tail
+        usefulfields.forEach(col => {
+          if (col.import === 'false') return
+
+          fields.push(col.Column)
+          _dec.push(col.Column + ' ' + col.type)
+
+          let val = ''
+          if (col.import === 'init') {
+            if (/^Nvarchar/ig.test(col.type)) {
+              val = ''
+            } else if (/^Decimal/ig.test(col.type) || /^int/ig.test(col.type)) {
+              val = 0
+            } else if (col.type === 'date') {
+              val = '1949-10-01'
+            } else if (col.type === 'datetime') {
+              val = '1949-10-01 00:00:00'
+            }
+          } else if (/^Nvarchar/ig.test(col.type)) {
+            val = 'mk'
+          } else if (/^Decimal/ig.test(col.type) || /^int/ig.test(col.type)) {
+            val = 1
+          } else if (col.type === 'date') {
+            val = '1949-10-01'
+          } else if (col.type === 'datetime') {
+            val = '1949-10-01 00:00:00'
+          }
+
+          vals.push(`'${val}'`)
+        })
+
+        vals.push(`'${new Date().getTime()}000010'`)
+        vals.push(`'bid'`)
+        vals =  `Select ${vals.join(',')}`
+
+        fields.push('jskey')
+        fields = fields.join(',')
+        
+        _dec = _dec.join(',')
+        _dec = _dec ? _dec + ',' : ''
+
+        let sql = `create table #${sheet} (${_dec}jskey nvarchar(50),BID nvarchar(50) )
+          Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50), @retmsg nvarchar(4000),@tbid Nvarchar(512)
+          Select @ErrorCode='', @retmsg='', @UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address=''
+        
+          ${_initCustomScript}
+
+          Insert into #${sheet} (${fields},BID)
+
+          /* excel鏁版嵁*/
+          ${vals}
+
+          ${_prevCustomScript}
+
+          ${_backCustomScript}
+
+          drop table #${sheet}
+          aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg
+        `
+
         sql = sql.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '').replace(/@datam@/ig, `''`).replace(/@typename@/ig, `'debug'`)
         
         if (workFlow === 'true') {
@@ -232,11 +274,25 @@
 
     let _value = ''
     if (value === 'default') {
-      let fields = usefulfields.filter(item => item.import !== 'false')
-      fields = fields.map(col => col.Column).join(',')
+      let fields = []
+      let decls = []
+      usefulfields.forEach(col => {
+        if (col.import === 'false') return
+        
+        if (col.type === 'date') {
+          decls.push(`${col.Column} Nvarchar(50)`)
+        } else {
+          decls.push(`${col.Column} ${col.type}`)
+        }
+        fields.push(col.Column)
+      })
+
+      decls = decls.join(',')
+      fields = fields.join(',')
       
       if (fields) {
         fields = fields + ','
+        decls = decls + ','
       }
 
       let database = btn.sheet.match(/(.*)\.(.*)\.|@db@/ig) || ''
@@ -244,7 +300,7 @@
 
       database = database ? (database[0] || '') : ''
 
-      _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From #${sheet}`
+      _value = `/* create table #${sheet} (${decls}jskey nvarchar(50),BID nvarchar(50) ) */\nInsert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From #${sheet}`
     } else if (value === 'flowSql') {
       let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
 
@@ -318,7 +374,7 @@
           </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={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, lang, time_id, typename</span></Tooltip>,&nbsp;
               {workFlow === 'true' ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="宸ヤ綔娴佸彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�"><span style={{color: '#26C281'}}>works_flow_code, works_flow_name, works_flow_param, works_flow_detail_id, status, statusname, work_group, work_grade, start_type, </span></Tooltip> : null}
               <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}
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
index be7041f..f22a3ef 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -596,18 +596,18 @@
 
   clearField = () => {
     const { verify } = this.state
-    const _this = this
+    const that = this
 
     confirm({
       content: `纭畾娓呯┖Excel鍒楀悧锛焋,
       onOk() {
-        _this.setState({
+        that.setState({
           verify: {
             ...verify,
             columns: []
           }
         }, () => {
-          _this.resetUniqueColumns()
+          that.resetUniqueColumns()
         })
       },
       onCancel() {}
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
index b7645c9..36f6164 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
@@ -210,12 +210,12 @@
           </Col>
           <Col span={10}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+              errorcode, retmsg
             </Form.Item>
           </Col>
           <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={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, lang, 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>
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎺掑簭銆佸垎椤典互鍙婃悳绱㈡潯浠跺彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}>, orderBy, pageSize, pageIndex{usefulfields ? ', ' + usefulfields : ''}</Tooltip>
               {linefields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'琛ㄥ崟鍙婅鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}>,&nbsp;{linefields}</Tooltip> : null}
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
index 7b23dda..502137b 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -810,12 +810,12 @@
 
   clearField = () => {
     const { verify } = this.state
-    const _this = this
+    const that = this
 
     confirm({
       content: `纭畾娓呯┖Excel鍒楀悧锛焋,
       onOk() {
-        _this.setState({
+        that.setState({
           verify: {
             ...verify,
             columns: []
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
index f4e335c..4949841 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
@@ -50,7 +50,7 @@
       _dataresource = '(' + _dataresource + ') tb'
     }
 
-    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
+    let custompage = /@pageSize@|@orderBy@|@mk_total/i.test(_dataresource + _customScript)
     
     // 姝e垯鏇挎崲
     regoptions.push({
@@ -73,6 +73,10 @@
       value: ''
     })
 
+    if (window.GLOB.process) {
+      regoptions.push({reg: /@works_flow_code@/ig, value: `'mk_flow_code'`})
+    }
+
     regoptions.forEach(item => {
       _dataresource = _dataresource.replace(item.reg, item.value)
       _customScript = _customScript.replace(item.reg, item.value)
diff --git a/src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.jsx
new file mode 100644
index 0000000..1704f52
--- /dev/null
+++ b/src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.jsx
@@ -0,0 +1,224 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Form, Row, Col, Button, notification, Tooltip, Select, Switch } from 'antd'
+
+import Utils from '@/utils/utils.js'
+import { checkSQL } from '@/utils/utils-custom.js'
+import CodeMirror from '@/templates/zshare/codemirror'
+// import './index.scss'
+
+class CustomForm extends Component {
+  static propTpyes = {
+    scripts: PropTypes.array,
+    columns: PropTypes.any,
+    systemScripts: PropTypes.array,
+    scriptsChange: PropTypes.func
+  }
+
+  state = {
+    editItem: null,
+    usefulfields: null,
+    loading: false,
+    skip: false
+  }
+
+  UNSAFE_componentWillMount () {
+    this.resetfield()
+  }
+
+  resetfield = () => {
+    const { columns } = this.props
+    let fields = columns.map(item => item.field)
+
+    this.setState({
+      usefulfields: fields.join(', ')
+    })
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record
+    })
+
+    this.props.form.setFieldsValue({
+      sql: record.sql
+    })
+  }
+
+  handleConfirm = () => {
+    const { type, scripts } = this.props
+    const { editItem, skip } = this.state
+
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (err) return
+
+      if (!values.sql || /^[\s\n]+$/.test(values.sql)) {
+        notification.warning({
+          top: 92,
+          message: '璇疯緭鍏ql!',
+          duration: 5
+        })
+        return
+      }
+      
+      values.uuid = editItem ? editItem.uuid : ''
+
+      if (type === 'fullscreen' && editItem) {
+        values.status = editItem.status || 'true'
+      }
+
+      let pass = checkSQL(values.sql, 'customscript')
+
+      if (!pass) return
+
+      let _scripts = fromJS(scripts).toJS()
+
+      if (values.uuid) {
+        _scripts = _scripts.map(item => {
+          if (values.uuid === item.uuid) {
+            return values
+          }
+          return item
+        })
+      } else {
+        values.uuid = Utils.getuuid()
+
+        _scripts.push(values)
+      }
+
+      if (skip) {
+        this.setState({
+          skip: false,
+          editItem: null
+        })
+        this.props.scriptsChange(_scripts, null, null, values)
+        this.props.form.setFieldsValue({
+          sql: ''
+        })
+      } else {
+        this.setState({loading: true})
+        this.props.scriptsChange(_scripts, () => {
+          this.setState({
+            loading: false,
+            editItem: null
+          })
+  
+          this.props.form.setFieldsValue({
+            sql: ''
+          })
+        }, () => {
+          this.setState({loading: false})
+        }, values)
+      }
+    })
+  }
+
+  handleCancel = () => {
+    this.setState({
+      editItem: null
+    })
+    
+    this.props.form.setFieldsValue({
+      sql: ''
+    })
+  }
+
+  selectScript = (value, option) => {
+    let _sql = this.props.form.getFieldValue('sql')
+    if (/^\s+$/.test(_sql)) {
+      _sql = ''
+    }
+    if (_sql) {
+      _sql = _sql + ` 
+
+      `
+    }
+
+    _sql = _sql.replace(/\s{6}$/, '')
+    _sql = _sql + `/*${option.props.children}*/
+    `
+    _sql = _sql.replace(/\s{4}$/, '')
+    _sql = _sql + value
+
+    this.props.form.setFieldsValue({
+      sql: _sql
+    })
+  }
+
+  render() {
+    const { systemScripts, type } = this.props
+    const { usefulfields, editItem, skip } = this.state
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
+        <Row gutter={24}>
+          {!type ? <Col span={8}>
+            <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
+              errorcode, retmsg
+            </Form.Item>
+          </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, lang, 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> : null}
+          {!type ? <Col span={8}>
+            <Form.Item style={{marginBottom: 0}} label="蹇嵎娣诲姞">
+              <Select
+                showSearch
+                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                onSelect={this.selectScript}
+                getPopupContainer={() => document.getElementById('verify-excelin-custom-scripts')}
+              >
+                <Select.Option key="debugger" value={`z_debug: select @ErrorCode='E',@retmsg='娴嬭瘯鏂偣' goto aaa`}>
+                  娴嬭瘯鏂偣
+                </Select.Option>
+                {systemScripts.map((option, i) =>
+                  <Select.Option key={i} value={option.value}>
+                    {option.name}
+                  </Select.Option>
+                )}
+              </Select>
+            </Form.Item>
+          </Col> : null}
+          <Col span={5} className="add" style={{paddingTop: '2px', whiteSpace: 'nowrap'}}>
+            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
+            {type === 'fullscreen' && !editItem ? '娣诲姞' : '淇濆瓨'}
+            </Button>
+            <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
+              鍙栨秷
+            </Button>
+          </Col>
+          <Col span={3} className="forced" style={{paddingTop: '12px', fontSize: '12px', whiteSpace: 'nowrap'}}>
+            寮哄埗淇濆瓨锛�
+            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
+          </Col>
+          <Col span={24} className="sql">
+            <Form.Item label="sql" required>
+              {getFieldDecorator('sql', {
+                initialValue: ''
+              })(<CodeMirror />)}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(CustomForm)
\ No newline at end of file
diff --git a/src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.scss b/src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/templates/sharecomponent/actioncomponent/verifypay/customscript/index.scss
diff --git a/src/templates/sharecomponent/actioncomponent/verifypay/index.jsx b/src/templates/sharecomponent/actioncomponent/verifypay/index.jsx
new file mode 100644
index 0000000..0aab183
--- /dev/null
+++ b/src/templates/sharecomponent/actioncomponent/verifypay/index.jsx
@@ -0,0 +1,516 @@
+import React, {Component} from 'react'
+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 { EditOutlined, StopOutlined, CheckCircleOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
+import moment from 'moment'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+
+import CustomScript from './customscript'
+import asyncComponent from '@/utils/asyncComponent'
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+const { TabPane } = Tabs
+const { confirm } = Modal
+const { Paragraph } = Typography
+
+const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
+const FullScripts = asyncComponent(() => import('@/templates/zshare/verifycard/fullScripts'))
+
+class VerifyPay extends Component {
+  static propTpyes = {
+    columns: PropTypes.array,  // 鏄剧ず鍒�
+    card: PropTypes.object,
+  }
+
+  state = {
+    verify: null,
+    oriVerify: null,
+    defaultSql: '',
+    systemScripts: [],
+    scriptsColumns: [
+      {
+        title: 'SQL',
+        dataIndex: 'sql',
+        width: '60%',
+        render: (text) => {
+          let title = text.match(/^\s*\/\*.+\*\//)
+          title = title && title[0] ? title[0] : ''
+          let _text = title ? text.replace(title, '') : text
+
+          return (
+            <div>
+              {title ? <span style={{color: '#a50'}}>{title}<span style={{fontSize: '12px', marginLeft: '5px'}}>{_text.length}</span></span> : null}
+              <Paragraph copyable={{ text: text }} ellipsis={{ rows: 4, expandable: true }}>{_text}</Paragraph>
+            </div>
+          )
+        }
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '10%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div style={{color: '#ff4d4f'}}>
+              绂佺敤
+              <StopOutlined style={{marginLeft: '5px'}} />
+            </div>
+          ) :
+          (
+            <div style={{color: '#26C281'}}>
+              鍚敤
+              <CheckCircleOutlined style={{marginLeft: '5px'}}/>
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '140px',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div style={{textAlign: 'center'}}>
+            <span className="operation-btn" title="缂栬緫" onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><EditOutlined /></span>
+            <span className="operation-btn" title="鐘舵�佸垏鎹�" onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><SwapOutlined /></span>
+            <Popconfirm
+              overlayClassName="popover-confirm"
+              title="纭畾鍒犻櫎鍚�?"
+              onConfirm={() => this.handleDelete(record)
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ]
+  }
+
+  UNSAFE_componentWillMount() {
+    const { card, columns } = this.props
+    let _verify = fromJS(card.verify || {}).toJS()
+
+    _verify.scripts = _verify.scripts || []
+
+    let sysfields = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'tbid', 'bid']
+    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)', '@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=\'\'', '@bid=\'\'']
+    
+    sysfields = sysfields.map(field => field.toLowerCase())
+    columns.forEach(_f => {
+      if (sysfields.includes(_f.field.toLowerCase())) return
+
+      if (/decimal|int/ig.test(_f.datatype)) {
+        _select.push(`@${_f.field}=1`)
+      } else if (/date/ig.test(_f.datatype)) {
+        _select.push(`@${_f.field}='1949-10-01'`)
+      } else {
+        _select.push(`@${_f.field}=''`)
+      }
+
+      _declare.push(`@${_f.field} ${_f.datatype}`)
+    })
+
+    let _sql = `Declare ${_declare.join(', ')}
+      Select ${_select.join(', ')}
+    `
+
+    this.setState({
+      defaultSql: _sql,
+      verify: _verify,
+      oriVerify: fromJS(_verify).toJS()
+    })
+  }
+
+  componentDidMount () {
+    this.getsysScript()
+  }
+
+  getsysScript = () => {
+    if (sessionStorage.getItem('mk_sys_scripts')) {
+      this.setState({
+        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
+      })
+      return
+    }
+    
+    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
+
+    _scriptSql = Utils.formatOptions(_scriptSql, 'x')
+
+    let _sParam = {
+      func: 'sPC_Get_SelectedList',
+      LText: _scriptSql,
+      obj_name: 'data',
+      arr_field: 'funcname,longparam',
+      exec_type: 'x'
+    }
+    
+    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    _sParam.secretkey = Utils.encrypt('', _sParam.timestamp)
+    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
+    
+    Api.getCloudConfig(_sParam).then(res => {
+      if (res.status) {
+        let _scripts = res.data.map(item => {
+          return {
+            name: item.funcname,
+            value: window.decodeURIComponent(window.atob(item.longparam))
+          }
+        })
+
+        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
+
+        this.setState({
+          systemScripts: _scripts
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  scriptsChange = (scripts, resolve, reject, values) => {
+    const { card } = this.props
+    const { defaultSql } = this.state
+
+    let verify = fromJS(this.state.verify).toJS()
+    verify.scripts = scripts
+
+    let sql = defaultSql
+
+    scripts.forEach(item => {
+      if (item.status === 'false') return
+
+      sql += `
+      ${item.sql}
+      `
+    })
+
+    if (card.output) {
+      sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${card.output} as mk_b_id`
+    } else {
+      sql += `
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    }
+
+    sql = sql.replace(/@\$|\$@/ig, '')
+    sql = sql.replace(/@datam@/ig, `''`)
+    sql = sql.replace(/@typename@/ig, `'debug'`)
+      
+    if (resolve) {
+      Api.sDebug(sql).then(res => {
+        if (res.status || res.ErrCode === '-2') {
+          resolve()
+          values && MKEmitter.emit('editLineId', values.uuid)
+
+          this.setState({ verify })
+        } else {
+          reject()
+  
+          Modal.error({
+            title: res.message
+          })
+        }
+      })
+    } else {
+      values && MKEmitter.emit('editLineId', values.uuid)
+
+      this.setState({ verify })
+    }
+  }
+
+  handleDelete = (record) => {
+    const { verify } = this.state
+
+    verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
+
+    this.setState({ verify: verify })
+  }
+
+  handleEdit = (record) => {
+    this.scriptsForm.edit(record)
+    let node = document.getElementById('mk-pay-script')
+
+    if (node && node.scrollTop) {
+      let inter = Math.ceil(node.scrollTop / 10)
+
+      let timer = setInterval(() => {
+        if (node.scrollTop - inter > 0) {
+          node.scrollTop = node.scrollTop - inter
+        } else {
+          node.scrollTop = 0
+          clearInterval(timer)
+        }
+      }, 10)
+    }
+  }
+
+  handleStatus = (record) => {
+    let verify = fromJS(this.state.verify).toJS()
+    record.status = record.status === 'false' ? 'true' : 'false'
+
+    verify.scripts = verify.scripts.map(item => {
+      if (item.uuid === record.uuid) {
+        return record
+      } else {
+        return item
+      }
+    })
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  handleConfirm = () => {
+    const { verify } = this.state
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      if (verify.scripts.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '浣跨敤绯荤粺鍑芥暟锛岄渶瑕佹坊鍔犺嚜瀹氫箟鑴氭湰锛�',
+          duration: 5
+        })
+        return
+      }
+
+      let _loading = false
+      if (this.scriptsForm && this.scriptsForm.state.editItem) {
+        _loading = true
+      } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
+        _loading = true
+      }
+
+      if (_loading) {
+        confirm({
+          content: `瀛樺湪鏈繚瀛橀」锛岀‘瀹氭彁浜ゅ悧锛焋,
+          onOk() {
+            resolve(verify)
+          },
+          onCancel() {}
+        })
+      } else {
+        resolve(verify)
+      }
+    })
+  }
+
+  handleCancel = () => {
+    const { verify, oriVerify } = this.state
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      if (!is(fromJS(verify), fromJS(oriVerify))) {
+        confirm({
+          content: '楠岃瘉淇℃伅宸蹭慨鏀癸紝纭畾鍙栨秷鍚楋紵',
+          onOk() {
+            resolve()
+          },
+          onCancel() {}
+        })
+      } else {
+        resolve()
+      }
+    })
+  }
+
+  showError = (errorType) => {
+    if (errorType === 'S') {
+      notification.success({
+        top: 92,
+        message: '鎵ц鎴愬姛锛�',
+        duration: 2
+      })
+    } else if (errorType === 'Y') {
+      Modal.success({
+        title: '鎵ц鎴愬姛锛�'
+      })
+    } else if (errorType === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 10
+      })
+    } else if (errorType === 'N') {
+      notification.error({
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 10
+      })
+    } else if (errorType === 'E') {
+      Modal.error({
+        title: '鎵ц澶辫触锛�'
+      })
+    } else if (errorType === 'NM') {
+      message.error('鎵ц澶辫触锛�')
+    }
+  }
+
+  timeChange = (val, type) => {
+    const { verify } = this.state
+
+    this.setState({
+      verify: {...verify, [type]: val}
+    })
+  }
+
+  render() {
+    const { card, columns } = this.props
+    const { verify, scriptsColumns } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div>
+        {card.label ? <div className="mk-com-name">{card.label} - 楠岃瘉淇℃伅</div> : null}
+        <Tabs className="pay-verify-card-box">
+          <TabPane tab={
+            <span>
+              鑷畾涔夎剼鏈�
+              {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
+            </span>
+          } key="scripts" id="mk-pay-script">
+            <FullScripts
+              scripts={verify.scripts}
+              getScriptsFullForm={() => this.scriptsFullForm}
+              getScriptsForm={() => this.scriptsForm}
+              handleStatus={this.handleStatus}
+              handleDelete={this.handleDelete}
+            >
+              <CustomScript
+                type="fullscreen"
+                columns={columns}
+                scripts={verify.scripts}
+                systemScripts={this.state.systemScripts}
+                scriptsChange={this.scriptsChange}
+                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
+              />
+            </FullScripts>
+            <CustomScript
+              columns={columns}
+              scripts={verify.scripts}
+              systemScripts={this.state.systemScripts}
+              scriptsChange={this.scriptsChange}
+              wrappedComponentRef={(inst) => this.scriptsForm = inst}
+            />
+            <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="鎻愮ず缂栫爜">
+                    <span className="errorval"> S </span>
+                    <Button onClick={() => {this.showError('S')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <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="鎻愮ず缂栫爜">
+                    <span className="errorval"> Y </span>
+                    <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <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">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <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="鎻愮ず缂栫爜">
+                    <span className="errorval"> F </span>
+                    <Button onClick={() => {this.showError('F')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <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="鎻愮ず缂栫爜">
+                    <span className="errorval"> E </span>
+                    <Button onClick={() => {this.showError('E')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> NM </span>
+                    <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label="鎻愮ず缂栫爜">
+                    <span className="errorval"> -2 </span>
+                    鎵ц澶辫触鏃犳彁绀�
+                  </Form.Item>
+                </Col>
+              </Row>
+            </Form>
+          </TabPane>
+        </Tabs>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(VerifyPay)
\ No newline at end of file
diff --git a/src/templates/sharecomponent/actioncomponent/verifypay/index.scss b/src/templates/sharecomponent/actioncomponent/verifypay/index.scss
new file mode 100644
index 0000000..ad27818
--- /dev/null
+++ b/src/templates/sharecomponent/actioncomponent/verifypay/index.scss
@@ -0,0 +1,84 @@
+.pay-verify-card-box {
+  .ant-tabs-nav-scroll {
+    text-align: center;
+  }
+  .ant-tabs-content {
+    min-height: 40vh;
+  }
+  table tr td {
+    word-wrap: break-word;
+    word-break: break-word;
+  }
+  .count-tip {
+    position: absolute;
+    top: 0px;
+    color: #1890ff;
+    font-size: 12px;
+  }
+  .verify-form {
+    .sql {
+      .ant-col-sm-8 {
+        width: 10.5%;
+      }
+      .ant-col-sm-16 {
+        width: 89.5%;
+        padding-top: 4px;
+      }
+      .CodeMirror {
+        height: 350px;
+      }
+    }
+    .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%;
+      }
+    }
+    .ant-form-explain {
+      white-space: nowrap;
+    }
+  }
+  .errorval {
+    display: inline-block;
+    width: 30px;
+  }
+  .operation-btn {
+    display: inline-block;
+    font-size: 16px;
+    padding: 0 5px;
+    cursor: pointer;
+  }
+  .ant-tabs-tabpane {
+    position: relative;
+    .excel-col-add {
+      position: relative;
+      float: right;
+      right: -9px;
+      margin-right: 10px;
+      top: 10px;
+      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/verifyprint/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
index 5e80f9d..c4af547 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -247,6 +247,8 @@
 
         if (/decimal|int/ig.test(_f.datatype)) {
           _select.push(`@${_f.field}=1`)
+        } else if (/date/ig.test(_f.datatype)) {
+          _select.push(`@${_f.field}='1949-10-01'`)
         } else {
           _select.push(`@${_f.field}=''`)
         }
diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
index c33d899..719ba0e 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
@@ -34,7 +34,7 @@
       _dataresource = '(' + _dataresource + ') tb'
     }
 
-    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
+    let custompage = /@pageSize@|@orderBy@|@mk_total/i.test(_dataresource + _customScript)
 
     // 姝e垯鏇挎崲
     let regoptions = [{
diff --git a/src/templates/sharecomponent/cardcomponent/index.jsx b/src/templates/sharecomponent/cardcomponent/index.jsx
index 795eb4c..aab7e55 100644
--- a/src/templates/sharecomponent/cardcomponent/index.jsx
+++ b/src/templates/sharecomponent/cardcomponent/index.jsx
@@ -270,7 +270,7 @@
 
   deletedetail = (cell) => {
     const { card } = this.props
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 - ${cell.content} 锛焋,
@@ -279,22 +279,22 @@
 
         _details = _details.filter(item => item.uuid !== cell.uuid)
 
-        _this.plotChange({details: _details})
+        that.plotChange({details: _details})
       },
       onCancel() {}
     })
   }
 
   deleteElem = (type) => {
-    let _this = this
+    let that = this
 
     confirm({
       content: '纭畾鍒犻櫎锛�',
       onOk() {
-        let _subelement = fromJS(_this.props.card.subelement).toJS()
+        let _subelement = fromJS(that.props.card.subelement).toJS()
         _subelement = _subelement.filter(_type => _type !== type)
 
-        _this.plotChange({subelement: _subelement})
+        that.plotChange({subelement: _subelement})
       },
       onCancel() {}
     })
diff --git a/src/templates/sharecomponent/chartgroupcomponent/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/index.jsx
index 4c90686..2c18248 100644
--- a/src/templates/sharecomponent/chartgroupcomponent/index.jsx
+++ b/src/templates/sharecomponent/chartgroupcomponent/index.jsx
@@ -203,13 +203,13 @@
    */
   deletechart = (plot) => {
     const { config } = this.props
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 ${plot.title} 锛焋,
       onOk() {
-        let _chartlist = fromJS(_this.state.chartlist).toJS()
-        let _chartview = _this.state.chartview
+        let _chartlist = fromJS(that.state.chartlist).toJS()
+        let _chartview = that.state.chartview
 
         _chartlist = _chartlist.filter(item => item.uuid !== plot.uuid)
 
@@ -217,11 +217,11 @@
           _chartview = _chartlist[0].uuid
         }
 
-        _this.setState({
+        that.setState({
           chartlist: _chartlist,
           chartview: _chartview
         })
-        _this.props.updatechartgroup({...config, charts: _chartlist}, _chartview)
+        that.props.updatechartgroup({...config, charts: _chartlist}, _chartview)
       },
       onCancel() {}
     })
diff --git a/src/templates/sharecomponent/columncomponent/index.jsx b/src/templates/sharecomponent/columncomponent/index.jsx
index c44b763..e488a3d 100644
--- a/src/templates/sharecomponent/columncomponent/index.jsx
+++ b/src/templates/sharecomponent/columncomponent/index.jsx
@@ -280,12 +280,12 @@
    */
   deleteElement = (card) => {
     const { config } = this.props
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 - ${card.label} 锛焋,
       onOk() {
-        let _columnlist = fromJS(_this.state.columnlist).toJS()
+        let _columnlist = fromJS(that.state.columnlist).toJS()
 
         _columnlist = _columnlist.filter(item => item.uuid !== card.uuid)
 
@@ -351,10 +351,10 @@
           }
         }
 
-        _this.setState({
+        that.setState({
           columnlist: _columnlist
         }, ()=> {
-          _this.props.updatecolumn({...config, columns: _columnlist})
+          that.props.updatecolumn({...config, columns: _columnlist})
         })
       },
       onCancel() {}
@@ -373,7 +373,7 @@
       columns: columnlist
     }
 
-    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
     if (srcid) {
       val.$srcId = srcid
     }
diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx
index 52d7eb1..550b5f6 100644
--- a/src/templates/sharecomponent/fieldscomponent/index.jsx
+++ b/src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -146,9 +146,20 @@
     if (type === 'search') {
       // 娣诲姞鎼滅储鏉′欢锛屽瓧娈甸泦涓瓨鍦ㄦ悳绱㈡潯浠跺瓧娈碉紝浣跨敤鎼滅储鏉′欢瀵硅薄鏇挎崲瀛楁闆嗭紝璁剧疆鏁版嵁绫诲瀷
       config.search.forEach(item => {
-        if (item.field && columns.has(item.field.toLowerCase())) {
-          let _datatype = columns.get(item.field.toLowerCase()).datatype
-          columns.set(item.field.toLowerCase(), {...item, origin: true, datatype: _datatype})
+        if (item.field) {
+          if (/,/.test(item.field)) {
+            item.field.split(',').forEach(n => {
+              if (columns.has(n.toLowerCase())) {
+                let _datatype = columns.get(n.toLowerCase()).datatype
+                columns.set(n.toLowerCase(), {...item, field: n, origin: true, datatype: _datatype})
+              }
+            })
+          } else {
+            if (columns.has(item.field.toLowerCase())) {
+              let _datatype = columns.get(item.field.toLowerCase()).datatype
+              columns.set(item.field.toLowerCase(), {...item, origin: true, datatype: _datatype})
+            }
+          }
         }
       })
     } else if (type === 'columns') {
@@ -192,13 +203,6 @@
     }
 
     let config = fromJS(this.props.config).toJS()
-
-    // 鑾峰彇宸查�夊瓧娈甸泦鍚�
-    let cards = selectCards
-    let columnsMap = new Map()
-    cards.forEach(card => {
-      columnsMap.set(card.field.toLowerCase(), card)
-    })
 
     let items = []
     let keys = []
diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
index 277f247..3edd6e1 100644
--- a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
@@ -54,7 +54,7 @@
     try {
       delete _val.$srcId
 
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         _val.$srcId = srcid
       }
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index 6380283..c861729 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -205,7 +205,7 @@
         return
       }
 
-      if (['checkcard', 'select', 'multiselect', 'link'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (['checkcard', 'select', 'multiselect', 'link'].includes(res.type) && res.resourceType === '1' && res.database !== 'sso' && /\s/.test(res.dataSource)) {
         this.setState({
           sqlVerifing: true
         })
@@ -213,13 +213,8 @@
         let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
         ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
-
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
         
-        Api.sDebug(sql, rduri).then(result => {
+        Api.sDebug(sql).then(result => {
           if (result.status || result.ErrCode === '-2') {
             this.setState({
               sqlVerifing: false,
@@ -252,19 +247,19 @@
    */
   deleteElement = (card) => {
     const { config } = this.props
-    let _this = this
+    let that = this
 
     confirm({
       content: `纭畾鍒犻櫎 - ${card.label} 锛焋,
       onOk() {
-        let _searchlist = fromJS(_this.state.searchlist).toJS()
+        let _searchlist = fromJS(that.state.searchlist).toJS()
 
         _searchlist = _searchlist.filter(item => item.uuid !== card.uuid)
 
-        _this.setState({
+        that.setState({
           searchlist: _searchlist
         }, () => {
-          _this.props.updatesearch({...config, search: _searchlist})
+          that.props.updatesearch({...config, search: _searchlist})
         })
       },
       onCancel() {}
@@ -330,8 +325,13 @@
     const { config } = this.props
     const { searchlist, visible, sqlVerifing, card, showField, setVisible } = this.state
 
+    let size = ''
+    if (config.wrap && config.wrap.searchSize) {
+      size = ' mk-size-' + config.wrap.searchSize
+    }
+
     return (
-      <div className={'model-table-search-list length' + searchlist.length + (showField ? ' show-field' : '')}>
+      <div className={'model-table-search-list length' + searchlist.length + (showField ? ' show-field' : '') + size}>
         <FieldsComponent config={{uuid: config.uuid, search: searchlist}} type="search" />
         <Switch className="switch-field-show" checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={showField} onChange={this.onFieldChange} />
         <DragElement
@@ -347,7 +347,7 @@
           title={card && card.copyType === 'search' ?  '鎼滅储鏉′欢-澶嶅埗' : '鎼滅储鏉′欢-缂栬緫'}
           wrapClassName="mk-scroll-modal"
           visible={visible}
-          width={850}
+          width={950}
           maskClosable={false}
           onOk={this.handleSubmit}
           confirmLoading={sqlVerifing}
diff --git a/src/templates/sharecomponent/searchcomponent/index.scss b/src/templates/sharecomponent/searchcomponent/index.scss
index b82e0a3..b156cdb 100644
--- a/src/templates/sharecomponent/searchcomponent/index.scss
+++ b/src/templates/sharecomponent/searchcomponent/index.scss
@@ -141,4 +141,14 @@
       display: block;
     }
   }
+}
+.model-table-search-list.mk-size-small {
+  .page-card {
+    height: 45px;
+  }
+  .mk-search-item-wrap.action {
+    .ant-form-item {
+      height: 45px!important;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
index e91fee9..c2871bb 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -234,8 +234,11 @@
         if (this.record.selectStyle === 'custom') {
           shows.push('backgroundColor')
         }
-        if (this.record.multiple === 'dropdown' && this.record.resourceType === '1') {
-          shows.push('mark', 'parentField')
+        if (this.record.multiple === 'dropdown') {
+          shows.push('mark')
+          if (this.record.resourceType === '1') {
+            shows.push('parentField')
+          }
         }
       }
       shows.push('linkField')
@@ -280,7 +283,7 @@
     } else if (type === 'dateweek' || type === 'daterange' || type === 'range') {
       reOptions.match = matchReg.class5
     } else if (type === 'checkcard') {
-      if (this.record.multiple === 'false') {
+      if (this.record.multiple === 'false' || this.record.multiple === 'dropdown') {
         reOptions.match = matchReg.class1
       } else if (this.record.multiple === 'true') {
         reOptions.match = matchReg.class3
@@ -595,19 +598,18 @@
           { required: item.required, message: '璇疯緭鍏�' + item.label + '!' }
         ]
         span = 24
-        className = 'text-area'
 
         if (this.record.type === 'select' || this.record.type === 'link') {
           extra = <span className="add-resource-empty" onClick={this.handleEmpty}>鍏ㄩ儴</span>
         }
         if (item.placeholder) {
+          className = 'show-public-var'
           extra = <><span className="resource-public-var">{item.placeholder}</span>{extra}</>
         }
 
         content = <CodeMirror />
       } else if (item.type === 'options') {
         span = 24
-        className = 'text-area'
 
         let type = this.record.type
         
@@ -654,7 +656,6 @@
         }
       } else if (item.type === 'fields') {
         span = 24
-        className = 'text-area'
 
         rules = [
           { required: item.required, message: '璇锋坊鍔�' + item.label + '!' }
@@ -667,7 +668,7 @@
         ]
 
         content = <Checkbox.Group style={{width: '105%'}} options={item.options} onChange={(values) => this.optionChange(item.key, values)}/>
-      } else if (item.type === 'multiselect') { // 澶氶��
+      } else if (item.type === 'multiselect') {
         content = <Select
           showSearch
           mode="multiple"
@@ -677,8 +678,8 @@
             <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option>
           )}
         </Select>
-      } else if (item.type === 'cascader') { // 澶氶��
-        content = <Cascader options={item.options} placeholder="" />
+      } else if (item.type === 'cascader') {
+        content = <Cascader options={item.options} />
       } else if (item.type === 'color') {
         className = 'color-form-item'
         rules = [
@@ -691,7 +692,7 @@
       fields.push(
         <Col span={span} key={index}>
           <Form.Item className={className} extra={extra} label={item.tooltip ?
-            <Tooltip placement="topLeft" title={item.tooltip}>
+            <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}>
               <QuestionCircleOutlined className="mk-form-tip" />
               {item.label}
             </Tooltip> : item.label
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.scss b/src/templates/sharecomponent/searchcomponent/searchform/index.scss
index 6a66718..aded9be 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.scss
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.scss
@@ -4,7 +4,7 @@
     padding-left: 6px!important;
     padding-bottom: 20px;
   }
-  .ant-form-item.text-area {
+  .ant-col-24 {
     // margin-bottom: 0px;
     .ant-form-item-control-wrapper {
       width: 84%;
@@ -45,10 +45,15 @@
     cursor: pointer;
     font-size: 14px;
   }
+  .show-public-var {
+    margin-top: 20px;
+  }
   .resource-public-var {
     position: absolute;
     left: 0px;
-    top: -22px;
-    font-size: 14px;
+    top: -45px;
+    right: 40px;
+    font-size: 13px;
+    color: rgba(0, 0, 0, 0.65);
   }
 }
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcomponent/index.jsx b/src/templates/sharecomponent/settingcomponent/index.jsx
index 6d9bb70..8657cbe 100644
--- a/src/templates/sharecomponent/settingcomponent/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/index.jsx
@@ -93,7 +93,7 @@
 
   resetSetting = (s, ori) => {
     let setting = fromJS(s).toJS()
-    let maxScript = 0
+    // let maxScript = 0
 
     setting.show = ori.show || 'true'
     setting.advanceType = ori.advanceType || 'modal'
@@ -103,43 +103,43 @@
     setting.searchLwidth = ori.searchLwidth !== undefined ? ori.searchLwidth : 33.3
     setting.resetContrl = ori.resetContrl || 'init'
 
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(m => {
-        let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
-        setting.scripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(m => {
+    //     let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
+    //     setting.scripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
 
-          if (item.status === 'false') return
+    //       if (item.status === 'false') return
 
-          if (/exec\s/ig.test(item.sql)) {
-            maxScript = 1000
-          } else if (item.sql.length > maxScript) {
-            maxScript = item.sql.length
-          }
-        })
-        setting.preScripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-        })
-        setting.cbScripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-        })
-        if (setting.dataresource) {
-          setting.dataresource = setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-        }
-      })
-    } else {
-      setting.scripts.forEach(item => {
-        if (item.status === 'false') return
+    //       if (/exec\s/ig.test(item.sql)) {
+    //         maxScript = 1000
+    //       } else if (item.sql.length > maxScript) {
+    //         maxScript = item.sql.length
+    //       }
+    //     })
+    //     setting.preScripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+    //     })
+    //     setting.cbScripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+    //     })
+    //     if (setting.dataresource) {
+    //       setting.dataresource = setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+    //     }
+    //   })
+    // } else {
+    //   setting.scripts.forEach(item => {
+    //     if (item.status === 'false') return
 
-        if (/exec\s/ig.test(item.sql)) {
-          maxScript = 1000
-        } else if (item.sql.length > maxScript) {
-          maxScript = item.sql.length
-        }
-      })
-    }
+    //     if (/exec\s/ig.test(item.sql)) {
+    //       maxScript = 1000
+    //     } else if (item.sql.length > maxScript) {
+    //       maxScript = item.sql.length
+    //     }
+    //   })
+    // }
 
-    setting.maxScript = maxScript
+    // setting.maxScript = maxScript
 
     return setting
   }
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
index 8c0ab17..ff665b9 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
@@ -79,17 +79,17 @@
 
     let status = fromJS(_setting).toJS()
 
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(m => {
-        let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
-        _scripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-        if (_setting.dataresource) {
-          _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
-        }
-      })
-    }
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(m => {
+    //     let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
+    //     _scripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     })
+    //     if (_setting.dataresource) {
+    //       _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     }
+    //   })
+    // }
 
     this.setState({
       setting: _setting,
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
index 846ae2f..74025d2 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
@@ -26,25 +26,25 @@
       _dataresource = ''
     }
 
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(item => {
-        let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
-        _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-        _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-      })
-    }
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(item => {
+    //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
+    //     _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+    //     _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+    //   })
+    // }
     
     _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|upid)@/ig, `'1949-10-01 15:00:00'`)
     _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id|datam|upid)@/ig, `'1949-10-01 15:00:00'`)
     _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
     _customScript = _customScript.replace(/@\$|\$@/ig, '')
-    _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
-    _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
+    // _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
+    // _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
     // _dataresource = _dataresource.replace(/@sum\$|\$sum@/ig, '')
-    _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '')
+    // _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '')
 
-    _dataresource = _dataresource.replace(/\$sum@/ig, '/*$sum@')
-    _dataresource = _dataresource.replace(/@sum\$/ig, '@sum$*/')
+    // _dataresource = _dataresource.replace(/\$sum@/ig, '/*$sum@')
+    // _dataresource = _dataresource.replace(/@sum\$/ig, '@sum$*/')
 
     // 澶栬仈鏁版嵁搴撴浛鎹�
     if (window.GLOB.externalDatabase !== null) {
diff --git a/src/templates/sharecomponent/tabscomponent/index.jsx b/src/templates/sharecomponent/tabscomponent/index.jsx
index a95725d..73c4dba 100644
--- a/src/templates/sharecomponent/tabscomponent/index.jsx
+++ b/src/templates/sharecomponent/tabscomponent/index.jsx
@@ -219,7 +219,7 @@
    */
   deleteElement = (card, group) => {
     const { config } = this.props
-    let _this = this
+    let that = this
     let tabgroups = fromJS(this.state.tabgroups).toJS()
 
     confirm({
@@ -243,10 +243,10 @@
           return _group
         })
 
-        _this.setState({
+        that.setState({
           tabgroups: tabgroups
         }, () => {
-          _this.props.updatetabs({...config, tabgroups: tabgroups})
+          that.props.updatetabs({...config, tabgroups: tabgroups})
         })
       },
       onCancel() {}
@@ -258,7 +258,7 @@
    */
   addTabGroup = () => {
     const { config } = this.props
-    let _this = this
+    let that = this
     let _tabgroups = fromJS(this.state.tabgroups).toJS()
 
     confirm({
@@ -275,10 +275,10 @@
           sublist:[]
         })
 
-        _this.setState({
+        that.setState({
           tabgroups: _tabgroups
         }, () => {
-          _this.props.updatetabs({...config, tabgroups: _tabgroups})
+          that.props.updatetabs({...config, tabgroups: _tabgroups})
         })
       },
       onCancel() {}
@@ -290,7 +290,7 @@
    */
   delTabGroup = (group) => {
     const { config } = this.props
-    let _this = this
+    let that = this
     let _tabgroups = fromJS(this.state.tabgroups).toJS()
 
     confirm({
@@ -298,10 +298,10 @@
       onOk() {
         _tabgroups = _tabgroups.filter(_group => _group.uuid !== group.uuid)
 
-        _this.setState({
+        that.setState({
           tabgroups: _tabgroups
         }, () => {
-          _this.props.updatetabs({...config, tabgroups: _tabgroups}, group.sublist)
+          that.props.updatetabs({...config, tabgroups: _tabgroups}, group.sublist)
         })
       },
       onCancel() {}
diff --git a/src/templates/sharecomponent/treesettingcomponent/index.jsx b/src/templates/sharecomponent/treesettingcomponent/index.jsx
index 055a295..51faa23 100644
--- a/src/templates/sharecomponent/treesettingcomponent/index.jsx
+++ b/src/templates/sharecomponent/treesettingcomponent/index.jsx
@@ -43,17 +43,17 @@
       loading: true
     })
     this.settingRef.handleConfirm().then(res => {
-      if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-        window.GLOB.funcs.forEach(m => {
-          let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
-          res.scripts.forEach(item => {
-            item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-          })
-          if (res.dataresource) {
-            res.dataresource = res.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-          }
-        })
-      }
+      // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+      //   window.GLOB.funcs.forEach(m => {
+      //     let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
+      //     res.scripts.forEach(item => {
+      //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+      //     })
+      //     if (res.dataresource) {
+      //       res.dataresource = res.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+      //     }
+      //   })
+      // }
       this.setState({
         visible: false,
         loading: false
diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
index 46b7486..ba10535 100644
--- a/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
+++ b/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
@@ -32,17 +32,17 @@
     let _setting = fromJS(config.setting).toJS()
     let _scripts = _setting.scripts || []
 
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(m => {
-        let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
-        _scripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-        if (_setting.dataresource) {
-          _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
-        }
-      })
-    }
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(m => {
+    //     let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
+    //     _scripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     })
+    //     if (_setting.dataresource) {
+    //       _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     }
+    //   })
+    // }
 
     this.setState({
       setting: _setting,
diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx
index 7d91a7c..a540544 100644
--- a/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx
+++ b/src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx
@@ -27,13 +27,13 @@
       _dataresource = ''
     }
 
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(item => {
-        let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
-        _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-        _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-      })
-    }
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(item => {
+    //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
+    //     _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+    //     _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+    //   })
+    // }
     
     _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
     _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx
index 8e48352..ceb6a74 100644
--- a/src/templates/subtableconfig/index.jsx
+++ b/src/templates/subtableconfig/index.jsx
@@ -588,13 +588,13 @@
   cancelConfig = () => {
     // const { config, originConfig } = this.state
 
-    // let _this = this
+    // let that = this
 
     // if (originConfig.isAdd) {
     //   confirm({
     //     content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
     //     onOk() {
-    //       _this.handleViewBack()
+    //       that.handleViewBack()
     //     },
     //     onCancel() {}
     //   })
diff --git a/src/templates/treepageconfig/index.jsx b/src/templates/treepageconfig/index.jsx
index af0d67b..f6df00d 100644
--- a/src/templates/treepageconfig/index.jsx
+++ b/src/templates/treepageconfig/index.jsx
@@ -444,13 +444,13 @@
    */
   cancelConfig = () => {
     // const { config, originMenu } = this.state
-    // let _this = this
+    // let that = this
 
     // if (config.isAdd) {
     //   confirm({
     //     content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
     //     onOk() {
-    //       _this.props.handleView()
+    //       that.props.handleView()
     //     },
     //     onCancel() {}
     //   })
diff --git a/src/templates/treepageconfig/updatetable/index.jsx b/src/templates/treepageconfig/updatetable/index.jsx
index 8de0cea..35b911b 100644
--- a/src/templates/treepageconfig/updatetable/index.jsx
+++ b/src/templates/treepageconfig/updatetable/index.jsx
@@ -29,7 +29,7 @@
 
   trigger = () => {
     const { config } = this.props
-    const _this = this
+    const that = this
 
     if (!config.enabled) {
       notification.warning({
@@ -45,7 +45,7 @@
       content: '',
       onOk() {
         return new Promise(resolve => {
-          _this.execUpdate(resolve)
+          that.execUpdate(resolve)
         })
       },
       onCancel() {}
@@ -637,7 +637,7 @@
 
   saveConfig = (_resolve, _config, errors) => {
     let err = errors.join('锛�')
-    let _this = this
+    let that = this
 
     if (err) {
       _resolve()
@@ -646,7 +646,7 @@
         content: '',
         onOk() {
           return new Promise(resolve => {
-            _this.saveNewMenu(resolve, _config)
+            that.saveNewMenu(resolve, _config)
           })
         },
         onCancel() {}
diff --git a/src/templates/zshare/codemirror/index.jsx b/src/templates/zshare/codemirror/index.jsx
index 0980534..dfe9c2b 100644
--- a/src/templates/zshare/codemirror/index.jsx
+++ b/src/templates/zshare/codemirror/index.jsx
@@ -169,8 +169,7 @@
         return
       }
 
-      let _href = window.location.href.split('#')[0]
-      localStorage.setItem(_href + 'sql_char', JSON.stringify([res.origin, res.value]))
+      localStorage.setItem(window.GLOB.sysSign + 'sql_char', JSON.stringify([res.origin, res.value]))
 
       _sql = _sql.replace(reg, res.value)
 
diff --git a/src/templates/zshare/customscript/index.jsx b/src/templates/zshare/customscript/index.jsx
index 0286596..e2da7de 100644
--- a/src/templates/zshare/customscript/index.jsx
+++ b/src/templates/zshare/customscript/index.jsx
@@ -333,7 +333,7 @@
             </Col>
             <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={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, lang, 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={'鎺掑簭銆佸垎椤典互鍙婃悳绱㈡潯浠跺彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}>orderBy{setting.laypage === 'true' ? ', pageSize, pageIndex': ''}{usefulFields ? ', ' + usefulFields : ''}</Tooltip>
                 {urlFields ?<Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'url鍙橀噺锛岃鎸夌収@xxx@鏍煎紡浣跨敤銆�'}>, <span style={{color: '#13c2c2'}}>{urlFields}</span></Tooltip> : ''}
diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx
index 9ce9e95..777fb99 100644
--- a/src/templates/zshare/editTable/index.jsx
+++ b/src/templates/zshare/editTable/index.jsx
@@ -385,14 +385,14 @@
   }
 
   clear = () => {
-    const _this = this
+    const that = this
     
     confirm({
       title: '纭畾娓呯┖鍒楄〃鍚楋紵',
       content: '',
       onOk() {
-        _this.setState({ data: [], editingKey: '' }, () => {
-          _this.props.onChange([])
+        that.setState({ data: [], editingKey: '' }, () => {
+          that.props.onChange([])
         })
       },
       onCancel() {}
@@ -419,7 +419,7 @@
     }
 
     try {
-      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+      let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
       if (srcid) {
         msg.$srcId = srcid
       }
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 621dd29..b494bb7 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -261,7 +261,7 @@
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
       tooltip: '鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\'',
-      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆�',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�硷細@BID@銆丂Appkey@銆丂UserID@銆丂SessionUid@銆丂LoginUID@銆丂lang@銆�',
       required: true
     },
     {
@@ -444,7 +444,7 @@
         text: '鏈湴'
       }, {
         value: 'sso',
-        text: '绯荤粺'
+        text: '鍗曠偣'
       }]
     },
     {
@@ -1012,12 +1012,20 @@
 
   let options = card.options || []
   if (['select', 'radio', 'link'].includes(card.type) && card.setAll === 'true') { // 鍏煎
-    options.unshift({
+    let cell = {
       key: 'empty',
       Value: '',
       Text: card.emptyText || '绌�',
       ParentID: ''
-    })
+    }
+
+    if (card.linkSubField) {
+      card.linkSubField.forEach(m => {
+        cell[m] = ''
+      })
+    }
+
+    options.unshift(cell)
   }
 
   let initval = card.initval || ''
@@ -1199,7 +1207,7 @@
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
       tooltip: '鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\'',
-      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�硷細@ID@銆丂BID@銆�',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�硷細@ID@銆丂BID@銆丂Appkey@銆丂UserID@銆丂SessionUid@銆丂LoginUID@銆丂lang@銆�',
       required: true,
       readonly: false
     },
@@ -1869,7 +1877,7 @@
         text: '鏈湴'
       }, {
         value: 'sso',
-        text: '绯荤粺'
+        text: '鍗曠偣'
       }]
     },
     {
@@ -1907,7 +1915,7 @@
       type: 'radio',
       key: 'readin',
       label: '鑷姩濉厖',
-      tooltip: '灏嗚〃鏍奸�変腑鐨勬暟鎹嚜鍔ㄥ~鍏呭埌琛ㄥ崟涓�傛敞锛氬湪鎵归噺鎿嶄綔鏃讹紝濡傛兂瑕佹墍閫夎锛堝綋鍓嶅瓧娈碉級鍏ㄩ儴淇敼璇疯涓哄惁鎴栭琛屻��',
+      tooltip: '灏嗚〃鏍奸�変腑鐨勬暟鎹嚜鍔ㄥ~鍏呭埌琛ㄥ崟涓�傛敞锛氬湪鎵归噺鎿嶄綔鏃讹紝濡傛兂瑕佹墍閫夎锛堝綋鍓嶅瓧娈碉級鍏ㄩ儴淇敼璇疯涓哄惁鎴栭琛岋紱浣跨敤鈥滅紦瀛樷�濇椂锛屽皢鍦ㄦ湰鍦颁繚瀛樹笌璇诲彇琛ㄥ崟淇℃伅锛岄�夎鏃朵娇鐢ㄨ淇℃伅濉厖銆�',
       initVal: card.readin || 'true',
       options: [{
         value: 'true',
@@ -1918,6 +1926,9 @@
       }, {
         value: 'top',
         text: '棣栬'
+      }, {
+        value: 'local',
+        text: '缂撳瓨'
       }]
     },
     {
@@ -2515,6 +2526,18 @@
     },
     {
       type: 'number',
+      key: 'contHeidht',
+      label: '楂樺害',
+      min: 1,
+      max: 2000,
+      precision: 1,
+      initVal: card.contHeidht,
+      tooltip: '瀵屾枃鏈紪杈戝尯鐨勯珮搴︼紝灏忎簬100鏃朵负绐楀彛鐨勭櫨鍒嗘瘮銆�',
+      required: false,
+      forbid: appType === 'mob'
+    },
+    {
+      type: 'number',
       key: 'labelwidth',
       min: 1,
       max: 100,
diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx
index 7b515e6..8867247 100644
--- a/src/templates/zshare/modalform/index.jsx
+++ b/src/templates/zshare/modalform/index.jsx
@@ -41,7 +41,7 @@
   hint: ['label', 'field', 'type', 'blacklist', 'supField', 'message', 'span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
   split: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', 'splitctrl', 'supField', 'opacity'],
   formula: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', 'supField', 'span', 'labelwidth', 'formula', 'eval', 'postfix'],
-  brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption', 'marginTop', 'marginBottom'],
+  brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption', 'marginTop', 'marginBottom', 'contHeidht'],
   funcvar: ['span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
   linkMain: ['readonly', 'required', 'hidden','declare', 'span', 'labelwidth', 'tooltip', 'interception', 'extra', 'place', 'marginTop', 'marginBottom'],
   popSelect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'dataSource', 'columns', 'primaryKey', 'order', 'controlField', 'laypage', 'onload', 'searchKey', 'showField', 'popWidth'],
@@ -764,6 +764,7 @@
           extra = <span className="add-resource-empty" onClick={this.handleEmpty}>绌�</span>
         }
         if (item.placeholder) {
+          className = 'show-public-var'
           extra = <><span className="resource-public-var">{item.placeholder}</span>{extra}</>
         }
 
@@ -1095,22 +1096,17 @@
 
           window.GLOB.formId = card.uuid
 
-          if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(values.type) && values.resourceType === '1' && values.dataSource) {
+          if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(values.type) && values.resourceType === '1' && values.database !== 'sso' && values.dataSource) {
             let _option = Utils.getSelectQueryOptions(values)
 
             let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
             ${_option.sql}`
     
-            // LoginUID|SessionUid|UserID|Appkey 宸叉浛鎹�
+            // LoginUID|SessionUid|UserID|Appkey|lang 宸叉浛鎹�
             sql = sql.replace(/@\$|\$@/ig, '')
-    
-            let rduri = ''
-            if (window.GLOB.mainSystemApi && values.database === 'sso') {
-              rduri = window.GLOB.mainSystemApi
-            }
             
             resolve({values, loading: true, promise: () => new Promise((resolve, reject) => {
-              Api.sDebug(sql, rduri).then(result => {
+              Api.sDebug(sql).then(result => {
                 if (result.status || result.ErrCode === '-2') {
                   resolve()
                 } else {
diff --git a/src/templates/zshare/modalform/index.scss b/src/templates/zshare/modalform/index.scss
index e718410..a59ba16 100644
--- a/src/templates/zshare/modalform/index.scss
+++ b/src/templates/zshare/modalform/index.scss
@@ -46,10 +46,15 @@
     cursor: pointer;
     font-size: 14px;
   }
+  .show-public-var {
+    margin-top: 20px;
+  }
   .resource-public-var {
     position: absolute;
     left: 0px;
-    top: -25px;
-    font-size: 14px;
+    top: -45px;
+    right: 40px;
+    font-size: 13px;
+    color: rgba(0, 0, 0, 0.65);
   }
 }
\ No newline at end of file
diff --git a/src/templates/zshare/pasteform/index.jsx b/src/templates/zshare/pasteform/index.jsx
index 73d666e..2a9a5b4 100644
--- a/src/templates/zshare/pasteform/index.jsx
+++ b/src/templates/zshare/pasteform/index.jsx
@@ -41,7 +41,7 @@
             _config = JSON.parse(window.decodeURIComponent(window.atob(_config)))
 
             if (typeof(_config) === 'object' && _config.$srcId) {
-              let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+              let srcid = localStorage.getItem(window.GLOB.sysSign + 'srcId')
               if (srcid && _config.$srcId !== srcid) {
                 notification.warning({
                   top: 92,
@@ -56,14 +56,14 @@
             }
           } catch (e) {
             // 閫氳繃sql璇彞娣诲姞瀛楁闆�
-            if (/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int)/ig.test(values.config)) {
+            if (/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int|datetime|date)/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)
+              let list = values.config.match(/[a-zA-Z0-9_]+\s+(nvarchar\(\d+\)|Decimal\(18,\d+\)|Int|datetime|date)/ig)
 
               list.forEach(item => {
                 _config.data.unshift({
diff --git a/src/templates/zshare/verifycard/baseform/index.jsx b/src/templates/zshare/verifycard/baseform/index.jsx
index d67515e..cbfc412 100644
--- a/src/templates/zshare/verifycard/baseform/index.jsx
+++ b/src/templates/zshare/verifycard/baseform/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Row, Col, Select, Radio, Tooltip, Input } from 'antd'
+import { Form, Row, Col, Select, Radio, Tooltip, Input, message } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -25,61 +25,65 @@
   state = {
     wxTemps: [],
     selectTemp: null,
-    miniTemps: []
+    WXApps: null
   }
 
   componentDidMount() {
-    let wxTemps = sessionStorage.getItem('wxTemplates')
+    const { appType, verify } = this.props
 
-    if (window.GLOB.WXAppID && window.GLOB.nginx && !wxTemps) {
-      Api.wxAccessToken().then(res => {
-        let wxtoken = res.oa_access_token || ''
-        // let minitoken = res.mini_access_token || ''
-  
-        if (wxtoken) {
-          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 => {
-                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}}', '')
-                }
+    let appId = window.GLOB.WXAppID || ''
 
-                return true
-              })
-            }
-            
-            sessionStorage.setItem('wxTemplates', JSON.stringify(temps))
-            localStorage.setItem('wxTemplates', JSON.stringify(temps))
+    if (window.GLOB.WXApps && !appType) {
+      let apps = window.GLOB.WXApps.filter(app => app.appType === 'public')
 
-            localStorage.removeItem('wxTemplates')
+      if (apps.length > 0) {
+        this.setState({WXApps: apps})
+      }
 
-            this.resetTemps(temps)
-          })
-        } else {
-          sessionStorage.setItem('wxTemplates', JSON.stringify([]))
-          localStorage.setItem('wxTemplates', JSON.stringify([]))
+      if (verify.wxAppId && apps.findIndex(item => item.appId === verify.wxAppId) > -1) {
+        appId = verify.wxAppId
+      }
+    }
 
-          localStorage.removeItem('wxTemplates')
-        }
-        // if (minitoken) {
-        //   Api.wxNginxRequest(`wxaapi/newtmpl/gettemplate?access_token=${minitoken}`, 'get').then(res => {
-        //     if (res.errmsg === 'ok' && res.data) {
-        //       sessionStorage.setItem('wxMiniTemplates', JSON.stringify(res.data))
-        //     } else {
-        //       sessionStorage.setItem('wxMiniTemplates', JSON.stringify([]))
-        //     }
-        //   })
-        // } else {
-        //   sessionStorage.setItem('wxMiniTemplates', JSON.stringify([]))
-        // }
-      })
+    let wxTemps = sessionStorage.getItem('wxTemplates' + appId)
+
+    if (appId && !wxTemps) {
+      if (verify.wxNote === 'true') {
+        this.getTemps(appId)
+      }
     } else if (wxTemps) {
       wxTemps = JSON.parse(wxTemps)
 
       this.resetTemps(wxTemps)
+    } else {
+      this.resetTemps([])
     }
+  }
+
+  getTemps = (appId) => {
+    // cgi-bin/template/get_all_private_template
+    Api.directRequest({
+      url: window.GLOB.baseurl + 'wechat/get_all_private_template?appid=' + appId,
+      method: 'get',
+    }).then(res => {
+      let temps = []
+      if (res.template_list) {
+        temps = res.template_list.filter(item => {
+          if (!item.content || item.content.length < 25 || sysTempsIds.includes(item.template_id)) return false
+          if (item.content) {
+            item.content = item.content.replace('{{first.DATA}}\n', '').replace('\n{{remark.DATA}}', '')
+          }
+
+          return true
+        })
+      } else if (res.errcode && res.errmsg) {
+        message.warning(res.errcode + ': ' + res.errmsg)
+      }
+      
+      sessionStorage.setItem('wxTemplates' + appId, JSON.stringify(temps))
+
+      this.resetTemps(temps)
+    })
   }
 
   resetTemps = (wxTemps) => {
@@ -102,14 +106,14 @@
         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: ''
-      }
+      // {
+      //   template_id: 'mk_category_temp',
+      //   title: '绫荤洰妯℃澘',
+      //   primary_industry: '',
+      //   deputy_industry: '',
+      //   content: '',
+      //   example: ''
+      // }
     ]
     
     let _wxTemps = [...wxTemps, ...sysTemps]
@@ -181,6 +185,7 @@
       delete _verify.pre_func
     }
     if (_verify.wxNote !== 'true') {
+      delete _verify.wxAppId
       delete _verify.wxTemplateId
       delete _verify.wxNoteLink
       delete _verify.wxNoteLinkUrl
@@ -197,6 +202,18 @@
     }
 
     this.props.onChange(_verify)
+
+    if (key === 'wxNote' && value === 'true' && window.GLOB.WXAppID) {
+      let wxTemps = sessionStorage.getItem('wxTemplates' + window.GLOB.WXAppID)
+
+      if (wxTemps) {
+        wxTemps = JSON.parse(wxTemps)
+
+        this.resetTemps(wxTemps)
+      } else {
+        this.getTemps(window.GLOB.WXAppID)
+      }
+    }
   }
 
   onNoteCodeChange = (val, option) => {
@@ -231,7 +248,7 @@
 
     let keys = []
     if (option.props.content) {
-      keys = option.props.content.match(/{{[a-zA-Z0-9]+\.DATA}}/g)
+      keys = option.props.content.match(/{{[a-zA-Z0-9_]+\.DATA}}/g)
       keys = keys.map(key => key.replace(/{{|\.DATA}}/g, ''))
     }
 
@@ -260,6 +277,45 @@
     this.setState({selectTemp})
 
     this.props.onChange(_verify)
+  }
+
+  onWxAppChange = (val) => {
+    const { verify } = this.props
+
+    let _verify = {...verify, wxAppId: val, wxNote: 'false'}
+
+    delete _verify.wxTemplateId
+    delete _verify.wxNoteLink
+    delete _verify.wxNoteLinkUrl
+    delete _verify.wxNoteMiniId
+    delete _verify.wxNoteLinkMenuId
+    delete _verify.wxNoteCallback
+    delete _verify.wxCustomTempId
+
+    _verify.wxNoteKeys = null
+    
+    if (this.state.selectTemp) {
+      this.setState({selectTemp: null})
+    }
+
+    let _verify_ = fromJS(_verify).toJS()
+    _verify_.wxNote = 'true'
+
+    this.props.onChange(_verify)
+
+    setTimeout(() => {
+      this.props.onChange(_verify_)
+
+      let wxTemps = sessionStorage.getItem('wxTemplates' + val)
+
+      if (wxTemps) {
+        wxTemps = JSON.parse(wxTemps)
+
+        this.resetTemps(wxTemps)
+      } else {
+        this.getTemps(val)
+      }
+    }, 20)
   }
 
   onWxNoteKeyChange = (key, val) => {
@@ -300,7 +356,7 @@
 
   render() {
     const { unionFields, verify, notes, emailCodes, card, appType, columns, fields } = this.props
-    const { wxTemps, selectTemp } = this.state
+    const { wxTemps, selectTemp, WXApps } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -337,6 +393,16 @@
   
         _columns.push(col)
       })
+    }
+
+    let miniable = ''
+    if (window.GLOB.WXApps) {
+      let apps = window.GLOB.WXApps.filter(app => app.appType === 'miniProgram')
+
+      if (apps.length > 1) {
+        miniable = apps.map(app => `${app.appId}锛�${app.appName}锛塦)
+        miniable = miniable.join('锛�')
+      }
     }
 
     return (
@@ -636,7 +702,7 @@
           <Col span={24}></Col>
           <Col span={8}>
             <Form.Item label={
-              <Tooltip placement="bottomLeft" title={'璇峰湪鏈嶅姟鍣ㄥ畬鎴愬叕浼楀彿閰嶇疆銆�'}>
+              <Tooltip placement="bottomLeft" title="璇峰湪鏈嶅姟鍣ㄥ畬鎴愬叕浼楀彿閰嶇疆銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
                 鍏紬鍙锋秷鎭�
               </Tooltip>
@@ -647,6 +713,22 @@
               </Radio.Group>
             </Form.Item>
           </Col>
+          {verify.wxNote === 'true' && WXApps ? <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="璇烽�夋嫨鍙戦�佹秷鎭殑鍏紬鍙枫��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍏紬鍙�
+              </Tooltip>
+            } required>
+              <Select value={verify.wxAppId || window.GLOB.WXAppID} onSelect={this.onWxAppChange}>
+                {WXApps.map(option =>
+                  <Select.Option key={option.appId} value={option.appId}>
+                    {option.appName}
+                  </Select.Option>
+                )}
+              </Select>
+            </Form.Item>
+          </Col> : null}
           {verify.wxNote === 'true' ? <Col span={8}>
             <Form.Item label="娑堟伅妯℃澘" required>
               <Select value={verify.wxTemplateId} onSelect={this.onWxTemplateChange}>
@@ -692,7 +774,7 @@
           </Col> : null}
           {verify.wxNoteLink === 'miniProgram' ? <Col span={8}>
             <Form.Item label={
-              <Tooltip placement="top" title="鍙寚瀹氳烦杞皬绋嬪簭鐨処D锛屾湭璁剧疆鏃堕粯璁や娇鐢ㄩ厤缃枃浠朵腑鐨勫皬绋嬪簭ID銆�">
+              <Tooltip placement="top" title={'鍙寚瀹氳烦杞皬绋嬪簭鐨処D锛屾湭璁剧疆鏃堕粯璁や娇鐢ㄩ厤缃枃浠朵腑鐨勫皬绋嬪簭ID銆�' + miniable}>
                 <QuestionCircleOutlined className="mk-form-tip" />
                 灏忕▼搴廔D
               </Tooltip>
diff --git a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
index 22d6853..7a33ed3 100644
--- a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
+++ b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
@@ -116,12 +116,12 @@
 
         let sql = this.props.initsql +  _prevCustomScript + _backCustomScript + tail
 
-        if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-          window.GLOB.funcs.forEach(item => {
-            let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
-            sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-          })
-        }
+        // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+        //   window.GLOB.funcs.forEach(item => {
+        //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
+        //     sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+        //   })
+        // }
 
         // 鏁版嵁鏉冮檺
         sql = sql.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '')
@@ -227,7 +227,7 @@
           </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, datam</span></Tooltip>,&nbsp;
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, lang, time_id, typename, datam</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>
               {formfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="琛ㄥ崟鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��">, <span style={{color: '#8E44AD'}}>{formfields}</span></Tooltip> : ''}
diff --git a/src/templates/zshare/verifycard/customform/index.jsx b/src/templates/zshare/verifycard/customform/index.jsx
index a111016..efca89b 100644
--- a/src/templates/zshare/verifycard/customform/index.jsx
+++ b/src/templates/zshare/verifycard/customform/index.jsx
@@ -76,12 +76,12 @@
           end
           aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
 
-        if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-          window.GLOB.funcs.forEach(item => {
-            let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
-            sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-          })
-        }
+        // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+        //   window.GLOB.funcs.forEach(item => {
+        //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
+        //     sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+        //   })
+        // }
         
         // 鏁版嵁鏉冮檺
         sql = sql.replace(/@\$|\$@/ig, '')
@@ -130,7 +130,7 @@
         <Row gutter={24}>
           <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={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, lang, 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, 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>
               {formfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="琛ㄥ崟鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��">, <span style={{color: '#8E44AD'}}>{formfields}</span></Tooltip> : ''}
diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx
index 05231cc..d371c52 100644
--- a/src/templates/zshare/verifycard/customscript/index.jsx
+++ b/src/templates/zshare/verifycard/customscript/index.jsx
@@ -183,12 +183,12 @@
 
         sql += _backCustomScript + tail
 
-        if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-          window.GLOB.funcs.forEach(item => {
-            let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
-            sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
-          })
-        }
+        // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+        //   window.GLOB.funcs.forEach(item => {
+        //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
+        //     sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
+        //   })
+        // }
 
         // 鏁版嵁鏉冮檺
         sql = sql.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '')
@@ -204,14 +204,19 @@
           sql = sql.replace(/@statusname@/ig, `'寮�濮�'`)
           sql = sql.replace(/@work_group@/ig, `'work_group'`)
           sql = sql.replace(/@work_grade@/ig, '0')
-          sql = sql.replace(/@start_type@/ig, `'寮�濮�'`)
-          sql = sql.replace(/@check_type@/ig, `'瀹℃牳'`)
-          sql = sql.replace(/@notice_type@/ig, `'鎶勯��'`)
-
-          sql = sql.replace(/@check_userids@/ig, `''`)
-          sql = sql.replace(/@notice_userids@/ig, `''`)
           
-          sql = sql.replace(/@works_flow_sign@/ig, `''`)
+          
+          if (flowType === 'start') {
+            sql = sql.replace(/@start_type@/ig, `'寮�濮�'`)
+          } else {
+            sql = sql.replace(/@check_type@/ig, `'瀹℃牳'`)
+            sql = sql.replace(/@notice_type@/ig, `'鎶勯��'`)
+
+            sql = sql.replace(/@check_userids@/ig, `''`)
+            sql = sql.replace(/@notice_userids@/ig, `''`)
+
+            sql = sql.replace(/@works_flow_sign@/ig, `''`)
+          }
         }
         
         if (skip) {
@@ -328,7 +333,7 @@
   }
 
   render() {
-    const { formfields, colfields, systemScripts, btn, type, workFlow } = this.props
+    const { formfields, colfields, systemScripts, btn, type, workFlow, flowType } = this.props
     const { getFieldDecorator } = this.props.form
     const { editItem, skip } = this.state
     const formItemLayout = {
@@ -359,8 +364,8 @@
           </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, datam</span></Tooltip>,&nbsp;
-              {window.GLOB.process && workFlow === 'true' ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="宸ヤ綔娴佸彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤锛寃orks_flow_sign 涓哄垎鏀惎鐢ㄩ珮绾ц缃椂鐨勬爣璁板�笺��"><span style={{color: '#26C281'}}>works_flow_code, works_flow_name, works_flow_param, works_flow_detail_id, status, statusname, work_group, work_grade, start_type, check_type, notice_type, check_userids, notice_userids, works_flow_sign, </span></Tooltip> : null}
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�"><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, lang, time_id, typename, datam</span></Tooltip>,&nbsp;
+              {window.GLOB.process && workFlow === 'true' ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={`宸ヤ綔娴佸彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤${flowType !== 'start' ? '锛寃orks_flow_sign 涓哄垎鏀惎鐢ㄩ珮绾ц缃椂鐨勬爣璁板��' : ''}銆俙}><span style={{color: '#26C281'}}>works_flow_code, works_flow_name, works_flow_param, works_flow_detail_id, status, statusname, work_group, work_grade, {flowType === 'start' ? 'start_type,' : 'check_type, notice_type, check_userids, notice_userids, works_flow_sign,'} </span></Tooltip> : null}
               <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>
               {formfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="琛ㄥ崟鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��">, <span style={{color: '#8E44AD'}}>{formfields}</span></Tooltip> : ''}
diff --git a/src/templates/zshare/verifycard/fullScripts/index.jsx b/src/templates/zshare/verifycard/fullScripts/index.jsx
index 0fee3ee..b5433c1 100644
--- a/src/templates/zshare/verifycard/fullScripts/index.jsx
+++ b/src/templates/zshare/verifycard/fullScripts/index.jsx
@@ -69,7 +69,7 @@
                 position = <span style={{color: 'orange'}}>鍒濆鍖�</span>
               } else if (item.position === 'front') {
                 position = <span style={{color: '#26C281'}}>sql鍓�</span>
-              } else {
+              } else if (item.position === 'back') {
                 position = <span style={{color: '#1890ff'}}>sql鍚�</span>
               }
 
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index 9e50ea7..9113732 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -663,20 +663,20 @@
       _verify.printTempId = ''
     }
 
-    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-      window.GLOB.funcs.forEach(m => {
-        let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
-        _verify.customverifys.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-        _verify.scripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-        _verify.cbScripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-      })
-    }
+    // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+    //   window.GLOB.funcs.forEach(m => {
+    //     let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig')
+    //     _verify.customverifys.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     })
+    //     _verify.scripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     })
+    //     _verify.cbScripts.forEach(item => {
+    //       item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
+    //     })
+    //   })
+    // }
 
     _verify.customverifys.forEach((item, i) => {
       item.$index = i + 1
@@ -695,11 +695,19 @@
       activeKey = 'cbScripts'
     }
 
+    let oriVerify = fromJS(_verify).toJS()
+
+    if (_verify.wxAppId) {
+      if (!window.GLOB.WXApps || window.GLOB.WXApps.filter(app => app.appType === 'public').length === 0) {
+        delete _verify.wxAppId
+      }
+    }
+
     this.setState({
       activeKey: activeKey,
       verifyInter: verifyInter,
       verify: _verify,
-      oriVerify: fromJS(_verify).toJS()
+      oriVerify: oriVerify
     })
 
     if (card.intertype === 'inner') return
@@ -817,6 +825,8 @@
         if (_f.datatype) { // 鑷畾涔夊瓧娈�
           if (/decimal|int/ig.test(_f.datatype)) {
             _select.push(`@${_f.field}=1`)
+          } else if (/date/ig.test(_f.datatype)) {
+            _select.push(`@${_f.field}='1949-10-01'`)
           } else {
             _select.push(`@${_f.field}=''`)
           }
@@ -1157,7 +1167,6 @@
   }
 
   orderSql = (record) => {
-    let _ModularDetailCode = ''
     let _lpline = ''
     if (record.TypeCharOne === 'Lp') {
       if (record.linkField.toLowerCase() === 'bid') {
@@ -1165,17 +1174,20 @@
       } else {
         _lpline = `set @ModularDetailCode= 'Lp'+ right('${record.mark || this.props.card.uuid}'+@${record.linkField.toLowerCase()},48)`
       }
-      _ModularDetailCode = '@ModularDetailCode'
     } else if (record.TypeCharOne === 'BN') {
-      _ModularDetailCode = `'${record.TypeCharOne}'`
+      if (record.linkField.toLowerCase() === 'bid') {
+        _lpline = `set @ModularDetailCode= 'BN'+ right(@BID@,48)`
+      } else {
+        _lpline = `set @ModularDetailCode= 'BN'+ right(@${record.linkField.toLowerCase()},48)`
+      }
     } else {
-      _ModularDetailCode = `'${record.ModularDetailCode}'`
+      _lpline = `set @ModularDetailCode= right('${record.ModularDetailCode}',50)`
     }
 
     let sql = `select @BillCode='', @${record.field}='', @ModularDetailCode=''
     ${_lpline}
     exec s_get_BillCode
-      @ModularDetailCode=${_ModularDetailCode},
+      @ModularDetailCode=@ModularDetailCode,
       @Type=${record.Type},
       @TypeCharOne='${record.TypeCharOne}',
       @TypeCharTwo ='${record.TypeCharTwo}',
@@ -1583,20 +1595,20 @@
         msg = '鑷畾涔夎剼鏈�'
       }
 
-      if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
-        window.GLOB.funcs.forEach(m => {
-          let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
-          verify.customverifys.forEach(item => {
-            item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-          })
-          verify.scripts.forEach(item => {
-            item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-          })
-          verify.cbScripts.forEach(item => {
-            item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
-          })
-        })
-      }
+      // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
+      //   window.GLOB.funcs.forEach(m => {
+      //     let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
+      //     verify.customverifys.forEach(item => {
+      //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+      //     })
+      //     verify.scripts.forEach(item => {
+      //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+      //     })
+      //     verify.cbScripts.forEach(item => {
+      //       item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
+      //     })
+      //   })
+      // }
 
       delete verify.limitInvalid
       delete verify.limitText
diff --git a/src/utils/sqlFormatter.js b/src/utils/sqlFormatter.js
index 0dd99e8..e14e46b 100644
--- a/src/utils/sqlFormatter.js
+++ b/src/utils/sqlFormatter.js
@@ -247,43 +247,43 @@
 	    };
  
 	    Formatter.prototype.getFormattedQueryFromTokens = function getFormattedQueryFromTokens() {
-	        var _this = this;
+	        var that = this;
 	        var formattedQuery = "";
 	        this.tokens.forEach(function (token, index) {
-	            _this.index = index;
+	            that.index = index;
 	            if (token.type === _tokenTypes2["default"].WHITESPACE) {
 	                // ignore (we do our own whitespace formatting)
 	            } else if (token.type === _tokenTypes2["default"].LINE_COMMENT) {
-	                formattedQuery = _this.formatLineComment(token, formattedQuery);
+	                formattedQuery = that.formatLineComment(token, formattedQuery);
 	            } else if (token.type === _tokenTypes2["default"].BLOCK_COMMENT) {
-	                formattedQuery = _this.formatBlockComment(token, formattedQuery);
+	                formattedQuery = that.formatBlockComment(token, formattedQuery);
 	            } else if (token.type === _tokenTypes2["default"].RESERVED_TOPLEVEL) {
-	                formattedQuery = _this.formatToplevelReservedWord(token, formattedQuery);
-	                _this.previousReservedWord = token;
+	                formattedQuery = that.formatToplevelReservedWord(token, formattedQuery);
+	                that.previousReservedWord = token;
 	            } else if (token.type === _tokenTypes2["default"].RESERVED_NEWLINE) {
-	                formattedQuery = _this.formatNewlineReservedWord(token, formattedQuery);
-	                _this.previousReservedWord = token;
+	                formattedQuery = that.formatNewlineReservedWord(token, formattedQuery);
+	                that.previousReservedWord = token;
 	            }else if (token.type === _tokenTypes2["default"].RESERVED) {
-	                formattedQuery = _this.formatWithSpaces(token, formattedQuery);
-	                _this.previousReservedWord = token;
+	                formattedQuery = that.formatWithSpaces(token, formattedQuery);
+	                that.previousReservedWord = token;
 	            } else if (token.type === _tokenTypes2["default"].OPEN_PAREN) {
-	                formattedQuery = _this.formatOpeningParentheses(token, formattedQuery);
+	                formattedQuery = that.formatOpeningParentheses(token, formattedQuery);
 	            } else if (token.type === _tokenTypes2["default"].CLOSE_PAREN) {
-	                formattedQuery = _this.formatClosingParentheses(token, formattedQuery);
+	                formattedQuery = that.formatClosingParentheses(token, formattedQuery);
 	            } else if (token.type === _tokenTypes2["default"].PLACEHOLDER) {
-	                formattedQuery = _this.formatPlaceholder(token, formattedQuery);
+	                formattedQuery = that.formatPlaceholder(token, formattedQuery);
 	            }   else if (token.value === '$') {
-	                formattedQuery = _this.formatNewWithSpaces(token, formattedQuery);
+	                formattedQuery = that.formatNewWithSpaces(token, formattedQuery);
 	            } else if (token.value === ",") {
-	                formattedQuery = _this.formatComma(token, formattedQuery);
+	                formattedQuery = that.formatComma(token, formattedQuery);
 	            } else if (token.value === ":") {
-	                formattedQuery = _this.formatWithSpaceAfter(token, formattedQuery);
+	                formattedQuery = that.formatWithSpaceAfter(token, formattedQuery);
 	            } else if (token.value === ".") {
-	                formattedQuery = _this.formatWithoutSpaces(token, formattedQuery);
+	                formattedQuery = that.formatWithoutSpaces(token, formattedQuery);
 	            } else if (token.value === ";") {
-	                formattedQuery = _this.formatQuerySeparator(token, formattedQuery);
+	                formattedQuery = that.formatQuerySeparator(token, formattedQuery);
 	            } else {
-	                formattedQuery = _this.formatWithSpaces(token, formattedQuery);
+	                formattedQuery = that.formatWithSpaces(token, formattedQuery);
 	            }
 	        });
 	        return formattedQuery;
@@ -545,10 +545,10 @@
 	    };
  
 	    Tokenizer.prototype.createParenRegex = function createParenRegex(parens) {
-	        var _this = this;
+	        var that = this;
  
 	        return new RegExp("^(" + parens.map(function (p) {
-	            return _this.escapeParen(p);
+	            return that.escapeParen(p);
 	        }).join("|") + ")", "i");
 	    };
  
@@ -669,13 +669,13 @@
 	    };
  
 	    Tokenizer.prototype.getStringNamedPlaceholderToken = function getStringNamedPlaceholderToken(input) {
-	        var _this2 = this;
+	        var that2 = this;
  
 	        return this.getPlaceholderTokenWithKey({
 	            input: input,
 	            regex: this.STRING_NAMED_PLACEHOLDER_REGEX,
 	            parseKey: function parseKey(v) {
-	                return _this2.getEscapedPlaceholderKey({ key: v.slice(2, -1), quoteChar: v.slice(-1) });
+	                return that2.getEscapedPlaceholderKey({ key: v.slice(2, -1), quoteChar: v.slice(-1) });
 	            }
 	        });
 	    };
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index d49eb33..3a6e6de 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -1,4 +1,5 @@
 import md5 from 'md5'
+import { fromJS } from 'immutable'
 import { notification } from 'antd'
 
 export default class MenuUtils {
@@ -558,6 +559,9 @@
           })
         }
       } else if (item.type === 'form') {
+        if (item.wrap.datatype === 'public' && item.wrap.publicId) {
+          item.wrap.publicId = md5(commonId + item.wrap.publicId)
+        }
         item.subcards = item.subcards.map(cell => {
           cell.uuid = this.getuuid()
   
@@ -626,7 +630,7 @@
         })
       }
 
-      if (item.setting && item.setting.supModule && item.setting.supModule[0] !== 'empty') {
+      if (item.setting && item.setting.supModule && item.setting.supModule[0] !== 'empty' && item.setting.supModule[0] !== 'preview') {
         item.setting.supModule = item.setting.supModule.map(c => {
           return md5(commonId + c)
         })
@@ -700,10 +704,6 @@
   * @return {String}  item 缁勪欢淇℃伅
   */
   static resetComponentConfig = (item, appType, commonId) => {
-    if (item.type === 'navbar') {
-      return item
-    }
-
     if (item.subtype === 'tablecard') { // 鍏煎
       item.type = 'card'
     }
@@ -721,7 +721,22 @@
       item.name = item.setting.name
     }
 
-    if (item.type === 'menubar') {
+    if (item.columns) {
+      item.columns = item.columns.map(cell => {
+        cell.uuid = this.getuuid()
+        return cell
+      })
+    }
+
+    if (item.type === 'navbar') {
+      if (appType === 'mob') {
+        item.menus.forEach(menu => {
+          menu.MenuID = this.getuuid()
+        })
+        item.wrap.MenuNo = item.wrap.MenuNo + sign
+      }
+      return item
+    } else if (item.type === 'menubar') {
       item.subMenus = item.subMenus.map(cell => {
         cell.uuid = this.getuuid()
         return cell
@@ -924,12 +939,6 @@
         return cell
       })
     }
-    if (item.columns) {
-      item.columns = item.columns.map(cell => {
-        cell.uuid = this.getuuid()
-        return cell
-      })
-    }
 
     if (item.wrap && item.wrap.doubleClick) {
       item.wrap.doubleClick = md5(commonId + item.wrap.doubleClick)
@@ -1105,6 +1114,8 @@
         value = item.initval || `${item.minValue || '-999999999'},${item.maxValue || '999999999'}`
       } else if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) {
         type = 'multi'
+      } else {
+        value = item.initval || '0'
       }
 
       newsearches.push({
@@ -1734,6 +1745,115 @@
 }
 
 /**
+ * @description 鑾峰彇鍙戦�佸閮ㄦ秷鎭�
+ */
+export function getOutMessage (config) {
+  let message = 'false'
+
+  let filterBtn = (cell) => {
+    if (['pop', 'exec', 'form', 'prompt', 'formSubmit'].includes(cell.OpenType) && cell.verify) {
+      if (cell.verify.noteEnable === 'true' || cell.verify.wxNote === 'true' || cell.verify.emailEnable === 'true') {
+        message = 'true'
+      }
+    }
+  }
+
+  let traversal = (components) => {
+    if (!components || message === 'true') return
+
+    components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          traversal(tab.components)
+        })
+      } else if (item.type === 'group') {
+        traversal(item.components)
+      } else {
+        if (item.action) {
+          item.action.forEach(cell => {
+            if (cell.OpenType === 'popview') {
+              if (cell.config) {
+                traversal(cell.config.components)
+              }
+            } else {
+              filterBtn(cell)
+            }
+          })
+        }
+
+        if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+          item.subcards.forEach(card => {
+            card.elements && card.elements.forEach(cell => {
+              if (cell.eleType !== 'button') return
+              
+              if (cell.OpenType === 'popview') {
+                if (cell.config) {
+                  traversal(cell.config.components)
+                }
+              } else {
+                filterBtn(cell)
+              }
+            })
+            card.backElements && card.backElements.forEach(cell => {
+              if (cell.eleType !== 'button') return
+              
+              if (cell.OpenType === 'popview') {
+                if (cell.config) {
+                  traversal(cell.config.components)
+                }
+              } else {
+                filterBtn(cell)
+              }
+            })
+          })
+        } else if (item.type === 'balcony') {
+          item.elements && item.elements.forEach(cell => {
+            if (cell.eleType !== 'button') return
+            
+            if (cell.OpenType === 'popview') {
+              if (cell.config) {
+                traversal(cell.config.components)
+              }
+            } else {
+              filterBtn(cell)
+            }
+          })
+        } else if (item.type === 'table') {
+          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') {
+                    if (cell.config) {
+                      traversal(cell.config.components)
+                    }
+                  } else {
+                    filterBtn(cell)
+                  }
+                })
+              }
+            })
+          }
+          loopCol(item.cols)
+        } else if (item.type === 'form') {
+          item.subcards.forEach(group => {
+            filterBtn(group.subButton)
+          })
+        }
+      }
+    })
+  }
+
+  traversal(config.components)
+
+  return message
+}
+
+/**
  * @description 妫�娴嬬粍浠跺唴瀹�
  */
 export function checkComponent (card) {
@@ -1794,23 +1914,31 @@
       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 === 'excelIn') {
+      if (!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') {
       if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
         errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
-      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom' && card.$c_ds && columns.length > 0) {
-        let cols = []
-        cell.verify.columns.forEach(col => {
-          if (col.output === 'false' || col.Column === '$Index') return
-          if (!columns.includes(col.Column)) {
-            cols.push(col.Column)
+      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom') {
+        if (!card.setting || card.setting.interType !== 'system') {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濋渶鑷畾涔夊鍑烘暟鎹簮锛乣})
+        } else if (card.type === 'balcony' || card.subtype === 'propcard') {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濋渶鑷畾涔夊鍑烘暟鎹簮锛乣})
+        } else if (card.$c_ds && columns.length > 0) {
+          let cols = []
+          cell.verify.columns.forEach(col => {
+            if (col.output === 'false' || col.Column === '$Index') return
+            if (!columns.includes(col.Column)) {
+              cols.push(col.Column)
+            }
+          })
+          if (cols.length) {
+            errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楋紙${cols.join('銆�')}锛夊湪瀛楁闆嗕腑涓嶅瓨鍦紒`})
           }
-        })
-        if (cols.length) {
-          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楋紙${cols.join('銆�')}锛夊湪瀛楁闆嗕腑涓嶅瓨鍦紒`})
         }
-      }
+      } 
     }
 
     if (['pop', 'prompt', 'exec'].includes(cell.OpenType) && cell.verify && !cell.output) {
@@ -1818,6 +1946,65 @@
         errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濇湭璁剧疆杩斿洖鍊肩煭淇″彂閫佹棤鏁堬紒`})
       } else if (cell.verify.emailEnable === 'true') {
         errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濇湭璁剧疆杩斿洖鍊奸偖浠跺彂閫佹棤鏁堬紒`})
+      }
+    }
+
+    if (['exec', 'prompt', 'pop', 'form', 'formSubmit'].includes(cell.OpenType)) {
+      if (cell.Ot !== 'requiredOnce' && ['pop', 'form'].includes(cell.OpenType) && cell.verify && cell.verify.uniques && cell.verify.uniques.length > 0) {
+        let forms = ['BID']
+    
+        if (cell.OpenType === 'form') {
+          forms.push(cell.field)
+        } else if (cell.modal && cell.modal.fields.length > 0) {
+          cell.modal.fields.forEach(n => {
+            if (!n.field) return
+            forms.push(n.field)
+          })
+        }
+        let emptys = []
+        cell.verify.uniques.forEach(m => {
+          if (m.status === 'false') return
+
+          m.field.split(',').forEach(n => {
+            if (!forms.includes(n)) {
+              emptys.push(n)
+            }
+          })
+        })
+
+        if (emptys.length) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濆敮涓�鎬ч獙璇佸瓧娈�${emptys.join('銆�')}锛屽湪琛ㄥ崟涓笉瀛樺湪锛乣})
+        }
+      }
+
+      if (cell.OpenType === 'form' && cell.formType === 'count_line') return
+     
+      if (cell.intertype === 'system') {
+        if (cell.Ot === 'notRequired' && cell.verify && cell.verify.voucher && cell.verify.voucher.enabled) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅娇鐢ㄤ簡鍒涘缓鍑瘉鍑芥暟锛岄渶瑕侀�夋嫨琛岋紒`})
+        }
+      } else if (cell.intertype === 'custom' || cell.intertype === 'outer') {
+        if (cell.callbackType === 'script' && (!cell.verify || !cell.verify.cbScripts || cell.verify.cbScripts.filter(item => item.status !== 'false').length === 0)) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅娇鐢ㄤ簡鑷畾涔夎剼鏈洖璋冿紝鍥炶皟鑴氭湰涓嶅彲涓虹┖锛乣})
+        } else if (cell.procMode === 'system' && cell.Ot === 'notRequired' && cell.verify && cell.verify.voucher && cell.verify.voucher.enabled) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅娇鐢ㄤ簡鍒涘缓鍑瘉鍑芥暟锛岄渶瑕侀�夋嫨琛岋紒`})
+        }
+      }
+    } else if (cell.OpenType === 'funcbutton') {
+      if (cell.funcType === 'print') {
+        if (!cell.verify || !cell.verify.printMode) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濊瀹屽杽楠岃瘉淇℃伅锛乣})
+        } else if (cell.intertype === 'system' && cell.verify.dataType === 'custom' && (!cell.verify.setting || cell.verify.columns.length === 0)) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅娇鐢ㄤ簡鑷畾涔夋墦鍗版暟鎹紝璇疯缃暟鎹簮锛乣})
+        }
+      } else if ((cell.funcType === 'refund' || cell.funcType === 'pay') && cell.payMode === 'system' && (!cell.verify || !cell.verify.scripts || cell.verify.scripts.filter(item => item.status !== 'false').length === 0)) {
+        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濋渶娣诲姞鑷畾涔夎剼鏈紒`})
+      }
+    } else if (cell.OpenType === 'innerpage' || cell.OpenType === 'outerpage') {
+      if (!cell.pageTemplate) {
+        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濋〉闈㈢被鍨嬭缃敊璇紒`})
+      } else if (cell.pageTemplate === 'pay' && cell.payMode === 'system' && (!cell.verify || !cell.verify.scripts || cell.verify.scripts.filter(item => item.status !== 'false').length === 0)) {
+        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濋渶娣诲姞鑷畾涔夎剼鏈紒`})
       }
     }
   }
@@ -1934,10 +2121,18 @@
   let _quot = sql.match(/'{1}/g)
   let _lparen = sql.match(/\({1}/g)
   let _rparen = sql.match(/\){1}/g)
+  let _ch_b = sql.match(/\$check@/ig)
+  let _ch_d = sql.match(/@check\$/ig)
+  let _m_b = sql.match(/\$@/ig)
+  let _m_d = sql.match(/@\$/ig)
 
   _quot = _quot ? _quot.length : 0
   _lparen = _lparen ? _lparen.length : 0
   _rparen = _rparen ? _rparen.length : 0
+  _ch_b = _ch_b ? _ch_b.length : 0
+  _ch_d = _ch_d ? _ch_d.length : 0
+  _m_b = _m_b ? _m_b.length : 0
+  _m_d = _m_d ? _m_d.length : 0
 
   if (_quot % 2 !== 0) {
     notification.warning({
@@ -1950,6 +2145,20 @@
     notification.warning({
       top: 92,
       message: 'sql涓�()蹇呴』鎴愬鍑虹幇',
+      duration: 5
+    })
+    return false
+  } else if (_ch_b !== _ch_d) {
+    notification.warning({
+      top: 92,
+      message: 'sql涓� $check@ 涓� @check$ 蹇呴』鎴愬鍑虹幇',
+      duration: 5
+    })
+    return false
+  } else if (_m_b !== _m_d) {
+    notification.warning({
+      top: 92,
+      message: 'sql涓� $@ 涓� @$ 蹇呴』鎴愬鍑虹幇',
       duration: 5
     })
     return false
@@ -2004,13 +2213,27 @@
       duration: 5
     })
     return false
+  } else if (/\send\s+begin\s/ig.test(sql)) {
+    notification.warning({
+      top: 92,
+      message: `end 鍚庝笉鍙揣璺� begin銆俙,
+      duration: 5
+    })
+    return false
+  } else if (/\sdecimal\(8,/ig.test(sql)) {
+    notification.warning({
+      top: 92,
+      message: `涓嶅彲浣跨敤 decimal(8`,
+      duration: 5
+    })
+    return false
   } else if (type === 'customscript' && /\son\s+[a-z0-9_]+\.[a-z0-9_]+\s*=\s*[a-z0-9_]+\.[a-z0-9_]+/ig.test(sql)) {
     let list = sql.match(/\son\s+[a-z0-9_]+\.[a-z0-9_]+\s*=\s*[a-z0-9_]+\.[a-z0-9_]+/ig)
     let errors = []
     list.forEach(str => {
       str = str.replace(/^\s/, '')
       let strs = str.match(/(\s|=)[a-z0-9_]+\./ig)
-      if (strs.length === 2 && (strs[0].replace(/\s|\./g, '') === strs[1].replace(/\s|\./g, ''))) {
+      if (strs.length === 2 && (strs[0].replace(/\s|\.|=/g, '') === strs[1].replace(/\s|\.|=/g, ''))) {
         errors.push(str)
       }
     })
@@ -2064,4 +2287,4035 @@
   }
 
   return true
+}
+
+/**
+ * @description 鑾峰彇璇█杞崲淇℃伅
+ */
+export function getLangTrans (config) {
+  let langList = sessionStorage.getItem('langList')
+  let appType = sessionStorage.getItem('appType')
+
+  if (appType === 'mob' || appType === 'pc') {
+    langList = sessionStorage.getItem('applangList')
+  }
+  
+  if (!langList) return
+
+  let defLang = ''
+
+  try {
+    langList = JSON.parse(langList)
+    defLang = langList[0]
+  } catch (e) {
+    defLang = ''
+  }
+
+  if (!defLang) return ''
+
+  let sql = []
+  let btn = []
+  let ops = []
+  let text = []
+  let menu = []
+
+  let filterElement = (card) => {
+    if (card.datatype === 'static' && card.eleType === 'text' && !/@.+@/g.test(card.value)) {
+      sql.push(card.value)
+    }
+    if (card.prefix) {
+      sql.push(card.prefix)
+    }
+    if (card.postfix) {
+      sql.push(card.postfix)
+    }
+  }
+
+  let filterSql = (sl) => {
+    if (!sl) return
+
+    let cutreg = /[\u4E00-\u9FA5銆傦紒锛屻�乚+/ig
+    let tbs = sl.match(cutreg)
+
+    if (!tbs) return
+    
+    text.push(...tbs)
+  }
+
+  let filterBtn = (btn) => {
+    if (!btn.verify) return
+
+    btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
+      filterSql(script.sql)
+    })
+    btn.verify.scripts && btn.verify.scripts.forEach(script => {
+      filterSql(script.sql)
+    })
+    btn.verify.cbScripts && btn.verify.cbScripts.forEach(script => {
+      filterSql(script.sql)
+    })
+
+    if (btn.OpenType === 'funcbutton') {
+      if (btn.intertype === 'system' && btn.verify.dataType === 'custom' && btn.verify.setting) {
+        filterSql(btn.verify.setting.dataresource)
+      }
+    } else if (btn.OpenType === 'excelOut') {
+      filterSql(btn.verify.dataresource)
+    }
+  }
+
+  let filterForm = (n) => {
+    sql.push(n.label)
+    if (n.resourceType === '1') {
+      filterSql(n.dataSource)
+    } else if (n.options) {
+      n.options.forEach(o => {
+        ops.push(o.Text)
+      })
+    }
+  }
+
+  let traversal = (components) => {
+    if (!components) return
+
+    components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          sql.push(tab.label)
+          traversal(tab.components)
+        })
+      } else if (item.type === 'group') {
+        traversal(item.components)
+      } else {
+        if (item.setting && (!item.wrap || !item.wrap.datatype || item.wrap.datatype === 'dynamic')) {
+          if (item.setting.interType === 'system') {
+            filterSql(item.setting.dataresource)
+            item.scripts && item.scripts.forEach(script => {
+              filterSql(script.sql)
+            })
+          }
+        }
+
+        if (item.columns) {
+          item.columns.forEach(cell => {
+            sql.push(cell.label)
+          })
+        }
+        if (item.search) {
+          if (item.type === 'topbar') {
+            if (item.search.fields) {
+              item.search.fields.forEach(cell => {
+                filterForm(cell)
+              })
+            }
+            if (item.search.groups) {
+              item.search.groups.forEach(group => {
+                if (group.fields) {
+                  group.fields.forEach(cell => {
+                    filterForm(cell)
+                  })
+                }
+              })
+            }
+          } else {
+            item.search.forEach(cell => {
+              filterForm(cell)
+            })
+          }
+        }
+        if (item.action) {
+          item.action.forEach(cell => {
+            btn.push(cell.label)
+            filterBtn(cell)
+            if (cell.OpenType === 'popview' && cell.config) {
+              traversal(cell.config.components)
+            } else if (cell.OpenType === 'pop') {
+              if (cell.modal && cell.modal.fields.length) {
+                cell.modal.fields.forEach(n => {
+                  filterForm(n)
+                })
+              }
+            }
+          })
+        }
+
+        if (item.type === 'navbar') {
+          if (item.menus) {
+            item.menus.forEach(first => {
+              menu.push(first.name)
+              if (first.sublist) {
+                first.sublist.forEach(sec => {
+                  menu.push(sec.name)
+                  if (sec.sublist) {
+                    sec.sublist.forEach(thd => {
+                      menu.push(thd.name)
+                    })
+                  }
+                })
+              }
+            })
+          }
+        } else if (item.type === 'menubar') {
+          item.subMenus.forEach(cell => {
+            if (cell.setting.name) {
+              menu.push(cell.setting.name)
+            }
+          })
+        } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+          item.subcards.forEach(card => {
+            card.elements && card.elements.forEach(cell => {
+              if (cell.eleType === 'button') {
+                btn.push(cell.label)
+                filterBtn(cell)
+                if (cell.OpenType === 'popview' && cell.config) {
+                  traversal(cell.config.components)
+                } else if (cell.OpenType === 'pop') {
+                  if (cell.modal && cell.modal.fields.length) {
+                    cell.modal.fields.forEach(n => {
+                      filterForm(n)
+                    })
+                  }
+                }
+              } else {
+                filterElement(cell)
+              }
+            })
+            card.backElements && card.backElements.forEach(cell => {
+              if (cell.eleType === 'button') {
+                btn.push(cell.label)
+                filterBtn(cell)
+                if (cell.OpenType === 'popview' && cell.config) {
+                  traversal(cell.config.components)
+                } else if (cell.OpenType === 'pop') {
+                  if (cell.modal && cell.modal.fields.length) {
+                    cell.modal.fields.forEach(n => {
+                      filterForm(n)
+                    })
+                  }
+                }
+              } else {
+                filterElement(cell)
+              }
+            })
+          })
+        } else if (item.type === 'balcony') {
+          item.elements && item.elements.forEach(cell => {
+            if (cell.eleType === 'button') {
+              btn.push(cell.label)
+              filterBtn(cell)
+              if (cell.OpenType === 'popview' && cell.config) {
+                traversal(cell.config.components)
+              } else if (cell.OpenType === 'pop') {
+                if (cell.modal && cell.modal.fields.length) {
+                  cell.modal.fields.forEach(n => {
+                    filterForm(n)
+                  })
+                }
+              }
+            } else {
+              filterElement(cell)
+            }
+          })
+        } else if (item.type === 'table') {
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              sql.push(col.label)
+              if (col.prefix) {
+                sql.push(col.prefix)
+              }
+              if (col.postfix) {
+                sql.push(col.postfix)
+              }
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType === 'button') {
+                    btn.push(cell.label)
+                    filterBtn(cell)
+                    if (cell.OpenType === 'popview' && cell.config) {
+                      traversal(cell.config.components)
+                    } else if (cell.OpenType === 'pop') {
+                      if (cell.modal && cell.modal.fields.length) {
+                        cell.modal.fields.forEach(n => {
+                          filterForm(n)
+                        })
+                      }
+                    }
+                  } else {
+                    filterElement(cell)
+                  }
+                })
+              }
+            })
+          }
+          loopCol(item.cols)
+        } else if (item.type === 'form') {
+          item.subcards.forEach(cell => {
+            filterBtn(cell.subButton)
+            cell.fields.forEach(n => {
+              filterForm(n)
+            })
+          })
+        }
+      }
+    })
+  }
+
+  if (config.interfaces) {
+    config.interfaces.forEach(item => {
+      if (item.setting.interType === 'system') {
+        filterSql(item.setting.dataresource)
+        item.scripts && item.scripts.forEach(script => {
+          filterSql(script.sql)
+        })
+      }
+    })
+  }
+
+  traversal(config.components)
+
+  if (config.MenuName) {
+    menu.push(config.MenuName)
+  }
+
+  if (config.fstMenuId && config.parentId && config.fstMenuId !== 'BillPrintTemp') {
+    let menulist = sessionStorage.getItem('fstMenuList')
+    try {
+      menulist = JSON.parse(menulist)
+    } catch(e) {
+      menulist = []
+    }
+
+    menulist.forEach(item => {
+      if (item.MenuID !== config.fstMenuId) return
+      menu.push(item.MenuName)
+      item.children.forEach(cell => {
+        if (cell.MenuID !== config.parentId) return
+        menu.push(cell.MenuName)
+      })
+    })
+  }
+
+  sql = sql.filter(Boolean)
+  btn = btn.filter(Boolean)
+  ops = ops.filter(Boolean)
+  text = text.filter(Boolean)
+  menu = menu.filter(Boolean)
+
+  sql = Array.from(new Set(sql))
+  btn = Array.from(new Set(btn))
+  ops = Array.from(new Set(ops))
+  text = Array.from(new Set(text))
+  menu = Array.from(new Set(menu))
+
+  sql = sql.map(l => `'${l}','title'`)
+  btn = btn.map(l => `'${l}','button'`)
+  ops = ops.map(l => `'${l}','list'`)
+  text = text.map(l => `'${l}','text'`)
+  menu = menu.map(l => `'${l}','menu'`)
+
+  let list = [...menu, ...btn, ...sql, ...ops, ...text]
+
+  let result = []
+
+  langList.forEach(lan => {
+    if (lan === defLang) return
+
+    list.forEach(n => {
+      result.push(`'${lan}',${n}`)
+    })
+  })
+
+  config.trans = true
+  
+  return result.join(';')
+}
+
+/**
+ * @description 璇█杞崲
+ */
+export function setLangTrans (config, btnDict, titDict, lisDict, menuDict, regs, tail) {
+  let filterElement = (card) => {
+    if (card.datatype === 'static' && card.eleType === 'text' && !/@.+@/g.test(card.value)) {
+      if (card.value && titDict[card.value]) {
+        card.value = titDict[card.value]
+      }
+    }
+    if (card.prefix && titDict[card.prefix]) {
+      card.prefix = titDict[card.prefix]
+    }
+    if (card.postfix && titDict[card.postfix]) {
+      card.postfix = titDict[card.postfix]
+    }
+  }
+
+  let filterSql = (sl) => {
+    if (!sl) return
+
+    regs.forEach(item => {
+      sl = sl.replace(item.reg, item.value)
+    })
+
+    return sl
+  }
+
+  let filterBtn = (btn) => {
+    if (btn.label && btnDict[btn.label]) {
+      btn.label = btnDict[btn.label]
+    }
+
+    if (btn.OpenType === 'tab' && btn.linkmenu) {
+      if (btn.linkmenu[0] === 'multiMenu') {
+        btn.multiMenus.forEach(menu => {
+          menu.menuId = menu.menuId.map(c => {
+            if (c.length <= 24) {
+              return md5(window.GLOB.appkey + c + sessionStorage.getItem('lang')).toLowerCase()
+            } else {
+              return c.slice(0, 24) + tail
+            }
+          })
+
+          menu.MenuID = menu.menuId[menu.menuId.length - 1]
+        })
+      } else {
+        btn.linkmenu = btn.linkmenu.map(c => {
+          if (c.length <= 24) {
+            return md5(window.GLOB.appkey + c + sessionStorage.getItem('lang')).toLowerCase()
+          } else {
+            return c.slice(0, 24) + tail
+          }
+        })
+        btn.MenuID = btn.linkmenu[btn.linkmenu.length - 1]
+      }
+    } else {
+      if (btn.refreshTab && btn.refreshTab.length > 0) {
+        btn.refreshTab = btn.refreshTab.map(c => {
+          if (c.length <= 24) {
+            return md5(window.GLOB.appkey + c + sessionStorage.getItem('lang')).toLowerCase()
+          } else {
+            return c.slice(0, 24) + tail
+          }
+        })
+      }
+      if (btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0) {
+        btn.openmenu = btn.openmenu.map(c => {
+          if (c.length <= 24) {
+            return md5(window.GLOB.appkey + c + sessionStorage.getItem('lang')).toLowerCase()
+          } else {
+            return c.slice(0, 24) + tail
+          }
+        })
+        btn.MenuID = btn.openmenu[btn.openmenu.length - 1]
+      } else if (btn.openmenu && typeof(btn.openmenu) === 'string' && btn.openmenu !== 'goback') {
+        btn.openmenu = btn.openmenu.slice(0, 24) + tail
+      }
+
+      if (btn.pageTemplate === 'linkpage' && btn.linkmenu && typeof(btn.linkmenu) === 'string') {
+        btn.linkmenu = btn.linkmenu.slice(0, 24) + tail
+      }
+    }
+
+    if (!btn.verify) return
+
+    btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
+      script.sql = filterSql(script.sql)
+    })
+    btn.verify.scripts && btn.verify.scripts.forEach(script => {
+      script.sql = filterSql(script.sql)
+    })
+    btn.verify.cbScripts && btn.verify.cbScripts.forEach(script => {
+      script.sql = filterSql(script.sql)
+    })
+
+    if (btn.OpenType === 'funcbutton') {
+      if (btn.intertype === 'system' && btn.verify.dataType === 'custom' && btn.verify.setting) {
+        btn.verify.setting.dataresource = filterSql(btn.verify.setting.dataresource)
+      }
+    } else if (btn.OpenType === 'excelOut' && btn.verify.dataresource) {
+      btn.verify.dataresource = filterSql(btn.verify.dataresource)
+    }
+  }
+
+  let filterForm = (n) => {
+    if (n.label && titDict[n.label]) {
+      n.label = titDict[n.label]
+    }
+    if (n.resourceType === '1') {
+      n.dataSource = filterSql(n.dataSource)
+    } else if (n.options) {
+      n.options.forEach(o => {
+        if (o.Text && lisDict[o.Text]) {
+          o.Text = lisDict[o.Text]
+        }
+      })
+    }
+  }
+
+  let resetMenu = (wrap) => {
+    if (!wrap.menu) return
+    
+    if (typeof(wrap.menu) === 'string') {
+      wrap.menu = wrap.menu.slice(0, 24) + tail
+      if (wrap.MenuID) {
+        wrap.MenuID = wrap.menu
+      }
+    } else {
+      wrap.menu = wrap.menu.map(c => {
+        if (c.length <= 24) {
+          return md5(window.GLOB.appkey + c + sessionStorage.getItem('lang')).toLowerCase()
+        } else {
+          return c.slice(0, 24) + tail
+        }
+      })
+      if (wrap.MenuID) {
+        wrap.MenuID = wrap.menu[wrap.menu.length - 1]
+      }
+    }
+  }
+  let resetMenus = (wrap) => {
+    if (!wrap.menus) return
+    
+    wrap.menus.forEach(m => {
+      if (typeof(m.menu) === 'string') {
+        m.menu = m.menu.slice(0, 24) + tail
+      } else {
+        m.menu = m.menu.map(c => {
+          if (c.length <= 24) {
+            return md5(window.GLOB.appkey + c + sessionStorage.getItem('lang')).toLowerCase()
+          } else {
+            return c.slice(0, 24) + tail
+          }
+        })
+        if (m.MenuID) {
+          m.MenuID = m.menu[m.menu.length - 1]
+        }
+      }
+    })
+  }
+
+  let traversal = (components) => {
+    if (!components) return
+
+    components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          if (tab.label && titDict[tab.label]) {
+            tab.label = titDict[tab.label]
+          }
+          traversal(tab.components)
+        })
+      } else if (item.type === 'group') {
+        traversal(item.components)
+      } else {
+        if (item.wrap && (item.wrap.click === 'menu' || item.wrap.click === 'menus')) {
+          if (item.wrap.click === 'menu') {
+            resetMenu(item.wrap)
+          } else if (item.wrap.click === 'menus') {
+            resetMenus(item.wrap)
+          }
+        } else if (item.plot && (item.plot.click === 'menu' || item.plot.click === 'menus')) {
+          if (item.plot.click === 'menu') {
+            resetMenu(item.plot)
+          } else if (item.plot.click === 'menus') {
+            resetMenus(item.plot)
+          }
+        }
+        if (item.setting && (!item.wrap || !item.wrap.datatype || item.wrap.datatype === 'dynamic')) {
+          if (item.setting.interType === 'system') {
+            item.setting.dataresource = filterSql(item.setting.dataresource)
+            item.scripts && item.scripts.forEach(script => {
+              script.sql = filterSql(script.sql)
+            })
+          }
+        }
+
+        if (item.columns) {
+          item.columns.forEach(cell => {
+            if (cell.label && titDict[cell.label]) {
+              cell.label = titDict[cell.label]
+            }
+          })
+        }
+        if (item.search) {
+          if (item.type === 'topbar') {
+            if (item.search.fields) {
+              item.search.fields.forEach(cell => {
+                filterForm(cell)
+              })
+            }
+            if (item.search.groups) {
+              item.search.groups.forEach(group => {
+                if (group.fields) {
+                  group.fields.forEach(cell => {
+                    filterForm(cell)
+                  })
+                }
+              })
+            }
+          } else {
+            item.search.forEach(cell => {
+              filterForm(cell)
+            })
+          }
+        }
+        if (item.action) {
+          item.action.forEach(cell => {
+            filterBtn(cell)
+            if (cell.OpenType === 'popview' && cell.config) {
+              traversal(cell.config.components)
+            } else if (cell.OpenType === 'pop') {
+              if (cell.modal && cell.modal.fields.length) {
+                cell.modal.fields.forEach(n => {
+                  filterForm(n)
+                })
+              }
+            }
+          })
+        }
+
+        if (item.type === 'navbar') {
+          item.uuid = item.uuid.slice(0, 24) + tail
+        } else if (item.type === 'login') {
+          item.wrap.linkmenu = item.wrap.linkmenu.slice(0, 24) + tail
+        } else if (item.type === 'menubar') {
+          item.subMenus = item.subMenus.map(cell => {
+            if (cell.setting.name && menuDict[cell.setting.name]) {
+              cell.setting.name = menuDict[cell.setting.name]
+            }
+            if (cell.setting.type === 'linkmenu') {
+              cell.setting.linkMenuId = cell.setting.linkMenuId.slice(0, 24) + tail
+            }
+            return cell
+          })
+        } else if (item.type === 'topbar') {
+          if (item.wrap.menus) {
+            resetMenus(item.wrap)
+          }
+        } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+          item.subcards.forEach(card => {
+            if (card.setting.click === 'menus') {
+              resetMenus(card)
+            } else if (card.setting.click === 'menu') {
+              resetMenu(card.setting)
+            }
+            card.elements && card.elements.forEach(cell => {
+              if (cell.eleType === 'button') {
+                filterBtn(cell)
+                if (cell.OpenType === 'popview' && cell.config) {
+                  traversal(cell.config.components)
+                } else if (cell.OpenType === 'pop') {
+                  if (cell.modal && cell.modal.fields.length) {
+                    cell.modal.fields.forEach(n => {
+                      filterForm(n)
+                    })
+                  }
+                }
+              } else {
+                filterElement(cell)
+              }
+            })
+            card.backElements && card.backElements.forEach(cell => {
+              if (cell.eleType === 'button') {
+                filterBtn(cell)
+                if (cell.OpenType === 'popview' && cell.config) {
+                  traversal(cell.config.components)
+                } else if (cell.OpenType === 'pop') {
+                  if (cell.modal && cell.modal.fields.length) {
+                    cell.modal.fields.forEach(n => {
+                      filterForm(n)
+                    })
+                  }
+                }
+              } else {
+                filterElement(cell)
+              }
+            })
+          })
+        } else if (item.type === 'balcony') {
+          item.elements && item.elements.forEach(cell => {
+            if (cell.eleType === 'button') {
+              filterBtn(cell)
+              if (cell.OpenType === 'popview' && cell.config) {
+                traversal(cell.config.components)
+              } else if (cell.OpenType === 'pop') {
+                if (cell.modal && cell.modal.fields.length) {
+                  cell.modal.fields.forEach(n => {
+                    filterForm(n)
+                  })
+                }
+              }
+            } else {
+              filterElement(cell)
+            }
+          })
+        } else if (item.type === 'table') {
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.label && titDict[col.label]) {
+                col.label = titDict[col.label]
+              }
+              if (col.prefix && titDict[col.prefix]) {
+                col.prefix = titDict[col.prefix]
+              }
+              if (col.postfix && titDict[col.postfix]) {
+                col.postfix = titDict[col.postfix]
+              }
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType === 'button') {
+                    filterBtn(cell)
+                    if (cell.OpenType === 'popview' && cell.config) {
+                      traversal(cell.config.components)
+                    } else if (cell.OpenType === 'pop') {
+                      if (cell.modal && cell.modal.fields.length) {
+                        cell.modal.fields.forEach(n => {
+                          filterForm(n)
+                        })
+                      }
+                    }
+                  } else {
+                    filterElement(cell)
+                  }
+                })
+              }
+            })
+          }
+          loopCol(item.cols)
+        } else if (item.type === 'form') {
+          item.subcards.forEach(cell => {
+            filterBtn(cell.subButton)
+            cell.fields.forEach(n => {
+              filterForm(n)
+            })
+          })
+        }
+      }
+    })
+  }
+
+  if (config.interfaces) {
+    config.interfaces.forEach(item => {
+      if (item.setting.interType === 'system') {
+        item.setting.dataresource = filterSql(item.setting.dataresource)
+        item.scripts && item.scripts.forEach(script => {
+          script.sql = filterSql(script.sql)
+        })
+      }
+    })
+  }
+
+  traversal(config.components)
+}
+
+/**
+ * @description 鑾峰彇鎵ц鑴氭湰
+ */
+export function getAllSqls (conf) {
+  let config = fromJS(conf).toJS()
+
+  let sqls = []
+  let urlFields = config.urlFields
+  let appType = sessionStorage.getItem('appType')
+  let process = config.process === 'true'
+  let sysVars = ['loginuid', 'sessionuid', 'userid', 'appkey', 'lang', 'username', 'fullname', 'menuname']
+
+  if (urlFields) {
+    urlFields = urlFields.map(n => n.toLowerCase())
+  }
+
+let callback = `
+COMMIT TRAN
+set NOCOUNT ON
+RETURN
+END TRY
+BEGIN CATCH
+  ROLLBACK TRAN
+  DECLARE @ErrorMessage NVARCHAR(4000);
+  DECLARE @ErrorSeverity INT;
+  DECLARE @ErrorState INT;
+
+  set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
+  set @retmsg=ERROR_MESSAGE();
+  select @ErrorMessage=ERROR_MESSAGE(), @ErrorSeverity=ERROR_SEVERITY(), @ErrorState=ERROR_STATE();
+
+  RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
+END CATCH
+
+aaa:
+select @ErrorCode as ErrorCode,@retmsg as retmsg
+GOTO_RETURN:
+  ROLLBACK TRAN`
+
+  let filterComponent = (components, mainSearch, label = '') => {
+    components.forEach(item => {
+      item.$menuname = (config.MenuName || '') + label + '-' + (item.name || '')
+
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          let _mainSearch = mainSearch || []
+
+          if (appType !== 'mob') {
+            tab.components.forEach(com => {
+              if (com.type !== 'search') return
+        
+              _mainSearch = com.search || []
+            })
+          }
+          filterComponent(tab.components, _mainSearch, label)
+        })
+      } else if (item.type === 'group') {
+        filterComponent(item.components, mainSearch, label)
+      } else {
+        if (item.wrap && item.setting) {
+          if (item.wrap.datatype === 'public' || item.wrap.datatype === 'static') {
+            item.setting.interType = 'other'
+          }
+        }
+
+        if (appType === 'mob' && item.type !== 'search' && item.type !== 'topbar' && item.search && item.search.length > 0) {
+          item.search = []
+        }
+        if (appType !== 'mob' && item.search && item.search.length > 0) {
+          item.search.forEach(cell => {
+            if (['select', 'link', 'multiselect', 'checkcard', 'radio'].includes(cell.type) && cell.resourceType === '1' && cell.dataSource) {
+              let msg = getFormSql(cell, '鎼滅储')
+      
+              sqls.push({uuid: md5(item.uuid + cell.uuid), type: 'sForm', ...msg})
+            }
+          })
+        }
+
+        if (item.subtype === 'tablecard') { // 鍏煎
+          item.type = 'card'
+        }
+
+        if (item.setting && item.setting.interType === 'system') {
+          if (item.format === 'object') {
+            item.setting.laypage = 'false'
+            item.setting.$top = true
+          }
+          item.setting.$name = item.$menuname || ''
+
+          let msg = getDataSource(item, mainSearch)
+
+          sqls.push({uuid: item.uuid, type: 'datasource', ...msg})
+        } else if (item.setting && item.setting.useMSearch === 'true') {
+          let searches = item.search || []
+          if (mainSearch.length > 0) {
+            searches = [...searches, ...mainSearch]
+          }
+          item.$searches = fromJS(searches).toJS()
+        }
+
+        item.action && item.action.forEach(cell => {
+          if (cell.hidden === 'true') return false
+          
+          resetButton(item, cell)
+        })
+
+        if (item.type === 'table') {
+          let getCols = (cols) => {
+            cols.forEach(col => {
+              if (col.type === 'action') {
+                col.type = 'custom'
+              }
+              if (col.type === 'colspan') {
+                getCols(col.subcols || [])
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  
+                  resetButton(item, cell)
+                })
+              } else if (item.subtype === 'editable' && col.editable === 'true') {
+                if (col.editType === 'select' && col.resourceType === '1') {
+                  let msg = getFormSql(col, '琛ㄥ崟')
+        
+                  sqls.push({uuid: col.uuid, type: 'tbForm', ...msg})
+                } else if (col.editType === 'popSelect') {
+                  if (col.pops) {
+                    col.pops.forEach(n => {
+                      let msg = getPopSelectSql(n)
+        
+                      sqls.push({uuid: n.uuid, type: 'popSource', ...msg})
+                    })
+                  } else {
+                    let msg = getPopSelectSql(col)
+        
+                    sqls.push({uuid: col.uuid, type: 'popSource', ...msg})
+                  }
+                }
+              }
+            })
+          }
+          
+          getCols(item.cols)
+  
+          if (item.subtype === 'editable' && item.submit.intertype === 'system') {
+            item.submit.logLabel = item.$menuname + '-鎻愪氦'
+            let msg = getEditTableSql(item.submit, item.cols, item.columns, item.setting)
+
+            sqls.push({uuid: 'submit_' + item.uuid, type: 'editable', ...msg})
+          }
+        } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+          item.subcards && item.subcards.forEach(card => {
+            card.elements && card.elements.forEach(cell => {
+              if (cell.eleType !== 'button' || cell.hidden === 'true') return
+              
+              resetButton(item, cell)
+            })
+  
+            if (!card.backElements || card.backElements.length === 0) return
+  
+            card.backElements.forEach(cell => {
+              if (cell.eleType !== 'button' || cell.hidden === 'true') return
+              
+              resetButton(item, cell, true)
+            })
+          })
+        } else if (item.type === 'balcony') {
+          item.elements.forEach(cell => {
+            if (cell.eleType !== 'button' || cell.hidden === 'true') return
+            
+            resetButton(item, cell)
+          })
+        } else if (item.type === 'form') {
+          item.subcards.forEach(group => {
+            group.subButton.OpenType = 'formSubmit'
+            if (!group.subButton.Ot) {
+              group.subButton.Ot = item.wrap.datatype === 'static' ? 'notRequired' : 'requiredSgl'
+            }
+            group.subButton.uuid = group.uuid
+            group.subButton.modal = {
+              fields: group.fields
+            }
+
+            resetButton(item, group.subButton)
+          })
+        } else if (item.type === 'module' && item.subtype === 'invoice') {
+          if (item.buyer.setting && item.buyer.setting.interType === 'system') {
+            let msg = getDataSource(item.buyer, [])
+            
+            sqls.push({uuid: item.uuid + 'buyer', type: 'datasource', ...msg})
+          }
+
+          if (item.detail.setting && item.detail.setting.interType === 'system') {
+            let _msg = getDataSource(item.detail, [])
+  
+            sqls.push({uuid: item.uuid + 'detail', type: 'datasource', ..._msg})
+          }
+
+          let btnmsg = getInvoicePreSql(item.billSaveBtn, item.$menuname + '-' + item.billSaveBtn.label)
+
+          sqls.push({uuid: item.uuid + item.billSaveBtn.type, type: 'button', ...btnmsg})
+
+          let _btnmsg = getInvoicePreSql(item.billOutBtn, item.$menuname + '-'  + item.billOutBtn.label)
+
+          sqls.push({uuid: item.uuid + item.billOutBtn.type, type: 'button', ..._btnmsg})
+
+          let backmsg = getInvoiceSysBackSql(item.billOutBtn, item.$menuname + '-'  + item.billOutBtn.label + '(鍥炶皟)')
+
+          sqls.push({uuid: item.uuid + 'billback', type: 'btnCallBack', ...backmsg})
+        }
+      }
+    })
+  }
+
+  let resetButton = (item, cell, isback) => {
+    cell.logLabel = item.$menuname + '-' + cell.label
+
+    if (['exec', 'prompt', 'pop', 'form', 'formSubmit'].includes(cell.OpenType)) {
+      if (cell.intertype === 'system' || cell.procMode === 'system') { // 绯荤粺鎺ュ彛
+        if (cell.verify && cell.verify.linkEnable === 'true' && /@/.test(cell.verify.linkUrl)) {
+          cell.returnValue = 'true'
+        }
+        if (item.subtype === 'dualdatacard' && isback) {
+          let _item = fromJS(item).toJS()
+          _item.columns = _item.subColumns || []
+          _item.setting.primaryKey = _item.setting.subKey
+
+          let msg = getSysDefaultSql(cell, _item)
+
+          sqls.push({uuid: cell.uuid, type: 'button', ...msg})
+        } else {
+          let msg = getSysDefaultSql(cell, item)
+
+          sqls.push({uuid: cell.uuid, type: 'button', ...msg})
+        }
+      }
+      if (cell.callbackType === 'script' && cell.verify && cell.verify.cbScripts) {
+        if (item.subtype === 'dualdatacard' && isback) {
+          let _item = fromJS(item).toJS()
+          _item.columns = _item.subColumns || []
+          
+          let msg = getSysBackSql(cell, _item)
+
+          sqls.push({uuid: 'back_' + cell.uuid, type: 'btnCallBack', ...msg})
+        } else {
+          let msg = getSysBackSql(cell, item)
+
+          sqls.push({uuid: 'back_' + cell.uuid, type: 'btnCallBack', ...msg})
+        }
+      }
+      if (['pop', 'formSubmit'].includes(cell.OpenType) && cell.modal && cell.modal.fields) {
+        cell.modal.fields.forEach(form => {
+          // 鏁版嵁婧恠ql璇彞锛岄澶勭悊锛屾潈闄愰粦鍚嶅崟瀛楁璁剧疆涓洪殣钘忚〃鍗�
+          if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(form.type) && form.resourceType === '1') {
+            let msg = getFormSql(form, '琛ㄥ崟')
+
+            sqls.push({uuid: md5(cell.uuid + form.uuid), type: 'form', ...msg})
+          } else if (form.type === 'popSelect') {
+            let msg = getPopSelectSql(form)
+        
+            sqls.push({uuid: form.uuid, type: 'popSource', ...msg})
+          }
+        })
+      }
+    } else if (cell.OpenType === 'excelIn') {
+      if (cell.intertype === 'system') {
+        let msg = getExcelInSql(cell)
+
+        sqls.push({uuid: cell.uuid, type: 'excelIn', ...msg})
+      }
+    } else if (cell.OpenType === 'excelOut') {
+      if (cell.intertype === 'system' && cell.verify && cell.verify.dataType === 'custom') {
+        let msg = getExcelOutSql(cell, item)
+
+        sqls.push({uuid: cell.uuid, type: 'excelOut', ...msg})
+      } else if (cell.intertype === 'system' && cell.verify && item.subtype === 'dualdatacard' && item.setting && item.setting.interType === 'system') {
+        let msg = getDoubleExcelOutSql(cell, item)
+
+        sqls.push({uuid: cell.uuid, type: 'excelOut', ...msg})
+      }
+    } else if (cell.OpenType === 'funcbutton') {
+      if (cell.funcType === 'print') {
+        if (cell.intertype === 'system' && cell.verify && cell.verify.dataType === 'custom') {
+          let msg = getPrintSql(cell, item)
+  
+          sqls.push({uuid: cell.uuid, type: 'print', ...msg})
+        }
+        if (cell.execMode === 'pop' && cell.modal && cell.modal.fields) {
+          cell.modal.fields.forEach(form => {
+            // 鏁版嵁婧恠ql璇彞锛岄澶勭悊锛屾潈闄愰粦鍚嶅崟瀛楁璁剧疆涓洪殣钘忚〃鍗�
+            if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(form.type) && form.resourceType === '1') {
+              let msg = getFormSql(form, '琛ㄥ崟')
+    
+              sqls.push({uuid: md5(cell.uuid + form.uuid), type: 'form', ...msg})
+            } else if (form.type === 'popSelect') {
+              let msg = getPopSelectSql(form)
+          
+              sqls.push({uuid: form.uuid, type: 'popSource', ...msg})
+            }
+          })
+        }
+      } else if ((cell.funcType === 'refund' || cell.funcType === 'pay') && cell.payMode === 'system') {
+        let msg = getPaySql(cell, item)
+
+        sqls.push({uuid: cell.uuid, type: 'pay', ...msg})
+      }
+    } else if (cell.OpenType === 'innerpage' || cell.OpenType === 'outerpage') {
+      if (cell.pageTemplate === 'pay' && cell.payMode === 'system') {
+        let msg = getPaySql(cell, item)
+
+        sqls.push({uuid: cell.uuid, type: 'pay', ...msg})
+      }
+    } else if (cell.OpenType === 'popview') {
+      if (cell.config && cell.config.components) {
+        let _mainSearch = []
+
+        if (appType === 'mob') {
+          cell.config.components.forEach(item => {
+            if (item.type === 'search' && item.wrap.field) {
+              _mainSearch.push({
+                type: 'text',
+                label: item.wrap.label,
+                field: item.wrap.field,
+                match: item.wrap.match,
+                required: item.wrap.required,
+                value: item.wrap.initval || ''
+              })
+            }
+          })
+        } else {
+          cell.config.components.forEach(component => {
+            if (component.type !== 'search') return
+
+            _mainSearch = component.search || []
+          })
+        }
+
+        filterComponent(cell.config.components, _mainSearch, '-' + cell.label)
+      }
+    }
+  }
+
+  let getSearches = (searches) => {
+    let sFields = []
+    searches.forEach(item => {
+      if (!item.field) return
+  
+      if (item.type === 'group') {
+        sFields.push(item.field)
+        sFields.push(item.datefield)
+        sFields.push(item.datefield + '1')
+      } else if (item.type === 'date') {
+        if (sFields.includes(item.field)) {
+          sFields.push(item.field + '1')
+        } else {
+          sFields.push(item.field)
+        }
+      } else if (item.type === 'dateweek') {
+        sFields.push(item.field)
+        sFields.push(item.field + '1')
+      } else if (item.type === 'range') {
+        sFields.push(item.field)
+        sFields.push(item.field + '1')
+      } else if (item.type === 'datemonth') {
+        if (item.match === '=') {
+          sFields.push(item.field)
+        } else {
+          sFields.push(item.field)
+          sFields.push(item.field + '1')
+        }
+      } else if (item.type === 'daterange') {
+        if (/,/.test(item.field)) {
+          sFields.push(item.field.split(',')[0])
+          sFields.push(item.field.split(',')[1])
+        } else {
+          sFields.push(item.field)
+          sFields.push(item.field + '1')
+        }
+      } else if (item.type === 'text' || item.type === 'select') {
+        item.field.split(',').forEach(field => {
+          sFields.push(field)
+        })
+      } else {
+        sFields.push(item.field)
+      }
+    })
+  
+    return sFields
+  }
+
+  let getSysDefaultSql = (btn, component) => {
+    let primaryId = '@ID@'
+    let BID = '@BID@'
+    let verify = btn.verify || {}
+    let _actionType = null
+    let setting = component.setting || {}
+    let columns = component.columns || []
+    let primaryKey = setting.primaryKey || 'id'
+    let colreps = [] // 寰呮浛鎹㈠彉閲忛泦
+
+    if (verify.invalid === 'true') {
+      if (component.wrap && (component.wrap.datatype === 'static' || component.wrap.datatype === 'public')) {
+        verify.invalid = 'false'
+      } else if (setting.maxScript && setting.maxScript >= 300) {
+        verify.invalid = 'false'
+      } else if (!setting.dataresource) {
+        verify.invalid = 'false'
+      } else if (btn.intertype !== 'system' && btn.procMode !== 'system') {
+        verify.invalid = 'false'
+      } else if (btn.sqlType === 'insert') {
+        verify.invalid = 'false'
+      } else if (btn.Ot === 'notRequired') {
+        verify.invalid = 'false'
+      }
+    }
+    if (verify.uniques && verify.uniques.length > 0 && btn.Ot === 'requiredOnce') {
+      if (component.wrap && (component.wrap.datatype === 'static' || component.wrap.datatype === 'public')) {
+        verify.uniques = []
+      }
+    }
+  
+    if (verify.default !== 'false') { // 鍒ゆ柇鏄惁浣跨敤榛樿sql
+      _actionType = btn.sqlType
+    }
+  
+    let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
+    let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
+    let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
+  
+    verify.scripts && verify.scripts.forEach(item => {
+      if (item.status === 'false') return
+  
+      if (item.position === 'init') {
+        _initCustomScript += `
+        /* 鑷畾涔夎剼鏈� */
+        ${item.sql}
+        `
+      } else if (item.position === 'front') {
+        _prevCustomScript += `
+        /* 鑷畾涔夎剼鏈� */
+        ${item.sql}
+        `
+      } else {
+        _backCustomScript += `
+        /* 鑷畾涔夎剼鏈� */
+        ${item.sql}
+        `
+      }
+    })
+  
+    // 闇�瑕佸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', 'mk_deleted', 'bid']
+  
+    let _sql = ''
+  
+    let _initFormfields = []
+    let _declares = []
+
+    let formdata = null
+    let formkeys = []
+    if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit') {
+      formdata = []
+      if (btn.modal && btn.modal.fields) {
+        btn.modal.fields.forEach(item => {
+          if (!item.field) return
+          
+          let _item = {
+            key: item.field,
+            fieldlen: item.fieldlength || 50,
+            writein: item.writein !== 'false',
+            type: item.type,
+            isconst: item.constant === 'true'
+          }
+
+          if (_item.type === 'datemonth') {
+            _item.type = 'text'
+          } else if (_item.type === 'number' || _item.type === 'rate') {
+            _item.fieldlen = item.decimal || 0
+          } else if (_item.type === 'date') {
+            _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
+          } else if (_item.type === 'datetime') {
+            _item.type = 'date'
+          } else if (item.declare === 'decimal') {
+            _item.type = 'number'
+            _item.fieldlen = item.decimal || 0
+          }
+    
+          formdata.push(_item)
+        })
+      }
+    } else if (btn.OpenType === 'form') {
+      formdata = []
+
+      let item = {
+        type: 'text',
+        readin: true,
+        writein: true,
+        fieldlen: 50,
+        key: btn.field
+      }
+      if (btn.formType === 'counter') {
+        item.type = 'number'
+        item.fieldlen = 0
+      } else if (btn.formType === 'switch' || btn.formType === 'radio') {
+        if (typeof(btn.openVal) === 'number') {
+          item.type = 'number'
+          item.fieldlen = 0
+        }
+      }
+      formdata.push(item)
+    }
+
+    // 鑾峰彇瀛楁閿�煎
+    formdata && formdata.forEach(form => {
+      let _key = form.key.toLowerCase()
+
+      if (!formkeys.includes(_key)) {
+        formkeys.push(_key)
+        if (form.type === 'number' || form.type === 'rate') {
+          _initFormfields.push(`@${_key}=@mk_${_key}_mk@`)
+        } else if (form.type === 'date') {
+          _initFormfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        } else if (form.type === 'select' || form.type === 'link' || form.type === 'radio') {
+          _initFormfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        } else if (form.isconst) {
+          _initFormfields.push(`@${_key}=N'@mk_${_key}_mk@'`)
+        } else {
+          _initFormfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        }
+      }
+      
+      if (!_vars.includes(_key)) {
+        _vars.push(_key)
+  
+        if (form.fieldlen && form.fieldlen > 4000) {
+          form.fieldlen = 'max'
+        }
+  
+        let _type = `nvarchar(${form.fieldlen})`
+  
+        if (form.type.match(/date/ig)) {
+          _type = 'datetime'
+        } else if (form.type === 'number') {
+          _type = `decimal(18,${form.fieldlen})`
+        } else if (form.type === 'rate') {
+          _type = `decimal(18,2)`
+        }
+  
+        _declares.push(`@${_key} ${_type}`)
+      }
+    })
+  
+    // 琛ㄥ崟鍙橀噺璧嬪��
+    if (_initFormfields.length > 0) {
+      _sql += `
+        /* 琛ㄥ崟鍙橀噺璧嬪�� */
+        select ${_initFormfields.join(',')}
+        `
+    }
+    if (btn.Ot !== 'notRequired' && columns.length > 0) {
+      _sql += '@mk_cols_values@'
+    }
+
+    // 鍘婚櫎绂佺敤鐨勯獙璇�
+    if (verify.contrasts) {
+      verify.contrasts = verify.contrasts.filter(item => item.status !== 'false')
+    }
+    if (verify.uniques) {
+      verify.uniques = verify.uniques.filter(item => item.status !== 'false')
+    }
+    if (verify.customverifys) {
+      verify.customverifys = verify.customverifys.filter(item => item.status !== 'false')
+    }
+    if (verify.billcodes) {
+      verify.billcodes = verify.billcodes.filter(item => item.status !== 'false')
+    }
+  
+    if (_initCustomScript) {
+      _sql += _initCustomScript
+    }
+  
+    // 鍚敤璐︽湡楠岃瘉
+    if (verify.accountdate === 'true') {
+      let orgcode = `''`
+      let date = `''`
+      if (verify.accountfield) {
+        orgcode = '@' + verify.accountfield
+      }
+      if (verify.voucherdate) {
+        date = '@' + verify.voucherdate
+      }
+  
+      _sql += `
+        /* 璐︽湡楠岃瘉 */
+        exec s_FIBVoucherDateCheck @OrgCode=${orgcode},@FIBVoucherDate=${date},@ErrorCode=@ErrorCode OUTPUT,@retmsg=@retmsg OUTPUT
+        if @ErrorCode!=''
+          GOTO aaa
+        `
+    }
+  
+    // 澶辨晥楠岃瘉锛屾坊鍔犳暟鎹椂涓嶇敤
+    if (verify.invalid === 'true') {
+      let datasource = setting.dataresource
+      let customScript = setting.customScript || ''
+
+      let regoptions = [{
+        reg: new RegExp('@orderBy@', 'ig'),
+        value: setting.order || primaryKey
+      }, {
+        reg: new RegExp('@pageSize@', 'ig'),
+        value: 1
+      }, {
+        reg: new RegExp('@pageIndex@', 'ig'),
+        value: 1
+      }]
+
+      regoptions.forEach(item => {
+        datasource = datasource.replace(item.reg, item.value)
+        customScript = customScript.replace(item.reg, item.value)
+      })
+  
+      if (customScript) {
+        _sql += `
+        /* 鏁版嵁婧愯嚜瀹氫箟鑴氭湰锛岃娉ㄦ剰鍙橀噺瀹氫箟鏄惁閲嶅 */
+        ${customScript}
+        `
+      }
+  
+      if (btn.Ot === 'requiredOnce') {
+        _sql += `
+        /* 澶辨晥楠岃瘉 */
+        select @tbid='', @ErrorCode='',@retmsg=''
+        select @tbid='X' from ${datasource} right join (select ID from  dbo.SplitComma(@ID@)) sp
+        on tb.${primaryKey} =sp.id where tb.${primaryKey} is null
+
+        If @tbid!=''
+        Begin
+          select @ErrorCode='E',@retmsg='鏁版嵁宸插け鏁�'
+          goto aaa
+        end
+        `
+      } else {
+        _sql += `
+        /* 澶辨晥楠岃瘉 */
+        select @tbid='', @ErrorCode='',@retmsg=''
+        select @tbid=${primaryKey} from ${datasource} where ${primaryKey}=@ID@
+        If @tbid=''
+        Begin
+          select @ErrorCode='E',@retmsg='鏁版嵁宸插け鏁�'
+          goto aaa
+        end
+        `
+      }
+    }
+  
+    // 姣旇緝楠岃瘉
+    if (verify.contrasts && verify.contrasts.length > 0) {
+      verify.contrasts.forEach(item => {
+        _sql += `
+        /* 姣旇緝楠岃瘉 */
+        If ${item.frontfield} ${item.operator} ${item.backfield}
+        Begin
+          select @ErrorCode='${item.errorCode}',@retmsg='${item.errmsg}'
+            goto aaa
+        end
+        `
+      })
+    }
+    
+    // 鑷畾涔夐獙璇�
+    verify.customverifys && verify.customverifys.forEach(item => {        
+      _sql += `
+        /* 鑷畾涔夐獙璇� */
+        select @tbid='', @ErrorCode='',@retmsg=''
+        select top 1 @tbid='X' from (${item.sql}) a
+        If @tbid ${item.result === 'true' ? '!=' : '='}''
+        Begin
+          select @ErrorCode='${item.errorCode}',@retmsg='${item.errmsg}'
+          goto aaa
+        end
+        `
+    })
+  
+    // 鍗曞彿鐢熸垚锛屼娇鐢ㄤ笂绾d锛圔ID锛夋垨鍒楄〃鏁版嵁锛屽0鏄庡彉閲忥紙妫�楠岋級
+    let _billcodesSql  = ''
+    if (formdata && verify.billcodes && verify.billcodes.length > 0) {
+      verify.billcodes.forEach(item => {
+        let _key = item.field.toLowerCase()
+        let _linkKey = item.linkField ? item.linkField.toLowerCase() : ''
+  
+        if (!formkeys.includes(_key)) return // 琛ㄥ崟涓笉鍚崟鍙风敓鎴愬瓧娈�
+  
+        let _lpline = ''
+        if (item.TypeCharOne === 'Lp') {
+          if (_linkKey === 'bid' && BID) { // 鏇挎崲bid
+            _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@BID@,48)`
+          } else {
+            _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@${_linkKey},48)`
+          }
+        } else if (item.TypeCharOne === 'BN') {
+          if (_linkKey === 'bid' && BID) { // 鏇挎崲bid
+            _lpline = `set @ModularDetailCode= 'BN'+ right(@BID@,48)`
+          } else {
+            _lpline = `set @ModularDetailCode= 'BN'+ right(@${_linkKey},48)`
+          }
+        } else {
+          _lpline = `set @ModularDetailCode= right('${item.ModularDetailCode}',50)`
+        }
+  
+        _billcodesSql += `
+        /* 鍗曞彿鐢熸垚 */
+        select @BillCode='', @${_key}='', @ModularDetailCode=''
+        ${_lpline}
+        exec s_get_BillCode
+          @ModularDetailCode=@ModularDetailCode,
+          @Type=${item.Type},
+          @TypeCharOne='${item.TypeCharOne}',
+          @TypeCharTwo ='${item.TypeCharTwo}',
+          @BillCode =@BillCode output,
+          @ErrorCode =@ErrorCode output, 
+          @retmsg=@retmsg output
+        if @ErrorCode!=''
+          goto aaa
+        set @${_key}=@BillCode
+        `
+      })
+  
+      if (_actionType !== 'insertOrUpdate') {
+        _sql += _billcodesSql
+      }
+    }
+  
+    // 鍞竴鎬ч獙璇侊紝蹇呴』瀛樺湪琛ㄥ崟锛堣〃鍗曞瓨鍦ㄦ椂锛屼富閿潎涓哄崟鍊硷級,蹇呴』濉啓鏁版嵁婧愶紝澶氳鎷兼帴鏃朵笉鍙敤
+    if (formdata && verify.uniques && verify.uniques.length > 0 && btn.Ot !== 'requiredOnce') {
+      verify.uniques.forEach(item => {
+        let _fieldValue = []                     // 琛ㄥ崟閿�煎field=value
+        let _value = []                          // 琛ㄥ崟鍊硷紝鐢ㄤ簬閿欒鎻愮ず
+        let _labels = item.fieldlabel.split(',') // 琛ㄥ崟鎻愮ず鏂囧瓧
+        let arr = [] // 楠岃瘉涓婚敭
+
+        item.field.split(',').forEach((_field, index) => {
+          let _key = _field.toLowerCase()
+          let _val = ''
+          let _val2 = ''
+  
+          arr.push(_key)
+          if (_key === 'bid') { // 琛ㄥ崟涓病鏈塨id鍒欎娇鐢ㄧ郴缁焍id鍙橀噺
+            _val = BID
+          } else {
+            _val = `'@mk_${_key}_mk@'`
+          }
+
+          _fieldValue.push(`${_key}=${_val}`)
+
+          if (_key === 'bid') { // 琛ㄥ崟涓病鏈塨id鍒欎娇鐢ㄧ郴缁焍id鍙橀噺
+            _val2 = `' + ${BID} + '`
+          } else {
+            _val2 = `@mk_${_key}_mk@`
+          }
+
+          _value.push(`${_labels[index] || ''}锛�${_val2}`)
+        })
+  
+        if (!arr.includes(primaryKey.toLowerCase())) {
+          _fieldValue.push(`${primaryKey} !=${primaryId}`)
+        }
+  
+        _sql += `
+        /* 鍞竴鎬ч獙璇� */
+        select @tbid='', @ErrorCode='',@retmsg=''
+        select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')}${item.verifyType === 'logic' ? ' and deleted=0' : ''}
+        If @tbid!=''
+        Begin
+          select @ErrorCode='${item.errorCode}',@retmsg='${_value.join(', ')} 宸插瓨鍦�'
+          goto aaa
+        end
+        `
+      })
+    } else if (verify.uniques && verify.uniques.length > 0 && btn.Ot === 'requiredOnce' && setting.dataresource) {
+      let datasource = setting.dataresource
+      if (/\s/.test(datasource)) { // 鎷兼帴鍒悕
+        if (!/tb$/.test(datasource)) {
+          datasource = '(' + datasource + ') tb'
+        }
+      } else {
+        datasource = datasource + ' tb'
+      }
+  
+      if (setting.customScript) {
+        _sql += `
+        /* 鏁版嵁婧愯嚜瀹氫箟鑴氭湰锛岃娉ㄦ剰鍙橀噺瀹氫箟鏄惁閲嶅 */
+        ${setting.customScript}
+        `
+      }
+  
+      verify.uniques.forEach(item => {
+        _sql += `
+        /* 鍚岀被鏁版嵁楠岃瘉 */
+        Set @tbid=''
+
+        Select top 1 @tbid='X' from (select distinct ${item.field},1 as n from ${datasource} inner join (select ID from  dbo.SplitComma(@ID@)) sp on tb.${primaryKey}=sp.ID ) a having sum(n)>1
+
+        If @tbid!=''
+        Begin
+          Set @ErrorCode='E' Set @retmsg='${item.fieldlabel} 鍊间笉鍞竴'
+          goto aaa
+        end
+        `
+      })
+    }
+  
+    let hasvoucher = false
+  
+    // 鍑瘉-鏄剧ず鍒椾腑閫夊彇,蹇呴』閫夎
+    if (verify.voucher && verify.voucher.enabled && btn.Ot !== 'requiredOnce') {
+      let _voucher = verify.voucher
+  
+      hasvoucher = true
+  
+      _sql += `
+        /* 鍒涘缓鍑瘉 */
+        exec s_BVoucher_Create
+          @Bill ='0',
+          @BVoucherType ='${_voucher.BVoucherType}',
+          @VoucherTypeOne ='${_voucher.VoucherTypeOne}',
+          @VoucherTypeTwo ='${_voucher.VoucherTypeTwo}',
+          @Type =${_voucher.Type},
+          @UserID=@UserID@,
+          @Username=@Username,
+          @FullName=@FullName,
+          @BVoucher =@BVoucher OUTPUT ,
+          @FIBVoucherDate =@FIBVoucherDate OUTPUT ,
+          @FiYear =@FiYear OUTPUT ,
+          @ErrorCode =@ErrorCode OUTPUT, 
+          @retmsg=@retmsg OUTPUT
+        if @ErrorCode!=''
+          GOTO aaa
+        `
+    }
+  
+    let _insertsql = ''
+    if (_actionType === 'insert' || _actionType === 'insertOrUpdate') { // 娣诲姞璇彞
+      let keys = []
+      let values = []
+  
+      formdata.forEach(item => {
+        if (item.writein === false) return
+        let _key = item.key.toLowerCase()
+  
+        keys.push(_key)
+        values.push('@' + _key)
+      })
+  
+      if (!keys.includes(primaryKey.toLowerCase())) {
+        keys.push(primaryKey.toLowerCase())
+        values.push(primaryId)
+      }
+      if (!keys.includes('createuserid')) {
+        keys.push('createuserid')
+        values.push('@userid@')
+      }
+      if (!keys.includes('createuser')) {
+        keys.push('createuser')
+        values.push('@username')
+      }
+      if (!keys.includes('createstaff')) {
+        keys.push('createstaff')
+        values.push('@fullname')
+      }
+      if (!keys.includes('bid')) {
+        keys.push('bid')
+        values.push('@BID@')
+      }
+  
+      if (!keys.includes('typename')) {
+        keys.push('typename')
+        values.push('@typename@')
+      }
+  
+      keys = keys.join(',')
+      values = values.join(',')
+      _insertsql = `insert into ${btn.sql} (${keys}) select ${values};`
+    }
+  
+    let _updatesql = ''
+    if (_actionType === 'update' || _actionType === 'audit' || _actionType === 'insertOrUpdate') { // 淇敼璇彞
+      let _form = []
+      let _arr = []
+  
+      formdata.forEach(item => {
+        if (item.writein === false) return
+        let _key = item.key.toLowerCase()
+        
+        _arr.push(_key)
+        _form.push(_key + '=@' + _key)
+      })
+  
+      if (_actionType === 'audit') {
+        if (!_arr.includes('submitdate')) {
+          _form.push('submitdate=getdate()')
+        }
+        if (!_arr.includes('submituser')) {
+          _form.push('submituser=@username')
+        }
+        if (!_arr.includes('submitstaff')) {
+          _form.push('submitstaff=@fullname')
+        }
+        if (!_arr.includes('submituserid')) {
+          _form.push('submituserid=@userid@')
+        }
+      } else {
+        if (!_arr.includes('modifydate')) {
+          _form.push('modifydate=getdate()')
+        }
+        if (!_arr.includes('modifyuser')) {
+          _form.push('modifyuser=@username')
+        }
+        if (!_arr.includes('modifystaff')) {
+          _form.push('modifystaff=@fullname')
+        }
+        if (!_arr.includes('modifyuserid')) {
+          _form.push('modifyuserid=@userid@')
+        }
+      }
+      
+      if (hasvoucher) {
+        if (!_arr.includes('bvoucher')) {
+          _form.push('BVoucher=@BVoucher')
+        }
+        if (!_arr.includes('fibvoucherdate')) {
+          _form.push('FIBVoucherDate=@FIBVoucherDate')
+        }
+        if (!_arr.includes('fiyear')) {
+          _form.push('FiYear=@FiYear')
+        }
+      }
+      if (!_arr.includes('typename')) {
+        _form.push('typename=@typename@')
+      }
+      _form = _form.join(',')
+  
+      let _ID = '=@ID@'
+      if (btn.Ot === 'requiredOnce') {
+        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
+      }
+  
+      _updatesql = `update ${btn.sql} set ${_form} where ${primaryKey}${_ID};`
+    }
+  
+    if (_prevCustomScript) {
+      _sql += _prevCustomScript
+    }
+  
+    // 娣诲姞銆佷慨鏀广�侀�昏緫鍒犻櫎銆佺墿鐞嗗垹闄�
+    if (_actionType === 'insert') {
+      _sql += `
+        /* 榛樿sql */
+        ${_insertsql}`
+    } else if (_actionType === 'update' || _actionType === 'audit') {
+      _sql += `
+        /* 榛樿sql */
+        ${_updatesql}`
+    } else if (_actionType === 'LogicDelete') { // 閫昏緫鍒犻櫎
+      let _ID = '=@ID@'
+      if (btn.Ot === 'requiredOnce') {
+        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
+      }
+  
+      _sql += `
+        /* 榛樿sql */
+        update ${btn.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@ where ${primaryKey}${_ID};`
+    
+    } else if (_actionType === 'delete') {      // 鐗╃悊鍒犻櫎
+      let _msg = ''
+      if (columns && columns.length > 0 && btn.Ot !== 'notRequired') {
+        let _index = 0
+        columns.forEach(col => {
+          if (_index >= 4 || col.field === primaryKey) return
+
+          colreps.push(col.field)
+
+          _msg += col.label + `=@mk_${col.field}_mk@,`
+          _index++
+        })
+      }
+  
+      let _ID = '=@ID@'
+      if (btn.Ot === 'requiredOnce') {
+        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
+      }
+  
+      _sql += `
+        /* 榛樿sql */
+        insert into snote (remark,createuserid,CreateUser,CreateStaff,typename) select left('鍒犻櫎琛�:${btn.sql} 鏁版嵁: ${_msg}${primaryKey}='+@ID@,200),@userid@,@username,@fullname,@typename@
+        delete ${btn.sql} where ${primaryKey}${_ID};`
+    } else if (_actionType === 'insertOrUpdate') {
+      _sql += `
+        /* 榛樿sql */
+        select @tbid=''
+        select @tbid='X' from ${btn.sql} where ${primaryKey}=@ID@
+        if @tbid=''
+          begin
+          ${_billcodesSql}
+          ${_insertsql}
+          end
+        else
+          begin
+          ${_updatesql}
+          end
+      `
+    }
+  
+    if (verify.workFlow === 'true' && verify.flowSql === 'true' && process) {
+      if (verify.flowType === 'start') {
+        _sql += `
+          /* 宸ヤ綔娴佸紓甯竤ql */
+          if @works_flow_error@ != ''
+          select @ErrorCode='E',@retmsg=@works_flow_error@ goto aaa
+
+          /* 宸ヤ綔娴侀粯璁ql */
+          insert into s_my_works_flow (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,work_group,works_flow_detail_id,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+          select @ID@,@works_flow_code@,@works_flow_name@,@works_flow_param@,@status@,@statusname@,@work_group@,@works_flow_detail_id@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+          insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+          select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+          insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+          select @ID@,@works_flow_code@,@works_flow_detail_id@,@userid@,@start_type@,@userid@,@UserName,@FullName,@time_id@
+          insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid,typecharone)
+          select @ID@,@works_flow_code@,@userid@,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@,'begin'
+        `
+      } else {
+        let field = '@works_flow_sign_field@'
+        let label = '@works_flow_sign_label@'
+
+        _sql += `
+          /* 宸ヤ綔娴佸紓甯竤ql */
+          if @works_flow_error@ != ''
+          select @ErrorCode='E',@retmsg=@works_flow_error@ goto aaa
+
+          if @works_flow_countersign@ = 'Y'
+          begin
+              /* 宸ヤ綔娴侀粯璁ql锛堜細绛撅級 */
+              declare @works_flow_statuscharone nvarchar(50),@works_flow_statuschartwo nvarchar(50),@works_flow_statuscharthree nvarchar(50),@works_flow_statuscharfour nvarchar(50),@works_flow_statuscharfive nvarchar(50),@works_flow_key_id nvarchar(50),@works_flow_key_status nvarchar(20),@s_my_works_flow_log_param  nvarchar(max),@s_my_works_flow_log_status int,@s_my_works_flow_log_statusname nvarchar(50),@s_my_works_flow_log_detail_id  nvarchar(50)
+              select @works_flow_statuscharone='',@works_flow_statuschartwo='',@works_flow_statuscharthree='',@works_flow_statuscharfour='',@works_flow_statuscharfive='',@works_flow_key_id='',@works_flow_key_status ='',@s_my_works_flow_log_param='',@s_my_works_flow_log_status=0,@s_my_works_flow_log_statusname='',@s_my_works_flow_log_detail_id=''
+
+              select @works_flow_statuscharone=statuscharone,@works_flow_statuschartwo=statuschartwo,@works_flow_statuscharthree=statuscharthree,@works_flow_statuscharfour=statuscharfour,@works_flow_statuscharfive=statuscharfive,@works_flow_key_id=id,@s_my_works_flow_log_param=works_flow_param,@s_my_works_flow_log_status=status,@s_my_works_flow_log_statusname=statusname,@s_my_works_flow_log_detail_id=works_flow_detail_id
+              from s_my_works_flow where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
+
+              if @works_flow_statuscharone + @works_flow_statuschartwo + @works_flow_statuscharthree + @works_flow_statuscharfour + @works_flow_statuscharfive = @works_flow_sign_values@
+              begin
+                  set @works_flow_key_status='Y'
+              end
+
+              if @works_flow_key_status='Y'
+              begin
+                  update s_my_works_flow set ${field}=${label},status=@status@,statusname=@statusname@,works_flow_param=@works_flow_param@,works_flow_detail_id=@works_flow_detail_id@,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname${verify.flowRemark ? ',remark=@' + verify.flowRemark : ''}
+                  where id=@works_flow_key_id
+
+                  insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid${verify.flowRemark ? ',remark' : ''},${field})
+                  select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@${verify.flowRemark ? ',@' + verify.flowRemark : ''},${label}
+                  
+                  update s_my_works_flow_role set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname 
+                  where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
+
+                  if @check_userids@ != ''
+                  begin
+                      insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid)
+                      select @ID@,@works_flow_code@,ID,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
+                      insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+                      select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@check_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
+                  end
+                  if @notice_userids@ != ''
+                  begin
+                      update n
+                      set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname 
+                      from (select * from s_my_works_flow_notice where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0) n
+                      inner join (select ID from dbo.SplitComma(@notice_userids@)) s
+                      on n.userid = s.id
+                      insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+                      select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@notice_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@notice_userids@)
+                  end
+              end
+              else
+              begin
+                  update s_my_works_flow set ${field}=${label},modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname${verify.flowRemark ? ',remark=@' + verify.flowRemark : ''}
+                  where id =@works_flow_key_id
+
+                  insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid${verify.flowRemark ? ',remark' : ''},${field})
+                  select @ID@,@works_flow_code@,@works_flow_name@ ,@s_my_works_flow_log_param,@s_my_works_flow_log_status,@s_my_works_flow_log_statusname,@s_my_works_flow_log_detail_id,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@${verify.flowRemark ? ',@' + verify.flowRemark : ''},${label}
+                
+                  update s_my_works_flow_role set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname 
+                  where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0 and userid =@userid@
+              end
+          end
+          else
+          begin
+              /* 宸ヤ綔娴侀粯璁ql锛堟垨绛撅級 */
+              set @retmsg =''
+              select @retmsg='X' from s_my_works_flow_role where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0 and userid =@userid@
+
+              if @retmsg =''
+              begin
+                  select @retmsg='X' from s_my_works_flow_role where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and userid=@userid@
+
+                  if @retmsg !=''
+                  begin
+                      select @ErrorCode='E', @retmsg='褰撳墠鍗曟嵁宸插鏍革紝璇峰埛鏂板悗閲嶈瘯'
+                      goto aaa
+                  end
+
+                  if @dataM@ !='' 
+                  begin
+                      set @retmsg =''
+                      select @retmsg='X' from s_my_works_flow_role where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0  
+
+                      if @retmsg != ''
+                      begin
+                          goto goto_mk
+                      end
+                  end
+
+                  select @retmsg='椤甸潰鏁版嵁宸叉洿鏂帮紝鎴栨病鏈夊綋鍓嶅崟鎹殑瀹℃壒鏉冮檺'
+                  goto aaa 
+              end 
+
+              goto_mk:
+
+              set @retmsg=''
+
+              update s_my_works_flow set status=@status@,statusname=@statusname@,works_flow_param=@works_flow_param@,works_flow_detail_id=@works_flow_detail_id@,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname${verify.flowRemark ? ',remark=@' + verify.flowRemark : ''}
+              where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
+              insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid${verify.flowRemark ? ',remark' : ''})
+              select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@${verify.flowRemark ? ',@' + verify.flowRemark : ''}
+
+              if @works_begin_branch@ = 'Y'
+              begin
+                  update s_my_works_flow_role set deleted=0,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
+                  where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and typecharone='begin'
+              end
+              else
+              begin
+                  update s_my_works_flow_role set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname 
+                  where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
+              end
+
+              if @check_userids@ != ''
+              begin
+                  insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid)
+                  select @ID@,@works_flow_code@,ID,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
+                  insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+                  select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@check_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
+              end
+              if @notice_userids@ != ''
+              begin
+                  update n
+                  set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname 
+                  from (select * from s_my_works_flow_notice where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0) n
+                  inner join (select ID from dbo.SplitComma(@notice_userids@)) s
+                  on n.userid = s.id
+                  insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+                  select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@notice_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@notice_userids@)
+              end
+          end
+        `
+      }
+
+      if (_backCustomScript) {
+        _sql += _backCustomScript
+      }
+    } else if (_backCustomScript) {
+      _sql += _backCustomScript
+    }
+
+    if (verify.workFlow === 'true' && process) {
+      if (verify.flowType === 'start') {
+        _sql = _sql.replace(/@start_type@/ig, `'寮�濮�'`)
+        // works_flow_error       娴佺▼閿欒
+        let worksReFields = ['works_flow_error', 'works_flow_code', 'works_flow_name', 'works_flow_param', 'works_flow_detail_id', 'status', 'statusname', 'work_group', 'work_grade']
+        worksReFields.forEach(n => {
+          _sql = _sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+        })
+      } else {
+        _sql = _sql.replace(/@check_type@/ig, verify.flowType === 'reject' ? `'椹冲洖'` : `'瀹℃牳'`)
+        _sql = _sql.replace(/@notice_type@/ig, `'鎶勯��'`)
+        // works_flow_error       娴佺▼閿欒
+        // works_flow_countersign 浼氱/鎴栫鏍囪 浼氱涓� Y
+        // works_begin_branch     椹冲洖鑷冲紑濮嬪垎鏀紙line.mknode === 'startEdge'锛�
+        // works_flow_sign_field  浼氱 鏍囪瀛楁 statuscharone/statuschartwo/statuscharthree/statuscharfour/statuscharfive
+        // works_flow_sign_label  浼氱 鏍囪鍊�   ***/***/宸插鏍�
+        // works_flow_sign_values 浼氱鏍囪鎷兼帴鍊硷紙闄ゆ湰浜哄锛�
+        let worksReFields = ['works_flow_error', 'works_flow_countersign', 'works_flow_sign_values', 'works_begin_branch', 'works_flow_sign_label', 'works_flow_code', 'works_flow_name', 'works_flow_param', 'works_flow_detail_id', 'status', 'statusname', 'work_group', 'work_grade', 'check_userids', 'notice_userids', 'works_flow_sign']
+        worksReFields.forEach(n => {
+          _sql = _sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+        })
+      }
+    }
+  
+    // if (btn.procMode === 'system' || btn.returnValue === 'true') {
+    //   _sql += `
+    //     aaa: if @ErrorCode!=''
+    //     insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@`
+    // } else if (btn.output) {
+    //   _sql += `
+    //     aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
+    // } else {
+    //   _sql += `
+    //     aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    // }
+
+    if (/@ErrorCode='(ENT|NNT|FNT|NMNT|CNT|-2NT)'/ig.test(_sql)) {
+      _sql = _sql.replace(/@ErrorCode='(ENT|NNT|FNT|NMNT|CNT|-2NT)'[\S\s]+\sgoto\s+aaa($|\s)/ig, (word) => {
+        return word.replace(/goto aaa/, 'goto mk_ent')
+      })
+      _sql += `
+          if 1=2
+          begin
+            mk_ent:
+            set @ErrorCode=left(@ErrorCode,1)
+          end
+        `
+    }
+
+    if (btn.procMode === 'system' || btn.returnValue === 'true') {
+      _sql += callback
+    } else if (btn.output) {
+      _sql += `
+        select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id
+        ${callback}
+        `
+    } else {
+      _sql += `
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+        ${callback}
+        `
+    }
+
+    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address']
+
+    // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
+    if (btn.Ot !== 'notRequired' && columns.length > 0) {
+      let _initColfields = []
+      columns.forEach(col => {
+        let _key = col.field.toLowerCase()
+
+        if (formkeys.includes(_key) || !new RegExp('@' + _key + '[^0-9a-z_@]', 'ig').test(_sql)) return
+        // if (_key === 'id' && !/@id[^0-9a-z_@]/ig.test(_sql)) return
+
+        colreps.push(col.field)
+  
+        if (col.type === 'number') {
+          _initColfields.push(`@${_key}=@mk_${_key}_mk@`)
+        } else {
+          _initColfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        }
+        
+        if (!_vars.includes(_key)) {
+          _declares.push(`@${_key} ${col.datatype || 'nvarchar(50)'}`)
+        }
+      })
+
+      // 鏄剧ず鍒楀彉閲忚祴鍊�
+      if (_initColfields.length > 0) {
+        _sql = _sql.replace('@mk_cols_values@', `
+          /* 鏄剧ず鍒楀彉閲忚祴鍊� */
+          select ${_initColfields.join(',')}
+        `)
+      } else {
+        _sql = _sql.replace('@mk_cols_values@', '')
+      }
+    }
+
+    let reps = []
+    let decSql = [`@tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50),@mk_deleted int,@bid nvarchar(50)`]
+    let secSql = [`@ErrorCode='S',@retmsg='', @BillCode='',@BVoucher='',@FIBVoucherDate='',@FiYear='',@ModularDetailCode='', @mk_deleted=1, @bid=@BID@`]
+
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(_sql)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        secSql.push(`@${s}=@${s}@`)
+        reps.push(s)
+      }
+    })
+
+    decSql = [...decSql, ..._declares]
+
+    // INSERT INTO s_paas_api_log (appkey,api_name,api_count,menuname,createuserid,createuser,createstaff,cdefine1,cdefine2) 
+    // SELECT @appkey@,'sPC_TableData_InUpDe',1,@menuname@,@UserID@,@username@,@fullname@,@SessionUid@,@LoginUID@
+    _sql = `/* ${btn.logLabel} */
+        BEGIN TRY 
+        begin TRAN
+
+        Declare ${decSql.join(',')}
+        /* 鍑瘉鍙婄敤鎴蜂俊鎭垵濮嬪寲璧嬪�� */
+        select ${secSql.join(',')}
+        ${_sql}
+    `
+
+    let regs = ['ID', 'BID', 'time_id', 'datam', 'typename']
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(_sql)) {
+        reps.push(s)
+      }
+    })
+
+    let map = new Map()
+    reps.push(...sysVars)
+    reps = reps.filter(n => {
+      if (map.has(n.toLowerCase())) {
+        return false
+      }
+
+      map.set(n.toLowerCase(), true)
+
+      return true
+    })
+
+    reps.forEach(n => {
+      _sql = _sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+
+    if (/\$@/ig.test(_sql)) {
+      _sql = _sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (btn.procMode === 'system') {
+      if (/\$check@|@check\$/ig.test(_sql)) {
+        _sql = _sql.replace(/\$check@|@check\$/ig, '')
+      }
+    } else {
+      if (/\$check@|@check\$/ig.test(_sql)) {
+        _sql = _sql.replace(/\$check@/ig, '@mk_check_begin@').replace(/@check\$/ig, '@mk_check_end@')
+        reps.push('mk_check_begin', 'mk_check_end')
+      }
+    }
+    if (/@db@/ig.test(_sql)) {
+      reps.push('db')
+    }
+
+    _sql = _sql.replace(/\n\x20{8,10}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    colreps = Array.from(new Set(colreps))
+    reps = [...reps, ...colreps]
+    
+    return { LText: _sql, md5: md5(_sql), reps }
+  }
+
+  let getSysBackSql = (btn, component) => {
+    let verify = btn.verify || {}
+    let columns = component.columns || []
+    let colreps = [] // 寰呮浛鎹㈠彉閲忛泦
+    let _prev = ''
+    let _back = ''
+    let tables = []
+    let reps = []
+
+    verify.cbScripts.forEach(script => {
+      if (script.status === 'false') return
+
+      if (/\s#[a-z0-9_]+(\s|\()/ig.test(script.sql)) {
+        tables.push(...script.sql.match(/\s#[a-z0-9_]+(\s|\()/ig))
+      }
+
+      if (script.position === 'front') {
+        _prev += `
+          /* 鑷畾涔夎剼鏈� */
+          ${script.sql}
+        `
+      } else {
+        _back += `
+          /* 鑷畾涔夎剼鏈� */
+          ${script.sql}
+        `
+      }
+    })
+
+    tables = tables.map(tb => tb.replace(/\s|\(/g, ''))
+  
+    // 闇�瑕佸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', 'mk_deleted', 'bid']
+  
+    let _sql = ''
+  
+    let _initFormfields = []
+    let _declares = []
+
+    let formdata = null
+    let formkeys = []
+    if (btn.OpenType === 'pop' || btn.OpenType === 'formSubmit') {
+      formdata = []
+      if (btn.modal && btn.modal.fields) {
+        btn.modal.fields.forEach(item => {
+          if (!item.field) return
+          
+          let _item = {
+            key: item.field,
+            fieldlen: item.fieldlength || 50,
+            writein: item.writein !== 'false',
+            type: item.type,
+            isconst: item.constant === 'true'
+          }
+    
+          if (_item.type === 'datemonth') {
+            _item.type = 'text'
+          } else if (_item.type === 'number' || _item.type === 'rate') {
+            _item.fieldlen = item.decimal || 0
+          } else if (_item.type === 'date') {
+            _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
+          } else if (_item.type === 'datetime') {
+            _item.type = 'date'
+          } else if (item.declare === 'decimal') {
+            _item.type = 'number'
+            _item.fieldlen = item.decimal || 0
+          }
+    
+          formdata.push(_item)
+        })
+      }
+    } else if (btn.OpenType === 'form') {
+      formdata = []
+
+      let item = {
+        type: 'text',
+        readin: true,
+        writein: true,
+        fieldlen: 50,
+        key: btn.field
+      }
+      if (btn.formType === 'counter') {
+        item.type = 'number'
+        item.fieldlen = 0
+      } else if (btn.formType === 'switch' || btn.formType === 'radio') {
+        if (typeof(btn.openVal) === 'number') {
+          item.type = 'number'
+          item.fieldlen = 0
+        }
+      }
+      formdata.push(item)
+    }
+
+    // 鑾峰彇瀛楁閿�煎
+    formdata && formdata.forEach(form => {
+      let _key = form.key.toLowerCase()
+
+      if (!formkeys.includes(_key)) {
+        formkeys.push(_key)
+        if (form.type === 'number' || form.type === 'rate') {
+          _initFormfields.push(`@${_key}=@mk_${_key}_mk@`)
+        } else if (form.type === 'date') {
+          _initFormfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        } else if (form.type === 'select' || form.type === 'link' || form.type === 'radio') {
+          _initFormfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        } else if (form.isconst) {
+          _initFormfields.push(`@${_key}=N'@mk_${_key}_mk@'`)
+        } else {
+          _initFormfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        }
+      }
+      
+      if (!_vars.includes(_key)) {
+        _vars.push(_key)
+  
+        if (form.fieldlen && form.fieldlen > 4000) {
+          form.fieldlen = 'max'
+        }
+  
+        let _type = `nvarchar(${form.fieldlen})`
+  
+        if (form.type.match(/date/ig)) {
+          _type = 'datetime'
+        } else if (form.type === 'number') {
+          _type = `decimal(18,${form.fieldlen})`
+        } else if (form.type === 'rate') {
+          _type = `decimal(18,2)`
+        }
+  
+        _declares.push(`@${_key} ${_type}`)
+      }
+    })
+  
+    // 琛ㄥ崟鍙橀噺璧嬪��
+    if (_initFormfields.length > 0) {
+      _sql += `
+        /* 琛ㄥ崟鍙橀噺璧嬪�� */
+        select ${_initFormfields.join(',')}
+        `
+    }
+
+    let testSql = _prev + _back + (btn.output || '')
+
+    // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
+    if (btn.Ot !== 'notRequired' && columns.length > 0) {
+      let _initColfields = []
+      columns.forEach(col => {
+        let _key = col.field.toLowerCase()
+
+        if (formkeys.includes(_key) || !new RegExp('@' + _key + '[^0-9a-z_@]', 'ig').test(testSql)) return
+        // if (_key === 'id' && !/@id[^0-9a-z_@]/ig.test(testSql)) return
+
+        colreps.push(col.field)
+  
+        if (col.type === 'number') {
+          _initColfields.push(`@${_key}=@mk_${_key}_mk@`)
+        } else {
+          _initColfields.push(`@${_key}='@mk_${_key}_mk@'`)
+        }
+        
+        if (!_vars.includes(_key)) {
+          _declares.push(`@${_key} ${col.datatype || 'nvarchar(50)'}`)
+        }
+      })
+
+      // 鏄剧ず鍒楀彉閲忚祴鍊�
+      if (_initColfields.length > 0) {
+        _sql += `
+          /* 鏄剧ず鍒楀彉閲忚祴鍊� */
+          select ${_initColfields.join(',')}
+        `
+      }
+    }
+
+    _sql += `
+        ${_prev}
+        /* 澶栭儴鎺ュ彛鍏ュ弬 */
+        @mk_outer_params@
+        ${_back}
+        `
+
+    // if (btn.output) {
+    //   _sql += `
+    //     aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
+    // } else {
+    //   _sql += `
+    //     aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    // }
+    if (/@ErrorCode='(ENT|NNT|FNT|NMNT|CNT|-2NT)'/ig.test(_sql)) {
+      _sql = _sql.replace(/@ErrorCode='(ENT|NNT|FNT|NMNT|CNT|-2NT)'[\S\s]+\sgoto\s+aaa($|\s)/ig, (word) => {
+        return word.replace(/goto aaa/, 'goto mk_ent')
+      })
+      _sql += `
+          if 1=2
+          begin
+            mk_ent:
+            set @ErrorCode=left(@ErrorCode,1)
+          end
+        `
+    }
+    if (btn.output) {
+      _sql += `
+        select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id
+        ${callback}
+        `
+    } else {
+      _sql += `
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+        ${callback}
+        `
+    }
+
+    let syses = ['tbid', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode', 'mk_deleted', 'bid', 'UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address']
+    let decSql = [`@ErrorCode nvarchar(50),@retmsg nvarchar(4000)`]
+    let secSql = [`@ErrorCode='S',@retmsg=''`]
+  
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(_sql)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else if (['mk_deleted'].includes(s)) {
+          secSql.push(`@mk_deleted int`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        if (['tbid', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode'].includes(s)) {
+          secSql.push(`@${s}=''`)
+        } else if (['mk_deleted'].includes(s)) {
+          secSql.push(`@mk_deleted=1`)
+        } else if (['bid'].includes(s)) {
+          secSql.push(`@bid=@BID@`)
+        } else {
+          secSql.push(`@${s}=@${s}@`)
+          reps.push(s)
+        }
+      }
+    })
+
+    decSql = [...decSql, ..._declares]
+
+    _sql = `/* ${btn.logLabel}(鍥炶皟) */
+        BEGIN TRY 
+        begin TRAN
+
+        Declare ${decSql.join(',')}
+        /* 鍒濆鍖栬祴鍊� */
+        select ${secSql.join(',')}
+        ${_sql}
+    `
+
+    let regs = ['ID', 'BID', 'time_id', 'datam', 'typename']
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(_sql)) {
+        reps.push(s)
+      }
+    })
+
+    let map = new Map()
+    reps.push(...sysVars)
+    reps = reps.filter(n => {
+      if (map.has(n.toLowerCase())) {
+        return false
+      }
+
+      map.set(n.toLowerCase(), true)
+
+      return true
+    })
+
+    reps.forEach(n => {
+      _sql = _sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+
+    if (/\$@/ig.test(_sql)) {
+      _sql = _sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(_sql)) {
+      reps.push('db')
+    }
+
+    _sql = _sql.replace(/\n\x20{8,10}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    reps = [...reps, ...colreps]
+
+    return { LText: _sql, md5: md5(_sql), reps, tbs: tables }
+  }
+
+  let getDataSource = (item, mainSearch = [], type) => {
+    let searches = item.search || []
+    if (item.setting.useMSearch === 'true' && mainSearch.length > 0) {
+      searches = [...searches, ...mainSearch]
+    }
+    item.$searches = fromJS(searches).toJS()
+    let sFields = getSearches(searches)
+
+    let _columns = []
+    if (item.subtype === 'dualdatacard') {
+      _columns = [...item.columns, ...item.subColumns]
+    } else if (item.columns) {
+      _columns = [...item.columns]
+    }
+
+    let arr_field = _columns.map(col => col.field).join(',')
+
+    let _customScript = ''
+    let _tailScript = ''
+    let _dataresource = ''
+    item.scripts && item.scripts.forEach(script => {
+      if (script.status === 'false') return
+      if (script.position !== 'back') {
+        _customScript += `
+        ${script.sql}
+        `
+      } else {
+        _tailScript += `
+        ${script.sql}
+        `
+      }
+    })
+
+    // if (_customScript || _tailScript) {
+    //   _tailScript += `${_tailScript}
+    //     aaa:
+    //     if @ErrorCode!=''
+    //       insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
+    //   `
+    // }
+
+    let _search = ''
+    if (item.setting.execute !== 'false') {
+      _dataresource = item.setting.dataresource || ''
+      _search = '@mk_search@'
+    }
+
+    if (type === 'print') {
+      _search = ''
+    }
+
+    if (/\s/.test(_dataresource) && !/\)\s+tb$/.test(_dataresource)) {
+      _dataresource = '(' + _dataresource + ') tb'
+    }
+
+    item.setting.dataresource = _dataresource
+    item.setting.customScript = _customScript
+
+    let testSql = _dataresource + _customScript + _tailScript
+    
+    let decSql = [`@ErrorCode nvarchar(50),@retmsg nvarchar(4000)`]
+    let secSql = [`@ErrorCode='S',@retmsg =''`]
+
+    let reps = []
+
+    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address']
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(testSql)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        secSql.push(`@${s}=@${s}@`)
+        reps.push(s)
+      }
+    })
+
+    decSql = `declare ${decSql.join(',')}${type === 'print' ? '@mk_print_declare@' : ''}
+      select ${secSql.join(',')}${type === 'print' ? '@mk_print_select@' : ''}`
+
+    // 涓嶉渶瑕佸崟寮曞彿锛歰rderBy銆乸ageSize銆乸ageIndex銆乨b
+    let regs = [...sFields, 'orderBy', 'pageSize', 'pageIndex', 'ID', 'BID', 'time_id', 'datam', 'typename']
+
+    if (item.hasExtend) {
+      regs.push('mk_time')
+    }
+    if (item.type === 'calendar') {
+      regs.push('mk_year')
+    }
+    if (window.GLOB.getLocation) {
+      regs.push('mk_longitude', 'mk_latitude')
+    }
+    if (urlFields) {
+      regs.push(...urlFields)
+    }
+    if (process) {
+      regs.push('works_flow_code')
+    }
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(testSql)) {
+        reps.push(s)
+      }
+    })
+
+    let LText = ''
+    let DateCount = ''
+    if (_dataresource) {
+      /*system_query*/
+      if (/@pageSize@|@orderBy@|@mk_total/i.test(testSql)) {
+        LText = `select ${arr_field} from ${_dataresource} ${_search} `
+      } else if (item.setting.laypage === 'true' && item.setting.order) {
+        LText = `select top @pageSize@ ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${_dataresource} ${_search}) tmptable where rows > @pageSize@ * (@pageIndex@ - 1) order by tmptable.rows `
+        reps.push('pageSize', 'orderBy', 'pageIndex')
+        if (item.subtype === 'dualdatacard') {
+          DateCount = `select count(1) as total from (select distinct ${item.setting.primaryKey || 'ID'} from ${_dataresource} ${_search})a`
+        } else {
+          DateCount = `select count(1) as total from ${_dataresource} ${_search}`
+        }
+      } else if (item.setting.$top) {
+        if (item.setting.order) {
+          LText = `select top 1 ${arr_field} from ${_dataresource} ${_search} order by @orderBy@ `
+          reps.push('orderBy')
+        } else {
+          LText = `select top 1 ${arr_field} from ${_dataresource} ${_search}  `
+        }
+      } else if (item.setting.$fixOrder) {
+        LText = `select ${arr_field} from ${_dataresource} ${_search} order by ${item.setting.order} `
+      } else if (item.setting.order) {
+        LText = `select ${arr_field} from ${_dataresource} ${_search} order by @orderBy@ `
+        reps.push('orderBy')
+      } else {
+        LText = `select ${arr_field} from ${_dataresource} ${_search}  `
+      }
+    }
+
+    let sub_name = ''
+    let tabid = ''
+    let parid = ''
+    let sub_field = ''
+
+    if (item.subtype === 'dualdatacard') {
+      arr_field = item.columns.map(col => col.field).join(',')
+      sub_name = item.setting.subdata
+      tabid = item.setting.primaryKey || ''
+      parid = item.setting.subBID || ''
+      sub_field = item.subColumns.map(col => col.field).join(',')
+    }
+
+    // INSERT INTO s_paas_api_log (appkey,api_name,api_count,menuname,createuserid,createuser,createstaff,cdefine1,cdefine2) 
+    // SELECT @appkey@,'sPC_Get_TableData',1,@menuname@,@UserID@,@username@,@fullname@,@SessionUid@,@LoginUID@
+    let sql = ''
+    let e_sql = `select ${_columns.map(col => col.field).join(',')} from (select ${_columns.map(col => /date/ig.test(col.datatype) ? `'1949-10-01' as ${col.field}` : `'0' as ${col.field}`).join(',')}) a where ${item.setting.primaryKey || 'ID'} != '0'`
+    if (DateCount) {
+      e_sql += `
+      select 0 as total
+      `
+    }
+
+    if (item.setting.transact === 'true' && !/BEGIN\s+TRY\s+begin\s+TRAN/.test(_customScript)) {
+      sql = `/* ${item.setting.$name} */
+        BEGIN TRY 
+        begin TRAN
+
+        SELECT obj_name='@mk_obj_name@',prm_field='',str_field='',
+        arr_field='${arr_field}',tabid='${tabid}',parid='${parid}',sub_name='${sub_name}',sub_field='${sub_field}'
+      `
+
+      _tailScript = `${_tailScript}
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+
+        COMMIT TRAN
+        set NOCOUNT ON
+        RETURN
+        END TRY
+        BEGIN CATCH
+          ROLLBACK TRAN
+          DECLARE @ErrorMessage NVARCHAR(4000);
+          DECLARE @ErrorSeverity INT;
+          DECLARE @ErrorState INT;
+
+          set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50))
+          set @retmsg=ERROR_MESSAGE();
+          select @ErrorMessage=ERROR_MESSAGE(), @ErrorSeverity=ERROR_SEVERITY(), @ErrorState=ERROR_STATE();
+
+          RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
+        END CATCH
+
+        aaa:
+        ${e_sql}
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+        GOTO_RETURN:
+          ROLLBACK TRAN
+      `
+    } else {
+      sql = `/* ${item.setting.$name} */
+        SELECT obj_name='@mk_obj_name@',prm_field='',str_field='',
+        arr_field='${arr_field}',tabid='${tabid}',parid='${parid}',sub_name='${sub_name}',sub_field='${sub_field}'
+      `
+
+      let tail = 'aaa:'
+      if (/\sgoto\s+aaa([^0-9a-z_]|$)/ig.test(_customScript) && !/BEGIN\s+TRY\s+begin\s+TRAN/.test(_customScript)) {
+        tail = `if 1=2
+        begin
+          aaa:
+          ${e_sql}
+        end`
+      }
+
+      _tailScript = `${_tailScript}
+        ${tail}
+          select @ErrorCode as ErrorCode,@retmsg as retmsg
+      `
+    }
+
+    if (DateCount) {
+      sql += `UNION ALL
+        SELECT obj_name='DateCount',prm_field='total',str_field='',
+        arr_field='',tabid='',parid='',sub_name='',sub_field=''
+      `
+    }
+    // sql += `UNION ALL
+    //     SELECT obj_name='mk_error_code',prm_field='ErrorCode,retmsg',str_field='',
+    //     arr_field='',tabid='',parid='',sub_name='',sub_field=''
+    //   `
+    sql += `
+      ${decSql}
+      ${_customScript}
+      ${LText}
+      ${DateCount}
+      ${_tailScript}
+    `
+
+    let map = new Map()
+    reps.push(...sysVars)
+    reps = reps.filter(n => {
+      if (map.has(n.toLowerCase())) {
+        return false
+      }
+
+      map.set(n.toLowerCase(), true)
+
+      return true
+    })
+    
+    reps.forEach(n => {
+      if (['orderBy', 'pageSize', 'pageIndex'].includes(n)) return
+
+      sql = sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+    if (/\$@/ig.test(sql)) {
+      sql = sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(sql)) {
+      reps.push('db')
+    }
+    reps.push('mk_obj_name')
+
+    sql = sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    return {LText: sql, md5: md5(sql), reps, luser: /@userid@/ig.test(testSql)}
+  }
+
+  let getExcelInSql = (item) => {
+    let btn = item.verify
+    let sheet = item.sheet.replace(/@db@/ig, '')
+    let database = ''
+    if (/@db@/ig.test(item.sheet)) {
+      database = '@db@'
+    }
+  
+    let sql = ''
+    
+    let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
+    let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
+    let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
+    let _regs = [
+      {reg: new RegExp('(^|\\s)@' + sheet + '(\\s|$)', 'ig'), value: ` #${sheet} `},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\(', 'ig'), value: ` #${sheet}(`},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\)', 'ig'), value: ` #${sheet})`},
+    ]
+
+    btn.scripts && btn.scripts.forEach(script => {
+      if (script.status === 'false') return
+
+      let _sql = script.sql
+
+      _regs.forEach(item => {
+        _sql = _sql.replace(item.reg, item.value)
+      })
+
+      if (script.position === 'init') {
+        _initCustomScript += `
+          /* 鑷畾涔夎剼鏈� */
+          ${_sql}
+        `
+      } else if (script.position === 'front') {
+        _prevCustomScript += `
+          /* 鑷畾涔夎剼鏈� */
+          ${_sql}
+        `
+      } else {
+        _backCustomScript += `
+          /* 鑷畾涔夎剼鏈� */
+          ${_sql}
+        `
+      }
+    })
+
+    let _uniquesql = ''
+    if (btn.uniques && btn.uniques.length > 0) {
+      let textFields = []
+      let numberFields = []
+      let dateFields = []
+      btn.columns.forEach((col) => {
+        if (/Nvarchar/ig.test(col.type)) {
+          textFields.push(col.Column)
+        } else if (/Decimal|int/ig.test(col.type)) {
+          numberFields.push(col.Column)
+        } else if (/date/ig.test(col.type)) {
+          dateFields.push(col.Column)
+        }
+      })
+      btn.uniques.forEach(unique => {
+        if (unique.status === 'false' || !unique.verifyType) return
+
+        let _fields = unique.field.split(',')
+        let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
+        _fields_ = _fields_.join(' and ')
+
+        let _where = []
+        _fields.forEach(f => {
+          if (textFields.includes(f)) {
+            _where.push(`${f}!=''`)
+          } else if (numberFields.includes(f)) {
+            _where.push(`${f}!=0`)
+          } else if (dateFields.includes(f)) {
+            _where.push(`${f}>'1949-10-01'`)
+          }
+        })
+        _where = _where.length ? `where ${_where.join(' and ')} ` : ''
+
+        if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
+          _fields_ += ' and b.deleted=0'
+        }
+
+        let _afields = []
+        _fields = _fields.map(f => {
+          if (numberFields.includes(f)) {
+            _afields.push(`cast(a.${f} as nvarchar(50))`)
+            return `cast(${f} as nvarchar(50))`
+          } else if (dateFields.includes(f)) {
+            _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+            return `CONVERT(nvarchar(50), ${f}, 21)`
+          }
+          _afields.push(`a.${f}`)
+
+          return f
+        })
+
+        _uniquesql += `
+          /* 閲嶅鎬ч獙璇� */
+          Set @tbid=''
+          Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from #${sheet} ) a group by ${unique.field} having sum(n)>1
+
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 閲嶅'
+            goto aaa
+          end
+
+          ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
+          Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${sheet} b on ${_fields_}
+
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
+            goto aaa
+          end` : ''}
+        `
+      })
+    }
+
+    let declarefields = []
+    let fields = []
+
+    btn.columns.forEach(col => {
+      if (col.import === 'false') return
+      
+      if (col.type === 'date') {
+        declarefields.push(`${col.Column} Nvarchar(50)`)
+      } else {
+        declarefields.push(`${col.Column} ${col.type}`)
+      }
+      fields.push(col.Column)
+    })
+
+    fields = fields.join(',')
+
+    let _insert = ''
+    if (btn.default !== 'false') {
+      _insert = `
+        /* 榛樿sql */
+        Insert into ${database}${sheet} (${fields},createuserid,createuser,createstaff,bid) 
+        Select ${fields},@UserID@,@username,@fullname,@BID@ From #${sheet}
+      `
+    }
+
+    sql = `/* ${item.logLabel} */
+      BEGIN TRY
+      begin TRAN
+
+      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50))
+      Declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)@mk_init_declare@
+
+      Select @ErrorCode='S',@retmsg=''@mk_init_select@
+      ${_initCustomScript}
+
+      Insert into #${sheet} (${fields},jskey,BID)
+
+      /* excel鏁版嵁*/
+      @mk_excel_data@
+
+      ${_uniquesql}
+      ${_prevCustomScript}
+      ${_insert}`
+
+    let mk_ent = ''
+    if (/@ErrorCode='(ENT|NNT|FNT|NMNT|CNT|-2NT)'/ig.test(sql + _backCustomScript)) {
+      mk_ent = `
+          if 1=2
+          begin
+            mk_ent:
+            set @ErrorCode=left(@ErrorCode,1)
+          end
+        `
+    }
+
+    if (btn.workFlow === 'true' && process) {
+      if (btn.flowSql === 'true') {
+        sql += `
+        /* 宸ヤ綔娴佸紓甯竤ql */
+        if @works_flow_error@ != ''
+        select @ErrorCode='E',@retmsg=@works_flow_error@ goto aaa
+
+        /* 宸ヤ綔娴侀粯璁ql */
+        insert into s_my_works_flow (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,work_group,works_flow_detail_id,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_name@,@works_flow_param@,@status@,@statusname@,@work_group@,@works_flow_detail_id@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+        from #${sheet}
+
+        insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+        from #${sheet}
+
+        insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_detail_id@,@userid@,@start_type@,@userid@,@UserName,@FullName,@time_id@
+        from #${sheet}
+
+        insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid,typecharone)
+        select jskey,@works_flow_code@,@userid@,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@,'begin'
+        from #${sheet}
+        `
+      }
+
+      sql += `
+        ${_backCustomScript}
+
+        drop table #${sheet}
+        ${mk_ent}
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+        ${callback}`
+
+      sql = sql.replace(/@start_type@/ig, `'寮�濮�'`)
+      // works_flow_error       娴佺▼閿欒
+      let worksReFields = ['works_flow_error', 'works_flow_code', 'works_flow_name', 'works_flow_param', 'works_flow_detail_id', 'status', 'statusname', 'work_group', 'work_grade']
+      worksReFields.forEach(n => {
+        sql = sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+      })
+    } else {
+      sql += `
+        ${_backCustomScript}
+
+        drop table #${sheet}
+        ${mk_ent}
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+        ${callback}`
+    }
+
+    if (/@ErrorCode='(ENT|NNT|FNT|NMNT|CNT|-2NT)'/ig.test(sql)) {
+      sql = sql.replace(/@ErrorCode='(ENT|NNT|FNT|NMNT|CNT|-2NT)'[\S\s]+\sgoto\s+aaa($|\s)/ig, (word) => {
+        return word.replace(/goto aaa/, 'goto mk_ent')
+      })
+    }
+
+    let reps = []
+    let decSql = []
+    let secSql = []
+
+    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address']
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(sql)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        secSql.push(`@${s}=@${s}@`)
+        reps.push(s)
+      }
+    })
+
+    decSql = decSql.length ? `,${decSql.join(',')}` : ''
+    secSql = secSql.length ? `,${secSql.join(',')}` : ''
+
+    sql = sql.replace(/@mk_init_declare@/ig, decSql)
+    sql = sql.replace(/@mk_init_select@/ig, secSql)
+
+    let regs = ['ID', 'BID', 'time_id', 'datam', 'typename']
+    
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(sql)) {
+        reps.push(s)
+      }
+    })
+
+    let map = new Map()
+    reps.push(...sysVars)
+    reps = reps.filter(n => {
+      if (map.has(n.toLowerCase())) {
+        return false
+      }
+
+      map.set(n.toLowerCase(), true)
+
+      return true
+    })
+
+    reps.forEach(n => {
+      sql = sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+
+    if (/\$@/ig.test(sql)) {
+      sql = sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/\$check@|@check\$/ig.test(sql)) {
+      sql = sql.replace(/\$check@/ig, '@mk_check_begin@').replace(/@check\$/ig, '@mk_check_end@')
+      reps.push('mk_check_begin', 'mk_check_end')
+    }
+    if (/@db@/ig.test(sql)) {
+      reps.push('db')
+    }
+
+    sql = sql.replace(/\n\x20{6,10}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    return {LText: sql, md5: md5(sql), reps}
+  }
+
+  let getEditTableSql = (btn, cols, columns, setting) => {
+    let sheet = btn.sheet.replace(/@db@/ig, '')
+    let database = ''
+    if (/@db@/ig.test(btn.sheet)) {
+      database = '@db@'
+    }
+  
+    let forms = []
+    let _forms = {}
+    let index = 0
+
+    let getColumns = (cols) => {
+      cols.forEach(item => {
+        if (item.type === 'colspan') {
+          getColumns(item.subcols)
+        } else if (item.editable === 'true') {
+          item.$sort = index
+          _forms[item.field] = item
+          index++
+        }
+      })
+    }
+
+    getColumns(cols)
+
+    columns.forEach(item => {
+      if (item.field === setting.primaryKey) return
+
+      if (_forms[item.field]) {
+        let _item = {..._forms[item.field]}
+        if (_item.editType === 'date') {
+          _item.datatype = _item.declareType || 'datetime'
+        } else {
+          _item.datatype = item.datatype
+        }
+
+        forms.push(_item)
+      } else {
+        forms.push({...item, $sort: 999})
+      }
+    })
+
+    forms.sort((a, b) => a.$sort - b.$sort)
+
+    let sql = ''
+  
+    let _initCustomScript = '' // 鍒濆鍖栬剼鏈�
+    let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
+    let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
+    let _regs = [
+      {reg: new RegExp('(^|\\s)@' + sheet + '(\\s|$)', 'ig'), value: ` #${sheet} `},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\(', 'ig'), value: ` #${sheet}(`},
+      {reg: new RegExp('(^|\\s)@' + sheet + '\\)', 'ig'), value: ` #${sheet})`},
+    ]
+
+    btn.scripts && btn.scripts.forEach(script => {
+      if (script.status === 'false') return
+
+      let _sql = script.sql
+
+      _regs.forEach(item => {
+        _sql = _sql.replace(item.reg, item.value)
+      })
+
+      if (script.position === 'init') {
+        _initCustomScript += `
+          /* 鑷畾涔夎剼鏈� */
+          ${_sql}
+        `
+      } else if (script.position === 'front') {
+        _prevCustomScript += `
+          /* 鑷畾涔夎剼鏈� */
+          ${_sql}
+        `
+      } else {
+        _backCustomScript += `
+          /* 鑷畾涔夎剼鏈� */
+          ${_sql}
+        `
+      }
+    })
+
+    let _uniquesql = ''
+    if (btn.uniques && btn.uniques.length > 0) {
+      let textFields = []
+      let numberFields = []
+      let dateFields = []
+      columns.forEach((col) => {
+        if (/Nvarchar/ig.test(col.datatype)) {
+          textFields.push(col.field)
+        } else if (/Decimal|int/ig.test(col.datatype)) {
+          numberFields.push(col.field)
+        } else if (/date/ig.test(col.datatype)) {
+          dateFields.push(col.field)
+        }
+      })
+      btn.uniques.forEach(unique => {
+        if (unique.status === 'false' || !unique.verifyType) return
+
+        let _fields = unique.field.split(',')
+        let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
+        _fields_ = _fields_.join(' and ')
+
+        let _where = []
+        _fields.forEach(f => {
+          if (textFields.includes(f)) {
+            _where.push(`${f}!=''`)
+          } else if (numberFields.includes(f)) {
+            _where.push(`${f}!=0`)
+          } else if (dateFields.includes(f)) {
+            _where.push(`${f}>'1949-10-01'`)
+          }
+        })
+        _where = _where.length ? `where ${_where.join(' and ')} ` : ''
+
+        if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
+          _fields_ += ' and b.deleted=0'
+        }
+
+        let _afields = []
+        _fields = _fields.map(f => {
+          if (numberFields.includes(f)) {
+            _afields.push(`cast(a.${f} as nvarchar(50))`)
+            return `cast(${f} as nvarchar(50))`
+          } else if (dateFields.includes(f)) {
+            _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+            return `CONVERT(nvarchar(50), ${f}, 21)`
+          }
+          _afields.push(`a.${f}`)
+
+          return f
+        })
+
+        _uniquesql += `
+          /* 閲嶅鎬ч獙璇� */
+          Set @tbid=''
+          Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from #${sheet} ) a group by ${unique.field} having sum(n)>1
+          
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 閲嶅'
+            goto aaa
+          end
+          
+          ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
+          Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${sheet} b on ${_fields_}
+          
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
+            goto aaa
+          end` : ''}
+        `
+      })
+    }
+
+    let declarefields = []
+    let fields = []
+
+    forms.forEach(col => {
+      let key = col.field.toLowerCase()
+      if (key === 'jskey' || key === 'bid' || key === 'data_type') return
+
+      declarefields.push(`${col.field} ${col.datatype}`)
+      fields.push(col.field)
+    })
+
+    fields = fields.join(',')
+
+    let _insert = ''
+    if (btn.default !== 'false') {
+      _insert = `
+        /* 榛樿sql */
+        Insert into ${database}${sheet} (${fields},createuserid,createuser,createstaff,bid) 
+        Select ${fields},@UserID@,@username,@fullname,@BID@ From #${sheet}
+      `
+    }
+
+    sql = `/* ${btn.logLabel} */
+      BEGIN TRY
+      begin TRAN
+
+      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(256))
+      Declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)@mk_init_declare@
+      Select @ErrorCode='S',@retmsg=''@mk_init_select@
+
+      ${_initCustomScript}
+      Insert into #${sheet} (${fields},jskey,data_type,BID)
+
+      /* table鏁版嵁*/
+      @mk_excel_data@
+
+      ${_uniquesql}
+      ${_prevCustomScript}
+      ${_insert}
+      ${_backCustomScript}
+
+      drop table #${sheet}
+
+      select @ErrorCode as ErrorCode,@retmsg as retmsg
+      ${callback}`
+  
+    let reps = []
+    let decSql = []
+    let secSql = []
+
+    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address']
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(sql)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        secSql.push(`@${s}=@${s}@`)
+        reps.push(s)
+      }
+    })
+
+    decSql = decSql.length ? `,${decSql.join(',')}` : ''
+    secSql = secSql.length ? `,${secSql.join(',')}` : ''
+
+    sql = sql.replace(/@mk_init_declare@/ig, decSql)
+    sql = sql.replace(/@mk_init_select@/ig, secSql)
+
+    let regs = ['BID', 'time_id', 'datam', 'typename']
+    
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(sql)) {
+        reps.push(s)
+      }
+    })
+
+    let map = new Map()
+    reps.push(...sysVars)
+    reps = reps.filter(n => {
+      if (map.has(n.toLowerCase())) {
+        return false
+      }
+
+      map.set(n.toLowerCase(), true)
+
+      return true
+    })
+
+    reps.forEach(n => {
+      sql = sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+
+    if (/\$@/ig.test(sql)) {
+      sql = sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(sql)) {
+      reps.push('db')
+    }
+
+    sql = sql.replace(/\n\x20{6,10}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    return {LText: sql, md5: md5(sql), reps}
+  }
+
+  let getExcelOutSql = (btn, component) => {
+    let item = {setting: {}, columns: [], search: [], useMSearch: 'false'}
+
+    btn.verify.columns.forEach(col => {
+      if (col.output === 'false' || !col.Column || col.Column === '$Index') return
+      item.columns.push({
+        field: col.Column
+      })
+    })
+
+    if (btn.verify.useSearch !== 'false') {
+      item.search = component.$searches
+    }
+
+    item.setting.interType = 'system'
+    item.setting.execute = btn.verify.defaultSql || 'true'
+    item.setting.dataresource = btn.verify.dataresource || ''
+    item.setting.queryType = btn.verify.queryType
+    item.setting.laypage = btn.pagination
+    item.setting.order = btn.verify.order || ''
+    item.setting.$name = btn.logLabel || ''
+
+    if (btn.Ot === 'requiredOnce') {
+      item.setting.primaryKey = btn.verify.primaryKey || component.setting.primaryKey || 'ID'
+    }
+
+    item.scripts = btn.verify.scripts || []
+
+    let msg = getDataSource(item, [])
+
+    return msg
+  }
+
+  let getDoubleExcelOutSql = (btn, component) => {
+    let item = fromJS(component).toJS()
+    item.search = item.$searches || []
+    item.subtype = 'datacard'
+    item.columns = [...item.columns, ...item.subColumns]
+
+    item.setting.laypage = btn.pagination
+    item.setting.$name = btn.logLabel || ''
+
+    let msg = getDataSource(item, [])
+
+    return msg
+  }
+
+  let getPrintSql = (btn, component) => {
+    let item = {setting: {}, columns: btn.verify.columns || [], search: [], useMSearch: 'false'}
+
+    item.setting.interType = 'system'
+    item.setting.execute = btn.verify.setting.defaultSql || 'true'
+    item.setting.dataresource = btn.verify.setting.dataresource || ''
+    item.setting.queryType = btn.verify.setting.queryType
+    item.setting.laypage = 'false'
+    item.setting.order = btn.verify.setting.order || ''
+    item.setting.$name = btn.logLabel || ''
+    item.setting.transact = 'true'
+    item.setting.$fixOrder = true
+
+    item.scripts = btn.verify.scripts || []
+
+    let msg = getDataSource(item, [], 'print')
+
+    msg.LText = msg.LText.replace(/@mk_obj_name@/ig, 'data')
+    msg.reps = msg.reps.filter(n => n !== 'mk_obj_name')
+
+    let formkeys = []
+    let colreps = []
+    let _declares = []
+    let _init = []
+    if (btn.execMode === 'pop' && btn.modal && btn.modal.fields) {
+      btn.modal.fields.forEach(item => {
+        if (!item.field) return
+        let _key = item.field.toLowerCase()
+
+        if (!new RegExp('@' + _key + '[^0-9a-z_]', 'ig').test(msg.LText)) return
+
+        formkeys.push(_key)
+        colreps.push(item.field)
+        
+        let _item = {
+          key: item.field,
+          fieldlen: item.fieldlength || 50,
+          writein: item.writein !== 'false',
+          type: item.type,
+          isconst: item.constant === 'true'
+        }
+  
+        if (_item.type === 'datemonth') {
+          _item.type = 'text'
+        } else if (_item.type === 'number' || _item.type === 'rate') {
+          _item.fieldlen = item.decimal || 0
+        } else if (_item.type === 'date') {
+          _item.type = item.declareType === 'nvarchar(50)' ? 'text' : 'date'
+        } else if (_item.type === 'datetime') {
+          _item.type = 'date'
+        } else if (item.declare === 'decimal') {
+          _item.type = 'number'
+          _item.fieldlen = item.decimal || 0
+        }
+  
+        if (_item.type === 'number' || _item.type === 'rate') {
+          _init.push(`@${_key}=@mk_${_key}_mk@`)
+        } else if (_item.type === 'date') {
+          _init.push(`@${_key}='@mk_${_key}_mk@'`)
+        } else if (_item.type === 'select' || _item.type === 'link' || _item.type === 'radio') {
+          _init.push(`@${_key}='@mk_${_key}_mk@'`)
+        } else if (_item.isconst) {
+          _init.push(`@${_key}=N'@mk_${_key}_mk@'`)
+        } else {
+          _init.push(`@${_key}='@mk_${_key}_mk@'`)
+        }
+
+        if (_item.fieldlen && _item.fieldlen > 4000) {
+          _item.fieldlen = 'max'
+        }
+  
+        let _type = `nvarchar(${_item.fieldlen})`
+  
+        if (_item.type.match(/date/ig)) {
+          _type = 'datetime'
+        } else if (_item.type === 'number') {
+          _type = `decimal(18,${_item.fieldlen})`
+        } else if (_item.type === 'rate') {
+          _type = `decimal(18,2)`
+        }
+  
+        _declares.push(`@${_key} ${_type}`)
+      })
+    }
+
+    // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
+    if (btn.Ot !== 'notRequired' && component.columns.length > 0) {
+      component.columns.forEach(col => {
+        let _key = col.field.toLowerCase()
+
+        if (formkeys.includes(_key) || !new RegExp('@' + _key + '[^0-9a-z_@]', 'ig').test(msg.LText)) return
+        // if (_key === 'id' && !/@id[^0-9a-z_@]/ig.test(msg.LText)) return
+
+        colreps.push(col.field)
+  
+        if (col.type === 'number') {
+          _init.push(`@${_key}=@mk_${_key}_mk@`)
+        } else {
+          _init.push(`@${_key}='@mk_${_key}_mk@'`)
+        }
+        
+        _declares.push(`@${_key} ${col.datatype || 'nvarchar(50)'}`)
+      })
+    }
+
+    _declares = _declares.length ? ',' + _declares.join(',') : ''
+    _init = _init.length ? ',' + _init.join(',') : ''
+
+    msg.LText = msg.LText.replace('@mk_print_declare@', _declares)
+    msg.LText = msg.LText.replace('@mk_print_select@', _init)
+
+    msg.reps = [...msg.reps, ...colreps]
+
+    return msg
+  }
+
+  let getPaySql = (btn, component) => {
+    let _sql = `/* ${btn.logLabel} */
+      BEGIN TRY
+      begin TRAN
+
+      Declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid nvarchar(50)@mk_init_declare@
+      Select @ErrorCode='S',@retmsg=''@mk_init_select@
+      `
+
+    btn.verify.scripts.forEach(item => {
+      if (item.status === 'false') return
+
+      _sql += `
+      ${item.sql}
+      `
+    })
+
+    if (btn.output) {
+      _sql += `
+        select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id
+        ${callback}`
+    } else {
+      _sql += `
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+        ${callback}`
+    }
+    
+    let reps = []
+    let decSql = []
+    let secSql = []
+
+    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'BID']
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(_sql)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        secSql.push(`@${s}=@${s}@`)
+        reps.push(s)
+      }
+    })
+
+    let regs = ['ID', 'time_id', 'datam', 'typename']
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(_sql)) {
+        reps.push(s)
+      }
+    })
+
+    syses = syses.map(n => n.toLowerCase())
+    syses.push('tbid')
+
+    let colreps = []
+    component.columns.forEach(col => {
+      let _key = col.field.toLowerCase()
+
+      if (syses.includes(_key) || !new RegExp('@' + _key + '[^0-9a-z_@]', 'ig').test(_sql)) return
+      // if (_key === 'id' && !/@id[^0-9a-z_@]/ig.test(_sql)) return
+
+      colreps.push(col.field)
+      
+      decSql.push(`@${col.field} ${col.datatype || 'nvarchar(50)'}`)
+
+      if (col.type === 'number') {
+        secSql.push(`@${col.field}=@mk_${col.field}_mk@`)
+      } else {
+        secSql.push(`@${col.field}='@mk_${col.field}_mk@'`)
+      }
+    })
+
+    decSql = decSql.length ? `,${decSql.join(',')}` : ''
+    secSql = secSql.length ? `,${secSql.join(',')}` : ''
+
+    _sql = _sql.replace(/@mk_init_declare@/ig, decSql)
+    _sql = _sql.replace(/@mk_init_select@/ig, secSql)
+
+    let map = new Map()
+    reps.push(...sysVars)
+    reps = reps.filter(n => {
+      if (map.has(n.toLowerCase())) {
+        return false
+      }
+
+      map.set(n.toLowerCase(), true)
+
+      return true
+    })
+
+    reps.forEach(n => {
+      _sql = _sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+
+    if (/\$@/ig.test(_sql)) {
+      _sql = _sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(_sql)) {
+      reps.push('db')
+    }
+
+    _sql = _sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    reps = [...reps, ...colreps]
+
+    return {LText: _sql, md5: md5(_sql), reps}
+  }
+
+  let getFormSql = (item, tname) => {
+    let arrfield = [item.valueField, item.valueText]
+
+    if (item.type === 'checkcard') {
+      arrfield = item.fields ? item.fields.map(f => f.field) : []
+      arrfield.push(item.cardValField)
+      if (item.urlField) {
+        arrfield.push(item.urlField)
+      } else if (item.colorField) {
+        arrfield.push(item.colorField)
+      } else if (item.parentField) {
+        arrfield.push(item.parentField)
+      }
+    }
+
+    if (item.linkField) {
+      arrfield.push(item.linkField)
+    }
+    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)
+    }
+
+    arrfield = Array.from(new Set(arrfield))
+
+    let _datasource = item.dataSource
+    let sql = ''
+
+    if (/\s/.test(_datasource)) { // 鎷兼帴鍒悕
+      _datasource = '(' + _datasource + ') tb'
+    }
+
+    arrfield = arrfield.join(',')
+
+    if (item.orderBy) {
+      sql = `select distinct ${arrfield},${item.orderBy} as orderfield from ${_datasource} order by orderfield ${item.orderType}`
+    } else {
+      sql = `select distinct ${arrfield} from ${_datasource}`
+    }
+
+    let reps = []
+
+    let decSql = []
+    let secSql = []
+
+    let syses = ['mk_departmentcode', 'mk_organization', 'mk_user_type']
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(sql)) {
+        if (['mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else {
+          decSql.push(`@${s} nvarchar(20)`)
+        }
+        secSql.push(`@${s}=@${s}@`)
+        reps.push(s)
+      }
+    })
+
+    decSql = decSql.join(',')
+    secSql = secSql.join(',')
+    decSql = decSql ? `Declare ${decSql} select ${secSql}` : ''
+
+    sql = `/* ${item.label}锛�${tname}锛� */
+      SELECT obj_name='${item.field}',prm_field='',str_field='',
+      arr_field='${arrfield}',tabid='',parid='',sub_name='',sub_field=''
+
+      ${decSql}
+      ${sql}
+
+      select 'S' as ErrorCode,'' as retmsg
+    `
+
+    let regs = ['ID', 'BID', 'datam']
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(sql)) {
+        reps.push(s)
+      }
+    })
+
+    reps.push(...sysVars)
+
+    reps.forEach(n => {
+      sql = sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+
+    if (/\$@/ig.test(sql)) {
+      sql = sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(sql)) {
+      reps.push('db')
+    }
+
+    // reps.push('mk_obj_name')
+
+    sql = sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    return {LText: sql, md5: md5(sql), reps}
+  }
+
+  let getPopSelectSql = (item) => {
+    let arrfield = item.columns.map(f => f.field)
+  
+    if (item.linkSubField && item.linkSubField.length > 0) {
+      item.linkSubField.forEach(n => {
+        if (!arrfield.includes(n)) {
+          arrfield.push(n)
+        }
+      })
+    }
+
+    arrfield = arrfield.join(',')
+    if (/\s/.test(item.dataSource)) { // 鎷兼帴鍒悕
+      item.dataSource = '(' + item.dataSource + ') tb'
+    }
+
+    let LText = ''
+    let DateCount = ''
+    let _search = ''
+    let reps = []
+    let sFields = []
+
+    if (item.searchKey) {
+      _search = '@mk_search@'
+      sFields = item.searchKey.split(',')
+    }
+
+    // 涓嶉渶瑕佸崟寮曞彿锛歰rderBy銆乸ageSize銆乸ageIndex銆乨b
+    let regs = [...sFields, 'orderBy', 'pageSize', 'pageIndex', 'ID', 'BID', 'time_id', 'datam']
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(item.dataSource)) {
+        reps.push(s)
+      }
+    })
+
+    let decSql = []
+    let secSql = []
+
+    let syses = ['mk_departmentcode', 'mk_organization', 'mk_user_type']
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(item.dataSource)) {
+        if (['mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else {
+          decSql.push(`@${s} nvarchar(20)`)
+        }
+        secSql.push(`@${s}=@${s}@`)
+        reps.push(s)
+      }
+    })
+
+    decSql = decSql.join(',')
+    secSql = secSql.join(',')
+    decSql = decSql ? `Declare ${decSql} select ${secSql}` : ''
+
+    if (item.laypage === 'true') {
+      /*system_query*/
+      LText = `select top @pageSize@ ${arrfield} from (select ${arrfield} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${item.dataSource} ${_search}) tmptable where rows > @pageSize@ * (@pageIndex@ - 1) order by tmptable.rows `
+      DateCount = `select count(1) as total from ${item.dataSource} ${_search}`
+
+      reps.push('pageSize', 'orderBy', 'pageIndex')
+    } else {
+      LText = `select ${arrfield} from ${item.dataSource} ${_search} order by @orderBy@ `
+      reps.push('orderBy')
+    }
+
+    let sql = `SELECT obj_name='data',prm_field='',str_field='',
+      arr_field='${arrfield}',tabid='',parid='',sub_name='',sub_field=''
+      `
+
+    if (DateCount) {
+      sql += `UNION ALL
+        SELECT obj_name='DateCount',prm_field='total',str_field='',
+        arr_field='',tabid='',parid='',sub_name='',sub_field=''
+      `
+    }
+
+    sql += `
+      ${decSql}
+      ${LText}
+      ${DateCount}
+
+      select 'S' as ErrorCode,'' as retmsg
+    `
+
+    let map = new Map()
+    reps.push(...sysVars)
+    reps = reps.filter(n => {
+      if (map.has(n.toLowerCase())) {
+        return false
+      }
+
+      map.set(n.toLowerCase(), true)
+
+      return true
+    })
+
+    reps.forEach(n => {
+      if (['orderBy', 'pageSize', 'pageIndex'].includes(n)) return
+
+      sql = sql.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+    if (/\$@/ig.test(sql)) {
+      sql = sql.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(sql)) {
+      reps.push('db')
+    }
+
+    sql = sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    return {LText: sql, md5: md5(sql), reps}
+  }
+
+  let getInvoicePreSql = (btn, logLabel) => {
+    let reps = []
+    let sysVars = ['loginuid', 'sessionuid', 'userid', 'appkey', 'lang', 'username', 'fullname', 'menuname']
+    let _script = ''
+    btn.scripts.forEach(item => {
+      if (item.status === 'false') return
+      _script += `
+      ${item.sql}
+      `
+    })
+
+    _script = _script.replace(/@typename@/ig, `'admin'`)
+    
+    let regs = ['ID', 'BID', 'time_id', 'datam', ...sysVars]
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(_script)) {
+        reps.push(s)
+      }
+    })
+
+    reps.forEach(n => {
+      _script = _script.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+    if (/\$@/ig.test(_script)) {
+      _script = _script.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(_script)) {
+      reps.push('db')
+    }
+
+    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
+    let decSql = []
+    let secSql = []
+  
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(_script)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        secSql.push(`@${s}='@${s}@'`)
+        reps.push(s)
+      }
+    })
+    decSql = decSql.join(',')
+    secSql = secSql.join(',')
+
+    let sql = `/* ${logLabel} */
+      BEGIN TRY 
+      begin TRAN
+
+      Declare @ErrorCode nvarchar(50), @retmsg nvarchar(4000), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @tbid nvarchar(50)${decSql ? ',' + decSql : ''}
+
+      Select @ErrorCode='S', @retmsg='', @account_id='@account_id@', @account_year_id='@account_year_id@', @account_code='@account_code@', @account_year_code='@account_year_code@'${secSql ? ',' + secSql : ''}
+
+      /* 鍙戠エ涓昏〃瀛楁 */
+      Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2), @business_type Nvarchar(20)
+
+      Select @invoice_type='@invoice_type@', @from_to_name='@from_to_name@', @from_to_tax_no='@from_to_tax_no@', @from_to_addr='@from_to_addr@', @from_to_tel='@from_to_tel@', @from_to_bank_name='@from_to_bank_name@', @from_to_account_no='@from_to_account_no@', @from_to_mob='@from_to_mob@', @from_to_email='@from_to_email@', @from_to_code='@from_to_code@', @orgname='@orgname@', @tax_no='@tax_no@', @addr='@addr@', @tel='@tel@', @bank_name='@bank_name@', @account_no='@account_no@', @remark='@remark@', @payee='@payee@', @reviewer='@reviewer@', @drawer='@drawer@', @io='@io@', @orgcode='@orgcode@', @total_net_amount=@total_net_amount@, @total_tax=@total_tax@, @total_amount=@total_amount@, @business_type='@business_type@'
+
+      /* 鍙戠エ鏄庣粏涓存椂琛� */
+
+      Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), tax_item Nvarchar(50), tax_method Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
+
+      Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type)
+
+      @mk_excel_data@
+
+      /* 鑷畾涔夎剼鏈� */
+      ${_script}
+      `
+
+    if (btn.type === 'billout') {
+      sql += callback
+    } else {
+      sql += `
+        select @ErrorCode as ErrorCode,@retmsg as retmsg
+        ${callback}
+        `
+    }
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    sql = sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    return {LText: sql, md5: md5(sql), reps}
+  }
+
+  let getInvoiceSysBackSql = (btn, logLabel) => {
+    let _prev = ''
+    let _back = ''
+    let tables = []
+    let reps = []
+
+    btn.cbScripts.forEach(script => {
+      if (script.status === 'false') return
+
+      if (/\s#[a-z0-9_]+(\s|\()/ig.test(script.sql)) {
+        tables.push(...script.sql.match(/\s#[a-z0-9_]+(\s|\()/ig))
+      }
+
+      if (script.position === 'front') {
+        _prev += `
+        /* 鑷畾涔夎剼鏈� */
+        ${script.sql}
+        `
+      } else {
+        _back += `
+        /* 鑷畾涔夎剼鏈� */
+        ${script.sql}
+        `
+      }
+    })
+
+    tables = tables.map(tb => tb.replace(/\s|\(/g, ''))
+
+    let syses = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
+    let decSql = []
+    let secSql = []
+    let testSql = _prev + _back
+
+    _prev = _prev.replace(/@typename@/ig, `'admin'`)
+    _back = _back.replace(/@typename@/ig, `'admin'`)
+
+    let regs = ['ID', 'BID', 'time_id', 'datam', ...sysVars]
+
+    regs.forEach(s => {
+      if (new RegExp('@' + s + '@', 'ig').test(testSql)) {
+        reps.push(s)
+      }
+    })
+
+    reps.forEach(n => {
+      _prev = _prev.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+      _back = _back.replace(new RegExp('@' + n + '@', 'ig'), `'@${n}@'`)
+    })
+    if (/\$@/ig.test(testSql)) {
+      _prev = _prev.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      _back = _back.replace(/\$@/ig, '@datam_begin@').replace(/@\$/ig, '@datam_end@')
+      reps.push('datam_begin', 'datam_end')
+    }
+    if (/@db@/ig.test(testSql)) {
+      reps.push('db')
+    }
+  
+    syses.forEach(s => {
+      if (new RegExp('@' + s + '[^0-9a-z_]', 'ig').test(testSql)) {
+        if (['RoleID', 'mk_departmentcode', 'mk_organization'].includes(s)) {
+          decSql.push(`@${s} nvarchar(512)`)
+        } else if (['mk_address'].includes(s)) {
+          decSql.push(`@mk_address nvarchar(100)`)
+        } else {
+          decSql.push(`@${s} nvarchar(50)`)
+        }
+        secSql.push(`@${s}='@${s}@'`)
+        reps.push(s)
+      }
+    })
+    decSql = decSql.join(',')
+    secSql = secSql.join(',')
+  
+    // 闇�瑕佸0鏄庣殑鍙橀噺闆�
+
+    let _sql = `/* ${logLabel} */
+      BEGIN TRY 
+      begin TRAN
+
+      Declare @ErrorCode nvarchar(50), @retmsg nvarchar(4000), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @tbid nvarchar(50)${decSql ? ',' + decSql : ''}
+
+      Select @ErrorCode='S', @retmsg='', @account_id='@account_id@', @account_year_id='@account_year_id@', @account_code='@account_code@', @account_year_code='@account_year_code@'${secSql ? ',' + secSql : ''}
+
+      ${_prev}
+      /* 澶栭儴鎺ュ彛鍏ュ弬 */
+      @mk_outer_params@
+      ${_back}
+      select @ErrorCode as ErrorCode,@retmsg as retmsg
+      ${callback}
+      `
+
+    _sql = _sql.replace(/\n\x20{6,8}/g, '\n').replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, '').replace(/\t+|\v+/g, '')
+
+    reps = reps.filter(n => {
+      if (sysVars.includes(n.toLowerCase())) {
+        return false
+      }
+
+      return true
+    })
+
+    return { LText: _sql, md5: md5(_sql), reps, tbs: tables }
+  }
+
+  let _mainSearch = []
+
+  if (appType === 'mob') {
+    let search = []
+    let ms = null
+    config.components.forEach(item => {
+      if (item.type === 'topbar' && item.wrap.type !== 'navbar' && item.search) {
+        ms = item.search
+      } else if (item.type === 'search' && item.wrap.field) {
+        search.push({
+          type: 'text',
+          field: item.wrap.field,
+        })
+      }
+    })
+
+    if (ms) {
+      if (ms.setting.type === 'search') {
+        search.push({
+          type: 'text',
+          field: ms.setting.field,
+        })
+      }
+      search.push(...ms.fields)
+
+      ms.groups.forEach(group => {
+        if (group.setting.type === 'search') {
+          search.push({
+            type: 'text',
+            field: group.setting.field,
+          })
+        }
+        search.push(...group.fields)
+      })
+
+      if (search.length > 0) {
+        search.forEach(cell => {
+          if (['select', 'link', 'multiselect', 'checkcard', 'radio'].includes(cell.type) && cell.resourceType === '1' && cell.dataSource) {
+            let msg = getFormSql(cell, '鎼滅储')
+    
+            sqls.push({uuid: cell.uuid, type: 'sForm', ...msg})
+          }
+        })
+      }
+    }
+
+    if (search.length > 0) {
+      _mainSearch = search
+    }
+  } else {
+    config.components.forEach(component => {
+      if (component.type !== 'search') return
+
+      _mainSearch = component.search || []
+    })
+  }
+
+  if (config.interfaces && config.interfaces.length > 0) {
+    config.interfaces.forEach(m => {
+      if (m.status !== 'true' || m.setting.interType !== 'system') return false
+
+      m.setting.laypage = 'false'
+      m.setting.$top = true
+      m.setting.$name = (config.MenuName || '') + '-' + (m.name || '')
+
+      let msg = getDataSource(m, _mainSearch)
+
+      sqls.push({uuid: m.uuid, type: 'interface', ...msg})
+    })
+  }
+
+  filterComponent(config.components, _mainSearch)
+
+  return sqls
 }
\ No newline at end of file
diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js
index 6210d62..5b0c6e2 100644
--- a/src/utils/utils-datamanage.js
+++ b/src/utils/utils-datamanage.js
@@ -5,6 +5,134 @@
 import MKEmitter from '@/utils/events.js'
 import Utils from './utils.js'
 
+const getBackendQueryParam = (setting, search, orderBy, pageIndex, pageSize, id, BID, year, dataName) => {
+  let item = window.GLOB.CacheData.get('sql_' + setting.uuid)
+
+  let searchKeys = null
+  if (setting.dataresource) {
+    searchKeys = []
+
+    if (search.length && setting.queryType !== 'statistics') {
+      searchKeys = Utils.getSearchkeys(search)
+    }
+
+    if (id) {
+      if (/^excel:/.test(id)) {
+        id = id.replace(/^excel:/, '')
+        searchKeys.push({
+          key: setting.primaryKey || 'ID',
+          match: '',
+          type: 'text_in',
+          value: id
+        })
+      } else {
+        searchKeys.push({
+          key: setting.primaryKey || 'ID',
+          match: '03',
+          type: 'text',
+          value: id
+        })
+      }
+    }
+  }
+
+  let values = {
+    time_id: Utils.getguid(),
+    roleid: sessionStorage.getItem('role_id') || '',
+    mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
+    mk_organization: sessionStorage.getItem('organization') || '',
+    mk_user_type: sessionStorage.getItem('mk_user_type') || '',
+    mk_nation: sessionStorage.getItem('nation') || '',
+    mk_province: sessionStorage.getItem('province') || '',
+    mk_city: sessionStorage.getItem('city') || '',
+    mk_district: sessionStorage.getItem('district') || '',
+    mk_address: sessionStorage.getItem('address') || '',
+    orderby: orderBy || '',
+    pagesize: setting.laypage ? pageSize : '9999',
+    pageindex: pageIndex,
+    id: id || '',
+    bid: BID || '',
+    typename: 'admin',
+    datam: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    datam_begin: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    datam_end: sessionStorage.getItem('dataM') === 'true' ? 'Y' : '',
+    mk_obj_name: dataName || 'data'
+  }
+
+  if (setting.hasExtend) {
+    values.mk_time = setting.extendTime
+  }
+  if (setting.$re_year) {
+    values.mk_year = year
+  }
+  if (window.GLOB.externalDatabase !== null) {
+    values.db = window.GLOB.externalDatabase
+  }
+  if (item.works_flow_code) {
+    values.works_flow_code = item.works_flow_code
+  }
+
+  item.urlkeys && item.urlkeys.forEach(key => {
+    values[key] = item.urlparam[key]
+  })
+
+  let allSearch = Utils.getAllSearchOptions(search)
+
+  allSearch.forEach(cell => {
+    values[cell.key.toLowerCase()] = cell.value
+  })
+
+  let exps = []
+
+  if (searchKeys) {
+    exps.push({
+      key: 'mk_search',
+      value: searchKeys
+    })
+  }
+
+  item.reps.forEach(n => {
+    let key = n.toLowerCase()
+    if (values.hasOwnProperty(key)) {
+      exps.push({
+        key: n,
+        value: values[key]
+      })
+    }
+  })
+
+  let md5_id = ''
+  if (window.GLOB.probation) {
+    md5_id = md5(item.id + JSON.stringify(exps) + Math.floor(new Date().getTime() / 600000))
+    md5_id = moment().format('YYYYMMDDHHmmss') + md5_id.slice(-18)
+  }
+
+  let cell = {
+    id: item.id,
+    menuname: setting.$name || '',
+    exps: exps,
+    md5_id: md5_id
+  }
+
+  if (dataName) {
+    cell.dataName = dataName
+    cell.luser = item.luser
+    return cell
+  }
+
+  let param = {
+    $backend: true,
+    $type: 's_Get_TableData',
+    data: [cell]
+  }
+
+  if (setting.database === 'sso' && window.GLOB.mainSystemApi) {
+    param.rduri = window.GLOB.mainSystemApi
+  }
+
+  return param
+}
+
 export default class DataUtils {
   /**
    * @description 鏁版嵁婧愮粺涓�鏌ヨ
@@ -13,17 +141,23 @@
     let param = null
 
     if (setting.interType === 'system') {
-      param = this.getDefaultQueryParam(setting, search, orderBy, pageIndex, pageSize, id, BID, year)
+      if (window.backend && window.GLOB.CacheData.has('sql_' + setting.uuid)) {
+        param = getBackendQueryParam(setting, search, orderBy, pageIndex, pageSize, id, BID, year)
+      } else {
+        param = this.getDefaultQueryParam(setting, search, orderBy, pageIndex, pageSize, id, BID, year)
+        param.BID = BID || ''
+        param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
+      }
     } else {
       param = this.getCustomQueryParam(setting, search, orderBy, pageIndex, pageSize, id, year)
-    }
 
-    if (BID) {
-      param.BID = BID
-    }
-    // 鏁版嵁绠$悊鏉冮檺
-    if (sessionStorage.getItem('dataM') === 'true') {
-      param.dataM = 'Y'
+      if (BID) {
+        param.BID = BID
+      }
+      // 鏁版嵁绠$悊鏉冮檺
+      if (sessionStorage.getItem('dataM') === 'true') {
+        param.dataM = 'Y'
+      }
     }
 
     return param
@@ -142,23 +276,24 @@
       { reg: /@orderBy@/ig, value: orderBy },
       { reg: /@pageSize@/ig, value: setting.laypage ? pageSize : '9999' },
       { reg: /@pageIndex@/ig, value: pageIndex},
-      { reg: /@select\$|\$select@/ig, value: ''},
-      { reg: /\$sum@/ig, value: '/*'},
-      { reg: /@sum\$/ig, value: '*/'},
+      // { reg: /@select\$|\$select@/ig, value: ''},
+      // { reg: /\$sum@/ig, value: '/*'},
+      // { reg: /@sum\$/ig, value: '*/'},
       { reg: /@ID@/ig, value: `'${id || ''}'`},
       { reg: /@BID@/ig, value: `'${BID || ''}'`},
       { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
       { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
       { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
       { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      { reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
       { reg: /@typename@/ig, value: `'admin'`},
     )
 
     if (setting.hasExtend) {
-      regoptions.push({ reg: /@mk_time@/ig, value: setting.extendTime })
+      regoptions.push({ reg: /@mk_time@/ig, value: `'${setting.extendTime}'` })
     }
     if (setting.$re_year) {
-      regoptions.push({ reg: /@mk_year@/ig, value: year })
+      regoptions.push({ reg: /@mk_year@/ig, value: `'${year}'` })
     }
 
     regoptions.forEach(item => {
@@ -279,9 +414,9 @@
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
     if (window.GLOB.debugger === true) {
-      _customScript && console.info(`${setting.$name ? `/*${setting.$name} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
-      LText && console.info(`${setting.$name ? `/*${setting.$name} 鏁版嵁婧�*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
-      DateCount && console.info(`${setting.$name ? `/*${setting.$name} 鎬绘暟鏌ヨ*/\n` : ''}` + DateCount.replace(/\n\s{8}/ig, '\n'))
+      _customScript && window.mkInfo(`${setting.$name ? `/*${setting.$name} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
+      LText && window.mkInfo(`${setting.$name ? `/*${setting.$name} 鏁版嵁婧�*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
+      DateCount && window.mkInfo(`${setting.$name ? `/*${setting.$name} 鎬绘暟鏌ヨ*/\n` : ''}` + DateCount.replace(/\n\s{8}/ig, '\n'))
     }
 
     if (setting.$name) {
@@ -320,6 +455,10 @@
       }
     } else if (window.GLOB.forcedUpdate) {
       param.s_version_up = 'true'
+    }
+
+    if (setting.database === 'sso' && window.GLOB.mainSystemApi) {
+      param.rduri = window.GLOB.mainSystemApi
     }
 
     return param
@@ -370,15 +509,16 @@
       { reg: /@orderBy@/ig, value: orderBy },
       { reg: /@pageSize@/ig, value: 999999 },
       { reg: /@pageIndex@/ig, value: 1},
-      { reg: /\$select@/ig, value: '/*'},
-      { reg: /@select\$/ig, value: '*/'},
-      { reg: /@sum\$|\$sum@/ig, value: ''},
+      // { reg: /\$select@/ig, value: '/*'},
+      // { reg: /@select\$/ig, value: '*/'},
+      // { reg: /@sum\$|\$sum@/ig, value: ''},
       { reg: /@ID@/ig, value: `''`},
       { reg: /@BID@/ig, value: `'${BID || ''}'`},
       { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
       { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
       { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
       { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      { reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
       { reg: /@typename@/ig, value: `'admin'`},
     )
 
@@ -413,8 +553,8 @@
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
     if (window.GLOB.debugger === true) {
-      _customScript &&  console.info(`${setting.$name ? `/*${setting.$name} 鑷畾涔夎剼鏈� 缁熻鏌ヨ*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
-      LText &&  console.info(`${setting.$name ? `/*${setting.$name} 鏁版嵁婧� 缁熻鏌ヨ*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
+      _customScript && window.mkInfo(`${setting.$name ? `/*${setting.$name} 鑷畾涔夎剼鏈� 缁熻鏌ヨ*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
+      LText && window.mkInfo(`${setting.$name ? `/*${setting.$name} 鏁版嵁婧� 缁熻鏌ヨ*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
     }
 
     if (setting.$name) {
@@ -491,8 +631,17 @@
 /**
  * @description 鐢熸垚鍗曚釜缁勪欢sPC_Get_structured_data璇锋眰鍙傛暟
  */
-export function getStructDefaultParam (component, searchlist, first) {
+export function getStructDefaultParam (component, searchlist, first, BID) {
   const { columns, setting, dataName, format, uuid } = component
+
+  if (window.backend && window.GLOB.CacheData.has('sql_' + uuid)) {
+    if (first) {
+      let item = window.GLOB.CacheData.get('sql_' + uuid)
+      window.GLOB.CacheData.set('first_' + item.id, uuid)
+    }
+
+    return getBackendQueryParam(setting, searchlist, setting.order, 1, 1000, '', BID, '', dataName)
+  }
 
   let _dataresource = setting.dataresource
   let _customScript = setting.customScript
@@ -549,7 +698,7 @@
 
   return {
     uuid: uuid,
-    name: dataName,
+    dataName: dataName,
     $name: setting.$name,
     columns: columns,
     par_tablename: '',
@@ -566,6 +715,39 @@
  * @description 鐢熸垚sPC_Get_structured_data璇锋眰鍙傛暟
  */
 export function getStructuredParams (params, config, BID) {
+  if (window.backend && params[0].exps) {
+    let param = {
+      $backend: true,
+      $type: 's_Get_structured_data',
+      data: params.map(item => {
+        let cell = {...item}
+
+        delete cell.dataName
+        delete cell.luser
+
+        return cell
+      })
+    }
+
+    if (config.cacheUseful === 'true') {
+      param.time_limit = config.cacheTime
+
+      if (config.timeUnit === 'day') {
+        param.time_limit = param.time_limit * 1440
+      } else if (config.timeUnit === 'hour') {
+        param.time_limit = param.time_limit * 60
+      }
+
+      if (params.findIndex(item => item.luser) > -1) {
+        param.data_md5 = md5(window.GLOB.appkey + params[0].id + sessionStorage.getItem('UserID'))
+      } else {
+        param.data_md5 = md5(window.GLOB.appkey + params[0].id)
+      }
+    }
+
+    return param
+  }
+
   let LText_field = []
   let diffUser = false
 
@@ -578,6 +760,7 @@
     { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
     { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
     { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+    { reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
     { reg: /@typename@/ig, value: `'admin'`},
   ]
 
@@ -599,14 +782,14 @@
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
     if (window.GLOB.debugger === true) {
-      _script && console.info(`${item.$name ? `/*${item.$name} 鑷畾涔夎剼鏈紙鍚屾鏌ヨ锛�*/\n` : ''}${_sql ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_script}`)
-      _sql && console.info(`${item.$name ? `/*${item.$name} 鏁版嵁婧愶紙鍚屾鏌ヨ锛�*/\n` : ''}` + _sql)
+      _script && window.mkInfo(`${item.$name ? `/*${item.$name} 鑷畾涔夎剼鏈紙鍚屾鏌ヨ锛�*/\n` : ''}${_sql ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_script}`)
+      _sql && window.mkInfo(`${item.$name ? `/*${item.$name} 鏁版嵁婧愶紙鍚屾鏌ヨ锛�*/\n` : ''}` + _sql)
     }
 
     item.columns.forEach(cell => {
-      LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
+      LText_field.push(`Select '${item.dataName}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
     })
-    return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(_sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
+    return `Select '${item.dataName}' as tablename,'${window.btoa(window.encodeURIComponent(_sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
   })
 
   let param = {
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 1fa8b28..cc69ca5 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -71,6 +71,7 @@
       uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
     }
     uuid = timestamp + uuid.join('')
+    uuid = uuid.replace(/minke/ig, 'mnkie')
     return uuid
   }
 
@@ -416,7 +417,11 @@
           item.$first = true
         }
       }
-      
+
+      if (window.backend && ['select', 'link', 'multiselect', 'checkcard', 'radio'].includes(item.type) && item.resourceType === '1') {
+        item.uuid = md5(config.uuid + item.uuid)
+      }
+
       item.oriInitval = item.initval
 
       if (values) {
@@ -712,6 +717,157 @@
     return searchText.join(' AND ')
   }
 
+  static getSearchkeys (searches) {
+    let searchText = []
+    let matchs = {
+      'like': '01',
+      'not like': '02',
+      '=': '03',
+      '>': '04',
+      '<': '05',
+      '>=': '06',
+      '<=': '07',
+    }
+
+    searches.forEach(item => {
+      if (item.forbid || !item.value) return
+
+      let cell = {
+        key: item.key,
+        match: item.match,
+        type: 'text',
+        value: item.value
+      }
+      
+      if (item.type === 'text' || item.type === 'select') { // 缁煎悎鎼滅储锛屾枃鏈垨涓嬫媺锛屾墍鏈夊瓧娈垫嫾鎺�
+        if (/,/.test(item.key)) {
+          cell.type = 'text_or'
+        }
+      } else if (item.type === 'multi') {
+        cell.type = 'text_multi'
+      } else if (item.type === 'date') {
+        let _val = item.value
+        let timetail = ''
+
+        if (item.match === '<' || item.match === '<=') { // 鏃堕棿涓�<=鏃讹紝鍖归厤鍚庝竴澶╃殑0鐐癸紝鍖归厤鏂瑰紡涓�<
+          cell.match = '<'
+          if (item.precision === 'day') {
+            _val = moment(_val, 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD')
+          }
+        }
+        if (item.match === '=') {
+          timetail = ''
+        } else if (item.precision === 'day') {
+          timetail = ' 00:00:00.000'
+        } else if (item.precision === 'hour') {
+          timetail = ':00:00.000'
+        } else if (item.precision === 'minute') {
+          timetail = ':00.000'
+        } else if (item.precision === 'second') {
+          timetail = '.000'
+        }
+
+        cell.value = _val + timetail
+      }
+      
+      if (item.type === 'datemonth') { // 鏈�-杩囨护鏉′欢锛屼粠鏈堝紑濮嬭嚦缁撴潫锛岀粨鏉熸椂闂翠负鏈堟湯鍔犱竴澶╃殑0鐐癸紝鏂瑰紡涓�<
+        if (item.match === '=') {
+          searchText.push(cell)
+        } else {
+          let _startval = moment(item.value, 'YYYY-MM').startOf('month').format('YYYY-MM-DD') + ' 00:00:00.000'
+          let _endval = moment(item.value, 'YYYY-MM').endOf('month').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000'
+  
+          searchText.push({
+            key: item.key,
+            match: '>=',
+            type: 'text',
+            value: _startval
+          }, {
+            key: item.key,
+            match: '<',
+            type: 'text',
+            value: _endval
+          })
+        }
+      } else if (item.type === 'dateweek') { // 鍛�-杩囨护鏉′欢
+        let _startval = moment(item.value, 'YYYY-MM-DD' ).startOf('week').format('YYYY-MM-DD') + ' 00:00:00.000'
+        let _endval = moment(item.value, 'YYYY-MM-DD').endOf('week').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000'
+
+        searchText.push({
+          key: item.key,
+          match: '>=',
+          type: 'text',
+          value: _startval
+        }, {
+          key: item.key,
+          match: '<',
+          type: 'text',
+          value: _endval
+        })
+      } else if (item.type === 'daterange') {
+        let val = item.value.split(',')
+        let _startval = ''
+        let _endval = ''
+
+        if (item.precision === 'day') {
+          _startval = val[0] + ' 00:00:00.000'
+          _endval = moment(val[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000'
+        } else if (item.precision === 'hour') {
+          _startval = val[0] + ':00:00.000'
+          _endval = val[1] + ':00:00.000'
+        } else if (item.precision === 'minute') {
+          _startval = val[0] + ':00.000'
+          _endval = val[1] + ':00.000'
+        } else if (item.precision === 'second') {
+          _startval = val[0] + '.000'
+          _endval = val[1] + '.000'
+        }
+
+        let _skey = item.key
+        let _ekey = item.key
+
+        if (/,/.test(item.key)) {
+          _skey = item.key.split(',')[0]
+          _ekey = item.key.split(',')[1]
+        }
+
+        searchText.push({
+          key: _skey,
+          match: '>=',
+          type: 'text',
+          value: _startval
+        }, {
+          key: _ekey,
+          match: '<',
+          type: 'text',
+          value: _endval
+        })
+      } else if (item.type === 'range') {
+        let val = item.value.split(',')
+
+        searchText.push({
+          key: item.key,
+          match: '>=',
+          type: 'text',
+          value: val[0] || -999999999
+        }, {
+          key: item.key,
+          match: '<=',
+          type: 'text',
+          value: val[1] || 999999999
+        })
+      } else {
+        searchText.push(cell)
+      }
+    })
+
+    searchText.forEach(item => {
+      item.match = matchs[item.match] || '01'
+    })
+
+    return searchText
+  }
+
   /**
    * @description 鑾峰彇鎼滅储鐢ㄤ簬姝e垯鏇挎崲
    * @param {Array}   searches     鎼滅储鏉′欢
@@ -916,6 +1072,7 @@
     sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
     sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
     sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+    sql = sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
 
     return {
       sql: sql,
@@ -1094,6 +1251,7 @@
       {reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
       {reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
       {reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      {reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
       {reg: /@typename@/ig, value: `'admin'`},
       {reg: /\$@/ig, value: isDM ? '/*' : ''},
       {reg: /@\$/ig, value: isDM ? '*/' : ''},
@@ -1338,8 +1496,8 @@
     sql = sql.replace(/\n\s{6}/ig, '\n')
 
     if (window.GLOB.debugger === true) {
-      console.info('%c' + item.logLabel, 'color: blue')
-      console.info(sql)
+      window.mkInfo('%c' + item.logLabel, 'color: blue')
+      window.mkInfo(sql)
     }
   } else {
     for(let i = 0; i < _Ltext.length; i += 20) {
@@ -1425,6 +1583,7 @@
       {reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
       {reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
       {reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      {reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
       {reg: /@typename@/ig, value: `'admin'`},
       {reg: /\$@/ig, value: isDM ? '/*' : ''},
       {reg: /@\$/ig, value: isDM ? '*/' : ''},
@@ -1582,8 +1741,8 @@
     sql = sql.replace(/\n\s{6}/ig, '\n')
 
     if (window.GLOB.debugger === true) {
-      console.info('%c' + btn.logLabel, 'color: blue')
-      console.info(sql)
+      window.mkInfo('%c' + btn.logLabel, 'color: blue')
+      window.mkInfo(sql)
     }
   } else {
     for(let i = 0; i < _Ltext.length; i += 20) {
@@ -1612,7 +1771,7 @@
  * @return {Array}   columns   鏄剧ず鍒�
  * @return {Boolean} retmsg    鏄惁闇�瑕佹暟鎹繑鍥�
  */
-export function getSysDefaultSql (btn, setting, formdata, param, data, columns, retmsg = false, moduleParams) {
+export function getSysDefaultSql (btn, setting, formdata, param, data, columns, retmsg = false) {
   let primaryId = param.ID
   let BID = param.BID || ''
   let verify = btn.verify || {}
@@ -1861,9 +2020,31 @@
   }
 
   // 澶辨晥楠岃瘉锛屾坊鍔犳暟鎹椂涓嶇敤
-  if (verify.invalid === 'true' && moduleParams && moduleParams.dataresource) {
-    let datasource = moduleParams.dataresource
-    let customScript = moduleParams.customScript || ''
+  if (verify.invalid === 'true' && setting.dataresource) {
+    let datasource = setting.dataresource
+    let customScript = setting.customScript || ''
+
+    let regoptions = [{
+      reg: new RegExp('@userName@', 'ig'),
+      value: `'${sessionStorage.getItem('User_Name') || ''}'`
+    }, {
+      reg: new RegExp('@fullName@', 'ig'),
+      value: `'${sessionStorage.getItem('Full_Name') || ''}'`
+    }, {
+      reg: new RegExp('@orderBy@', 'ig'),
+      value: setting.order || primaryKey
+    }, {
+      reg: new RegExp('@pageSize@', 'ig'),
+      value: 1
+    }, {
+      reg: new RegExp('@pageIndex@', 'ig'),
+      value: 1
+    }]
+
+    regoptions.forEach(item => {
+      datasource = datasource.replace(item.reg, item.value)
+      customScript = customScript.replace(item.reg, item.value)
+    })
 
     if (customScript) {
       _sql += `
@@ -1938,7 +2119,6 @@
 
       if (!keys.includes(_key)) return // 琛ㄥ崟涓笉鍚崟鍙风敓鎴愬瓧娈�
 
-      let _ModularDetailCode = ''
       let _lpline = ''
       if (item.TypeCharOne === 'Lp') {
         if (_linkKey === 'bid' && BID) { // 鏇挎崲bid
@@ -1946,33 +2126,29 @@
         } else {
           _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@${_linkKey},48)`
         }
-        _ModularDetailCode = '@ModularDetailCode'
       } else if (item.TypeCharOne === 'BN') {
-        let _val = ''
         if (_linkKey === 'bid' && BID) { // 鏇挎崲bid
-          _val = BID
-        } else if (_data.hasOwnProperty(_linkKey)) {
-          _val = _data[_linkKey]
+          _lpline = `set @ModularDetailCode= 'BN'+ right(@BID@,48)`
+        } else {
+          _lpline = `set @ModularDetailCode= 'BN'+ right(@${_linkKey},48)`
         }
-        _ModularDetailCode = `'${item.TypeCharOne + _val}'`
       } else {
-        _ModularDetailCode = `'${item.ModularDetailCode}'`
+        _lpline = `set @ModularDetailCode= right('${item.ModularDetailCode}',50)`
       }
 
-      let _declare = ''
+      // let _declare = ''
 
-      if (!_vars.includes(_key)) {
-        _declare = `Declare @${_key} nvarchar(50)`
-        _vars.push(_key)
-      }
+      // if (!_vars.includes(_key)) {
+      //   _declare = `Declare @${_key} nvarchar(50)`
+      //   _vars.push(_key)
+      // }
 
       _billcodesSql += `
       /* 鍗曞彿鐢熸垚 */
-      ${_declare}
       select @BillCode='', @${_key}='', @ModularDetailCode=''
       ${_lpline}
       exec s_get_BillCode
-        @ModularDetailCode=${_ModularDetailCode},
+        @ModularDetailCode=@ModularDetailCode,
         @Type=${item.Type},
         @TypeCharOne='${item.TypeCharOne}',
         @TypeCharTwo ='${item.TypeCharTwo}',
@@ -2011,11 +2187,6 @@
         _value.push(`${_labels[index] || ''}锛�${_val || ''}`)
       })
 
-      let _verifyType = ''
-      if (item.verifyType === 'logic') {
-        _verifyType = ' and deleted=0'
-      }
-
       if (!arr.includes(primaryKey.toLowerCase())) {
         _fieldValue.push(`${primaryKey} !='${primaryId}'`)
       }
@@ -2023,7 +2194,7 @@
       _sql += `
       /* 鍞竴鎬ч獙璇� */
       select @tbid='', @ErrorCode='',@retmsg=''
-      select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')}${_verifyType}
+      select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')}${item.verifyType === 'logic' ? ' and deleted=0' : ''}
       If @tbid!=''
       Begin
         select @ErrorCode='${item.errorCode}',@retmsg='${_value.join(', ')} 宸插瓨鍦�'
@@ -2230,7 +2401,7 @@
     if (data && columns && columns.length > 0 && btn.Ot !== 'notRequired') {
       let _index = 0
       columns.forEach(col => {
-        if (!col.field || col.Hide === 'true' || _index >= 4) return
+        if (!col.field || col.Hide === 'true' || _index >= 4 || col.field === primaryKey) return
         _msg += col.label + '=' + data[col.field] + ','
         _index++
       })
@@ -2563,15 +2734,29 @@
       begin
           select @retmsg='X' from s_my_works_flow_role where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and userid=@userid@
 
-          if @retmsg !='' 
+          if @retmsg !=''
           begin
               select @ErrorCode='E', @retmsg='褰撳墠鍗曟嵁宸插鏍革紝璇峰埛鏂板悗閲嶈瘯'
-            goto aaa 
+            goto aaa
+          end
+
+          if @dataM@ !='' 
+          begin
+            set @retmsg =''
+            select @retmsg='X' from s_my_works_flow_role where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0  
+
+            if @retmsg != ''
+            begin
+                goto goto_mk
+            end
           end
 
           select @retmsg='椤甸潰鏁版嵁宸叉洿鏂帮紝鎴栨病鏈夊綋鍓嶅崟鎹殑瀹℃壒鏉冮檺'
             goto aaa 
-      end
+      end 
+
+      goto_mk:
+
       set @retmsg=''
 
       update s_my_works_flow set status=@status@,statusname=@statusname@,works_flow_param=@works_flow_param@,works_flow_detail_id=@works_flow_detail_id@,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname${verify.flowRemark ? ',remark=@' + verify.flowRemark : ''}
@@ -2610,14 +2795,17 @@
       _sql += _backCustomScript
     }
 
-    _sql = _sql.replace(/@works_flow_sign@/ig, `'${sign}'`)
+    if (verify.flowType === 'start') {
+      _sql = _sql.replace(/@start_type@/ig, `'寮�濮�'`)
+    } else {
+      _sql = _sql.replace(/@works_flow_sign@/ig, `'${sign}'`)
 
-    _sql = _sql.replace(/@check_userids@/ig, `'${checkIds.join(',')}'`)
-    _sql = _sql.replace(/@notice_userids@/ig, `'${noticeIds.join(',')}'`)
+      _sql = _sql.replace(/@check_type@/ig, verify.flowType === 'reject' ? `'椹冲洖'` : `'瀹℃牳'`)
+      _sql = _sql.replace(/@notice_type@/ig, `'鎶勯��'`)
 
-    _sql = _sql.replace(/@start_type@/ig, `'寮�濮�'`)
-    _sql = _sql.replace(/@check_type@/ig, verify.flowType === 'reject' ? `'椹冲洖'` : `'瀹℃牳'`)
-    _sql = _sql.replace(/@notice_type@/ig, `'鎶勯��'`)
+      _sql = _sql.replace(/@check_userids@/ig, `'${checkIds.join(',')}'`)
+      _sql = _sql.replace(/@notice_userids@/ig, `'${noticeIds.join(',')}'`)
+    }
 
     _sql = _sql.replace(/@works_flow_code@/ig, `'${flow.flow_code}'`)
     _sql = _sql.replace(/@works_flow_name@/ig, `'${flow.flow_name}'`)
@@ -2670,6 +2858,7 @@
   _sql = _sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
   _sql = _sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
   _sql = _sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+  _sql = _sql.replace(/@lang@/ig, `'${sessionStorage.getItem('lang')}'`)
   _sql = _sql.replace(/@typename@/ig, `'admin'`)
 
   if (window.GLOB.externalDatabase !== null) {
@@ -2683,8 +2872,8 @@
   }
 
   if (window.GLOB.debugger === true) {
-    console.info('%c' + btn.logLabel, 'color: blue')
-    console.info(_sql)
+    window.mkInfo('%c' + btn.logLabel, 'color: blue')
+    window.mkInfo(_sql)
   }
 
   if (retmsg) {
@@ -2781,23 +2970,23 @@
 /**
  * @description 鐢熸垚鏇挎崲鍑芥暟鍒楄〃
  */
-export function setGLOBFuncs () {
-  window.GLOB.funcs = []
-  if (!window.GLOB.IndexDB) {
-    return
-  }
+// export function setGLOBFuncs () {
+//   window.GLOB.funcs = []
+//   if (!window.GLOB.IndexDB) {
+//     return
+//   }
 
-  let objectStore = window.GLOB.IndexDB.transaction('funcs').objectStore('funcs')
+//   let objectStore = window.GLOB.IndexDB.transaction('funcs').objectStore('funcs')
 
-  objectStore.openCursor().onsuccess = (event) => {
-    let cursor = event.target.result
+//   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()
-    }
-  }
-}
\ No newline at end of file
+//     if (cursor) {
+//       window.GLOB.funcs.push({
+//         func_code: cursor.value.func_code,
+//         key_sql: window.decodeURIComponent(window.atob(cursor.value.key_sql))
+//       })
+//       cursor.continue()
+//     }
+//   }
+// }
\ No newline at end of file
diff --git a/src/views/appcheck/index.jsx b/src/views/appcheck/index.jsx
index 49c4d5b..0351a5a 100644
--- a/src/views/appcheck/index.jsx
+++ b/src/views/appcheck/index.jsx
@@ -1,16 +1,14 @@
 import React, {Component} from 'react'
-import { Spin, notification, Table, ConfigProvider, Typography, Row, Col, Tooltip } from 'antd'
+import { Spin, notification, Table, Typography, Row, Col, Tooltip } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
-import enUS from 'antd/es/locale/en_US'
-import zhCN from 'antd/es/locale/zh_CN'
 
 import Api from '@/api'
+import { langs } from '@/store/options.js'
 import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
 const { Paragraph } = Typography
 
-const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 const Header = asyncComponent(() => import('./header'))
 
 const skinStyle = {
@@ -86,6 +84,10 @@
               }
               cell.copyright = _param.copyright || ''
               cell.logo = _param.logo || ''
+              cell.wxAppId = _param.wxAppId || ''
+              cell.wxAppName = _param.wxAppName || ''
+              cell.wxMerchId = _param.wxMerchId || ''
+              cell.wxMerchName = _param.wxMerchName || ''
             }
 
             return cell
@@ -139,116 +141,118 @@
 
     return (
       <div className="mk-app-check">
-        <ConfigProvider locale={_locale}>
-          <Header view="manage" />
-          {loading ?
-            <div className="loading-mask">
-              <Spin size="large" />
-            </div> : null
-          }
-          <div className="view-wrap">
-            <div className="left-view">
-              <div className="app-table">
-                <Table
-                  rowKey="ID"
-                  columns={columns}
-                  dataSource={applist}
-                  pagination={false}
-                  rowSelection={{ type: 'radio', selectedRowKeys: selectApp ? [selectApp.ID] : [], onChange: this.onSelectChange }}
-                  onRow={(record) => ({ onClick: () => this.setState({ selectApp: record })})}
-                />
-              </div>
-            </div>
-            <div className="right-view">
-              {selectApp ? <div className="app-title">{selectApp.remark}</div> : null}
-              {selectApp && selectApp.sublist.map((item, index) => {
-                let css = skinStyle[item.css] ? skinStyle[item.css].name : ''
-                let color = skinStyle[item.css] ? skinStyle[item.css].color : '#e8e8e8'
-                let binding = ''
-                if (item.user_binding) {
-                  if (item.user_binding.indexOf('uname_pwd') > -1) {
-                    binding = '鐢ㄦ埛鍚�'
-                  }
-                  if (item.user_binding.indexOf('sms_vcode') > -1) {
-                    binding = binding ? binding + '锛屾墜鏈哄彿' : '鎵嬫満鍙�'
-                  }
-                }
-                return (
-                  <div className="sub-app" key={index} style={{borderColor: color}}>
-                    <Row>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">搴旂敤绫诲瀷:</div>
-                          <div className="content" style={{fontSize: '18px', fontWeight: 600}}>{item.typename}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">璇█:</div>
-                          <div className="content" style={{textDecoration: 'underline'}}>{item.lang === 'en-US' ? '鑻辨枃' : '涓枃'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鏉冮檺绠$悊:</div>
-                          <div className="content">{item.role_type === 'false' ? '涓嶅惎鐢�' : '鍚敤'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鐨偆:</div>
-                          <div className="content" style={{color: color}}>{css}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          {binding ? <div className="label">
-                            <Tooltip placement="topLeft" title="寰俊鍏紬鍙风櫥褰曟椂锛岀郴缁熺敤鎴蜂笌寰俊鐢ㄦ埛鐨勭粦瀹氭柟寮忋��">
-                              <QuestionCircleOutlined className="mk-form-tip" />
-                              鐢ㄦ埛缁戝畾:
-                            </Tooltip>
-                          </div> : null}
-                          <div className="content">{binding}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鏍囬:</div>
-                          <div className="content">{item.title || '鏃�'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">缃戠珯澶村儚:</div>
-                          <div className="content">{item.favicon ? <img style={{width: '18px', height: '18px'}} src={item.favicon} alt="" /> : '鏃�'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鐗堟潈:</div>
-                          <div className="content">{item.copyright || '鏃�'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">LOGO:</div>
-                          <div className="content">{item.logo ? <img style={{height: '18px'}} src={item.logo} alt="" /> : '鏃�'}</div>
-                        </div>
-                      </Col>
-                    </Row>
-                    <div className="action">
-                      <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}` }}></Paragraph>
-                    </div>
-                  </div>
-                )
-              })}
+        <Header view="manage" />
+        {loading ?
+          <div className="loading-mask">
+            <Spin size="large" />
+          </div> : null
+        }
+        <div className="view-wrap">
+          <div className="left-view">
+            <div className="app-table">
+              <Table
+                rowKey="ID"
+                columns={columns}
+                dataSource={applist}
+                pagination={false}
+                rowSelection={{ type: 'radio', selectedRowKeys: selectApp ? [selectApp.ID] : [], onChange: this.onSelectChange }}
+                onRow={(record) => ({ onClick: () => this.setState({ selectApp: record })})}
+              />
             </div>
           </div>
-        </ConfigProvider>
+          <div className="right-view">
+            {selectApp ? <div className="app-title">{selectApp.remark}</div> : null}
+            {selectApp && selectApp.sublist.map((item, index) => {
+              let css = skinStyle[item.css] ? skinStyle[item.css].name : ''
+              let color = skinStyle[item.css] ? skinStyle[item.css].color : '#e8e8e8'
+              let binding = ''
+              if (item.user_binding) {
+                if (item.user_binding.indexOf('uname_pwd') > -1) {
+                  binding = '鐢ㄦ埛鍚�'
+                }
+                if (item.user_binding.indexOf('sms_vcode') > -1) {
+                  binding = binding ? binding + '锛屾墜鏈哄彿' : '鎵嬫満鍙�'
+                }
+              }
+              return (
+                <div className="sub-app" key={index} style={{borderColor: color}}>
+                  <Row>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">搴旂敤绫诲瀷:</div>
+                        <div className="content" style={{fontSize: '18px', fontWeight: 600}}>{item.typename}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">璇█:</div>
+                        <div className="content" style={{textDecoration: 'underline'}}>{langs[item.lang]}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">鏉冮檺绠$悊:</div>
+                        <div className="content">{item.role_type === 'false' ? '涓嶅惎鐢�' : '鍚敤'}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        {item.wxAppName || item.wxMerchName ? <>
+                          <div className="label">鍏宠仈搴旂敤:</div>
+                          <div className="content">{`${item.wxAppName}${item.wxAppName && item.wxMerchName ? ' / ' + item.wxMerchName : item.wxMerchName || ''}`}</div>
+                        </> : null}
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">鐨偆:</div>
+                        <div className="content" style={{color: color}}>{css}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        {binding ? <div className="label">
+                          <Tooltip placement="topLeft" title="寰俊鍏紬鍙风櫥褰曟椂锛岀郴缁熺敤鎴蜂笌寰俊鐢ㄦ埛鐨勭粦瀹氭柟寮忋��">
+                            <QuestionCircleOutlined className="mk-form-tip" />
+                            鐢ㄦ埛缁戝畾:
+                          </Tooltip>
+                        </div> : null}
+                        <div className="content">{binding}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">鏍囬:</div>
+                        <div className="content">{item.title || '鏃�'}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">缃戠珯澶村儚:</div>
+                        <div className="content">{item.favicon ? <img style={{width: '18px', height: '18px'}} src={item.favicon} alt="" /> : '鏃�'}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">鐗堟潈:</div>
+                        <div className="content">{item.copyright || '鏃�'}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">LOGO:</div>
+                        <div className="content">{item.logo ? <img style={{height: '18px'}} src={item.logo} alt="" /> : '鏃�'}</div>
+                      </div>
+                    </Col>
+                  </Row>
+                  <div className="action">
+                    <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}${item.wxAppId ? '/' + item.wxAppId : ''}` }}></Paragraph>
+                  </div>
+                </div>
+              )
+            })}
+          </div>
+        </div>
       </div>
     )
   }
diff --git a/src/views/appmanage/index.jsx b/src/views/appmanage/index.jsx
index c2d907c..c352ad1 100644
--- a/src/views/appmanage/index.jsx
+++ b/src/views/appmanage/index.jsx
@@ -1,14 +1,13 @@
 import React, {Component} from 'react'
 import { fromJS } from 'immutable'
-import { Spin, notification, Input, Button, Table, Modal, ConfigProvider, Typography, Row, Col, Tooltip } from 'antd'
+import { Spin, notification, Input, Button, Table, Modal, Typography, Row, Col, Tooltip } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import md5 from 'md5'
-import enUS from 'antd/es/locale/en_US'
-import zhCN from 'antd/es/locale/zh_CN'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
+import { langs } from '@/store/options.js'
 import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
@@ -16,12 +15,12 @@
 const { Paragraph } = Typography
 const { Search } = Input
 
-const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 const Header = asyncComponent(() => import('./header'))
 const MutilForm = asyncComponent(() => import('./mutilform'))
 const TransForm = asyncComponent(() => import('./transform'))
 const ScriptForm = asyncComponent(() => import('./scriptform'))
 const SubMutilForm = asyncComponent(() => import('./submutilform'))
+const TransMenu = asyncComponent(() => import('./transmenu'))
 
 const skinStyle = {
   bg_black_style_blue: {name: '钃濊壊', color: '#1890ff'},
@@ -378,7 +377,7 @@
   }
 
   deleteTran = (record) => {
-    const _this = this
+    const that = this
 
     let param = {
       func: 's_sVersion_del',
@@ -396,7 +395,7 @@
                 message: '鎿嶄綔鎴愬姛锛�',
                 duration: 3
               })
-              _this.getTransList()
+              that.getTransList()
             } else {
               notification.warning({
                 top: 92,
@@ -415,7 +414,7 @@
   }
 
   enableTran = (record) => {
-    const _this = this
+    const that = this
 
     let param = {
       func: 's_sVersion_sub',
@@ -433,7 +432,7 @@
                 message: '鎿嶄綔鎴愬姛锛�',
                 duration: 3
               })
-              _this.getTransList()
+              that.getTransList()
             } else {
               Modal.error({
                 title: result.message,
@@ -486,6 +485,10 @@
               cell.share_des = _param.share_des || '' // 鍒嗕韩鎻忚堪
               cell.share_url = _param.share_url || '' // 鍒嗕韩鍥剧墖
               cell.share_link = _param.share_link || '' // 鍒嗕韩閾炬帴
+              cell.wxAppId = _param.wxAppId || ''
+              cell.wxAppName = _param.wxAppName || ''
+              cell.wxMerchId = _param.wxMerchId || ''
+              cell.wxMerchName = _param.wxMerchName || ''
 
               if (cell.adapter && (cell.adapter === 'true' || cell.adapter === 'false')) {
                 cell.adapter = ''
@@ -517,8 +520,7 @@
         })
 
         if (!selectApp && applist[0]) {
-          let _href = window.location.href.split('#')[0] + 'app_record'
-          let record = localStorage.getItem(_href)
+          let record = localStorage.getItem(window.GLOB.sysSign + 'app_record')
           record = record ? JSON.parse(record) : null
 
           if (record && record.dates) {
@@ -537,7 +539,7 @@
             })
 
             if (reset) {
-              localStorage.setItem(_href, JSON.stringify(record))
+              localStorage.setItem(window.GLOB.sysSign + 'app_record', JSON.stringify(record))
             }
           }
         }
@@ -599,7 +601,7 @@
   }
 
   deleteApp = (record) => {
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾鍒犻櫎銆�' + record.remark + '銆嬪悧锛�',
@@ -619,12 +621,12 @@
                 duration: 5
               })
 
-              _this.setState({
+              that.setState({
                 selectApp: null,
                 selectSubApp: null,
                 loading: true
               })
-              _this.getAppList()
+              that.getAppList()
             } else {
               if (result.message.indexOf('kei_no宸茶鑿滃崟浣跨敤锛屼笉鍙垹闄�') > -1) {
                 result.message = 'kei_no宸茶鑿滃崟浣跨敤锛屼笉鍙垹闄�'
@@ -647,7 +649,7 @@
   
   deleteSubApp = (record) => {
     const { selectApp } = this.state
-    const _this = this
+    const that = this
 
     let param = {
       func: 's_kei_addupt',
@@ -674,7 +676,11 @@
     })
 
     // 瀛愬簲鐢↖D銆乼ypename銆佸簲鐢↖D銆丆loudUserID銆乤ppkey銆乴ogin_types(鏄惁闇�瑕佺櫥褰曪紝宸插純鐢�)銆乴ink_type(鏄惁浣跨敤鐭繛鎺ワ紝宸插純鐢�)銆乺ole_type(鏄惁浣跨敤瑙掕壊绠$悊)銆乴ang銆乧ss(鐨偆)銆乼itle(鏍囬)銆乫avicon(鍥炬爣)銆乽ser_binding(鐢ㄦ埛缁戝畾)銆乻ms_id(鐭俊妯℃澘ID)銆佽嚜瀹氫箟
-    param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', topHeight: item.topHeight || '', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
+    param.LText = sublist.map(item => {
+      let _par = this.getCusParam(item)
+
+      return `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify(_par)))}'`
+    })
     param.LText = param.LText.join(' union all ')
     param.LText = Utils.formatOptions(param.LText, 'x')
     
@@ -690,11 +696,11 @@
                 duration: 5
               })
       
-              _this.setState({
+              that.setState({
                 selectSubApp: null,
                 loading: true
               })
-              _this.getAppList()
+              that.getAppList()
             } else {
               notification.warning({
                 top: 92,
@@ -715,17 +721,16 @@
   jumpApp = (item) => {
     const { selectApp } = this.state
 
-    let _href = window.location.href.split('#')[0] + 'app_record'
-    let record = localStorage.getItem(_href)
+    let record = localStorage.getItem(window.GLOB.sysSign + 'app_record')
     record = record ? JSON.parse(record) : null
 
     if (!record || !record.dates) {
-      localStorage.setItem(_href, JSON.stringify({preId: selectApp.ID, activeId: selectApp.ID, dates: {[selectApp.ID]: new Date().getTime()}}))
+      localStorage.setItem(window.GLOB.sysSign + 'app_record', JSON.stringify({preId: selectApp.ID, activeId: selectApp.ID, dates: {[selectApp.ID]: new Date().getTime()}}))
     } else {
       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()}}))
+        localStorage.setItem(window.GLOB.sysSign + 'app_record', 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}))
+        localStorage.setItem(window.GLOB.sysSign + 'app_record', JSON.stringify({...record, preId: selectApp.ID}))
       }
     }
 
@@ -733,7 +738,23 @@
     if (item.typename === 'pc') {
       route = 'pcdesign'
     }
-    let param = {...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'}
+
+    let applangList = []
+    if (item.lang === 'zh-CN') {
+      selectApp.sublist.forEach(cell => {
+        if (cell.typename === item.typename && cell.lang !== 'zh-CN') {
+          applangList.push(cell.lang)
+        }
+      })
+    }
+    if (applangList.length) {
+      applangList.unshift('zh-CN')
+      applangList = JSON.stringify(applangList)
+    } else {
+      applangList = ''
+    }
+
+    let param = {...item, kei_no: selectApp.kei_no, remark: selectApp.remark, applangList, type: 'app'}
 
     window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify(param)))}`))
   }
@@ -741,7 +762,22 @@
   jumpMenu = (item) => {
     const { selectApp } = this.state
 
-    window.open(window.location.href.replace(/#.+/ig, `#/role/${window.btoa(window.encodeURIComponent(JSON.stringify({...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'})))}`))
+    let applangList = []
+    if (item.lang === 'zh-CN') {
+      selectApp.sublist.forEach(cell => {
+        if (cell.typename === item.typename && cell.lang !== 'zh-CN') {
+          applangList.push(cell.lang)
+        }
+      })
+    }
+    if (applangList.length) {
+      applangList.unshift('zh-CN')
+      applangList = JSON.stringify(applangList)
+    } else {
+      applangList = ''
+    }
+
+    window.open(window.location.href.replace(/#.+/ig, `#/role/${window.btoa(window.encodeURIComponent(JSON.stringify({...item, kei_no: selectApp.kei_no, remark: selectApp.remark, applangList, type: 'app'})))}`))
   }
 
   onSelectChange = selectedRowKeys => {
@@ -785,7 +821,7 @@
       }
     })
 
-    const _this = this
+    const that = this
 
     confirm({
       content: '纭畾瑕佹墽琛屽悧锛�',
@@ -821,10 +857,10 @@
                 message: '鎵ц鎴愬姛銆�',
                 duration: 3
               })
-              _this.setState({
+              that.setState({
                 scriptIndex: 1
               }, () => {
-                _this.getScriptList()
+                that.getScriptList()
               })
             }
             resolve()
@@ -876,10 +912,10 @@
         ID = selectApp.ID
       } else {
         let lowerKei = res.kei_no.toLowerCase()
-        if (lowerKei === 'mob') {
+        if (['mob', 'pad', 'pc', 'admin'].includes(lowerKei)) {
           notification.warning({
             top: 92,
-            message: '搴旂敤缂栫爜涓嶅厑璁镐娇鐢╩ob锛�',
+            message: '搴旂敤缂栫爜涓嶅厑璁镐娇鐢╩ob銆乸ad銆乸c銆乤dmin锛�',
             duration: 3
           })
           return
@@ -920,7 +956,11 @@
           return item
         })
 
-        param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', topHeight: item.topHeight || '', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
+        param.LText = selectApp.sublist.map(item => {
+          let _par = this.getCusParam(item)
+    
+          return `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify(_par)))}'`
+        })
         param.LText = param.LText.join(' union all ')
         param.LText = Utils.formatOptions(param.LText, 'x')
       }
@@ -957,6 +997,56 @@
         })
       })
     })
+  }
+
+  getCusParam = (item) => {
+    let _par = {
+      sysBgColor: item.sysBgColor || '#ffffff'
+    }
+    if (item.userbind) {
+      _par.userbind = item.userbind
+    }
+    if (item.instantMessage) {
+      _par.instantMessage = item.instantMessage
+    }
+    if (item.apptype) {
+      _par.apptype = item.apptype
+    }
+    if (item.topHeight) {
+      _par.topHeight = item.topHeight
+    }
+    if (item.typename === 'pad') {
+      _par.direction = item.direction || 'vertical'
+    }
+    if (item.typename !== 'pc') {
+      _par.statusBarColor = item.statusBarColor || 'black'
+      _par.delay = item.delay || 0
+    }
+    if (item.adapter) {
+      _par.adapter = item.adapter
+    }
+    if (item.share) {
+      _par.share = item.share
+    }
+    if (item.share_des) {
+      _par.share_des = item.share_des
+    }
+    if (item.share_url) {
+      _par.share_url = item.share_url
+    }
+    if (item.share_link) {
+      _par.share_link = item.share_link
+    }
+    if (item.wxAppId) {
+      _par.wxAppId = item.wxAppId
+      _par.wxAppName = item.wxAppName || item.wxAppId
+    }
+    if (item.wxMerchId) {
+      _par.wxMerchId = item.wxMerchId
+      _par.wxMerchName = item.wxMerchName || item.wxMerchId
+    }
+
+    return _par
   }
 
   submitSubCard = () => {
@@ -1013,7 +1103,11 @@
         return item
       })
 
-      param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', topHeight: item.topHeight || '', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
+      param.LText = sublist.map(item => {
+        let _par = this.getCusParam(item)
+
+        return `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify(_par)))}'`
+      })
       param.LText = param.LText.join(' union all ')
       param.LText = Utils.formatOptions(param.LText, 'x')
 
@@ -1055,221 +1149,222 @@
 
     return (
       <div className="mk-app-manage">
-        <ConfigProvider locale={_locale}>
-          <Header view="manage" />
-          {loading ?
-            <div className="loading-mask">
-              <Spin size="large" />
-            </div> : null
-          }
-          <div className="view-wrap">
-            <div className="left-view">
-              <div className="app-table">
-                <div className="app-action">
-                  <Button className="mk-green" onClick={() => this.setState({ visible: 'plus' })}>娣诲姞搴旂敤</Button>
-                </div>
-                <Table
-                  rowKey="ID"
-                  columns={columns}
-                  dataSource={applist}
-                  pagination={false}
-                  rowSelection={{ type: 'radio', selectedRowKeys: selectApp ? [selectApp.ID] : [], onChange: this.onSelectChange }}
-                  onRow={(record) => ({ onClick: () => this.setState({ selectApp: record })})}
-                />
+        <Header view="manage" />
+        {loading ?
+          <div className="loading-mask">
+            <Spin size="large" />
+          </div> : null
+        }
+        <div className="view-wrap">
+          <div className="left-view">
+            <div className="app-table">
+              <div className="app-action">
+                <Button className="mk-green" onClick={() => this.setState({ visible: 'plus' })}>娣诲姞搴旂敤</Button>
               </div>
-              <div className={'trans-table' + (this.state.transTotal <= 10 ? ' no-footer' : '')}>
-                <div className="app-action">
-                  <Button className="mk-green" onClick={() => this.setState({ transVisible: 'plus' })}>娣诲姞浼犺緭鍙�</Button>
-                  <Search placeholder="缁煎悎鎼滅储" onSearch={value => this.tranSearch(value)} enterButton />
-                </div>
-                <Table
-                  rowKey="ID"
-                  columns={transcolumns}
-                  dataSource={translist}
-                  pagination={{
-                    current: this.state.transIndex,
-                    pageSize: 10,
-                    total: this.state.transTotal || 0,
-                    showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
-                  }}
-                  rowSelection={{ type: 'radio', selectedRowKeys: selectTran ? [selectTran.ID] : [], onChange: this.onTransChange }}
-                  onRow={(record) => ({ onClick: () => {
-                    if (this.forbid) {
-                      this.forbid = false
-                      return
-                    }
-                    this.onTransSelect(record)
-                  }})}
-                  onChange={this.changeTable}
-                />
+              <Table
+                rowKey="ID"
+                columns={columns}
+                dataSource={applist}
+                pagination={false}
+                rowSelection={{ type: 'radio', selectedRowKeys: selectApp ? [selectApp.ID] : [], onChange: this.onSelectChange }}
+                onRow={(record) => ({ onClick: () => this.setState({ selectApp: record })})}
+              />
+            </div>
+            <div className={'trans-table' + (this.state.transTotal <= 10 ? ' no-footer' : '')}>
+              <div className="app-action">
+                <Button className="mk-green" onClick={() => this.setState({ transVisible: 'plus' })}>娣诲姞浼犺緭鍙�</Button>
+                <Search placeholder="缁煎悎鎼滅储" onSearch={value => this.tranSearch(value)} enterButton />
               </div>
-              {selectTran ? <div className="script-table">
-                <div className="app-action">
-                  <Button className="mk-green" onClick={() => this.setState({ scriptVisible: true })}>娣诲姞鑴氭湰</Button>
-                  <Button className="mk-danger" onClick={this.deleteScripts} style={{marginLeft: '15px'}}>鍒犻櫎</Button>
-                  <Search placeholder="缁煎悎鎼滅储" defaultValue={this.state.scriptSearchKey} onSearch={value => this.scriptSearch(value)} enterButton />
-                </div>
-                <Table
-                  rowKey="ID"
-                  columns={scriptcolumns}
-                  dataSource={scriptlist}
-                  pagination={{
-                    current: this.state.scriptIndex,
-                    pageSize: 10,
-                    total: this.state.scriptTotal || 0,
-                    showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
-                  }}
-                  rowSelection={{ type: 'checkbox', selectedRowKeys: selectScriptKeys, onChange: this.onScriptChange }}
-                  onRow={(record) => ({ onClick: () => this.onScriptSelect(record)})}
-                  onChange={this.changeScriptTable}
-                />
-              </div> : null}
+              <Table
+                rowKey="ID"
+                columns={transcolumns}
+                dataSource={translist}
+                pagination={{
+                  current: this.state.transIndex,
+                  pageSize: 10,
+                  total: this.state.transTotal || 0,
+                  showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
+                }}
+                rowSelection={{ type: 'radio', selectedRowKeys: selectTran ? [selectTran.ID] : [], onChange: this.onTransChange }}
+                onRow={(record) => ({ onClick: () => {
+                  if (this.forbid) {
+                    this.forbid = false
+                    return
+                  }
+                  this.onTransSelect(record)
+                }})}
+                onChange={this.changeTable}
+              />
             </div>
-            <div className="right-view">
-              {selectApp ? <div className="app-title">{selectApp.remark}</div> : null}
-              {selectApp && selectApp.sublist.map((item, index) => {
-                let css = skinStyle[item.css] ? skinStyle[item.css].name : ''
-                let color = skinStyle[item.css] ? skinStyle[item.css].color : '#e8e8e8'
-                let binding = ''
-                if (item.user_binding === 'true') {
-                  binding = '鐢ㄦ埛缁戝畾'
-                }
-                if (item.share === 'true') {
-                  binding = binding ? binding + '銆佸垎浜�' : '鍒嗕韩'
-                }
-
-                return (
-                  <div className="sub-app" key={index} style={{borderColor: color}}>
-                    <Row>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">搴旂敤绫诲瀷:</div>
-                          <div className="content" style={{fontSize: '18px', fontWeight: 600}}>{item.typename}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">璇█:</div>
-                          <div className="content" style={{textDecoration: 'underline'}}>{item.lang === 'en-US' ? '鑻辨枃' : '涓枃'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鏉冮檺绠$悊:</div>
-                          <div className="content">{item.role_type === 'false' ? '涓嶅惎鐢�' : '鍚敤'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          {/* <div className="label">鐨偆:</div>
-                          <div className="content" style={{color: color}}>{css}</div> */}
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鐨偆:</div>
-                          <div className="content" style={{color: color}}>{css}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          {/* {binding ? <div className="label">
-                            <Tooltip placement="topLeft" title="寰俊鍏紬鍙风櫥褰曟椂锛岀郴缁熺敤鎴蜂笌寰俊鐢ㄦ埛鐨勭粦瀹氭柟寮忋��">
-                              <QuestionCircleOutlined className="mk-form-tip" />
-                              鐢ㄦ埛缁戝畾:
-                            </Tooltip>
-                          </div> : null} */}
-                          {binding ? <div className="label">
-                            <Tooltip placement="topLeft" title="寰俊鍏紬鍙锋垨灏忕▼搴忎腑锛岀粦瀹氱郴缁熺敤鎴枫�佽嚜瀹氫箟鍒嗕韩绛夊姛鑳姐��">
-                              <QuestionCircleOutlined className="mk-form-tip" />
-                              鎵╁睍鍔熻兘:
-                            </Tooltip>
-                          </div> : null}
-                          <div className="content">{binding}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鏍囬:</div>
-                          <div className="content">{item.title || '鏃�'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">缃戠珯澶村儚:</div>
-                          <div className="content">{item.favicon ? <img style={{width: '18px', height: '18px', borderRadius: '4px'}} src={item.favicon} alt="" /> : '鏃�'}</div>
-                        </div>
-                      </Col>
-                    </Row>
-                    <div className="action">
-                      <Button type="link" onClick={() => this.jumpMenu(item)} style={{color: 'rgba(30, 228, 224, 1)'}}>鑿滃崟&鏉冮檺</Button>
-                      <Button type="link" onClick={() => this.setState({ selectSubApp: item, subVisible: 'edit' })} style={{color: '#8E44AD'}}>淇敼</Button>
-                      <Button type="link" onClick={() => this.deleteSubApp(item)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button>
-                      <Button type="link" onClick={() => this.jumpApp(item)}>缂栬緫搴旂敤</Button>
-                      <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}` }}></Paragraph>
-                    </div>
-                  </div>
-                )
-              })}
-            </div>
+            {selectTran ? <div className="script-table">
+              <div className="app-action">
+                <Button className="mk-green" onClick={() => this.setState({ scriptVisible: true })}>娣诲姞鑴氭湰</Button>
+                <Button className="mk-danger" onClick={this.deleteScripts} style={{marginLeft: '15px'}}>鍒犻櫎</Button>
+                <Search placeholder="缁煎悎鎼滅储" defaultValue={this.state.scriptSearchKey} onSearch={value => this.scriptSearch(value)} enterButton />
+              </div>
+              <Table
+                rowKey="ID"
+                columns={scriptcolumns}
+                dataSource={scriptlist}
+                pagination={{
+                  current: this.state.scriptIndex,
+                  pageSize: 10,
+                  total: this.state.scriptTotal || 0,
+                  showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
+                }}
+                rowSelection={{ type: 'checkbox', selectedRowKeys: selectScriptKeys, onChange: this.onScriptChange }}
+                onRow={(record) => ({ onClick: () => this.onScriptSelect(record)})}
+                onChange={this.changeScriptTable}
+              />
+            </div> : null}
           </div>
-          <Modal
-            title={'缂栬緫搴旂敤'}
-            width={'600px'}
-            maskClosable={false}
-            visible={visible !== false}
-            onCancel={() => this.setState({visible: false, confirmloading: false})}
-            confirmLoading={this.state.confirmloading}
-            onOk={this.submitCard}
-            cancelText="鍙栨秷"
-            okText="纭畾"
-            destroyOnClose
-          >
-            <MutilForm type={visible} card={visible === 'edit' ? selectApp : ''} wrappedComponentRef={(inst) => this.mobcardRef = inst} inputSubmit={this.submitCard} />
-          </Modal>
-          <Modal
-            title={transVisible === 'plus' ? '娣诲姞浼犺緭鍙�' : '缂栬緫浼犺緭鍙�'}
-            width={'600px'}
-            maskClosable={false}
-            visible={transVisible !== false}
-            onCancel={() => this.setState({transVisible: false, confirmloading: false})}
-            confirmLoading={this.state.confirmloading}
-            onOk={this.submitTrans}
-            cancelText="鍙栨秷"
-            okText="纭畾"
-            destroyOnClose
-          >
-            <TransForm type={transVisible} card={transVisible === 'edit' ? this.state.editTran : ''} wrappedComponentRef={(inst) => this.transRef = inst} inputSubmit={this.submitTrans} />
-          </Modal>
-          <Modal
-            title={'娣诲姞鑴氭湰'}
-            width={900}
-            maskClosable={false}
-            visible={scriptVisible}
-            onCancel={() => this.setState({scriptVisible: false, confirmloading: false})}
-            confirmLoading={this.state.confirmloading}
-            onOk={this.submitScript}
-            cancelText="鍙栨秷"
-            okText="纭畾"
-            destroyOnClose
-          >
-            <ScriptForm applist={applist} wrappedComponentRef={(inst) => this.scriptRef = inst} inputSubmit={this.submitScript} />
-          </Modal>
-          <Modal
-            title={subVisible === 'plus' ? '娣诲姞瀛愬簲鐢�' : '缂栬緫瀛愬簲鐢�'}
-            width={'850px'}
-            maskClosable={false}
-            visible={subVisible !== false}
-            onCancel={() => this.setState({subVisible: false, confirmloading: false})}
-            confirmLoading={this.state.confirmloading}
-            onOk={this.submitSubCard}
-            cancelText="鍙栨秷"
-            okText="纭畾"
-            destroyOnClose
-          >
-            <SubMutilForm type={subVisible} card={subVisible === 'edit' ? selectSubApp : ''} wrappedComponentRef={(inst) => this.submobcardRef = inst} inputSubmit={this.submitSubCard} />
-          </Modal>
-        </ConfigProvider>
+          <div className="right-view">
+            {selectApp ? <div className="app-title">{selectApp.remark}</div> : null}
+            {selectApp && selectApp.sublist.map((item, index) => {
+              let css = skinStyle[item.css] ? skinStyle[item.css].name : ''
+              let color = skinStyle[item.css] ? skinStyle[item.css].color : '#e8e8e8'
+              let binding = ''
+              if (item.user_binding === 'true') {
+                binding = '鐢ㄦ埛缁戝畾'
+              }
+              if (item.share === 'true') {
+                binding = binding ? binding + '銆佸垎浜�' : '鍒嗕韩'
+              }
+
+              return (
+                <div className="sub-app" key={index} style={{borderColor: color}}>
+                  <Row>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">搴旂敤绫诲瀷:</div>
+                        <div className="content" style={{fontSize: '18px', fontWeight: 600}}>{item.typename}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">璇█:</div>
+                        <div className="content" style={{textDecoration: 'underline'}}>{langs[item.lang]}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">鏉冮檺绠$悊:</div>
+                        <div className="content">{item.role_type === 'false' ? '涓嶅惎鐢�' : '鍚敤'}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        {item.wxAppName || item.wxMerchName ? <>
+                          <div className="label">鍏宠仈搴旂敤:</div>
+                          <div className="content">{`${item.wxAppName}${item.wxAppName && item.wxMerchName ? ' / ' + item.wxMerchName : item.wxMerchName || ''}`}</div>
+                        </> : null}
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">鐨偆:</div>
+                        <div className="content" style={{color: color}}>{css}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        {/* {binding ? <div className="label">
+                          <Tooltip placement="topLeft" title="寰俊鍏紬鍙风櫥褰曟椂锛岀郴缁熺敤鎴蜂笌寰俊鐢ㄦ埛鐨勭粦瀹氭柟寮忋��">
+                            <QuestionCircleOutlined className="mk-form-tip" />
+                            鐢ㄦ埛缁戝畾:
+                          </Tooltip>
+                        </div> : null} */}
+                        {binding ? <div className="label">
+                          <Tooltip placement="topLeft" title="寰俊鍏紬鍙锋垨灏忕▼搴忎腑锛岀粦瀹氱郴缁熺敤鎴枫�佽嚜瀹氫箟鍒嗕韩绛夊姛鑳姐��">
+                            <QuestionCircleOutlined className="mk-form-tip" />
+                            鎵╁睍鍔熻兘:
+                          </Tooltip>
+                        </div> : null}
+                        <div className="content">{binding}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">鏍囬:</div>
+                        <div className="content">{item.title || '鏃�'}</div>
+                      </div>
+                    </Col>
+                    <Col span={12}>
+                      <div className="app-item">
+                        <div className="label">缃戠珯澶村儚:</div>
+                        <div className="content">{item.favicon ? <img style={{width: '18px', height: '18px', borderRadius: '4px'}} src={item.favicon} alt="" /> : '鏃�'}</div>
+                      </div>
+                    </Col>
+                  </Row>
+                  <div className="action">
+                    {item.lang !== 'zh-CN' ? <TransMenu app={item} supApp={selectApp} /> : null}
+                    <Button type="link" onClick={() => this.jumpMenu(item)} style={{color: 'rgba(30, 228, 224, 1)'}}>鑿滃崟&鏉冮檺</Button>
+                    <Button type="link" onClick={() => this.setState({ selectSubApp: item, subVisible: 'edit' })} style={{color: '#8E44AD'}}>淇敼</Button>
+                    <Button type="link" onClick={() => this.deleteSubApp(item)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button>
+                    <Button type="link" onClick={() => this.jumpApp(item)}>缂栬緫搴旂敤</Button>
+                    <Paragraph style={{display: 'inline-block', margin: 0}} copyable={{ text: `${window.GLOB.baseurl}${item.typename === 'pad' ? 'mob' : item.typename}/index.html#/index/${this.state.selectApp.kei_no}/${item.typename !== 'pc' ? item.typename + '/' : ''}${item.lang}${item.wxAppId ? '/' + item.wxAppId : ''}` }}></Paragraph>
+                  </div>
+                </div>
+              )
+            })}
+          </div>
+        </div>
+        <Modal
+          title={'缂栬緫搴旂敤'}
+          width={'600px'}
+          maskClosable={false}
+          visible={visible !== false}
+          onCancel={() => this.setState({visible: false, confirmloading: false})}
+          confirmLoading={this.state.confirmloading}
+          onOk={this.submitCard}
+          cancelText="鍙栨秷"
+          okText="纭畾"
+          destroyOnClose
+        >
+          <MutilForm type={visible} card={visible === 'edit' ? selectApp : ''} wrappedComponentRef={(inst) => this.mobcardRef = inst} inputSubmit={this.submitCard} />
+        </Modal>
+        <Modal
+          title={transVisible === 'plus' ? '娣诲姞浼犺緭鍙�' : '缂栬緫浼犺緭鍙�'}
+          width={'600px'}
+          maskClosable={false}
+          visible={transVisible !== false}
+          onCancel={() => this.setState({transVisible: false, confirmloading: false})}
+          confirmLoading={this.state.confirmloading}
+          onOk={this.submitTrans}
+          cancelText="鍙栨秷"
+          okText="纭畾"
+          destroyOnClose
+        >
+          <TransForm type={transVisible} card={transVisible === 'edit' ? this.state.editTran : ''} wrappedComponentRef={(inst) => this.transRef = inst} inputSubmit={this.submitTrans} />
+        </Modal>
+        <Modal
+          title={'娣诲姞鑴氭湰'}
+          width={900}
+          maskClosable={false}
+          visible={scriptVisible}
+          onCancel={() => this.setState({scriptVisible: false, confirmloading: false})}
+          confirmLoading={this.state.confirmloading}
+          onOk={this.submitScript}
+          cancelText="鍙栨秷"
+          okText="纭畾"
+          destroyOnClose
+        >
+          <ScriptForm applist={applist} wrappedComponentRef={(inst) => this.scriptRef = inst} inputSubmit={this.submitScript} />
+        </Modal>
+        <Modal
+          title={subVisible === 'plus' ? '娣诲姞瀛愬簲鐢�' : '缂栬緫瀛愬簲鐢�'}
+          width={'970px'}
+          maskClosable={false}
+          visible={subVisible !== false}
+          onCancel={() => this.setState({subVisible: false, confirmloading: false})}
+          confirmLoading={this.state.confirmloading}
+          onOk={this.submitSubCard}
+          cancelText="鍙栨秷"
+          okText="纭畾"
+          destroyOnClose
+        >
+          <SubMutilForm type={subVisible} card={subVisible === 'edit' ? selectSubApp : ''} wrappedComponentRef={(inst) => this.submobcardRef = inst} inputSubmit={this.submitSubCard} />
+        </Modal>
       </div>
     )
   }
diff --git a/src/views/appmanage/index.scss b/src/views/appmanage/index.scss
index 65395e4..474ecaa 100644
--- a/src/views/appmanage/index.scss
+++ b/src/views/appmanage/index.scss
@@ -101,6 +101,14 @@
           .ant-typography-copy {
             color: #26C281;
           }
+          .ant-btn {
+            padding: 0 5px;
+            margin: 0 10px;
+          }
+          .anticon-swap {
+            color: #1890ff;
+            padding: 5px 10px;
+          }
         }
       }
     }
diff --git a/src/views/appmanage/submutilform/index.jsx b/src/views/appmanage/submutilform/index.jsx
index 20d6daf..369b47f 100644
--- a/src/views/appmanage/submutilform/index.jsx
+++ b/src/views/appmanage/submutilform/index.jsx
@@ -3,6 +3,7 @@
 import { Form, Row, Col, Select, Radio, Input, Tooltip, InputNumber, Checkbox } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
+import { langs } from '@/store/options.js'
 import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
@@ -16,17 +17,33 @@
     inputSubmit: PropTypes.func  // input鍥炶溅鎻愪氦
   }
 
-  state = {typename: 'mob', adapters: [], exts: []}
+  state = {
+    typename: 'mob',
+    adapters: [],
+    exts: [],
+    WXApps: null,
+    WXMerchs: null
+  }
 
   UNSAFE_componentWillMount() {
     const { card } = this.props
     let adapters = []
     let exts = []
     let typename = 'mob'
+    let _langs = []
+    Object.keys(langs).forEach(key => {
+      _langs.push({value: key, label: langs[key]})
+    })
 
     if (card) {
       typename = card.typename || 'mob'
       adapters = card.adapter ? card.adapter.split(',') : []
+
+      if (!adapters.includes('fbdH5')) {
+        adapters.unshift('H5')
+      }
+
+      adapters = adapters.filter(n => n !== 'fbdH5')
 
       if (typename !== 'pc') {
         if (card.user_binding === 'true') {
@@ -36,9 +53,26 @@
           exts.push('share')
         }
       }
+    } else {
+      adapters = ['H5']
     }
 
-    this.setState({typename, adapters, exts})
+    let WXApps = null
+    let WXMerchs = null
+    if (window.GLOB.WXApps) {
+      WXApps = window.GLOB.WXApps.filter(app => app.appType === 'public')
+
+      if (WXApps.length === 0) {
+        WXApps = null
+      }
+      WXMerchs = window.GLOB.WXApps.filter(app => app.appType === 'merchant')
+
+      if (WXMerchs.length === 0) {
+        WXMerchs = null
+      }
+    }
+
+    this.setState({typename, adapters, exts, langs: _langs, WXApps, WXMerchs})
   }
 
   /**
@@ -48,12 +82,26 @@
     return new Promise(resolve => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
+          if (values.adapter) {
+            if (!values.adapter.includes('H5')) {
+              values.adapter.unshift('fbdH5')
+            }
+          }
+
           values.adapter = values.adapter ? values.adapter.join(',') : ''
 
           if (values.exts) {
             values.user_binding = values.exts.includes('user_binding') ? 'true' : 'false'
             values.share = values.exts.includes('share') ? 'true' : 'false'
             delete values.exts
+          }
+          if (values.wxAppId) {
+            let app = window.GLOB.WXApps.filter(app => app.appType === 'public' && values.wxAppId === app.appId)[0]
+            values.wxAppName = app ? app.appName : values.wxAppId
+          }
+          if (values.wxMerchId) {
+            let app = window.GLOB.WXApps.filter(app => app.appType === 'merchant' && values.wxMerchId === app.appId)[0]
+            values.wxMerchName = app ? app.appName : values.wxMerchId
           }
 
           resolve(values)
@@ -80,7 +128,7 @@
   render() {
     const { card, type } = this.props
     const { getFieldDecorator } = this.props.form
-    const { typename, adapters, exts } = this.state
+    const { typename, adapters, exts, langs, WXApps, WXMerchs } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -113,10 +161,9 @@
               {getFieldDecorator('lang', {
                 initialValue: card ? card.lang || 'zh-CN' : 'zh-CN'
               })(
-                <Radio.Group disabled={type === 'edit'}>
-                  <Radio value="zh-CN">涓枃</Radio>
-                  <Radio value="en-US">鑻辨枃</Radio>
-                </Radio.Group>
+                <Select disabled={type === 'edit'}>
+                  {langs.map(item => <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>)}
+                </Select>
               )}
             </Form.Item>
           </Col>
@@ -163,6 +210,7 @@
                 initialValue: adapters
               })(
                 <Checkbox.Group onChange={this.onAdapterChange}>
+                  <Checkbox value="H5">H5</Checkbox>
                   <Checkbox value="app">app</Checkbox>
                   <Checkbox value="weixin">鍏紬鍙�</Checkbox>
                   <Checkbox value="wxmini">灏忕▼搴�</Checkbox>
@@ -170,6 +218,38 @@
               )}
             </Form.Item>
           </Col> : null}
+          {WXApps ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鐢ㄦ埛鍙�氳繃姝ゅ叕浼楀彿杩涜鏀粯銆侀��娆俱�佹巿鏉冪櫥褰曘��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍏宠仈搴旂敤
+              </Tooltip>
+            }>
+              {getFieldDecorator('wxAppId', {
+                initialValue: card ? card.wxAppId : ''
+              })(
+                <Select allowClear>
+                  {WXApps.map(item => <Select.Option key={item.appId} value={item.appId}>{item.appName}</Select.Option>)}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {WXMerchs ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鐢ㄦ埛鍙�氳繃姝ゅ晢鎴峰彿杩涜鏀粯鍙婇��娆俱��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍏宠仈鍟嗘埛
+              </Tooltip>
+            }>
+              {getFieldDecorator('wxMerchId', {
+                initialValue: card ? card.wxMerchId : ''
+              })(
+                <Select allowClear>
+                  {WXMerchs.map(item => <Select.Option key={item.appId} value={item.appId}>{item.appName}</Select.Option>)}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
           {typename !== 'pc' && (adapters.includes('weixin') || adapters.includes('wxmini')) ? <Col span={12}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="鍦ㄥ叕浼楀彿鎴栧皬绋嬪簭涓紝鍙坊鍔犵粦瀹氱郴缁熺敤鎴枫�佽嚜瀹氫箟鍒嗕韩绛夊姛鑳斤紝鑷畾涔夊垎浜缃悗锛屽綋鍓嶅瓙搴旂敤灏嗛粯璁や娇鐢ㄦ鍒嗕韩閾炬帴銆�">
diff --git a/src/views/appmanage/transmenu/index.jsx b/src/views/appmanage/transmenu/index.jsx
new file mode 100644
index 0000000..52f0433
--- /dev/null
+++ b/src/views/appmanage/transmenu/index.jsx
@@ -0,0 +1,521 @@
+import React, { Component } from 'react'
+import { is, fromJS } from 'immutable'
+import { Modal, notification, Spin, Select } from 'antd'
+import { SwapOutlined } from '@ant-design/icons'
+import moment from 'moment'
+import md5 from 'md5'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import MenuUtils, { setLangTrans } from '@/utils/utils-custom.js'
+import './index.scss'
+
+const { confirm } = Modal
+
+class TransMenu extends Component {
+  state = {
+    visible: false,
+    loading: false,
+    saveing: false,
+    dicts: [],
+    menus: [],
+    values: '',
+    kei_no: '',
+    zhApp: null
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  trigger = () => {
+    const { supApp, app } = this.props
+
+    let zhApp = supApp.sublist.filter(item => item.typename === app.typename && item.lang === 'zh-CN')[0]
+
+    this.setState({
+      loading: true,
+      visible: true,
+      saveing: false,
+      values: '',
+      kei_no: supApp.kei_no,
+      zhApp
+    })
+    
+    this.getDicts()
+    this.getMenus(zhApp, supApp.kei_no)
+  }
+  
+  getDicts = () => {
+    // let sql = `select id,lang,lang_name,mother_tongue,translation,use_type,case when use_type='menu' then '鑿滃崟' when  use_type='button' then '鎸夐挳'  when  use_type='title' then '鏍囬'   when  use_type='list' then '閫夐」' else '鏂囨湰' end as use_type_text from s_app_lang_translation where appkey=@appkey@ and deleted=0 and translation != ''`
+    let sql = `select mother_tongue as reg,translation as value,use_type as type,case when use_type='menu' then '鑿滃崟' when  use_type='button' then '鎸夐挳'  when  use_type='title' then '鏍囬'   when  use_type='list' then '閫夐」' else '鏂囨湰' end as use_type_text from s_app_lang_translation where appkey=@appkey@ and deleted=0 and translation != '' and lang='${sessionStorage.getItem('lang') || ''}'`
+
+    let param = {
+      func: 'sPC_Get_SelectedList',
+      LText: Utils.formatOptions(sql, 'x'),
+      obj_name: 'data',
+      arr_field: 'reg,value,type',
+      exec_type: 'x'
+    }
+
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt('', param.timestamp)
+    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+
+    Api.getCloudConfig(param).then(result => {
+      if (!result.status) {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+        return
+      }
+
+      this.setState({dicts: result.data || []})
+    })
+  }
+
+  getMenus = (zhApp, kei_no) => {
+    if (this.state.menus.length > 0) {
+      this.setState({loading: false})
+      return
+    }
+
+    let param = {
+      func: 's_get_app_menus',
+      TypeCharOne: kei_no,
+      typename: zhApp.typename,
+      LText: `select '${window.GLOB.appkey}'`,
+      timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
+      lang: 'zh-CN'
+    }
+
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    Api.getCloudConfig(param).then(result => {
+      if (result.status) {
+        let menus = []
+        result.menus.forEach(item => {
+          if (zhApp.userbind === item.MenuID || zhApp.instantMessage === item.MenuID) return
+          
+          menus.push(item)
+        })
+
+        this.setState({menus: menus, loading: false})
+      } else {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  submit = () => {
+    const { values } = this.state
+
+    if (!values) {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨鑿滃崟锛�',
+        duration: 5
+      })
+      return
+    }
+
+    this.setState({saveing: true})
+
+    this.transThdMenu()
+  }
+
+  transThdMenu = () => {
+    const { app } = this.props
+    const { zhApp, dicts, values, kei_no } = this.state
+
+    let _param = {
+      func: 'sPC_Get_LongParam',
+      TypeCharOne: kei_no,
+      typename: zhApp.typename,
+      MenuID: values,
+      lang: 'zh-CN'
+    }
+
+    Api.getCloudConfig(_param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        this.setState({saveing: false})
+        return
+      }
+
+      let config = null
+      if (res.LongParam) {
+        try {
+          config = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
+        } catch (e) {
+          console.warn('Parse Failure')
+          config = ''
+        }
+      }
+
+      if (!config) {
+        notification.warning({
+          top: 92,
+          message: '鏈幏鍙栧埌鑿滃崟閰嶇疆淇℃伅',
+          duration: 5
+        })
+        this.setState({saveing: false})
+      }
+
+      let btnDict = {}
+      let titDict = {}
+      let lisDict = {}
+      let menuDict = {}
+      let regs = []
+
+      dicts.forEach(item => {
+        if (item.type === 'button') {
+          btnDict[item.reg] = item.value
+        } else if (item.type === 'title') {
+          titDict[item.reg] = item.value
+        } else if (item.type === 'list') {
+          lisDict[item.reg] = item.value
+        } else if (item.type === 'text') {
+          regs.push({reg: new RegExp(item.reg, 'g'), value: item.value, sort: item.reg.length})
+        } else if (item.type === 'menu') {
+          menuDict[item.reg] = item.value
+        }
+      })
+
+      regs.sort((a, b) => b.sort - a.sort)
+
+      let tail = md5(window.GLOB.appkey + kei_no + zhApp.typename + app.lang).toLowerCase()
+
+      tail = tail.slice(-8)
+
+      let menus_rolelist = ''
+      if (config.type === 'navbar') {
+        config.menus.forEach(item => {
+          if (item.linkMenuId) {
+            item.linkMenuId = item.linkMenuId.slice(0, 24) + tail
+          } else {
+            item.MenuID = item.MenuID.slice(0, 24) + tail
+          }
+          if (item.name && menuDict[item.name]) {
+            item.name = menuDict[item.name]
+          }
+          if (item.sublist) {
+            item.sublist.forEach(sec => {
+              if (sec.linkMenuId) {
+                sec.linkMenuId = sec.linkMenuId.slice(0, 24) + tail
+              } else {
+                sec.MenuID = sec.MenuID.slice(0, 24) + tail
+              }
+              if (sec.name && menuDict[sec.name]) {
+                sec.name = menuDict[sec.name]
+              }
+              if (sec.sublist) {
+                sec.sublist.forEach(thd => {
+                  if (thd.linkMenuId) {
+                    thd.linkMenuId = thd.linkMenuId.slice(0, 24) + tail
+                  } else {
+                    thd.MenuID = thd.MenuID.slice(0, 24) + tail
+                  }
+                  if (thd.name && menuDict[thd.name]) {
+                    thd.name = menuDict[thd.name]
+                  }
+                })
+              }
+            })
+          }
+        })
+        if (config.columns) {
+          config.columns.forEach(cell => {
+            if (cell.label && titDict[cell.label]) {
+              cell.label = titDict[cell.label]
+            }
+          })
+        }
+
+        config.MenuNo = 'navbar_' + app.lang
+        if (config.name === menuDict[config.name]) {
+          config.name = menuDict[config.name]
+        } else {
+          config.name = config.name + '_' + app.lang
+        }
+
+        menus_rolelist = {
+          type: 'navbar',
+          version: '1.0',
+          key: config.uuid,
+          title: config.name,
+          children: []
+        }
+
+        if (config.wrap.permission === 'true') {
+          menus_rolelist.children = config.menus.map(fst => {
+            if (fst.property === 'classify' && fst.sublist.length > 0) {
+              return {
+                key: fst.MenuID,
+                title: fst.name,
+                children: fst.sublist.map(scd => {
+                  if (scd.property === 'classify' && scd.sublist.length > 0) {
+                    return {
+                      key: scd.MenuID,
+                      title: scd.name,
+                      children: scd.sublist.map(thd => {
+                        return { key: thd.MenuID, title: thd.name }
+                      })
+                    }
+                  } else {
+                    return { key: scd.MenuID, title: scd.name }
+                  }
+                })
+              }
+            } else {
+              return { key: fst.MenuID, title: fst.name }
+            }
+          })
+        } else {
+          menus_rolelist.pass = true
+        }
+        menus_rolelist = window.btoa(window.encodeURIComponent(JSON.stringify(menus_rolelist)))
+      } else {
+        setLangTrans(config, btnDict, titDict, lisDict, menuDict, regs, tail)
+  
+        if (config.components) {
+          let commonId = Utils.getuuid()
+          if (config.interfaces && config.interfaces.length > 0) {
+            config.interfaces = config.interfaces.map(inter => {
+              inter.uuid = md5(commonId + inter.uuid)
+              return inter
+            })
+          }
+          config.components = MenuUtils.resetConfig(config.components, commonId, false)
+          config.tables = config.tables || []
+          config.style = config.style || {}
+        }
+  
+        config.enabled = false
+        config.Template = 'webPage'
+        if (config.MenuNo) {
+          config.MenuNo = config.MenuNo + '_' + app.lang
+        }
+        if (config.MenuName === menuDict[config.MenuName]) {
+          config.MenuName = menuDict[config.MenuName]
+        } else {
+          config.MenuName = config.MenuName + '_' + app.lang
+        }
+      }
+
+      delete config.tbkey
+      
+      config.uuid = values.slice(0, 24) + tail
+      config.MenuID = config.uuid
+      config.open_edition = ''
+      
+      let param = {
+        func: 'sPC_TrdMenu_AddUpt',
+        FstID: 'mk_app',
+        SndID: 'mk_app',
+        ParentID: 'mk_app',
+        MenuID: config.uuid,
+        MenuNo: config.MenuNo,
+        EasyCode: '',
+        TypeCharOne: kei_no,
+        Typename: app.typename,
+        Template: config.Template || config.type,
+        MenuName: config.MenuName || config.name || '',
+        PageParam: JSON.stringify({Template: config.Template || config.type}),
+        lang: app.lang
+      }
+
+      if (menus_rolelist) {
+        param.menus_rolelist = menus_rolelist
+      }
+
+      Api.getCloudConfig({
+        func: 'sPC_Get_LongParam',
+        TypeCharOne: kei_no,
+        typename: app.typename,
+        MenuID: config.MenuID,
+        lang: app.lang
+      }).then(res => {
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 5
+          })
+          this.setState({saveing: false})
+          return
+        }
+
+        config.open_edition = res.open_edition || ''
+        param.open_edition = config.open_edition
+        param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
+
+        if (res.LongParam) {
+          const that = this
+          confirm({
+            title: '鑿滃崟宸插瓨鍦紝纭畾閲嶆柊鐢熸垚鍚�?',
+            content: '',
+            onOk() {
+              that.setMenu(param, config)
+            },
+            onCancel() {}
+          })
+        } else {
+          this.setMenu(param, config)
+        }
+      })
+    })
+  }
+
+  setMenu = (param, config) => {
+    const { app } = this.props
+    const { kei_no } = this.state
+
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt('', param.timestamp)
+
+    Api.getCloudConfig(param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        this.setState({saveing: false})
+        return
+      }
+
+      if (config.type === 'navbar') {
+        Api.getCloudConfig({
+          func: 's_get_keyids',
+          bid: app.ID
+        }).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+            this.setState({saveing: false})
+            return
+          }
+  
+          let appViewList = res.data || []
+          appViewList = appViewList.filter(item => item.keys_id !== config.uuid)
+          appViewList.unshift({
+            appkey: window.GLOB.appkey || '',
+            bid: app.ID,
+            kei_no: kei_no || '',
+            keys_id: config.uuid,
+            keys_type: 'navbar',
+            remark: config.name
+          })
+  
+          let param = {
+            func: 's_kei_link_keyids_addupt',
+            BID: app.ID,
+            exec_type: 'x',
+            LText: ''
+          }
+  
+          param.LText = appViewList.map(item => `select '${item.keys_id}','${item.keys_type}','${item.kei_no}','${item.appkey}','${item.bid}','${sessionStorage.getItem('CloudUserID')}','${item.remark}'`)
+          param.LText = param.LText.join(' union all ')
+          param.LText = Utils.formatOptions(param.LText, 'x')
+    
+          param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+          param.secretkey = Utils.encrypt('', param.timestamp)
+  
+          Api.getCloudConfig(param).then(result => {
+            if (!result.status) {
+              notification.warning({
+                top: 92,
+                message: result.message,
+                duration: 5
+              })
+              this.setState({saveing: false})
+              return
+            }
+  
+            notification.success({
+              top: 92,
+              message: '娣诲姞鎴愬姛銆�',
+              duration: 5
+            })
+            
+            this.setState({
+              loading: false,
+              visible: false
+            })
+          })
+        })
+      } else {
+        notification.success({
+          top: 92,
+          message: '娣诲姞鎴愬姛銆�',
+          duration: 5
+        })
+        
+        this.setState({
+          loading: false,
+          visible: false
+        })
+      }
+    })
+  }
+
+  cancel = () => {
+    this.setState({
+      loading: false,
+      visible: false
+    })
+  }
+
+  render () {
+    const { supApp, app } = this.props
+    const { visible, loading, saveing, menus } = this.state
+
+    if (supApp.sublist.findIndex(item => item.typename === app.typename && item.lang === 'zh-CN') === -1) return null
+
+    return (
+      <>
+        <SwapOutlined onClick={this.trigger}/>
+        <Modal
+          wrapClassName="sync-menu-modal"
+          title="鑿滃崟杞崲"
+          visible={visible}
+          width={600}
+          closable={false}
+          maskClosable={false}
+          onOk={this.submit}
+          onCancel={this.cancel}
+          confirmLoading={saveing}
+          destroyOnClose
+        >
+          {loading ? <Spin /> : <div>
+            <Select
+              showSearch
+              placeholder="璇烽�夋嫨鑿滃崟"
+              dropdownMatchSelectWidth={false}
+              onChange={(val) => this.setState({values: val})}
+              filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+            >
+              {menus.map((item, i) => (<Select.Option key={i} value={item.MenuID}>{`${item.MenuName}锛�${item.MenuNo}锛塦}</Select.Option>))}
+            </Select>
+          </div>}
+        </Modal>
+      </>
+    )
+  }
+}
+
+export default TransMenu
\ No newline at end of file
diff --git a/src/views/appmanage/transmenu/index.scss b/src/views/appmanage/transmenu/index.scss
new file mode 100644
index 0000000..73c8958
--- /dev/null
+++ b/src/views/appmanage/transmenu/index.scss
@@ -0,0 +1,16 @@
+.sync-menu-modal {
+  .ant-modal-body {
+    position: relative;
+    padding: 24px 50px;
+    min-height: 250px;
+    max-height: calc(100vh - 210px);
+    .ant-select {
+      width: 300px;
+    }
+    .ant-spin {
+      position: absolute;
+      left: calc(50% - 10px);
+      top: 75px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/views/basedesign/index.jsx b/src/views/basedesign/index.jsx
index da66e53..011b207 100644
--- a/src/views/basedesign/index.jsx
+++ b/src/views/basedesign/index.jsx
@@ -1,7 +1,5 @@
 import React, {Component} from 'react'
-import { notification, Spin, ConfigProvider } from 'antd'
-import enUS from 'antd/es/locale/en_US'
-import zhCN from 'antd/es/locale/zh_CN'
+import { notification, Spin } from 'antd'
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
@@ -10,7 +8,6 @@
 import '@/assets/css/design.scss'
 import './index.scss'
 
-const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 const Header = asyncComponent(() => import('@/menu/header'))
 const ComTableConfig = asyncLoadComponent(() => import('@/templates/comtableconfig'))
 const TreePageConfig = asyncLoadComponent(() => import('@/templates/treepageconfig'))
@@ -105,44 +102,29 @@
             console.warn('Parse Failure')
             _LongParam = ''
           }
-          editMenu.LongParam = _LongParam
-        } else if (editMenu.PageParam.copyMenuId) {
-          let _param = {
-            func: 'sPC_Get_LongParam',
-            MenuID: editMenu.PageParam.copyMenuId
-          }
-      
-          Api.getCloudConfig(_param).then(res => {
-            if (res.status) {
-              if (res.LongParam) {
-                let _LongParam = ''
-                try {
-                  _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
-                  _LongParam.type = 'user'
-                } catch (e) {
-                  console.warn('Parse Failure')
-                  _LongParam = ''
-                }
-                editMenu.LongParam = _LongParam
-              }
-              
-              this.setState({
-                editMenu: editMenu,
-                loading: false,
-                tabview: editMenu.type
-              })
-            } else {
-              this.setState({
-                loading: false
-              })
-              notification.warning({
-                top: 92,
-                message: res.message,
-                duration: 5
-              })
+
+          if (_LongParam && (_LongParam.Template === 'BaseTable' || _LongParam.Template === 'CustomPage')) {
+            let _param = {
+              MenuId: editMenu.MenuID,
+              MenuID: editMenu.MenuID,
+              ParentId: _LongParam.ParentId,
+              MenuName: _LongParam.MenuName,
+              MenuNo: _LongParam.MenuNo
             }
-          })
-          return
+            let url = ''
+            if (_LongParam.Template === 'BaseTable') {
+              url = window.location.href.split('#')[0] + `#/tabledesign/${window.btoa(window.encodeURIComponent(JSON.stringify(_param)))}`
+            } else {
+              _param.MenuType = 'custom'
+              _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
+              url = window.location.href.split('#')[0] + `#/menudesign/${_param}`
+            }
+            
+            window.history.replaceState(null, null, url)
+            window.location.reload()
+            return
+          }
+          editMenu.LongParam = _LongParam
         }
         
         this.setState({
@@ -189,58 +171,56 @@
 
     return (
       <div className="mk-base-design-wrap">
-        <ConfigProvider locale={_locale}>
-          <Header/>
-          {this.state.tabview === 'CommonTable' ?
-            <ComTableConfig
-              menu={editMenu}
-              reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
-              handleView={this.handleView}
-            /> : null
-          }
-          {this.state.tabview === 'SubTable' ?
-            <SubTable
-              menu={editMenu}
-              editTab={this.state.editTab}
-              editSubTab={this.state.editSubTab}
-              tabConfig={this.state.tabConfig}
-              btnTab={btnTab}
-              btnTabConfig={this.state.btnTabConfig}
-              config={subConfig}
-              handleView={this.handleView}
-            /> : null
-          }
-          {this.state.tabview === 'Modal' ?
-            <ModalConfig
-              menu={editMenu}
-              editTab={this.state.editTab}
-              tabConfig={this.state.tabConfig}
-              editSubTab={this.state.editSubTab}
-              subTabConfig={this.state.subTabConfig}
-              btnTab={btnTab}
-              btnTabConfig={this.state.btnTabConfig}
-              editAction={this.state.editAction}
-              subConfig={subConfig}
-              handleView={this.handleView}
-            /> : null
-          }
-          {this.state.tabview === 'TreePage' ?
-            <TreePageConfig
-              menu={editMenu}
-              reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
-              handleView={this.handleView}
-            /> : null
-          }
-          {this.state.tabview === 'FormTab' ?
-            <UpdateFormTab
-              menu={editMenu}
-              btnTab={btnTab}
-              config={subConfig}
-              handleView={this.handleView}
-            /> : null
-          }
-          {loading ? <Spin className="loading-view" size="large"/> : null}
-        </ConfigProvider>
+        <Header/>
+        {this.state.tabview === 'CommonTable' ?
+          <ComTableConfig
+            menu={editMenu}
+            reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
+            handleView={this.handleView}
+          /> : null
+        }
+        {this.state.tabview === 'SubTable' ?
+          <SubTable
+            menu={editMenu}
+            editTab={this.state.editTab}
+            editSubTab={this.state.editSubTab}
+            tabConfig={this.state.tabConfig}
+            btnTab={btnTab}
+            btnTabConfig={this.state.btnTabConfig}
+            config={subConfig}
+            handleView={this.handleView}
+          /> : null
+        }
+        {this.state.tabview === 'Modal' ?
+          <ModalConfig
+            menu={editMenu}
+            editTab={this.state.editTab}
+            tabConfig={this.state.tabConfig}
+            editSubTab={this.state.editSubTab}
+            subTabConfig={this.state.subTabConfig}
+            btnTab={btnTab}
+            btnTabConfig={this.state.btnTabConfig}
+            editAction={this.state.editAction}
+            subConfig={subConfig}
+            handleView={this.handleView}
+          /> : null
+        }
+        {this.state.tabview === 'TreePage' ?
+          <TreePageConfig
+            menu={editMenu}
+            reloadmenu={() => {localStorage.setItem('menuUpdate', new Date().getTime())}}
+            handleView={this.handleView}
+          /> : null
+        }
+        {this.state.tabview === 'FormTab' ?
+          <UpdateFormTab
+            menu={editMenu}
+            btnTab={btnTab}
+            config={subConfig}
+            handleView={this.handleView}
+          /> : null
+        }
+        {loading ? <Spin className="loading-view" size="large"/> : null}
       </div>
     )
   }
diff --git a/src/views/basedesign/updateFormTab/index.jsx b/src/views/basedesign/updateFormTab/index.jsx
index d17db4b..a70d45b 100644
--- a/src/views/basedesign/updateFormTab/index.jsx
+++ b/src/views/basedesign/updateFormTab/index.jsx
@@ -28,7 +28,7 @@
 
   trigger = () => {
     const { config, menu, btnTab } = this.props
-    const _this = this
+    const that = this
 
     if (!config || !menu || !menu.LongParam) {
       notification.warning({
@@ -78,7 +78,7 @@
       content: '',
       onOk() {
         return new Promise(resolve => {
-          _this.execUpdate(resolve, _config)
+          that.execUpdate(resolve, _config)
         })
       },
       onCancel() {}
diff --git a/src/views/billprint/index.jsx b/src/views/billprint/index.jsx
index 416c51d..25fbfea 100644
--- a/src/views/billprint/index.jsx
+++ b/src/views/billprint/index.jsx
@@ -2,6 +2,7 @@
 import { is, fromJS } from 'immutable'
 import { Col, Row, Spin, notification, Button, Modal } from 'antd'
 import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -65,6 +66,7 @@
         let param = JSON.parse(window.decodeURIComponent(window.atob(params.param)))
   
         sessionStorage.setItem('dataM', param.dataM || '')
+
         this.setState({
           BID: param.id || '',
           tempId: param.tempId,
@@ -90,7 +92,7 @@
   }
 
   componentDidMount() {
-    const _this = this
+    const that = this
 
     if (window.GLOB.sysType !== 'cloud') {
       Object.defineProperty(window, 'debugger', {
@@ -118,7 +120,7 @@
             window.GLOB.breakpoint = value + ''
             sessionStorage.setItem('breakpoint', value)
           }
-          _this.debugChange()
+          that.debugChange()
         }
       })
     }
@@ -144,7 +146,7 @@
         window.GLOB.breakpoint = false
         sessionStorage.removeItem('breakpoint')
         
-        _this.debugChange()
+        that.debugChange()
       }
     }
   }
@@ -302,6 +304,22 @@
         let _pars = []
 
         config.components = config.components.filter(item => !['tabs', 'search'].includes(item.type))
+
+        if (window.backend && config.allSqls) {
+          let urlparam = urlParam || {}
+          let keys = Object.keys(urlparam)
+          config.allSqls.forEach(item => {
+            item.id = md5(window.GLOB.appkey + item.v_id)
+            if (item.type === 'datasource' || item.type === 'excelOut') {
+              item.urlkeys = keys
+              item.urlparam = urlparam
+              if (config.flow_code) {
+                item.works_flow_code = config.flow_code
+              }
+            }
+            window.GLOB.CacheData.set('sql_' + item.uuid, item)
+          })
+        }
 
         let userName = sessionStorage.getItem('User_Name') || ''
         let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -487,6 +505,8 @@
             component.setting.sync = 'false'
             return component
           }
+
+          component.setting.uuid = component.uuid
     
           let _customScript = ''
           let _tailScript = ''
@@ -532,11 +552,17 @@
     
           component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
           component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
+
+          if (window.backend && config.allSqls) {
+            component.setting.sync = 'false'
+          } else if (_tailScript) {
+            component.setting.sync = 'false'
+          }
+          component.dataName = 'mk' + component.uuid.slice(-18)
     
           // floor    缁勪欢鐨勫眰绾�
           // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
           if (component.setting.sync === 'true') {
-            component.dataName = 'mk' + component.uuid.slice(-18)
             let param = this.getDefaultParam(component)
             _pars.push(param)
           } else if (component.subtype !== 'dualdatacard') {
@@ -554,8 +580,29 @@
         _pars = this.getFormatParam(_pars, config.MenuName)
 
         if (_pars) {
-          _pars.componentId = 'union'
+          _pars.componentId = ''
           params.unshift(_pars)
+        } else if (window.backend && config.allSqls && params.length > 0) {
+          let data = []
+          params = params.filter(item => {
+            if (!item.$backend || item.public) return true
+
+            item.data[0].exps.forEach(cell => {
+              if (cell.key === 'mk_obj_name') {
+                cell.value = 'mk' + item.componentId.slice(-18)
+              }
+            })
+            data.push(item.data[0])
+            return false
+          })
+          if (data.length > 0) {
+            params.push({
+              $backend: true,
+              $type: 's_Get_TableData',
+              componentId: '',
+              data
+            })
+          }
         }
 
         if (config.everyPCount && !config.printPage) { // 鍏煎
@@ -682,6 +729,8 @@
         }
         return
       }
+
+      inter.setting.uuid = inter.uuid
 
       let _customScript = ''
       let _tailScript = ''
@@ -813,6 +862,7 @@
       { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
       { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
       { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
+      { reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
       { reg: /@typename@/ig, value: `'admin'`},
     ]
 
@@ -837,8 +887,8 @@
 
       // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
       if (window.GLOB.debugger === true) {
-        _script && console.info(`${_sql ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_script}`)
-        _sql &&  console.info(_sql)
+        _script && window.mkInfo(`${_sql ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_script}`)
+        _sql && window.mkInfo(_sql)
       }
 
       item.columns.forEach(cell => {
@@ -875,11 +925,13 @@
       return new Promise(resolve => {
         Api.genericInterface(item).then(res => {
           if (!res.status) {
-            notification.warning({
-              top: 92,
-              message: res.message,
-              duration: 5
-            })
+            if (res.ErrCode !== '-2') {
+              notification.warning({
+                top: 92,
+                message: res.message,
+                duration: 5
+              })
+            }
             resolve()
           } else {
             let _data = { $$empty: true }
@@ -910,7 +962,6 @@
 
     let deffers = params.map(item => {
       let componentId = item.componentId
-      let ispublic = item.public
       delete item.componentId
       delete item.public
       return new Promise(resolve => {
@@ -921,7 +972,7 @@
             }
             if (res.ErrCode === 'version_up') {
               this.reloadTabs()
-            } else {
+            } else if (res.ErrCode !== '-2') {
               notification.warning({
                 top: 92,
                 message: res.message,
@@ -932,13 +983,12 @@
           } else {
             res.componentId = componentId
 
-            if (ispublic) {
-              let _data = { $$empty: true }
-              if (res.data && res.data[0]) {
-                _data = res.data[0]
-              }
-              window.GLOB.CacheData.set(componentId, _data)
+            let _data = { $$empty: true }
+            if (res.data && res.data[0]) {
+              _data = res.data[0]
             }
+            window.GLOB.CacheData.set(componentId, _data)
+
             resolve(res)
           }
         })
@@ -961,7 +1011,7 @@
         _results.forEach(res => {
           if ((res.componentId === item.uuid || res.componentId === item.componentId) && res.data) {
             item.dataArray = fromJS(res.data).toJS()
-          } else if (res.componentId === 'union' && res[item.dataName]) {
+          } else if (res[item.dataName]) {
             let data = res[item.dataName]
             if (!Array.isArray(data)) {
               data = [data]
@@ -993,63 +1043,79 @@
         }
       }
 
-      while (!over) {
-        let page = []
-        let count = 0
-        let _pageover = false
-
-        comps.forEach(comp => {
-          let item = fromJS(comp).toJS()
-
-          if (item.wrap.printType === 'headerOrfooter') { // 椤电湁椤佃剼
-            item.data = item.dataArray || null
-            setData(item)
-            page.push(item)
-            comp.added = true
-          }
-
-          if (_pageover) return
-
-          if (item.$page && comp.dataArray.length > 0) {
-            item.data = []
-
-            while (count + 1 <= limit && comp.dataArray.length > 0) {
-              item.data.push(comp.dataArray.shift())
-              count++
-            }
-
-            if (count >= limit || comp.dataArray.length > 0) {
-              _pageover = true
-            }
-
-            if (comp.dataArray.length === 0) {
+      if (this.state.config.printPage === 'custom' && this.state.config.printScripts) {
+        try {
+          // eslint-disable-next-line
+          let func = new Function('components', 'pages', 'notification', this.state.config.printScripts)
+          func(comps, pages, notification)
+        } catch (e) {
+          console.warn(e)
+    
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔夎剼鏈墽琛岄敊璇紒',
+            duration: 5
+          })
+        }
+      } else {
+        while (!over) {
+          let page = []
+          let count = 0
+          let _pageover = false
+  
+          comps.forEach(comp => {
+            let item = fromJS(comp).toJS()
+  
+            if (item.wrap.printType === 'headerOrfooter') { // 椤电湁椤佃剼
+              item.data = item.dataArray || null
+              setData(item)
+              page.push(item)
               comp.added = true
             }
-
-            setData(item)
-            page.push(item)
-          } else if (!comp.added) {
-            if (item.wrap.printHeight) {
-              count += item.wrap.printHeight
-              if (count >= limit) {
-                _pageover = true
-                return
+  
+            if (_pageover) return
+  
+            if (item.$page && comp.dataArray.length > 0) {
+              item.data = []
+  
+              while (count + 1 <= limit && comp.dataArray.length > 0) {
+                item.data.push(comp.dataArray.shift())
+                count++
               }
+  
+              if (count >= limit || comp.dataArray.length > 0) {
+                _pageover = true
+              }
+  
+              if (comp.dataArray.length === 0) {
+                comp.added = true
+              }
+  
+              setData(item)
+              page.push(item)
+            } else if (!comp.added) {
+              if (item.wrap.printHeight) {
+                count += item.wrap.printHeight
+                if (count >= limit) {
+                  _pageover = true
+                  return
+                }
+              }
+  
+              item.data = item.dataArray || null
+  
+              setData(item)
+              page.push(item)
+              comp.added = true
             }
-
-            item.data = item.dataArray || null
-
-            setData(item)
-            page.push(item)
-            comp.added = true
+          })
+  
+          pages.push(page)
+          pageIndex++
+  
+          if (pageIndex >= 2000 || comps.findIndex(comp => !comp.added) === -1) {
+            over = true
           }
-        })
-
-        pages.push(page)
-        pageIndex++
-
-        if (pageIndex >= 2000 || comps.findIndex(comp => !comp.added) === -1) {
-          over = true
         }
       }
 
@@ -1090,6 +1156,14 @@
   reloadTabs = () => {
     if (this.reloading) return
 
+    let time = new Date().getTime()
+
+    let oldTime = sessionStorage.getItem('mk_reloadTabs')
+    
+    if (oldTime && time - oldTime < 180000) return
+
+    sessionStorage.setItem('mk_reloadTabs', time)
+
     this.reloading = true
 
     Api.getAppVersion(true).then(() => {
diff --git a/src/views/billprint/index.scss b/src/views/billprint/index.scss
index 3ad6384..9616d80 100644
--- a/src/views/billprint/index.scss
+++ b/src/views/billprint/index.scss
@@ -57,6 +57,9 @@
       display: none!important;
     }
   }
+  .braft-content p {
+    margin: 0px!important;
+  }
   .ant-table-thead > tr > th {
     color: rgba(0,0,0,1);
     background: transparent!important;
diff --git a/src/views/design/header/editfirstmenu/index.jsx b/src/views/design/header/editfirstmenu/index.jsx
index 4d1b286..add92a2 100644
--- a/src/views/design/header/editfirstmenu/index.jsx
+++ b/src/views/design/header/editfirstmenu/index.jsx
@@ -92,7 +92,7 @@
       return
     }
     
-    let _this = this
+    let that = this
     confirm({
       title: `纭畾鍒犻櫎鑿滃崟銆�${item.MenuName}銆嬪悧锛焋,
       content: '',
@@ -103,7 +103,7 @@
         }
         return Api.getCloudConfig(param).then(res => {
           if (res.status) {
-            _this.props.reload()
+            that.props.reload()
           } else {
             notification.warning({
               top: 92,
diff --git a/src/views/design/header/index.jsx b/src/views/design/header/index.jsx
index 1184437..20ba503 100644
--- a/src/views/design/header/index.jsx
+++ b/src/views/design/header/index.jsx
@@ -16,6 +16,8 @@
 const VersionsUp = asyncComponent(() => import('./versions'))
 const ThawMenu = asyncComponent(() => import('@/components/thawmenu'))
 const MenuForm = asyncComponent(() => import('./editfirstmenu/menuform'))
+const TransMenu = asyncComponent(() => import('./transmenu'))
+
 const { confirm } = Modal
 
 class Header extends Component {
@@ -24,19 +26,21 @@
     userName: sessionStorage.getItem('CloudUserName'),
     avatar: Utils.getrealurl(sessionStorage.getItem('CloudAvatar')),
     logo: sessionStorage.getItem('CloudLogo') || MainLogo,
+    subLang: sessionStorage.getItem('subLangList') !== null,
     visible: false,
     loading: false
   }
 
   logout = () => {
     // 閫�鍑虹櫥褰�
-    let _this = this
+    let that = this
     confirm({
       title: '鎮ㄧ‘瀹氳閫�鍑哄悧?',
       content: '',
       onOk() {
         sessionStorage.clear()
-        _this.props.history.replace('/login')
+        that.props.history.replace('/login')
+        window.location.reload()
       },
       onCancel() {}
     })
@@ -154,6 +158,9 @@
               } catch (e) {
                 trdItem.PageParam = {OpenType: 'newtab'}
               }
+              if (trdItem.PageParam.Template === 'RolePermission' || trdItem.PageParam.Template === 'NewPage') {
+                trdItem.PageParam.backend = 'level1'
+              }
 
               if (trdItem.type === 'CustomPage' && window.GLOB.memberLevel < 20) { // 浼氬憳绛夌骇澶т簬绛変簬20鏃讹紝鏈夌紪杈戞潈闄�
                 trdItem.forbidden = true
@@ -229,69 +236,69 @@
     }, () => {})
   }
 
-  setSystemFuncs = () => {
-    if (!window.GLOB.IndexDB) {
-      return
-    }
-    this.getfuncTime().then(res => {
-      Api.getSystemFuncs(res.createDate).then(result => {
-        if (!result.status) {
-          notification.error({
-            top: 92,
-            message: result.message,
-            duration: 10
-          })
-        } else if (result.func_detail && result.func_detail.length > 0) {
-          this.writeFuncs(result.func_detail)
-        }
-      })
-    })
-  }
+  // setSystemFuncs = () => {
+  //   if (!window.GLOB.IndexDB) {
+  //     return
+  //   }
+  //   this.getfuncTime().then(res => {
+  //     Api.getSystemFuncs(res.createDate).then(result => {
+  //       if (!result.status) {
+  //         notification.error({
+  //           top: 92,
+  //           message: result.message,
+  //           duration: 10
+  //         })
+  //       } else if (result.func_detail && result.func_detail.length > 0) {
+  //         this.writeFuncs(result.func_detail)
+  //       }
+  //     })
+  //   })
+  // }
 
-  writeFuncs = (funcs) => {
-    let shim = +sessionStorage.getItem('sys_time_shim')
-    let timestamp = moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss')
+  // writeFuncs = (funcs) => {
+  //   let shim = +sessionStorage.getItem('sys_time_shim')
+  //   let timestamp = moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss')
 
-    let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs')
+  //   let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs')
 
-    objectStore.clear()
+  //   objectStore.clear()
 
-    funcs.forEach(item => {
-      if (!item.key_sql) return
-      item.id = item.func_code
-      objectStore.add(item)
-    })
+  //   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) => {
-      let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version')
-      let request = objectStore.get('funcs')
+  // getfuncTime = () => {
+  //   return new Promise((resolve, reject) => {
+  //     let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version')
+  //     let request = objectStore.get('funcs')
 
-      request.onerror = (event) => {
-        console.warn(event)
-        reject()
-      }
+  //     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'})
+  //     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.onerror = () => {
+  //           reject()
+  //         }
+  //         add.onsuccess = () => {
+  //           resolve({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'})
+  //         }
+  //       }
+  //     }
+  //   })
+  // }
 
   getSmStemp = () => {
     if (!sessionStorage.getItem('msgTemplate')) {
@@ -340,10 +347,6 @@
     window.addEventListener('storage', (e) => {
       if (e.key === 'menuUpdate') {
         this.reload()
-      } else if (e.key === 'wxTemplates') {
-        if (e.newValue) {
-          sessionStorage.setItem('wxTemplates', e.newValue)
-        }
       }
     })
     MKEmitter.addListener('mkUpdateMenuList', this.reload)
@@ -381,7 +384,6 @@
       }, 100)
 
       setTimeout(() => {
-        // positecgroup
         // this.setSystemFuncs()
         this.getSmStemp()
       }, 500)
@@ -410,7 +412,7 @@
 
   render () {
     const { mainMenu, editLevel } = this.props
-    const { menulist, visible, loading, logo } = this.state
+    const { menulist, visible, loading, logo, subLang } = this.state
 
     return (
       <header className={'sys-header-container ant-menu-dark ' + (['level2', 'level3'].includes(editLevel) ? 'mask' : '')} id="main-header-container">
@@ -494,6 +496,12 @@
               缂栬緫
             </Button>
           </div> : null}
+          {window.GLOB.systemType !== 'production' && subLang ? <div className="entrance">
+            <div className="icon"><PlusOutlined /></div>
+            <div className="title">鑿滃崟杞崲</div>
+            <div className="detail">鍙�夋嫨姣嶈绯荤粺鐨勮彍鍗曪紝蹇�熻浆鎹㈠埌褰撳墠璇█銆傛墦鍗版ā鏉胯鍦℉S涓嬪鍒跺悗锛屽湪姝ゅ閫夋嫨鎸囧畾妯℃澘杩涜璇█杞崲銆�</div>
+            <TransMenu reload={this.reload} menulist={menulist}/>
+          </div> : null}
         </div>
         {/* 缂栬緫鑿滃崟 */}
         {editLevel === 'level1' ? <EditMenu menulist={this.state.menulist} reload={this.reload} exitEdit={this.exitEdit}/> : null}
diff --git a/src/views/design/header/transmenu/index.jsx b/src/views/design/header/transmenu/index.jsx
new file mode 100644
index 0000000..805f411
--- /dev/null
+++ b/src/views/design/header/transmenu/index.jsx
@@ -0,0 +1,889 @@
+import React, { Component } from 'react'
+import { is, fromJS } from 'immutable'
+import { Modal, Radio, notification, Button, Spin, Select, Cascader } from 'antd'
+import moment from 'moment'
+import md5 from 'md5'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import MenuUtils, { setLangTrans } from '@/utils/utils-custom.js'
+import './index.scss'
+
+const { confirm } = Modal
+
+class TransMenu extends Component {
+  state = {
+    visible: false,
+    loading: false,
+    saveing: false,
+    lang: '',
+    type: '',
+    dicts: [],
+    menus: [],
+    billMenus: [],
+    tabMenus: [],
+    values: '',
+    images: '',
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  trigger = () => {
+    let langs = sessionStorage.getItem('subLangList')
+    langs = JSON.parse(langs)
+
+    this.setState({
+      lang: langs[0],
+      loading: true,
+      visible: true,
+      saveing: false,
+      type: 'menu',
+      images: '',
+      values: ''
+    })
+    
+    this.getDicts()
+    this.getMenus(langs[0])
+  }
+  
+  getDicts = () => {
+    // let sql = `select id,lang,lang_name,mother_tongue,translation,use_type,case when use_type='menu' then '鑿滃崟' when  use_type='button' then '鎸夐挳'  when  use_type='title' then '鏍囬'   when  use_type='list' then '閫夐」' else '鏂囨湰' end as use_type_text from s_app_lang_translation where appkey=@appkey@ and deleted=0 and translation != ''`
+    let sql = `select mother_tongue as reg,translation as value,use_type as type,case when use_type='menu' then '鑿滃崟' when  use_type='button' then '鎸夐挳'  when  use_type='title' then '鏍囬'   when  use_type='list' then '閫夐」' else '鏂囨湰' end as use_type_text from s_app_lang_translation where appkey=@appkey@ and deleted=0 and translation != '' and lang='${sessionStorage.getItem('lang') || ''}'`
+
+    let param = {
+      func: 'sPC_Get_SelectedList',
+      LText: Utils.formatOptions(sql, 'x'),
+      obj_name: 'data',
+      arr_field: 'reg,value,type',
+      exec_type: 'x'
+    }
+
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt('', param.timestamp)
+    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+
+    Api.getCloudConfig(param).then(result => {
+      if (!result.status) {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+        return
+      }
+
+      this.setState({dicts: result.data || []})
+    })
+  }
+
+  getMenus = (lang) => {
+    if (this.state.menus.length > 0) {
+      this.setState({loading: false})
+      return
+    }
+
+    let _param = {
+      func: 's_get_pc_menus',
+      systemType: window.GLOB.sysType,
+      pro_sys: '',
+      lang: lang,
+      debug: 'Y'
+    }
+
+    Api.getCloudConfig(_param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        return
+      }
+
+      let menus = []
+
+      res.fst_menu && res.fst_menu.forEach(fst => {
+        let fstItem = {
+          value: fst.MenuID,
+          label: fst.MenuName,
+          children: []
+        }
+  
+        fst.snd_menu && fst.snd_menu.forEach(snd => {
+          let sndItem = {
+            value: snd.MenuID,
+            label: snd.MenuName,
+            children: []
+          }
+
+          snd.trd_menu && snd.trd_menu.forEach(trd => {
+            let trdItem = {
+              value: trd.MenuID,
+              label: trd.MenuName,
+              MenuNo: trd.MenuNo,
+            }
+
+            if (!trd.PageParam) return
+            
+            let PageParam = null
+            try {
+              PageParam = JSON.parse(trd.PageParam)
+            } catch (e) {
+              PageParam = null
+            }
+
+            if (!PageParam || !['BaseTable', 'CustomPage'].includes(PageParam.Template)) return
+
+            trdItem.PageParam = PageParam
+
+            sndItem.children.push(trdItem)
+          })
+
+          if (sndItem.children.length === 0) return
+
+          fstItem.children.push(sndItem)
+        })
+
+        if (fstItem.children.length === 0) return
+  
+        menus.push(fstItem)
+      })
+
+      menus.push({
+        value: 'home_page_id',
+        label: '棣栭〉',
+      })
+
+      this.setState({menus: menus, loading: false})
+    })
+  }
+
+  submit = () => {
+    const { values, type } = this.state
+
+    if (!values) {
+      notification.warning({
+        top: 92,
+        message: type === 'menu' ? '璇烽�夋嫨鑿滃崟锛�' : '璇烽�夋嫨妯℃澘锛�',
+        duration: 5
+      })
+      return
+    }
+
+    if (type === 'bill') {
+      this.billSubmit()
+      return
+    } else if (type === 'tab') {
+      this.tabSubmit()
+      return
+    }
+
+    if (values.length !== 3 && values[0] !== 'home_page_id') {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨鑿滃崟锛�',
+        duration: 5
+      })
+      return
+    }
+
+    this.setState({saveing: true})
+
+    if (values[0] === 'home_page_id') {
+      this.transThdMenu({
+        value: 'home_page_id',
+        MenuID: 'home_page_id',
+        label: '棣栭〉'
+      })
+    } else {
+      this.transFirstMenu(values[0], values[1], values[2])
+    }
+  }
+
+  transFirstMenu = (firstId, secId, thdId) => {
+    const { menulist } = this.props
+    const { menus, dicts } = this.state
+    let tail = md5(window.GLOB.appkey + sessionStorage.getItem('lang')).toLowerCase()
+
+    tail = tail.slice(-8)
+
+    let oriFirstMenu = menus.filter(item => item.value === firstId)[0]
+    let oriSecMenu = oriFirstMenu.children.filter(item => item.value === secId)[0]
+    let oriThdMenu = oriSecMenu.children.filter(item => item.value === thdId)[0]
+
+    oriThdMenu = fromJS(oriThdMenu).toJS()
+
+    let curFirstId = firstId
+    if (curFirstId.length <= 24) {
+      curFirstId = md5(window.GLOB.appkey + curFirstId + sessionStorage.getItem('lang')).toLowerCase()
+    } else {
+      curFirstId = curFirstId.slice(0, 24) + tail
+    }
+
+    let curSectId = secId
+    if (curSectId.length <= 24) {
+      curSectId = md5(window.GLOB.appkey + curSectId + sessionStorage.getItem('lang')).toLowerCase()
+    } else {
+      curSectId = curSectId.slice(0, 24) + tail
+    }
+
+    let curThdId = thdId
+    if (curThdId.length <= 24) {
+      curThdId = md5(window.GLOB.appkey + curThdId + sessionStorage.getItem('lang')).toLowerCase()
+    } else {
+      curThdId = curThdId.slice(0, 24) + tail
+    }
+
+    let firstName = oriFirstMenu.label
+    let secName = oriSecMenu.label
+
+    dicts.forEach(item => {
+      if (item.type !== 'menu') return
+      if (item.reg === firstName) {
+        firstName = item.value
+      }
+      if (item.reg === secName) {
+        secName = item.value
+      }
+      if (item.reg === oriThdMenu.label) {
+        oriThdMenu.label = item.value
+      }
+    })
+
+    let firstParam = {
+      func: 'sPC_MainMenu_Add',
+      MenuID: curFirstId,
+      MenuName: firstName,
+      PageParam: JSON.stringify({
+        OpenType: 'menu',
+        linkUrl: ''
+      })
+    }
+
+    let secParam = {
+      func: 'sPC_SndMenu_Add',
+      ParentID: curFirstId,
+      MenuID: curSectId,
+      MenuName: secName,
+      PageParam: JSON.stringify({
+        Icon: ''
+      })
+    }
+
+    oriThdMenu.fstMenuId = curFirstId
+    oriThdMenu.parentId = curSectId
+    oriThdMenu.MenuID = curThdId
+
+    if (menulist.findIndex(item => item.MenuID === firstParam.MenuID) === -1) {
+      Api.getCloudConfig(firstParam).then(res => {
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 5
+          })
+          this.setState({saveing: false})
+          return
+        }
+
+        this.transSecondMenu(secParam, oriThdMenu, true)
+      })
+    } else {
+      this.transSecondMenu(secParam, oriThdMenu)
+    }
+  }
+
+  transSecondMenu = (secParam, oriThdMenu, reload) => {
+    const { menulist } = this.props
+
+    let creat = true
+
+    menulist.forEach(item => {
+      if (item.children.findIndex(cell => cell.MenuID === secParam.MenuID) > -1) {
+        creat = false
+      }
+    })
+
+    if (creat) {
+      Api.getCloudConfig(secParam).then(res => {
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 5
+          })
+          this.setState({saveing: false})
+          return
+        }
+
+        this.transThdMenu(oriThdMenu, true)
+      })
+    } else {
+      this.transThdMenu(oriThdMenu, reload)
+    }
+  }
+
+  transThdMenu = (menu, reload) => {
+    const { menulist } = this.props
+    const { lang, dicts } = this.state
+
+    let _param = {
+      func: 'sPC_Get_LongParam',
+      MenuID: menu.value,
+      lang: lang
+    }
+
+    let creat = true
+
+    if (menu.MenuID === 'home_page_id') {
+      creat = false
+    } else {
+      menulist.forEach(item => {
+        item.children.forEach(cell => {
+          if (cell.children.findIndex(n => n.MenuID === menu.MenuID) > -1) {
+            creat = false
+          }
+        })
+      })
+    }
+
+    Api.getCloudConfig(_param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        this.setState({saveing: false})
+        return
+      }
+
+      let config = null
+      if (res.LongParam) {
+        try {
+          config = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
+        } catch (e) {
+          console.warn('Parse Failure')
+          config = ''
+        }
+      }
+
+      if (!config) {
+        notification.warning({
+          top: 92,
+          message: '鏈幏鍙栧埌鑿滃崟閰嶇疆淇℃伅',
+          duration: 5
+        })
+        this.setState({saveing: false})
+
+        if (reload) {
+          this.props.reload()
+        }
+        return
+      }
+
+      let btnDict = {}
+      let titDict = {}
+      let lisDict = {}
+      let regs = []
+
+      dicts.forEach(item => {
+        if (item.type === 'button') {
+          btnDict[item.reg] = item.value
+        } else if (item.type === 'title') {
+          titDict[item.reg] = item.value
+        } else if (item.type === 'list') {
+          lisDict[item.reg] = item.value
+        } else if (item.type === 'text') {
+          regs.push({reg: new RegExp(item.reg, 'g'), value: item.value, sort: item.reg.length})
+        }
+      })
+
+      regs.sort((a, b) => b.sort - a.sort)
+
+      let tail = md5(window.GLOB.appkey + sessionStorage.getItem('lang')).toLowerCase()
+
+      tail = tail.slice(-8)
+
+      setLangTrans(config, btnDict, titDict, lisDict, {}, regs, tail)
+
+      if (config.components) {
+        let commonId = Utils.getuuid()
+        if (config.interfaces && config.interfaces.length > 0) {
+          config.interfaces = config.interfaces.map(inter => {
+            inter.uuid = md5(commonId + inter.uuid)
+            return inter
+          })
+        }
+        config.components = MenuUtils.resetConfig(config.components, commonId, false)
+        config.tables = config.tables || []
+        config.style = config.style || {}
+      }
+
+      delete config.tbkey
+
+      config.enabled = false
+      config.MenuName = menu.label
+      config.fstMenuId = menu.fstMenuId || ''
+      config.parentId = menu.parentId || ''
+      config.uuid = menu.MenuID || ''
+      config.open_edition = ''
+      if (config.MenuNo) {
+        config.MenuNo = config.MenuNo + '_' + sessionStorage.getItem('lang')
+      }
+
+      let param = {
+        func: 'sPC_TrdMenu_AddUpt',
+        FstID: config.fstMenuId,
+        SndID: config.parentId,
+        ParentID: config.parentId,
+        MenuID: config.uuid,
+        MenuNo: config.MenuNo || '',
+        EasyCode: config.easyCode || '',
+        Template: config.Template,
+        MenuName: config.MenuName || '',
+        PageParam: JSON.stringify({Template: config.Template, OpenType: config.OpenType || 'newtab'})
+      }
+
+      if (creat) {
+        param.open_edition = config.open_edition
+        param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
+
+        this.setMenu(param, true)
+      } else {
+        Api.getCloudConfig({
+          func: 'sPC_Get_LongParam',
+          MenuID: menu.MenuID
+        }).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+            this.setState({saveing: false})
+            return
+          }
+
+          config.open_edition = res.open_edition || ''
+          param.open_edition = config.open_edition
+          param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
+  
+          if (res.LongParam) {
+            const that = this
+            confirm({
+              title: '鑿滃崟宸插瓨鍦紝纭畾閲嶆柊鐢熸垚鍚�?',
+              content: '',
+              onOk() {
+                that.setMenu(param, true)
+              },
+              onCancel() {}
+            })
+          } else {
+            this.setMenu(param, true)
+          }
+        })
+      }
+    })
+  }
+
+  setMenu = (param, reload) => {
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt('', param.timestamp)
+
+    Api.getCloudConfig(param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        this.setState({saveing: false})
+        return
+      }
+
+      notification.success({
+        top: 92,
+        message: '娣诲姞鎴愬姛銆�',
+        duration: 5
+      })
+      
+      this.setState({
+        loading: false,
+        visible: false
+      })
+
+      if (reload) {
+        this.props.reload()
+      }
+    })
+  }
+
+  cancel = () => {
+    this.setState({
+      loading: false,
+      visible: false
+    })
+  }
+
+  onChange = (e) => {
+    this.setState({
+      type: e.target.value,
+      images: '',
+      values: ''
+    })
+
+    if (e.target.value === 'bill') {
+      this.getBillMenus()
+    } else if (e.target.value === 'tab') {
+      this.getTabMenus()
+    }
+  }
+
+  getBillMenus = () => {
+    const { billMenus } = this.state
+
+    if (billMenus.length) return
+
+    let _param = {
+      func: 's_get_sPrintTemplate_web',
+      OrderCol: 'ID desc',
+      lang_s: sessionStorage.getItem('lang'),
+      dataM: 'Y',
+      PageIndex: 1,
+      PageSize: 1000
+    }
+
+    Api.getCloudConfig(_param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        return
+      }
+
+      this.setState({billMenus: res.data || []})
+    })
+  }
+
+  getTabMenus = () => {
+    const { tabMenus } = this.state
+
+    if (tabMenus.length) return
+
+    let _param = {
+      func: 's_get_sPrintTemplate',
+      OrderCol: 'ID desc',
+      lang_s: sessionStorage.getItem('lang'),
+      dataM: 'Y',
+      PageIndex: 1,
+      PageSize: 1000
+    }
+
+    Api.getCloudConfig(_param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        return
+      }
+
+      this.setState({tabMenus: res.data || []})
+    })
+  }
+
+  billSubmit = () => {
+    const { dicts, values, billMenus } = this.state
+
+    let _param = {
+      func: 'sPC_Get_LongParam',
+      MenuID: values
+    }
+
+    this.setState({saveing: true})
+
+    let temp = billMenus.filter(item => item.ID === values)[0]
+
+    Api.getCloudConfig(_param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        this.setState({saveing: false})
+        return
+      }
+
+      let config = null
+      if (res.LongParam) {
+        try {
+          config = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
+        } catch (e) {
+          console.warn('Parse Failure')
+          config = ''
+        }
+      }
+
+      if (!config) {
+        notification.warning({
+          top: 92,
+          message: '鏈幏鍙栧埌妯℃澘閰嶇疆淇℃伅',
+          duration: 5
+        })
+        this.setState({saveing: false})
+        return
+      }
+
+      let btnDict = {}
+      let titDict = {}
+      let lisDict = {}
+      let regs = []
+
+      dicts.forEach(item => {
+        if (item.type === 'button') {
+          btnDict[item.reg] = item.value
+        } else if (item.type === 'title') {
+          titDict[item.reg] = item.value
+        } else if (item.type === 'list') {
+          lisDict[item.reg] = item.value
+        } else if (item.type === 'text') {
+          regs.push({reg: new RegExp(item.reg, 'g'), value: item.value, sort: item.reg.length})
+        }
+      })
+
+      regs.sort((a, b) => b.sort - a.sort)
+
+      let tail = md5(window.GLOB.appkey + sessionStorage.getItem('lang')).toLowerCase()
+
+      tail = tail.slice(-8)
+
+      setLangTrans(config, btnDict, titDict, lisDict, {}, regs, tail)
+
+      if (config.components) {
+        let commonId = Utils.getuuid()
+        if (config.interfaces && config.interfaces.length > 0) {
+          config.interfaces = config.interfaces.map(inter => {
+            inter.uuid = md5(commonId + inter.uuid)
+            return inter
+          })
+        }
+        config.components = MenuUtils.resetConfig(config.components, commonId, false)
+        config.tables = config.tables || []
+        config.style = config.style || {}
+      }
+
+      delete config.tbkey
+      
+      config.enabled = false
+      config.MenuNo = temp.PrintTempNO || ''
+      config.MenuName = temp.PrintTempName || ''
+      config.fstMenuId = 'BillPrintTemp'
+      config.parentId = 'BillPrintTemp'
+      config.uuid = values
+      config.MenuID = config.uuid
+
+      config.open_edition = res.open_edition || ''
+
+      let param = {
+        func: 'sPC_TrdMenu_AddUpt',
+        FstID: config.fstMenuId,
+        SndID: config.parentId,
+        ParentID: config.parentId,
+        MenuID: config.uuid,
+        MenuNo: config.MenuNo || '',
+        EasyCode: config.easyCode || '',
+        Template: config.Template,
+        MenuName: config.MenuName || '',
+        open_edition: config.open_edition,
+        PageParam: JSON.stringify({Template: config.Template, OpenType: config.OpenType || 'newtab'})
+      }
+
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+      param.secretkey = Utils.encrypt('', param.timestamp)
+
+      Api.getCloudConfig(param).then(res => {
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 5
+          })
+          this.setState({saveing: false})
+          return
+        }
+
+        notification.success({
+          top: 92,
+          message: '杞崲鎴愬姛銆�',
+          duration: 5
+        })
+        
+        this.setState({
+          saveing: false,
+          visible: false
+        })
+      })
+    })
+  }
+
+  tabSubmit = () => {
+    const { values, dicts, tabMenus } = this.state
+
+    let param = {
+      func: 's_PrintTemplateMGetData',
+      Type: 'Y',
+      ID: values
+    }
+
+    this.setState({saveing: true})
+
+    let temp = tabMenus.filter(item => item.ID === values)[0]
+
+    Api.getCloudConfig(param).then(result => {
+      if (!result.status) {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+        this.setState({saveing: false})
+      } else if (!result.ConfigParam) {
+        notification.warning({
+          top: 92,
+          message: '鏈幏鍙栧埌鎵撳嵃妯℃澘淇℃伅锛�',
+          duration: 5
+        })
+        this.setState({saveing: false})
+      } else {
+        let config = ''
+        try {
+          config = JSON.parse(window.decodeURIComponent(window.atob(result.ConfigParam)))
+        } catch (e) {
+          config = ''
+        }
+  
+        if (!config) {
+          notification.warning({
+            top: 92,
+            message: '鏈幏鍙栧埌鎵撳嵃妯℃澘淇℃伅锛�',
+            duration: 5
+          })
+          this.setState({saveing: false})
+          return
+        }
+
+        let titDict = {}
+
+        dicts.forEach(item => {
+          if (item.type === 'title') {
+            titDict[item.reg] = item.value
+          }
+        })
+
+        config.elements.forEach(item => {
+          if (item.type === 'text' && item.value && titDict[item.value]) {
+            item.value = titDict[item.value]
+          }
+        })
+
+        config.name = temp.PrintTempName || ''
+        config.remark = temp.Remark || ''
+        config.PrintTempNO = temp.PrintTempNO || ''
+
+        let _param = {
+          func: 's_PrintTemplateMSub',
+          ID: values,
+          ConfigParam: window.btoa(window.encodeURIComponent(JSON.stringify(config))),
+          Images: temp.Images || '',
+          PrintTempName: config.name,
+          Remark: config.remark,
+          PrintTempNO: config.PrintTempNO
+        }
+
+        Api.getCloudConfig(_param).then(result => {
+          if (!result.status) {
+            notification.warning({
+              top: 92,
+              message: result.message,
+              duration: 5
+            })
+            this.setState({saveing: false})
+            return
+          }
+
+          notification.success({
+            top: 92,
+            message: '杞崲鎴愬姛銆�',
+            duration: 5
+          })
+          
+          this.setState({
+            saveing: false,
+            visible: false
+          })
+        })
+      }
+    })
+  }
+
+  render () {
+    const { visible, loading, saveing, menus, type, billMenus, tabMenus, images } = this.state
+
+    return (
+      <>
+        <Button type="primary" onClick={this.trigger}>
+          杞崲
+        </Button>
+        <Modal
+          wrapClassName="sync-menu-modal"
+          title="鑿滃崟杞崲"
+          visible={visible}
+          width={600}
+          closable={false}
+          maskClosable={false}
+          onOk={this.submit}
+          onCancel={this.cancel}
+          confirmLoading={saveing}
+          destroyOnClose
+        >
+          {loading ? <Spin /> : <div>
+            <Radio.Group defaultValue="menu" onChange={this.onChange}>
+              <Radio.Button value="menu">鑿滃崟</Radio.Button>
+              <Radio.Button value="bill">鍗曟嵁鎵撳嵃妯℃澘</Radio.Button>
+              <Radio.Button value="tab">鏍囩鎵撳嵃妯℃澘</Radio.Button>
+            </Radio.Group>
+            {type === 'menu' ? <Cascader popupClassName="sync-cascader" onChange={(val) => this.setState({values: val})} options={menus} expandTrigger="hover" placeholder="璇烽�夋嫨鑿滃崟"/> : null}
+            {type === 'bill' ? <Select
+              showSearch
+              placeholder="璇烽�夋嫨鍗曟嵁妯℃澘"
+              dropdownMatchSelectWidth={false}
+              onChange={(val, option) => this.setState({values: val, images: option.props.images || ''})}
+              filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+            >
+              {billMenus.map((item, i) => (<Select.Option key={i} images={item.Images || ''} value={item.ID}>{`${item.PrintTempName}锛�${item.PrintTempNO}锛塦}</Select.Option>))}
+            </Select> : null}
+            {type === 'tab' ? <Select
+              showSearch
+              placeholder="璇烽�夋嫨鏍囩妯℃澘"
+              dropdownMatchSelectWidth={false}
+              onChange={(val, option) => this.setState({values: val, images: option.props.images || ''})}
+              filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+            >
+              {tabMenus.map((item, i) => (<Select.Option key={i} images={item.Images || ''} value={item.ID}>{`${item.PrintTempName}锛�${item.PrintTempNO}锛塦}</Select.Option>))}
+            </Select> : null}
+            {images ? <img src={images} alt=""/> : null}
+          </div>}
+        </Modal>
+      </>
+    )
+  }
+}
+
+export default TransMenu
\ No newline at end of file
diff --git a/src/views/design/header/transmenu/index.scss b/src/views/design/header/transmenu/index.scss
new file mode 100644
index 0000000..9d4d17c
--- /dev/null
+++ b/src/views/design/header/transmenu/index.scss
@@ -0,0 +1,36 @@
+.sync-menu-modal {
+  .ant-modal-body {
+    position: relative;
+    padding: 24px 50px;
+    min-height: 250px;
+    max-height: calc(100vh - 210px);
+    .ant-cascader-picker, .ant-select {
+      width: 300px;
+    }
+    .ant-radio-group {
+      display: block;
+      margin-bottom: 20px;
+      .ant-radio-button-wrapper {
+        width: 150px;
+        text-align: center;
+      }
+    }
+    img {
+      max-width: 300px;
+      max-height: 150px;
+      display: block;
+      margin: 10px;
+    }
+    .ant-spin {
+      position: absolute;
+      left: calc(50% - 10px);
+      top: 75px;
+    }
+  }
+}
+.sync-cascader {
+  .ant-cascader-menu {
+    height: 200px;
+    min-width: 120px;
+  }
+}
\ No newline at end of file
diff --git a/src/views/design/index.jsx b/src/views/design/index.jsx
index f965c69..080b267 100644
--- a/src/views/design/index.jsx
+++ b/src/views/design/index.jsx
@@ -6,7 +6,7 @@
 
 import Header from './header'
 import Sidemenu from './sidemenu'
-import { setGLOBFuncs } from '@/utils/utils.js'
+// import { setGLOBFuncs } from '@/utils/utils.js'
 
 import '@/assets/css/design.scss'
 import './index.scss'
@@ -34,7 +34,7 @@
       window.GLOB.breakpoint = false
       window.GLOB.designView = true
       sessionStorage.removeItem('breakpoint')
-      setGLOBFuncs()
+      // setGLOBFuncs()
     }
   }
 
diff --git a/src/views/design/sidemenu/editthdmenu/index.jsx b/src/views/design/sidemenu/editthdmenu/index.jsx
index d482996..e90f4a7 100644
--- a/src/views/design/sidemenu/editthdmenu/index.jsx
+++ b/src/views/design/sidemenu/editthdmenu/index.jsx
@@ -214,8 +214,8 @@
         MenuName: res.MenuName,
         PageParam: JSON.stringify(PageParam),
         LongParam: '',
-        LText: '',
-        LTexttb: ''
+        // LText: '',
+        // LTexttb: ''
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
diff --git a/src/views/design/sidemenu/index.jsx b/src/views/design/sidemenu/index.jsx
index d43da38..c8a061f 100644
--- a/src/views/design/sidemenu/index.jsx
+++ b/src/views/design/sidemenu/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import { is, fromJS } from 'immutable'
 import { Menu, Popover, Modal, notification } from 'antd'
-import { EditOutlined, PlusOutlined, SettingOutlined, ApiOutlined } from '@ant-design/icons'
+import { EditOutlined, PlusOutlined, SettingOutlined, ApiOutlined, SoundOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -249,8 +249,8 @@
         MenuName: res.MenuName,
         PageParam: JSON.stringify(PageParam),
         LongParam: '',
-        LText: '',
-        LTexttb: ''
+        // LText: '',
+        // LTexttb: ''
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -326,7 +326,7 @@
                 {item.children.map(cell => {
                   return (
                     <Menu.Item key={cell.MenuID}>
-                      <span className={'editable-menu-item ' + (cell.up_action ? 'unupdate' : '')} onDoubleClick={() => this.editmenu(cell)}>{cell.PageParam && cell.PageParam.interfaces === 'true' ? <ApiOutlined title="鑿滃崟涓娇鐢ㄤ簡澶栭儴鎺ュ彛" /> : null}{cell.MenuName}</span>
+                      <span className={'editable-menu-item ' + (cell.up_action ? 'unupdate' : '') + (window.backend && window.GLOB.systemType !== 'production' && cell.PageParam.backend !== 'level1' ? ' unbackend' : '')} onDoubleClick={() => this.editmenu(cell)}>{cell.PageParam.interfaces === 'true' ? <ApiOutlined title="鑿滃崟涓娇鐢ㄤ簡澶栭儴鎺ュ彛" /> : null}{cell.PageParam.msg === 'true' ? <SoundOutlined title="鑿滃崟涓彂閫佷簡娑堟伅" /> : null}{cell.MenuName}</span>
                     </Menu.Item>
                   )
                 })}
diff --git a/src/views/design/sidemenu/index.scss b/src/views/design/sidemenu/index.scss
index 3521e56..8c978da 100644
--- a/src/views/design/sidemenu/index.scss
+++ b/src/views/design/sidemenu/index.scss
@@ -23,11 +23,31 @@
         top: 11px;
         color: orange;
       }
+      .anticon-sound {
+        position: absolute;
+        left: 25px;
+        top: 11px;
+        color: orange;
+      }
+      .anticon-api + .anticon-sound {
+        left: 5px;
+      }
     }
 
     .editable-menu-item.unupdate {
       color: orange;
     }
+    .editable-menu-item.unbackend::before {
+      content: '';
+      display: block;
+      position: absolute;
+      width: 4px;
+      height: 4px;
+      background-color: orange;
+      border-radius: 4px;
+      top: 10px;
+      left: 42px;
+    }
   }
   .ant-menu-sub.ant-menu-inline {
     position: relative;
diff --git a/src/views/design/sidemenu/thdmenuplus/index.jsx b/src/views/design/sidemenu/thdmenuplus/index.jsx
index be78279..e657796 100644
--- a/src/views/design/sidemenu/thdmenuplus/index.jsx
+++ b/src/views/design/sidemenu/thdmenuplus/index.jsx
@@ -174,8 +174,8 @@
         MenuName: values.MenuName,
         PageParam: JSON.stringify(PageParam),
         LongParam: '',
-        LText: '',
-        LTexttb: '',
+        // LText: '',
+        // LTexttb: '',
         Sort: sysMenu.menuSort
       }
 
@@ -246,6 +246,8 @@
 
           config.components = MenuUtils.resetConfig(config.components, commonId)
           config.enabled = false
+          
+          delete config.tbkey
 
           param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(config)))
         }
diff --git a/src/views/imdesign/index.jsx b/src/views/imdesign/index.jsx
index 6bd3c0c..1960d4b 100644
--- a/src/views/imdesign/index.jsx
+++ b/src/views/imdesign/index.jsx
@@ -2,13 +2,11 @@
 import { withRouter } from 'react-router'
 import { is, fromJS } from 'immutable'
 import moment from 'moment'
-import { ConfigProvider, notification, Modal, Collapse, Button, Spin } from 'antd'
+import { notification, Modal, Collapse, Button, Spin } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined, LeftOutlined, UserOutlined, EllipsisOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
-import antdEnUS from 'antd/es/locale/en_US'
-import antdZhCN from 'antd/es/locale/zh_CN'
 // import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import getWrapForm from './options'
@@ -32,7 +30,6 @@
 
 class ImDesign extends Component {
   state = {
-    localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
     loading: true,
     MenuId: '',
     MenuName: '',
@@ -49,10 +46,12 @@
     try {
       let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
 
+      if (param.lang) {
+        sessionStorage.setItem('lang', param.lang)
+      }
       if (param.type === 'app') {
         sessionStorage.setItem('appId', param.ID || '')
         sessionStorage.setItem('appName', param.remark || '')
-        sessionStorage.setItem('lang', param.lang || 'zh-CN')
         sessionStorage.setItem('kei_no', param.kei_no || '')
         sessionStorage.setItem('typename', param.typename || 'mob')
         sessionStorage.setItem('adapter', param.adapter || '')
@@ -60,9 +59,6 @@
         sessionStorage.setItem('userbind', param.userbind || '')
         sessionStorage.setItem('instantMessage', param.instantMessage || '')
 
-        this.setState({
-          localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
-        })
         this.getAppMessage(param.MenuID)
       } else if (param.type === 'view') {
         window.GLOB.winWidth = 420
@@ -149,7 +145,8 @@
     let param = {
       MenuID: config.wrap.linkmenu,
       copyMenuId: '',
-      type: 'view'
+      type: 'view',
+      lang: sessionStorage.getItem('lang')
     }
 
     param = window.btoa(window.encodeURIComponent(JSON.stringify(param)))
@@ -177,7 +174,7 @@
       }
 
       sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
-      this.props.history.replace('/imdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID, type: 'view'}))))
+      this.props.history.replace('/imdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID, type: 'view', lang: sessionStorage.getItem('lang')}))))
       window.location.reload()
     })
   }
@@ -361,8 +358,8 @@
         PageParam: JSON.stringify({Template: 'imPage'}),
         open_edition: config.open_edition,
         menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify({type: 'im', key: config.uuid, title: config.MenuName, children: []}))),
-        LText: '',
-        LTexttb: ''
+        // LText: '',
+        // LTexttb: ''
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -421,96 +418,94 @@
   }
 
   render () {
-    const { localedict, loading, settingshow, controlshow, MenuId, config, menuloading } = this.state
+    const { loading, settingshow, controlshow, MenuId, config, menuloading } = this.state
 
     return (
-      <ConfigProvider locale={localedict}>
-        <div className="mk-mob-view" id="mk-mob-design-view">
-          <Header/>
-          {loading ? <Spin className="view-spin" size="large" /> : null}
-          <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
-            <div className="draw">
-              {settingshow ? <DoubleLeftOutlined onClick={() => {this.setState({settingshow: false})}} /> : null}
-              {!settingshow ? <DoubleRightOutlined onClick={() => {this.setState({settingshow: true})}} /> : null}
-            </div>
-            <div className="pc-setting-tools">
-              <Collapse accordion defaultActiveKey="basedata" bordered={false}>
-                {/* 鍩烘湰淇℃伅 */}
-                <Panel header="鍩烘湰淇℃伅" forceRender key="basedata">
-                  {/* 鑿滃崟淇℃伅 */}
-                  {config ? <MenuForm
-                    config={config}
-                    MenuId={MenuId}
-                    updateConfig={this.updateConfig}
-                  /> : null}
-                </Panel>
-                <Panel header="椤甸潰鏍峰紡" key="background">
-                  {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
-                </Panel>
-              </Collapse>
-            </div>
+      <div className="mk-mob-view" id="mk-mob-design-view">
+        <Header/>
+        {loading ? <Spin className="view-spin" size="large" /> : null}
+        <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
+          <div className="draw">
+            {settingshow ? <DoubleLeftOutlined onClick={() => {this.setState({settingshow: false})}} /> : null}
+            {!settingshow ? <DoubleRightOutlined onClick={() => {this.setState({settingshow: true})}} /> : null}
           </div>
-          <div className={'menu-control ' + (!controlshow ? 'hidden' : '')}>
-            <div className="draw">
-              {controlshow ? <DoubleRightOutlined onClick={() => {this.setState({controlshow: false})}}/> : null}
-              {!controlshow ? <DoubleLeftOutlined onClick={() => {this.setState({controlshow: true})}}/> : null}
-            </div>
-            <div className="wrap">
-              <Button type="primary" onClick={this.submitConfig} id="save-config" loading={menuloading}>淇濆瓨</Button>
-              <NormalForm title="鍗虫椂閫氫俊璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
-                <Button type="default" style={{borderColor: 'rgb(64, 169, 255)', color: 'rgb(64, 169, 255)'}}>璁剧疆</Button>
-              </NormalForm>
-              <Button type="default" className="mk-border-purple" onClick={this.backView}>鍚庨��</Button>
-              <CreateView resetmenu={this.getAppMenus} />
-              <Transfer MenuID={MenuId} />
-              <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
-            </div>
+          <div className="pc-setting-tools">
+            <Collapse accordion defaultActiveKey="basedata" bordered={false}>
+              {/* 鍩烘湰淇℃伅 */}
+              <Panel header="鍩烘湰淇℃伅" forceRender key="basedata">
+                {/* 鑿滃崟淇℃伅 */}
+                {config ? <MenuForm
+                  config={config}
+                  MenuId={MenuId}
+                  updateConfig={this.updateConfig}
+                /> : null}
+              </Panel>
+              <Panel header="椤甸潰鏍峰紡" key="background">
+                {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
+              </Panel>
+            </Collapse>
           </div>
-          <div className={'menu-body menu-view'}>
-            <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}>
-              <div className="instant-message" style={config ? config.style : null}>
-                <div className="header">
-                  <LeftOutlined/>
-                  <span className="title">鏈嬪弸</span>
-                  {config && config.wrap.linkmenu ? <EllipsisOutlined onDoubleClick={this.changeEditMenu}/> : null}
-                </div>
-                <div className="mk-content-wrap">
-                  <div className="line-wrap">
-                    <div className="time-line">12:34</div>
-                    <div className="line-msg">
-                      <div className="portrait">
-                        <div className="img"><UserOutlined /></div>
-                      </div>
-                      <div className="msg">
-                        <div className="title">鏈嬪弸</div>
-                        <div className="words">鎮ㄥソ</div>
-                      </div>
+        </div>
+        <div className={'menu-control ' + (!controlshow ? 'hidden' : '')}>
+          <div className="draw">
+            {controlshow ? <DoubleRightOutlined onClick={() => {this.setState({controlshow: false})}}/> : null}
+            {!controlshow ? <DoubleLeftOutlined onClick={() => {this.setState({controlshow: true})}}/> : null}
+          </div>
+          <div className="wrap">
+            <Button type="primary" onClick={this.submitConfig} id="save-config" loading={menuloading}>淇濆瓨</Button>
+            <NormalForm title="鍗虫椂閫氫俊璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+              <Button type="default" style={{borderColor: 'rgb(64, 169, 255)', color: 'rgb(64, 169, 255)'}}>璁剧疆</Button>
+            </NormalForm>
+            <Button type="default" className="mk-border-purple" onClick={this.backView}>鍚庨��</Button>
+            <CreateView resetmenu={this.getAppMenus} />
+            <Transfer MenuID={MenuId} />
+            <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
+          </div>
+        </div>
+        <div className={'menu-body menu-view'}>
+          <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}>
+            <div className="instant-message" style={config ? config.style : null}>
+              <div className="header">
+                <LeftOutlined/>
+                <span className="title">鏈嬪弸</span>
+                {config && config.wrap.linkmenu ? <EllipsisOutlined onDoubleClick={this.changeEditMenu}/> : null}
+              </div>
+              <div className="mk-content-wrap">
+                <div className="line-wrap">
+                  <div className="time-line">12:34</div>
+                  <div className="line-msg">
+                    <div className="portrait">
+                      <div className="img"><UserOutlined /></div>
                     </div>
-                  </div>
-                  <div className="line-wrap">
-                    <div className="time-line">12:45</div>
-                    <div className="line-msg right">
-                      <div className="msg">
-                        <div className="words">
-                          鎮ㄥソ
-                        </div>
-                      </div>
-                      <div className="portrait">
-                        <div className="img"><UserOutlined /></div>
-                      </div>
+                    <div className="msg">
+                      <div className="title">鏈嬪弸</div>
+                      <div className="words">鎮ㄥソ</div>
                     </div>
                   </div>
                 </div>
-                <div className="send-wrap">
-                  <div className="adm-input"></div>
-                  <div className="send"><Button>鍙戦��</Button></div>
+                <div className="line-wrap">
+                  <div className="time-line">12:45</div>
+                  <div className="line-msg right">
+                    <div className="msg">
+                      <div className="words">
+                        鎮ㄥソ
+                      </div>
+                    </div>
+                    <div className="portrait">
+                      <div className="img"><UserOutlined /></div>
+                    </div>
+                  </div>
                 </div>
+              </div>
+              <div className="send-wrap">
+                <div className="adm-input"></div>
+                <div className="send"><Button>鍙戦��</Button></div>
               </div>
             </div>
           </div>
-          <StyleController />
         </div>
-      </ConfigProvider>
+        <StyleController />
+      </div>
     )
   }
 }
diff --git a/src/views/interface/history/index.jsx b/src/views/interface/history/index.jsx
index 2b3bdb6..4d313e6 100644
--- a/src/views/interface/history/index.jsx
+++ b/src/views/interface/history/index.jsx
@@ -43,13 +43,13 @@
   }
 
   clear = () => {
-    const _this = this
+    const that = this
     confirm({
       content: 'Are you sure you want to clear all your history requests?',
       onOk() {
         Api.clearInterfaces()
 
-        _this.setState({list: [], historys: []})
+        that.setState({list: [], historys: []})
       },
       onCancel() {}
     })
diff --git a/src/views/interface/index.jsx b/src/views/interface/index.jsx
index 573e87c..f13789e 100644
--- a/src/views/interface/index.jsx
+++ b/src/views/interface/index.jsx
@@ -1,7 +1,5 @@
-import React, {Component} from 'react'
-import { ConfigProvider } from 'antd'
-import enUS from 'antd/es/locale/en_US'
-import zhCN from 'antd/es/locale/zh_CN'
+import React, { Component } from 'react'
+import { withRouter } from 'react-router'
 
 import Header from './header'
 import History from './history'
@@ -9,20 +7,25 @@
 
 import './index.scss'
 
-const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
-
 class Interface extends Component {
+  componentDidMount () {
+    if (!sessionStorage.getItem('UserID') || /^visitor/.test(sessionStorage.getItem('UserID'))) {
+      this.props.history.replace('/login')
+      return
+    }
+  }
   render () {
+    if (!sessionStorage.getItem('UserID') || /^visitor/.test(sessionStorage.getItem('UserID'))) {
+      return null
+    }
     return (
       <div className="interface-view">
-        <ConfigProvider locale={_locale}>
-          <Header key="header"/>
-          <History key="history"/>
-          <WorkSpace key="workspace"/>
-        </ConfigProvider>
+        <Header key="header"/>
+        <History key="history"/>
+        <WorkSpace key="workspace"/>
       </div>
     )
   }
 }
 
-export default Interface
\ No newline at end of file
+export default withRouter(Interface)
\ No newline at end of file
diff --git a/src/views/interface/workspace/request/index.jsx b/src/views/interface/workspace/request/index.jsx
index 33f2c1e..a73885e 100644
--- a/src/views/interface/workspace/request/index.jsx
+++ b/src/views/interface/workspace/request/index.jsx
@@ -226,6 +226,9 @@
     param.sign = md5(values)
     param.t = param.t || new Date().getTime()
 
+    window.mkInfo(values)
+    window.mkInfo(param.sign)
+
     return param
   }
 
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index 70daeea..37d2515 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -7,8 +7,6 @@
 import Utils from '@/utils/utils.js' 
 import MKEmitter from '@/utils/events.js'
 import { styles } from '@/store/options.js'
-import zhCN from '@/locales/zh-CN/login.js'
-import enUS from '@/locales/en-US/login.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncLoadComponent from '@/utils/asyncLoadComponent'
 import './index.scss'
@@ -17,14 +15,9 @@
 const Resetpwd = asyncLoadComponent(() => import('@/components/resetPassword'))
 const LoginCloudForm = asyncComponent(() => import('./logincloudform'))
 const LoginCodeForm = asyncComponent(() => import('./logincodeform'))
-const iszhCN = sessionStorage.getItem('lang') !== 'en-US'
-
-const _href = window.location.href.split('#')[0]
 
 class Login extends Component {
   state = {
-    selectedlang: iszhCN ? 'zh-CN' : 'en-US',
-    dict: iszhCN ? zhCN : enUS,
     isDisabled: false,
     auth: false,
     authError: '',
@@ -38,7 +31,6 @@
     langList: [],
     syncApp: false,
     loginWays: null,
-    touristLogin: false,
     syncing: false,
   }
 
@@ -133,7 +125,7 @@
       sessionStorage.removeItem('visitorUserID')
       sessionStorage.removeItem('visitorLoginUID')
       
-      let users = localStorage.getItem(_href + 'users')
+      let users = localStorage.getItem(window.GLOB.sysSign + 'users')
       
       if (users) {
         try {
@@ -164,9 +156,9 @@
 
       users.unshift({username: param.username, password: param.remember ? param.password : ''})
 
-      localStorage.setItem(_href + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(users))))
+      localStorage.setItem(window.GLOB.sysSign + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(users))))
 
-      let level = localStorage.getItem(_href + 'pwdlevel')
+      let level = localStorage.getItem(window.GLOB.sysSign + 'pwdlevel')
 
       if (level && process.env.NODE_ENV === 'production') {
         let visible = false
@@ -371,6 +363,9 @@
     // md5("/ws/location/v1/ip?callback=callbackFunction&key=key&output=jsonp secret key")
     // md5("/ws/location/v1/ip?callback=callbackFunction&key=BA7BZ-4QB65-LFCIA-QPDA6-4G6O7-MJB4Q&output=jsonpuThL4ZM3XOj642ksEQh76tyHFjh4")
 
+    sessionStorage.removeItem('subLangList')
+    sessionStorage.removeItem('langList')
+
     setTimeout(() => {
       Api.delCacheConfig()
     }, 50)
@@ -383,14 +378,14 @@
       }
     }
 
-    const _addressUrl = _href + 'queryAddress'
+    const _addressUrl = window.location.href.split('#')[0] + 'queryAddress'
 
     if (localStorage.getItem(_addressUrl) === 'true') {
       this.queryAddress()
     }
 
     const timeStamp = new Date().getTime()
-    const _authUrl = _href + 'AuthCode'
+    const _authUrl = window.location.href.split('#')[0] + 'AuthCode'
 
     let authCode = localStorage.getItem(_authUrl)
     let _s = md5('mksoft' + moment().format('YYYYMMDD'))
@@ -437,7 +432,7 @@
           lictime = Math.floor(new Date(lictime).getTime() / 86400000)
           let curtime = Math.floor(new Date().getTime() / 86400000)
           let licday = lictime - curtime
-          let _mindUrl = _href + 'notMind'
+          let _mindUrl = window.location.href.split('#')[0] + 'notMind'
 
           if (licday < 0 || isNaN(licday)) {
             Modal.warning({
@@ -527,12 +522,12 @@
             localStorage.setItem(_authUrl, box)
 
             if (res.e_files === 'true') {
-              localStorage.setItem(_href + 'files', md5(_href + 'files'))
-              localStorage.setItem(_href + 'filesDate', res.e_files_end_date)
+              localStorage.setItem(window.GLOB.sysSign + 'files', md5(window.GLOB.sysSign + 'files'))
+              localStorage.setItem(window.GLOB.sysSign + 'filesDate', res.e_files_end_date)
               window.GLOB.storeFiles = true
               window.GLOB.storeDate = Math.ceil((new Date(res.e_files_end_date).getTime() - new Date().getTime()) / 86400000)
             } else {
-              localStorage.removeItem(_href + 'files')
+              localStorage.removeItem(window.GLOB.sysSign + 'files')
               window.GLOB.storeFiles = false
             }
     
@@ -548,7 +543,7 @@
             }
           } else {
             localStorage.removeItem(_authUrl)
-            localStorage.removeItem(_href + 'files')
+            localStorage.removeItem(window.GLOB.sysSign + 'files')
             window.GLOB.storeFiles = false
 
             this.setState({
@@ -622,10 +617,6 @@
         sessionStorage.setItem('visitorUserID', result.UserID || '')
         sessionStorage.setItem('visitorLoginUID', result.LoginUID || '')
 
-        if (result.UserID && result.LoginUID) {
-          this.setState({touristLogin: true})
-        }
-
         // 鑾峰彇绯荤粺淇℃伅
         let _param = {
           func: 's_Get_style',
@@ -644,7 +635,7 @@
           
           if (res.status) {
             // positecgroup
-            // if (window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
+            // if (res.member_type && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
             //   if (md5(('mk' + window.GLOB.appkey + res.sys_datetime + res.member_type + res.registry_date).toLowerCase()) !== res.secret_key) {
             //     Modal.warning({
             //       title: '瀵嗛挜閿欒锛岃鑱旂郴绠$悊鍛橈紒',
@@ -668,14 +659,13 @@
               res.menu_type = 'shutter'
             }
 
-            let _url = _href + 'system'
             let systemMsg = {
               favicon: res.titlelogo || '',
               platTitle: res.titleName || '',
               platName: res.SysName || '',
               bgImage: res.Banner || '',
               loginlogo: res.loginlogo || '',
-              copyRight: res.CopyRightYear && res.CopyRightOrg ? `Copyright漏${res.CopyRightYear}    ${this.state.dict['login.copyright']}    ${res.CopyRightOrg}` : '',
+              copyRight: res.CopyRightYear && res.CopyRightOrg ? `Copyright漏${res.CopyRightYear}    ${window.GLOB.dict['copyrights_by'] || '鎵�鏈夌浉鍏崇増鏉冨綊'}    ${res.CopyRightOrg}` : '',
               ICP: res.ICP || '',
               mainlogo: res.indexlogo || '',
               doclogo: res.doclogo || '',
@@ -704,12 +694,12 @@
               level = ''
             }
 
-            localStorage.setItem(_href + 'pwdlevel', level)
+            localStorage.setItem(window.GLOB.sysSign + 'pwdlevel', level)
 
             if (res.srcid) {
-              localStorage.setItem(_href + 'srcId', res.srcid)
+              localStorage.setItem(window.GLOB.sysSign + 'srcId', res.srcid)
             } else {
-              localStorage.removeItem(_href + 'srcId')
+              localStorage.removeItem(window.GLOB.sysSign + 'srcId')
             }
 
             sessionStorage.setItem('home_background', res.index_background_color || '')
@@ -724,21 +714,41 @@
             document.title = systemMsg.platTitle
 
             try {
-              localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify(systemMsg))))
+              localStorage.setItem(window.GLOB.sysSign + 'system', window.btoa(window.encodeURIComponent(JSON.stringify(systemMsg))))
             } catch (e) {
-              localStorage.removeItem(_url)
+              localStorage.removeItem(window.GLOB.sysSign + 'system')
             }
 
-            let _loginurl = _href + 'loginways'
+            if (res.lang_translation_js && res.lang_data && res.lang_data[0] && (res.lang_data.length > 1 || res.lang_data[0].Lang !== 'zh-CN')) {
+              let lang = sessionStorage.getItem('lang')
+              let js_trans = res.lang_translation_js.map(item => {
+                if (['not_empty', 'not_zero', 'max_limit', 'less_limit'].includes(item.msn_code)) {
+                  item.translation = ' ' + item.translation
+                }
+                if (['input_tip', 'select_tip', 'max_limit', 'less_limit'].includes(item.msn_code)) {
+                  item.translation = item.translation + ' '
+                }
+                if (lang === item.lang) {
+                  window.GLOB.dict[item.msn_code] = item.translation
+                }
+
+                return {
+                  lang: item.lang,
+                  key: item.msn_code,
+                  val: item.translation
+                }
+              })
+
+              localStorage.setItem(window.GLOB.sysSign + 'js_trans', JSON.stringify(js_trans))
+            }
+
+            let _loginurl = window.GLOB.sysSign + 'loginways'
             let login_ways = []
-            let login_types = []
             if (res.login_ways && res.login_ways.length > 0) {
               res.login_ways.forEach(item => {
                 // 鐭俊楠岃瘉鐮佺櫥褰曪紝蹇呴』璁剧疆鐭俊Id
                 if (item.way_no === 'sms_vcode' && !item.sms_id) return
-                if (login_types.includes(item.way_no)) return
-
-                login_types.push(item.way_no)
+                if (!['sms_vcode', 'uname_pwd', 'app_scan', 'weixin_scan'].includes(item.way_no)) return
 
                 login_ways.push({
                   type: item.way_no,
@@ -760,6 +770,30 @@
               localStorage.setItem(_loginurl, window.btoa(window.encodeURIComponent(JSON.stringify(login_ways))))
             } catch (e) {
               localStorage.removeItem(_loginurl)
+            }
+
+            if (res.lang_data && res.lang_data.length > 1 && window.GLOB.systemType !== 'production') {
+              let list = res.lang_data.map(item => item.Lang)
+              let lang = 'zh-CN'
+              if (window.GLOB.defLang && list.includes(window.GLOB.defLang)) {
+                lang = window.GLOB.defLang
+              }
+
+              if (list.includes(lang)) {
+                list = [lang, ...list.filter(item => item !== lang)]
+                if (lang === sessionStorage.getItem('lang')) {
+                  sessionStorage.setItem('langList', JSON.stringify(list))
+                } else {
+                  sessionStorage.setItem('subLangList', JSON.stringify(list))
+                }
+              }
+            }
+
+            if (res.lang_data.length === 1 && res.lang_data[0].Lang !== sessionStorage.getItem('lang')) {
+              localStorage.setItem(window.location.href.split('#')[0] + 'lang', res.lang_data[0].Lang)
+              sessionStorage.setItem('lang', res.lang_data[0].Lang)
+              window.location.reload()
+              return
             }
             
             this.setState({
@@ -822,7 +856,7 @@
       }
     })
     
-    let loginWays = localStorage.getItem(_href + 'loginways')
+    let loginWays = localStorage.getItem(window.GLOB.sysSign + 'loginways')
     if (loginWays) {
       try {
         loginWays = JSON.parse(window.decodeURIComponent(window.atob(loginWays)))
@@ -935,7 +969,7 @@
         })
 
         if (result.verifyResult === 'success') {
-          let level = localStorage.getItem(_href + 'pwdlevel')
+          let level = localStorage.getItem(window.GLOB.sysSign + 'pwdlevel')
           if (level) {
             let visible = false
             let tip = '瀵嗙爜寮哄害涓嶅锛岃淇敼瀵嗙爜锛�'
@@ -985,7 +1019,7 @@
   }
 
   render () {
-    const { lineColor, loginlogo, bgImage, copyRight, webSite, ICP, loginWays, touristLogin, platName } = this.state
+    const { lineColor, loginlogo, bgImage, copyRight, webSite, ICP, loginWays, platName } = this.state
 
     return (
       <div className="login-container" id="mk-login-view">
@@ -994,13 +1028,10 @@
         </div>
         <div className="login-middle" style={bgImage ? {backgroundImage: 'url(' + bgImage + ')'} : null}>
           {loginWays ? <LoginForm
-            dict={this.state.dict}
             auth={this.state.auth}
             authError={this.state.authError}
             platName={platName}
-            touristLogin={touristLogin}
             loginWays={loginWays}
-            lang={this.state.selectedlang}
             langList={this.state.langList}
             isDisabled={this.state.isDisabled}
             handleSubmit={() => this.handleSubmit()}
@@ -1017,9 +1048,7 @@
         </div>
         {/* 缂栬緫鐘舵�佺櫥褰� */}
         <Modal
-          title={this.state.dict['login.sync.cloud']}
-          okText={this.state.dict['login.ok']}
-          cancelText={this.state.dict['login.cancel']}
+          title="鍚屾浜戠搴旂敤"
           visible={this.state.syncApp}
           onOk={this.syncSubmit}
           maskClosable={false}
@@ -1036,8 +1065,8 @@
         {/* 浜屾楠岃瘉 */}
         <Modal
           title="浜屾楠岃瘉"
-          okText={this.state.dict['login.ok']}
-          cancelText={this.state.dict['login.cancel']}
+          okText={window.GLOB.dict['ok'] || '纭畾'}
+          cancelText={window.GLOB.dict['cancel'] || '鍙栨秷'}
           visible={this.state.codeVisible}
           onOk={this.codeSubmit}
           maskClosable={false}
diff --git a/src/views/login/logincloudform.jsx b/src/views/login/logincloudform.jsx
index 374ef07..7ecb9f5 100644
--- a/src/views/login/logincloudform.jsx
+++ b/src/views/login/logincloudform.jsx
@@ -2,17 +2,11 @@
 import PropTypes from 'prop-types'
 import { Form, Input } from 'antd'
 import { UserOutlined, LockOutlined } from '@ant-design/icons'
-import zhCN from '@/locales/zh-CN/login.js'
-import enUS from '@/locales/en-US/login.js'
 import './index.scss'
 
 class HeaderLoginForm extends Component {
   static propTpyes = {
     handleSubmit: PropTypes.func
-  }
-
-  state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
   }
 
   handleConfirm = () => {
@@ -60,12 +54,12 @@
       <Form style={{margin: '0px 10px'}}>
         <Form.Item>
           {getFieldDecorator('cloudusername', {
-            rules: [{ required: true, message: this.state.dict['login.username.empty'] }],
+            rules: [{ required: true, message: '璇疯緭鍏ョ敤鎴峰悕' }],
             initialValue: '',
           })(
             <Input
               prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
-              placeholder={this.state.dict['login.username']}
+              placeholder="鐢ㄦ埛鍚�"
               autoComplete="off"
               onPressEnter={(e) => {this.handleSubmit(e, 'cloudpassword')}}
             />
@@ -77,10 +71,10 @@
             rules: [
               {
                 required: true,
-                message: this.state.dict['login.password.empty'],
+                message: '璇疯緭鍏ュ瘑鐮�',
               }
             ]
-          })(<Input.Password onPressEnter={(e) => {this.handleSubmit(e, 'cloudusername')}} placeholder={this.state.dict['login.password']} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
+          })(<Input.Password onPressEnter={(e) => {this.handleSubmit(e, 'cloudusername')}} placeholder="瀵嗙爜" prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
         </Form.Item>
       </Form>
     )
diff --git a/src/views/login/loginform.jsx b/src/views/login/loginform.jsx
index 8939de7..067b948 100644
--- a/src/views/login/loginform.jsx
+++ b/src/views/login/loginform.jsx
@@ -15,10 +15,9 @@
   static propTpyes = {
     isDisabled: PropTypes.bool,
     handleSubmit: PropTypes.func,
-    dict: PropTypes.object,
+    authLogin: PropTypes.func,
     auth: PropTypes.bool,
-    touristLogin: PropTypes.bool,
-    lang: PropTypes.string,
+    authError: PropTypes.string,
     langList: PropTypes.array,
     loginWays: PropTypes.array
   }
@@ -33,14 +32,23 @@
     verdisabled: false,
     hasScan: false,
     timeout: false,
-    users: []
+    vispwd: window.GLOB.vispwd,
+    wayLabels: {},
+    dict: window.GLOB.dict,
+    users: [],
+    lang: sessionStorage.getItem('lang')
   }
 
   UNSAFE_componentWillMount () {
     let remember = true
-    let _url = window.location.href.split('#')[0]
+
+    if (localStorage.getItem(window.location.href.split('#')[0] + 'users')) { // 杩囨浮
+      localStorage.setItem(window.GLOB.sysSign + 'users', localStorage.getItem(window.location.href.split('#')[0] + 'users'))
+      localStorage.setItem(window.GLOB.sysSign + 'remember', localStorage.getItem(window.location.href.split('#')[0] + 'remember'))
+      localStorage.removeItem(window.location.href.split('#')[0] + 'users')
+    }
     
-    if (localStorage.getItem(_url + 'remember') === 'false') {
+    if (localStorage.getItem(window.GLOB.sysSign + 'remember') === 'false') {
       remember = false
     }
     if (!window.GLOB.keepKey) {
@@ -48,9 +56,26 @@
     }
 
     let smsId = ''
-    let _loginWays = []
+    // let wayLabels = {app_scan: 'APP鎵爜', weixin_scan: '寰俊鎵爜', uname_pwd: '璐﹀彿鐧诲綍', sms_vcode: '鐭俊鐧诲綍'}
 
-    let users = localStorage.getItem(_url + 'users')
+    // loginWays.forEach(item => {
+    //   item.label = window.GLOB.dict[item.type] || wayLabels[item.type]
+    //   wayLabels[item.type] = item.label
+    //   if (item.type === 'sms_vcode') {
+    //     smsId = item.smsId
+    //     _loginWays.push(item)
+    //   } else if (item.type === 'uname_pwd') {
+    //     _loginWays.push(item)
+    //   } else if (item.type === 'app_scan') {
+    //     _loginWays.push(item)
+    //     hasScan = true
+    //   } else if (item.type === 'weixin_scan') {
+    //     _loginWays.push(item)
+    //     hasScan = true
+    //   }
+    // })
+
+    let users = localStorage.getItem(window.GLOB.sysSign + 'users')
     let _user = null
     
     if (users) {
@@ -63,16 +88,11 @@
       users = []
     }
 
-    if (users[0]) {
-      _user = users[0]
-    }
-
     this.setState({
       users: users,
       username: _user ? _user.username : '',
       password: _user ? _user.password : '',
       smsId: smsId,
-      loginWays: _loginWays,
       remember
     })
   }
@@ -94,21 +114,20 @@
   }
 
   changelang = (val) => {
-    const _href = window.location.href.split('#')[0]
-    localStorage.setItem(_href + 'lang', val)
+    localStorage.setItem(window.location.href.split('#')[0] + 'lang', val)
     sessionStorage.setItem('lang', val)
 
     window.location.reload()
   }
 
   handleSubmit = e => {
+    const { dict } = this.state
     // 鐧诲綍鍙傛暟妫�楠�
     e && e.preventDefault()
     if (!this.props.auth) {
       warning({
-        title: this.props.dict['login.auth.tip'],
-        okText: this.props.dict['login.auth.ok'],
-        cancelText: this.props.dict['login.auth.cancel'],
+        title: this.props.authError || dict['auth_tip'] || '绯荤粺鏈巿鏉冿紝璇疯仈绯荤鐞嗗憳銆�',
+        okText: dict['got_it'] || '鐭ラ亾浜�',
         onOk() {},
         onCancel() {}
       })
@@ -140,16 +159,16 @@
   }
 
   getvercode = () => {
-    const { smsId } = this.state
+    const { smsId, dict } = this.state
     let _phone = this.props.form.getFieldValue('phone')
     if (!_phone) {
-      message.warning('璇疯緭鍏ユ墜鏈哄彿锛�')
+      message.warning(dict['phone_no_required'] || '璇疯緭鍏ユ墜鏈哄彿锛�')
       return
     } else if (!/^1[3456789]\d{9}$/.test(_phone)) {
-      message.warning('鎵嬫満鍙锋牸寮忛敊璇紝璇烽噸濉紒')
+      message.warning(dict['phone_error'] || '鎵嬫満鍙锋牸寮忛敊璇紝璇烽噸濉紒')
       return
-    } else if (!this.props.touristLogin) {
-      message.warning('鏈幏鍙栭獙璇佺爜璁剧疆锛岃绋嶅悗鎴栧埛鏂伴噸璇曪紒')
+    } else if (!sessionStorage.getItem('visitorUserID') || !sessionStorage.getItem('visitorLoginUID')) {
+      message.warning(dict['vercode_error'] || '鏈幏鍙栭獙璇佺爜璁剧疆锛岃绋嶅悗鎴栧埛鏂伴噸璇曪紒')
       return
     }
 
@@ -257,9 +276,8 @@
 
   rememberChange = (e) => {
     let val = e.target.checked
-    let _url = window.location.href.split('#')[0]
 
-    localStorage.setItem(_url + 'remember', val)
+    localStorage.setItem(window.GLOB.sysSign + 'remember', val)
   }
 
   complete = (val) => {
@@ -287,9 +305,7 @@
     
     this.setState({users: _users})
 
-    let _url = window.location.href.split('#')[0]
-
-    localStorage.setItem(_url + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(_users))))
+    localStorage.setItem(window.GLOB.sysSign + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(_users))))
   }
 
   /**
@@ -304,7 +320,7 @@
   render() {
     const { langList } = this.props
     const { getFieldDecorator } = this.props.form
-    const { remember, users } = this.state
+    const { remember, users, dict, lang, vispwd } = this.state
 
     return (
       <Form className={`login-form login-form-1`} id="login-form" onSubmit={this.handleSubmit}>
@@ -312,7 +328,7 @@
         <div className="form-item-wrap">
           <Form.Item>
             {getFieldDecorator('username', {
-              rules: [{ required: true, message: this.props.dict['login.username.empty'] }],
+              rules: [{ required: true, message: dict['username_required'] || '璇疯緭鍏ョ敤鎴峰悕' }],
               initialValue: this.state.username || '',
             })(
               <AutoComplete
@@ -329,7 +345,7 @@
               >
                 <Input
                   prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
-                  placeholder={this.props.dict['login.username']}
+                  placeholder={dict['username'] || '鐢ㄦ埛鍚�'}
                   autoComplete="off"
                 />
               </AutoComplete>
@@ -341,20 +357,20 @@
               rules: [
                 {
                   required: true,
-                  message: this.props.dict['login.password.empty'],
+                  message: dict['password_required'] || '璇疯緭鍏ュ瘑鐮�',
                 }
               ]
-            })(<Input.Password placeholder={this.props.dict['login.password']} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
+            })(<Input.Password placeholder={dict['password'] || '瀵嗙爜'} visibilityToggle={vispwd} prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} />)}
           </Form.Item>
           {window.GLOB.keepKey ? <Form.Item className="minline">
             {getFieldDecorator('remember', {
               valuePropName: 'checked',
               initialValue: remember,
-            })(<Checkbox onChange={this.rememberChange}>{this.props.dict['login.remember']}</Checkbox>)}
+            })(<Checkbox onChange={this.rememberChange}>{dict['remember_me'] || '璁颁綇瀵嗙爜'}</Checkbox>)}
           </Form.Item> : <div style={{height: '30px', float: 'left'}}></div>}
           {langList && langList.length > 0 ? <Form.Item className="minline right">
             {getFieldDecorator('lang', {
-              initialValue: this.props.lang,
+              initialValue: lang,
             })(
               <Select
                 onChange={(value) => {this.changelang(value)}}
@@ -368,7 +384,7 @@
           </Form.Item> : null}
           <Form.Item className="btn-login">
             <Button type="primary" htmlType="submit" className="login-form-button" disabled={this.props.isDisabled} loading={this.props.isDisabled}>
-              {this.props.dict['login.submit']}
+              {dict['log_in'] || '鐧诲綍'}
             </Button>
           </Form.Item>
         </div>
diff --git a/src/views/main/index.jsx b/src/views/main/index.jsx
index 8f64b52..8723ebc 100644
--- a/src/views/main/index.jsx
+++ b/src/views/main/index.jsx
@@ -1,7 +1,4 @@
 import React, {Component} from 'react'
-import { ConfigProvider } from 'antd'
-// import enUS from 'antd/es/locale/en_US'
-import zhCN from 'antd/es/locale/zh_CN'
 
 import asyncComponent from '@/utils/asyncComponent'
 import Header from '@/components/header'
@@ -76,14 +73,12 @@
 
     return (
       <div className="mk-main-view">
-        <ConfigProvider locale={zhCN}>
-          <Header key="header"/>
-          {navBar === 'shutter' ? <Sidemenu key="sidemenu"/> : null}
-          {navBar === 'shutter' || navBar === 'menu_board_navigation' ?
-            <Tabview key="tabview"/> :
-            <Breadview key="breadview"/>}
-          {window.GLOB.systemType === 'production' ? <QueryLog /> : null}
-        </ConfigProvider>
+        <Header key="header"/>
+        {navBar === 'shutter' ? <Sidemenu key="sidemenu"/> : null}
+        {navBar === 'shutter' || navBar === 'menu_board_navigation' ?
+          <Tabview key="tabview"/> :
+          <Breadview key="breadview"/>}
+        {window.GLOB.systemType === 'production' ? <QueryLog /> : null}
         <ImgScale />
       </div>
     )
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index ad11d1f..4b91a51 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -4,16 +4,16 @@
 import { is, fromJS } from 'immutable'
 import moment from 'moment'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button, Typography, Spin } from 'antd'
+import { notification, Modal, Collapse, Card, Switch, Button, Typography, Spin } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
 import html2canvas from 'html2canvas'
 import md5 from 'md5'
 
 import Api from '@/api'
-import Utils, { setGLOBFuncs } from '@/utils/utils.js'
-import antdZhCN from 'antd/es/locale/zh_CN'
+import Utils from '@/utils/utils.js'
+import { langs } from '@/store/options'
 import MKEmitter from '@/utils/events.js'
-import { getTables, getFuncsAndInters } from '@/utils/utils-custom.js'
+import { getTables, getFuncsAndInters, getOutMessage, getLangTrans, getAllSqls } from '@/utils/utils-custom.js'
 import asyncComponent from '@/utils/asyncComponent'
 
 import '@/assets/css/design.scss'
@@ -22,7 +22,6 @@
 const { Panel } = Collapse
 const { confirm } = Modal
 const { Paragraph } = Typography
-const _locale = antdZhCN
 
 const MenuForm = asyncComponent(() => import('./menuform'))
 const HomeForm = asyncComponent(() => import('./homeform'))
@@ -67,6 +66,7 @@
     eyeopen: false,
     view: '',
     popConfig: null,
+    langName: '',
     needUpdate: false
   }
 
@@ -98,12 +98,17 @@
 
       sessionStorage.setItem('MenuType', param.MenuType || 'custom')
 
+      if (param.lang) {
+        sessionStorage.setItem('lang', param.lang)
+      }
+
       this.setState({
         MenuType: param.MenuType,
         MenuId: param.MenuId || param.MenuID,
         ParentId: param.ParentId || '',
         MenuName: param.MenuName || '',
         MenuNo: param.MenuNo || '',
+        langName: sessionStorage.getItem('lang') !== 'zh-CN' && langs[sessionStorage.getItem('lang')] ? `锛�${langs[sessionStorage.getItem('lang')]}锛塦 : ''
       }, () => {
         this.getMenuParam()
       })
@@ -128,7 +133,7 @@
     MKEmitter.addListener('changeEditMenu', this.changeEditMenu)
     setTimeout(() => {
       this.getRoleFields()
-      setGLOBFuncs()
+      // setGLOBFuncs()
     }, 1000)
 
     document.onkeydown = (event) => {
@@ -772,6 +777,20 @@
         duration: 5
       })
       return
+    } else if (this.checklog()) {
+      if (sessionStorage.getItem('langList') && !config.trans) {
+
+      } else if (config.enabled && !config.allSqls) {
+
+      } else {
+        notification.success({
+          top: 92,
+          message: '褰撳墠閰嶇疆鏈慨鏀癸紝鏃犻渶淇濆瓨銆�',
+          duration: 5
+        })
+        MKEmitter.emit('completeSave')
+        return
+      }
     }
 
     this.setState({
@@ -787,6 +806,52 @@
       } else if (!config.enabled && config.force && _pass) {
         config.enabled = true
         delete config.force
+      }
+
+      let long_data = ''
+      if (config.enabled) {
+        let sqls = getAllSqls(config)
+        let _t = moment().format('YYYYMMDDHHmmss')
+        let getguid = () => {
+          let uuid = ''
+          for (let i = 0; i < 18; i++) {
+            uuid += String.fromCharCode(Math.floor(Math.random() * 26) + 65)
+          }
+          uuid = uuid.replace(/minke/ig, 'MNKIE')
+          return uuid
+        }
+
+        long_data = []
+        let oriIds = {}
+        if (config.allSqls) {
+          config.allSqls.forEach(item => {
+            if (!item.md5) return
+            oriIds[item.uuid + item.md5] = item.v_id
+          })
+        }
+        
+        config.allSqls = sqls.map(item => {
+          let v_id = _t + getguid()
+
+          if (oriIds[item.uuid + item.md5]) {
+            v_id = oriIds[item.uuid + item.md5]
+          }
+          
+          long_data.push(`${md5(window.GLOB.appkey + v_id)},${item.uuid},${v_id},${window.btoa(window.encodeURIComponent(item.LText))}`)
+          
+          return {
+            uuid: item.uuid,
+            v_id: v_id,
+            type: item.type,
+            reps: item.reps,
+            md5: item.md5 || '',
+            luser: item.luser === true
+          }
+        })
+
+        long_data = long_data.join(';')
+      } else {
+        delete config.allSqls
       }
 
       if (config.cacheUseful !== 'true') {
@@ -828,12 +893,16 @@
       } else {
         let urlparam = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
         urlparam.type = 'admin'
+        urlparam.lang = sessionStorage.getItem('lang')
+
         url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
         config.tbkey = key
       }
 
       let interfaces = getFuncsAndInters(config)
+      let msg = getOutMessage(config)
       let urlFields = config.urlFields ? config.urlFields.join(',') : ''
+      let langSql = getLangTrans(config)
 
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
@@ -845,14 +914,17 @@
         EasyCode: config.easyCode || '',
         Template: 'CustomPage',
         MenuName: config.MenuName || '',
-        PageParam: JSON.stringify({Template: 'CustomPage', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false', menuColor: config.menuColor || '', interfaces, urlFields}),
+        PageParam: JSON.stringify({Template: 'CustomPage', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false', menuColor: config.menuColor || '', interfaces, msg, backend: 'level1', urlFields}),
         open_edition: config.open_edition,
-        LText: '',
-        LTexttb: '',
+        long_data: long_data,
         debug_md5: key,
         debug_url: url,
         debug_list: window.btoa(tbs),
         LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config)))
+      }
+
+      if (langSql) {
+        param.lang_translation = window.btoa(window.encodeURIComponent(langSql))
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -1185,11 +1257,11 @@
   }
 
   render () {
-    const { view, comloading, MenuType, MenuId, config, settingshow, ParentId, menuloading, eyeopen, needUpdate } = this.state
+    const { view, comloading, MenuType, MenuId, config, settingshow, ParentId, menuloading, eyeopen, needUpdate, langName } = this.state
 
     return (
-      <ConfigProvider locale={_locale}>
-        <Header menuName={config ? config.MenuName : ''}/>
+      <>
+        <Header menuName={config ? config.MenuName + langName : ''}/>
         <DndProvider backend={HTML5Backend}>
           {view !== 'popview' ? <div className={'pc-menu-view ' + (MenuType || '')}>
             <div className="menu-body">
@@ -1252,8 +1324,8 @@
                     <StyleCombControlButton menu={config} />
                     <PasteController insert={this.insert} />
                     {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>
+                    <Button type="primary" id="save-config" disabled={!config} className={needUpdate ? 'update-tip' : ''} onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
+                    <Button type="default" disabled={menuloading} onClick={this.closeView}>鍏抽棴</Button>
                   </div>
                 } style={{ width: '100%' }}>
                   {config && !comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : <Spin className="loading-config" size="large" />}
@@ -1265,7 +1337,7 @@
         <ModalController />
         <StyleController />
         <StyleCombController />
-      </ConfigProvider>
+      </>
     )
   }
 }
diff --git a/src/views/menudesign/index.scss b/src/views/menudesign/index.scss
index 74d1cf2..5521e68 100644
--- a/src/views/menudesign/index.scss
+++ b/src/views/menudesign/index.scss
@@ -17,6 +17,13 @@
     top: calc(50vh - 70px);
     z-index: 10;
   }
+  .mini-radio {
+    white-space: nowrap;
+    span.ant-radio + * {
+      padding-right: 0px;
+      padding-left: 4px;
+    }
+  }
   .mk-hidden {
     text-decoration: line-through!important;
     span {
@@ -179,7 +186,10 @@
       > .ant-card {
         >.ant-card-head {
           margin-bottom: 0px;
-          position: relative;
+          position: sticky;
+          top: 0px;
+          z-index: 10;
+          background: #ffffff;
           .ant-card-head-title {
             color: #1890ff;
             padding: 5px 0;
diff --git a/src/views/menudesign/popview/index.jsx b/src/views/menudesign/popview/index.jsx
index 394ca23..496f116 100644
--- a/src/views/menudesign/popview/index.jsx
+++ b/src/views/menudesign/popview/index.jsx
@@ -284,7 +284,7 @@
                 <PasteController insert={this.insert} />
                 <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} />
                 <Button type="primary" id="save-pop-config" onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
-                <Button type="default" onClick={this.closeView}>杩斿洖</Button>
+                <Button type="default" disabled={menuloading} onClick={this.closeView}>杩斿洖</Button>
               </div>
             } style={{ width: '100%' }}>
               {!comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
diff --git a/src/views/menudesign/popview/index.scss b/src/views/menudesign/popview/index.scss
index 2ea36fa..02b8796 100644
--- a/src/views/menudesign/popview/index.scss
+++ b/src/views/menudesign/popview/index.scss
@@ -123,7 +123,10 @@
       > .ant-card {
         >.ant-card-head {
           margin-bottom: 0px;
-          position: relative;
+          position: sticky;
+          top: 0px;
+          z-index: 10;
+          background: #ffffff;
           .ant-card-head-title {
             color: #1890ff;
             padding: 5px 0;
diff --git a/src/views/menudesign/printmenuform/index.jsx b/src/views/menudesign/printmenuform/index.jsx
index 5809dcd..5aff337 100644
--- a/src/views/menudesign/printmenuform/index.jsx
+++ b/src/views/menudesign/printmenuform/index.jsx
@@ -1,14 +1,20 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, InputNumber, Select, Radio, Tooltip, Input } from 'antd'
+import { Form, Row, Col, InputNumber, Select, Radio, Tooltip, Input, Modal } from 'antd'
 import { QuestionCircleOutlined, EditOutlined } from '@ant-design/icons'
 
+import CodeMirror from '@/templates/zshare/codemirror'
 // import './index.scss'
 
 class MainSearch extends Component {
   static propTpyes = {
     config: PropTypes.object,
     updateConfig: PropTypes.func
+  }
+
+  state = {
+    visible: false,
+    printScripts: ''
   }
 
   selectChange = (key, value) => {
@@ -76,9 +82,22 @@
     })
   }
 
+  onScriptChange = (val) => {
+    this.setState({printScripts: val})
+  }
+
+  submit = () => {
+    const { config } = this.props
+    const { printScripts } = this.state
+
+    this.setState({visible: false})
+    this.props.updateConfig({...config, printScripts})
+  }
+
   render() {
     const { config } = this.props
     const { getFieldDecorator } = this.props.form
+    const { visible, printScripts } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -91,186 +110,206 @@
     }
 
     return (
-      <Form {...formItemLayout}>
-        <Row>
-          <Col span={24}>
-            <Form.Item label="鑿滃崟鍚嶇О">
-              <span style={{display: 'inline-block', wordBreak: 'break-all', lineHeight: 1.5}}>
-                {config.MenuName}
-              </span>
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="鑿滃崟鍙傛暟">
-              <span style={{display: 'inline-block', wordBreak: 'break-all', lineHeight: 1.5}}>
-                {config.MenuNo}
-              </span>
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="鎵撳嵃灏哄">
-              {getFieldDecorator('pageSize', {
-                initialValue: config.pageSize || 'A4',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鎵撳嵃灏哄!'
-                  }
-                ]
-              })(
-                <Select onChange={(val) => this.selectChange('pageSize', val)}>
-                  <Select.Option value="A3">A3</Select.Option>
-                  <Select.Option value="A4">A4</Select.Option>
-                  <Select.Option value="A5">A5</Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="鎵撳嵃甯冨眬">
-              {getFieldDecorator('pageLayout', {
-                initialValue: config.pageLayout || 'vertical',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鎵撳嵃甯冨眬!'
-                  }
-                ]
-              })(
-                <Radio.Group onChange={(e) => this.selectChange('pageLayout', e.target.value)}>
-                  <Radio value="vertical">绾靛悜</Radio>
-                  <Radio value="horizontal">妯悜</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="鎵撳嵃杈硅窛">
-              {getFieldDecorator('pagePadding', {
-                initialValue: config.pagePadding || 'default',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇烽�夋嫨鎵撳嵃杈硅窛!'
-                  }
-                ]
-              })(
-                <Radio.Group onChange={(e) => this.selectChange('pagePadding', e.target.value)}>
-                  <Radio value="default">榛樿</Radio>
-                  <Radio value="without">鏃�</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
-            <Form.Item label="椤甸潰甯冨眬">
-              {getFieldDecorator('printPage', {
-                initialValue: config.printPage || 'auto'
-              })(
-                <Radio.Group onChange={(e) => this.selectChange('printPage', e.target.value)}>
-                  <Radio value="auto">鑷�傚簲</Radio>
-                  <Radio value="page">鍒嗛〉</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          {config.printPage === 'page' ? <Col span={24}>
-            <Form.Item label="姣忛〉鏁�(鏉�)">
-              {getFieldDecorator('everyPCount', {
-                initialValue: config.everyPCount || 15,
-                rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ユ瘡椤垫暟!'
-                  }
-                ]
-              })(<InputNumber min={1} max={1000} precision={1} onChange={(val) => this.selectChange('everyPCount', val)}/>)}
-            </Form.Item>
-          </Col> : null}
-          <Col span={24}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="閽堝涓嶈鍒欑焊寮狅紝鍙嚜瀹氫箟璁剧疆鎵撳嵃楂樺害鍜屽搴︼紝娉細鍚屾椂璁剧疆鎵撳嵃瀹藉害鍜岄珮搴﹀悗鏂瑰彲鐢熸晥銆�">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鑷畾涔�
-              </Tooltip>
-            }>
-              {getFieldDecorator('printCustom', {
-                initialValue: config.printCustom || 'false'
-              })(
-                <Radio.Group onChange={(e) => this.selectChange('printCustom', e.target.value)}>
-                  <Radio value="false">涓嶅惎鐢�</Radio>
-                  <Radio value="true">鍚敤</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          {config.printCustom === 'true' ? <Col span={24}>
-            <Form.Item label="鎵撳嵃瀹藉害">
-              {getFieldDecorator('printWidth', {
-                initialValue: config.printWidth || ''
-              })(<InputNumber min={10} max={9999} precision={0} onChange={(val) => this.selectChange('printWidth', val)}/>)}
-            </Form.Item>
-          </Col> : null}
-          {config.printCustom === 'true' ? <Col span={24}>
-            <Form.Item label="鎵撳嵃楂樺害">
-              {getFieldDecorator('printHeight', {
-                initialValue: config.printHeight || ''
-              })(<InputNumber min={10} max={9999} precision={0} onChange={(val) => this.selectChange('printHeight', val)}/>)}
-            </Form.Item>
-          </Col> : null}
-          <Col span={24}>
-            <Form.Item label="鍥炶皟">
-              {getFieldDecorator('callback', {
-                initialValue: config.callback || 'false'
-              })(
-                <Radio.Group onChange={(e) => this.selectChange('callback', e.target.value)}>
-                  <Radio value="false">涓嶅惎鐢�</Radio>
-                  <Radio value="true">鍚敤</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          {config.callback === 'true' ? <Col span={24}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鍥炶皟鍑芥暟鎵ц鎴愬姛鍚庨粯璁や細鍒锋柊婧愯彍鍗曢〉锛岃繑鍥炰俊鎭紙@retmsg锛変腑鍚湁锛園no_target_menu@锛夊彲闃绘姝ら」鍒锋柊銆�">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鍥炶皟鍑芥暟
-              </Tooltip>
-            }>
-              s_print_proc <EditOutlined style={{cursor: 'pointer'}} onClick={() => {window.open('#/proc/s_print_proc')}}/>
-            </Form.Item>
-          </Col> : null}
-          {config.callback === 'true' ? <Col span={24}>
-            <Form.Item label="鍥炶皟鍙傛暟">
-              {getFieldDecorator('callNo', {
-                initialValue: config.callNo || '',
-                rules: [
-                  {
-                    required: true,
-                    message: '璇峰~鍐欏洖璋冨弬鏁�!'
-                  },
-                  {
-                    pattern: /^[a-zA-Z0-9_]+$/,
-                    message: '鍥炶皟鍙傛暟鍙彲浣跨敤瀛楁瘝銆佹暟瀛椾互鍙奯'
-                  }
-                ]
-              })(<Input onChange={(e) => this.selectChange('callNo', e.target.value)}/>)}
-            </Form.Item>
-          </Col> : null}
-          <Col span={24}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鍙嚜瀹氫箟鍦ㄦ祻瑙堝櫒鏍囬鏍忎腑鏄剧ず鐨勭綉椤垫爣棰樸��">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                缃戦〉鏍囬
-              </Tooltip>
-            }>
-              {getFieldDecorator('webTitle', {
-                initialValue: config.webTitle || ''
-              })(<Input onChange={(e) => this.selectChange('webTitle', e.target.value)}/>)}
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
+      <>
+        <Form {...formItemLayout}>
+          <Row>
+            <Col span={24}>
+              <Form.Item label="鑿滃崟鍚嶇О">
+                <span style={{display: 'inline-block', wordBreak: 'break-all', lineHeight: 1.5}}>
+                  {config.MenuName}
+                </span>
+              </Form.Item>
+            </Col>
+            <Col span={24}>
+              <Form.Item label="鑿滃崟鍙傛暟">
+                <span style={{display: 'inline-block', wordBreak: 'break-all', lineHeight: 1.5}}>
+                  {config.MenuNo}
+                </span>
+              </Form.Item>
+            </Col>
+            <Col span={24}>
+              <Form.Item label="鎵撳嵃灏哄">
+                {getFieldDecorator('pageSize', {
+                  initialValue: config.pageSize || 'A4',
+                  rules: [
+                    {
+                      required: true,
+                      message: '璇烽�夋嫨鎵撳嵃灏哄!'
+                    }
+                  ]
+                })(
+                  <Select onChange={(val) => this.selectChange('pageSize', val)}>
+                    <Select.Option value="A3">A3</Select.Option>
+                    <Select.Option value="A4">A4</Select.Option>
+                    <Select.Option value="A5">A5</Select.Option>
+                  </Select>
+                )}
+              </Form.Item>
+            </Col>
+            <Col span={24}>
+              <Form.Item label="鎵撳嵃甯冨眬">
+                {getFieldDecorator('pageLayout', {
+                  initialValue: config.pageLayout || 'vertical',
+                  rules: [
+                    {
+                      required: true,
+                      message: '璇烽�夋嫨鎵撳嵃甯冨眬!'
+                    }
+                  ]
+                })(
+                  <Radio.Group onChange={(e) => this.selectChange('pageLayout', e.target.value)}>
+                    <Radio value="vertical">绾靛悜</Radio>
+                    <Radio value="horizontal">妯悜</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            <Col span={24}>
+              <Form.Item label="鎵撳嵃杈硅窛">
+                {getFieldDecorator('pagePadding', {
+                  initialValue: config.pagePadding || 'default',
+                  rules: [
+                    {
+                      required: true,
+                      message: '璇烽�夋嫨鎵撳嵃杈硅窛!'
+                    }
+                  ]
+                })(
+                  <Radio.Group onChange={(e) => this.selectChange('pagePadding', e.target.value)}>
+                    <Radio value="default">榛樿</Radio>
+                    <Radio value="without">鏃�</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            <Col span={24}>
+              <Form.Item label="椤甸潰甯冨眬">
+                {getFieldDecorator('printPage', {
+                  initialValue: config.printPage || 'auto'
+                })(
+                  <Radio.Group className="mini-radio" onChange={(e) => this.selectChange('printPage', e.target.value)}>
+                    <Radio value="auto">鑷�傚簲</Radio>
+                    <Radio value="page">鍒嗛〉</Radio>
+                    <Radio value="custom">鑷畾涔�</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            {config.printPage === 'custom' ? <Col span={24}>
+              <Form.Item label="鑷畾涔夎剼鏈�">
+                <EditOutlined style={{color: '#1890ff'}} onClick={() => this.setState({visible: true, printScripts: config.printScripts || ''})} />
+              </Form.Item>
+            </Col> : null}
+            {config.printPage === 'page' ? <Col span={24}>
+              <Form.Item label="姣忛〉鏁�(鏉�)">
+                {getFieldDecorator('everyPCount', {
+                  initialValue: config.everyPCount || 15,
+                  rules: [
+                    {
+                      required: true,
+                      message: '璇疯緭鍏ユ瘡椤垫暟!'
+                    }
+                  ]
+                })(<InputNumber min={1} max={1000} precision={1} onChange={(val) => this.selectChange('everyPCount', val)}/>)}
+              </Form.Item>
+            </Col> : null}
+            <Col span={24}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="閽堝涓嶈鍒欑焊寮狅紝鍙嚜瀹氫箟璁剧疆鎵撳嵃楂樺害鍜屽搴︼紝娉細鍚屾椂璁剧疆鎵撳嵃瀹藉害鍜岄珮搴﹀悗鏂瑰彲鐢熸晥銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鑷畾涔�
+                </Tooltip>
+              }>
+                {getFieldDecorator('printCustom', {
+                  initialValue: config.printCustom || 'false'
+                })(
+                  <Radio.Group onChange={(e) => this.selectChange('printCustom', e.target.value)}>
+                    <Radio value="false">涓嶅惎鐢�</Radio>
+                    <Radio value="true">鍚敤</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            {config.printCustom === 'true' ? <Col span={24}>
+              <Form.Item label="鎵撳嵃瀹藉害">
+                {getFieldDecorator('printWidth', {
+                  initialValue: config.printWidth || ''
+                })(<InputNumber min={10} max={9999} precision={0} onChange={(val) => this.selectChange('printWidth', val)}/>)}
+              </Form.Item>
+            </Col> : null}
+            {config.printCustom === 'true' ? <Col span={24}>
+              <Form.Item label="鎵撳嵃楂樺害">
+                {getFieldDecorator('printHeight', {
+                  initialValue: config.printHeight || ''
+                })(<InputNumber min={10} max={9999} precision={0} onChange={(val) => this.selectChange('printHeight', val)}/>)}
+              </Form.Item>
+            </Col> : null}
+            <Col span={24}>
+              <Form.Item label="鍥炶皟">
+                {getFieldDecorator('callback', {
+                  initialValue: config.callback || 'false'
+                })(
+                  <Radio.Group onChange={(e) => this.selectChange('callback', e.target.value)}>
+                    <Radio value="false">涓嶅惎鐢�</Radio>
+                    <Radio value="true">鍚敤</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            {config.callback === 'true' ? <Col span={24}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鍥炶皟鍑芥暟鎵ц鎴愬姛鍚庨粯璁や細鍒锋柊婧愯彍鍗曢〉锛岃繑鍥炰俊鎭紙@retmsg锛変腑鍚湁锛園no_target_menu@锛夊彲闃绘姝ら」鍒锋柊銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鍥炶皟鍑芥暟
+                </Tooltip>
+              }>
+                s_print_proc <EditOutlined style={{cursor: 'pointer'}} onClick={() => {window.open('#/proc/s_print_proc')}}/>
+              </Form.Item>
+            </Col> : null}
+            {config.callback === 'true' ? <Col span={24}>
+              <Form.Item label="鍥炶皟鍙傛暟">
+                {getFieldDecorator('callNo', {
+                  initialValue: config.callNo || '',
+                  rules: [
+                    {
+                      required: true,
+                      message: '璇峰~鍐欏洖璋冨弬鏁�!'
+                    },
+                    {
+                      pattern: /^[a-zA-Z0-9_]+$/,
+                      message: '鍥炶皟鍙傛暟鍙彲浣跨敤瀛楁瘝銆佹暟瀛椾互鍙奯'
+                    }
+                  ]
+                })(<Input onChange={(e) => this.selectChange('callNo', e.target.value)}/>)}
+              </Form.Item>
+            </Col> : null}
+            <Col span={24}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鍙嚜瀹氫箟鍦ㄦ祻瑙堝櫒鏍囬鏍忎腑鏄剧ず鐨勭綉椤垫爣棰樸��">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  缃戦〉鏍囬
+                </Tooltip>
+              }>
+                {getFieldDecorator('webTitle', {
+                  initialValue: config.webTitle || ''
+                })(<Input onChange={(e) => this.selectChange('webTitle', e.target.value)}/>)}
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+        <Modal
+          title="鑷畾涔夎剼鏈�"
+          wrapClassName="normal-css-modal"
+          visible={visible}
+          width={800}
+          maskClosable={false}
+          onOk={this.submit}
+          onCancel={() => { this.setState({ visible: false })}}
+          destroyOnClose
+        >
+          <CodeMirror mode="text/javascript" theme="cobalt" value={printScripts} onChange={this.onScriptChange} />
+        </Modal>
+      </>
     )
   }
 }
diff --git a/src/views/mkiframe/index.jsx b/src/views/mkiframe/index.jsx
index b6e9761..4730c77 100644
--- a/src/views/mkiframe/index.jsx
+++ b/src/views/mkiframe/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
-import { Spin, notification, ConfigProvider } from 'antd'
-import zhCN from 'antd/es/locale/zh_CN'
+import { Spin, notification } from 'antd'
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncLoadComponent'
@@ -76,6 +75,7 @@
             } else {
               sessionStorage.clear()
               this.props.history.replace('/login')
+              window.location.reload()
             }
           })
         }
@@ -103,6 +103,7 @@
           sessionStorage.clear()
           sessionStorage.setItem('iframe', `/iframe/${menuId}/@loginuid@/${bid || ''}`)
           this.props.history.replace('/login')
+          window.location.reload()
         }
       })
     }
@@ -164,6 +165,14 @@
 
   reloadTabs = () => {
     if (this.reloading) return
+
+    let time = new Date().getTime()
+
+    let oldTime = sessionStorage.getItem('mk_reloadTabs')
+    
+    if (oldTime && time - oldTime < 180000) return
+
+    sessionStorage.setItem('mk_reloadTabs', time)
 
     this.reloading = true
 
@@ -267,11 +276,9 @@
 
     return (
       <div className="main-iframe">
-        <ConfigProvider locale={zhCN}>
-          {loading ? <Spin size="large" /> : null}
-          {!loading && type === 'CustomPage' ? <CustomPage MenuID={MenuId} param={{$BID: BID}} changeTemp={this.changeTemp}/> : null}
-          {!loading && type === 'BaseTable' ? <BaseTable MenuID={MenuId} param={{$BID: BID}} changeTemp={this.changeTemp}/> : null}
-        </ConfigProvider>
+        {loading ? <Spin size="large" /> : null}
+        {!loading && type === 'CustomPage' ? <CustomPage MenuID={MenuId} param={{$BID: BID}} changeTemp={this.changeTemp}/> : null}
+        {!loading && type === 'BaseTable' ? <BaseTable MenuID={MenuId} param={{$BID: BID}} changeTemp={this.changeTemp}/> : null}
         <ImgScale />
       </div>
     )
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index b713e00..a87df2d 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -3,16 +3,15 @@
 import { withRouter } from 'react-router'
 import { is, fromJS } from 'immutable'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
+import { notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import md5 from 'md5'
 
 import Api from '@/api'
-import Utils, { setGLOBFuncs } from '@/utils/utils.js'
-import antdZhCN from 'antd/es/locale/zh_CN'
+import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
-import MenuUtils, { getTables, getFuncsAndInters } from '@/utils/utils-custom.js'
+import MenuUtils, { getTables, getFuncsAndInters, getOutMessage, getLangTrans, getAllSqls } from '@/utils/utils-custom.js'
 import asyncComponent from '@/utils/asyncComponent'
 
 import '@/assets/css/design.scss'
@@ -75,7 +74,9 @@
     viewType: 'menu',
     view: '',
     eyeopen: false,
-    needUpdate: false
+    needUpdate: false,
+    appLoginId: '',
+    appHomeId: ''
   }
 
   UNSAFE_componentWillMount() {
@@ -99,11 +100,14 @@
 
     try {
       let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
+      
+      if (param.lang) {
+        sessionStorage.setItem('lang', param.lang)
+      }
 
       if (param.type === 'app') {
         sessionStorage.setItem('appId', param.ID || '')
         sessionStorage.setItem('appName', param.remark || '')
-        sessionStorage.setItem('lang', param.lang || 'zh-CN')
         sessionStorage.setItem('kei_no', param.kei_no || '')
         sessionStorage.setItem('typename', param.typename || 'mob')
         sessionStorage.setItem('adapter', param.adapter || '')
@@ -111,6 +115,16 @@
         sessionStorage.setItem('direction', param.direction || 'vertical')
         sessionStorage.setItem('userbind', param.userbind || '')
         sessionStorage.setItem('instantMessage', param.instantMessage || '')
+
+        if (param.applangList) {
+          sessionStorage.setItem('applangList', param.applangList)
+        } else {
+          sessionStorage.removeItem('applangList')
+        }
+
+        if (param.wxAppId) {
+          sessionStorage.setItem('wxAppId', param.wxAppId)
+        }
 
         this.getAppMessage(param.MenuID)
       } else if (param.type === 'view') {
@@ -127,10 +141,29 @@
           adapters = []
         }
 
+        let appLoginId = ''
+        let appHomeId = ''
+        if (sessionStorage.getItem('appViewList')) {
+          try {
+            let appMenus = JSON.parse(sessionStorage.getItem('appViewList'))
+            appMenus.forEach(item => {
+              if (item.keys_type === 'login') {
+                appLoginId = item.keys_id
+              } else if (item.keys_type === 'index') {
+                appHomeId = item.keys_id
+              }
+            })
+          } catch (e) {
+
+          }
+        }
+
         this.setState({
           adapters,
           MenuId: param.MenuID,
-          viewType: /^userbind/.test(param.MenuID) ? 'userbind' : 'menu'
+          viewType: /^userbind/.test(param.MenuID) ? 'userbind' : 'menu',
+          appLoginId: appLoginId,
+          appHomeId: appHomeId
         }, () => {
           this.getMenuParam(param)
         })
@@ -163,9 +196,14 @@
     MKEmitter.addListener('changePopview', this.initPopview)
     MKEmitter.addListener('triggerMenuSave', this.submitConfig)
     MKEmitter.addListener('changeEditMenu', this.changeEditMenu)
+
+    if (sessionStorage.getItem('wxAppId')) {
+      window.GLOB.WXAppID = sessionStorage.getItem('wxAppId')
+    }
+
     setTimeout(() => {
       this.getRoleFields()
-      setGLOBFuncs()
+      // setGLOBFuncs()
     }, 1000)
 
     document.onkeydown = (event) => {
@@ -390,7 +428,8 @@
       MenuID: menu.MenuID,
       copyMenuId: menu.copyMenuId || '',
       clearMenu: menu.clearMenu !== 'false',
-      type: 'view'
+      type: 'view',
+      lang: sessionStorage.getItem('lang')
     }
 
     param.MenuNo = menu.MenuNo || ''
@@ -463,12 +502,12 @@
             })
           } else {
             sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
-            this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'}))))
+            this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view', lang: sessionStorage.getItem('lang')}))))
           }
         })
       } else {
         sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
-        this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID || homeId, type: 'view'}))))
+        this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID || homeId, type: 'view', lang: sessionStorage.getItem('lang')}))))
       }
     })
   }
@@ -1286,6 +1325,7 @@
 
     let traversal = (components) => {
       return components.map(item => {
+        item.miniStyle = ''
         if (item.style) {
           item.miniStyle = this.transferStyle(item.style)
         }
@@ -1301,12 +1341,18 @@
         }
 
         if (item.type === 'tabs') {
+          if (item.setting.backgroundColor) {
+            item.miniStyle += `--tabs-header-background: ${item.setting.backgroundColor};`
+          }
           item.subtabs.forEach(tab => {
             tab.components = traversal(tab.components)
           })
         } else if (item.type === 'group') {
           item.components = traversal(item.components)
         } else if (['card', 'carousel', 'timeline'].includes(item.type)) {
+          if (item.wrap.display === 'hidden') {
+            item.miniStyle += 'display:none;'
+          }
           item.subcards.forEach(card => {
             card.miniStyle = this.transferStyle(card.style)
             card.elements = card.elements.map(cell => {
@@ -1406,6 +1452,20 @@
         activeKey: 'basedata'
       })
       return
+    } else if (this.checklog()) {
+      if ((sessionStorage.getItem('applangList') && !config.trans) || (adapters.includes('wxmini') && !config.hasOwnProperty('miniStyle'))) {
+
+      } else if (config.enabled && !config.allSqls) {
+        
+      } else {
+        notification.success({
+          top: 92,
+          message: '褰撳墠閰嶇疆鏈慨鏀癸紝鏃犻渶淇濆瓨銆�',
+          duration: 5
+        })
+        MKEmitter.emit('completeSave')
+        return
+      }
     }
 
     this.setState({
@@ -1421,6 +1481,52 @@
       } else if (!config.enabled && config.force && _pass) {
         config.enabled = true
         delete config.force
+      }
+
+      let long_data = ''
+      if (config.enabled) {
+        let sqls = getAllSqls(config)
+        let _t = moment().format('YYYYMMDDHHmmss')
+        let getguid = () => {
+          let uuid = ''
+          for (let i = 0; i < 18; i++) {
+            uuid += String.fromCharCode(Math.floor(Math.random() * 26) + 65)
+          }
+          uuid = uuid.replace(/minke/ig, 'MNKIE')
+          return uuid
+        }
+
+        long_data = []
+        let oriIds = {}
+        if (config.allSqls) {
+          config.allSqls.forEach(item => {
+            if (!item.md5) return
+            oriIds[item.uuid + item.md5] = item.v_id
+          })
+        }
+        
+        config.allSqls = sqls.map(item => {
+          let v_id = _t + getguid()
+
+          if (oriIds[item.uuid + item.md5]) {
+            v_id = oriIds[item.uuid + item.md5]
+          }
+          
+          long_data.push(`${md5(window.GLOB.appkey + v_id)},${item.uuid},${v_id},${window.btoa(window.encodeURIComponent(item.LText))}`)
+          
+          return {
+            uuid: item.uuid,
+            v_id: v_id,
+            type: item.type,
+            reps: item.reps,
+            md5: item.md5 || '',
+            luser: item.luser === true
+          }
+        })
+
+        long_data = long_data.join(';')
+      } else {
+        delete config.allSqls
       }
 
       if (config.cacheUseful !== 'true') {
@@ -1465,7 +1571,7 @@
           typename: sessionStorage.getItem('typename') || '',
           adapter: sessionStorage.getItem('adapter') || '',
           sysBgColor: sessionStorage.getItem('sysBgColor') || '',
-          MenuName: config.MenuName || '',
+          MenuName: config.MenuName || ''
         }
 
         url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
@@ -1476,6 +1582,9 @@
         roleParam.pass = true
       }
 
+      delete config.miniTitle
+      delete config.miniReloadUp
+
       config.components.forEach(item => {
         if (item.type === 'login') {
           roleParam.login = true
@@ -1483,6 +1592,13 @@
           config.loginview = true
         } else if (item.type === 'navbar') {
           config.tabview = true
+        } else if (item.type === 'topbar' && adapters.includes('wxmini')) {
+          if (item.wrap.minishow !== 'true') {
+            config.miniTitle = item.wrap.title || ''
+          }
+          if (item.wrap.reload === 'true') {
+            config.miniReloadUp = true
+          }
         }
       })
 
@@ -1508,7 +1624,11 @@
       menus_used_list = window.btoa(window.encodeURIComponent(menus_used_list || 'del'))
 
       let interfaces = getFuncsAndInters(config)
+      let msg = getOutMessage(config)
       roleParam.interfaces = interfaces
+      roleParam.msg = msg
+      roleParam.backend = 'level1'
+      let langSql = getLangTrans(config)
 
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
@@ -1522,15 +1642,20 @@
         TypeCharOne: sessionStorage.getItem('kei_no'),
         Typename: sessionStorage.getItem('typename'),
         MenuName: config.MenuName || '',
-        PageParam: JSON.stringify({Template: 'webPage', interfaces}),
+        PageParam: JSON.stringify({Template: 'webPage', interfaces, msg}),
         open_edition: config.open_edition,
         menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))),
-        LText: '',
-        LTexttb: '',
+        long_data: long_data,
+        // LText: '',
+        // LTexttb: '',
         menus_used_list,
         debug_md5: key,
         debug_url: url,
         debug_list: window.btoa(tbs)
+      }
+
+      if (langSql) {
+        param.lang_translation = window.btoa(window.encodeURIComponent(langSql))
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -1594,8 +1719,8 @@
               PageParam: JSON.stringify({Template: NavBar.type}),
               open_edition: _item ? (_item.open_edition || '') : '',
               menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roles))),
-              LText: '',
-              LTexttb: ''
+              // LText: '',
+              // LTexttb: ''
             }
 
             _param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(NavBar)))
@@ -1907,6 +2032,8 @@
     param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     param.secretkey = Utils.encrypt('', param.timestamp)
 
+    const that = this
+
     confirm({
       title: '纭畾璁剧疆鏈〉闈负棣栭〉鍚楋紵',
       content: '',
@@ -1920,6 +2047,10 @@
             })
           } else {
             sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
+
+            that.setState({
+              appHomeId: config.MenuID
+            })
           }
         })
       },
@@ -1967,6 +2098,7 @@
     param.secretkey = Utils.encrypt('', param.timestamp)
 
     let hasLogin = config.components.findIndex(item => item.type === 'login') > -1
+    const that = this
 
     confirm({
       title: '纭畾璁剧疆鏈〉闈负鐧诲綍椤靛悧锛�',
@@ -1981,6 +2113,10 @@
             })
           } else {
             sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
+
+            that.setState({
+              appLoginId: config.MenuID
+            })
           }
         })
       },
@@ -2045,95 +2181,93 @@
 
 
   render () {
-    const { view, viewType, comloading, loading, settingshow, controlshow, activeKey, MenuId, config, menuloading, adapters, eyeopen, needUpdate } = this.state
+    const { view, viewType, comloading, loading, settingshow, controlshow, activeKey, MenuId, config, menuloading, adapters, eyeopen, needUpdate, appLoginId, appHomeId } = this.state
 
     return (
-      <ConfigProvider locale={antdZhCN}>
-        <div className={'mk-mob-view ' + viewType} id="mk-mob-design-view">
-          <Header/>
-          {loading ? <Spin className="view-spin" size="large" /> : null}
-          <DndProvider backend={HTML5Backend}>
-            {view !== 'popview' ? <><div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
-              <div className="draw">
-                {settingshow ? <DoubleLeftOutlined onClick={() => {this.setState({settingshow: false})}} /> : null}
-                {!settingshow ? <DoubleRightOutlined onClick={() => {this.setState({settingshow: true})}} /> : null}
-              </div>
-              <div className="pc-setting-tools">
-                <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
-                  {/* 鍩烘湰淇℃伅 */}
-                  <Panel header="鍩烘湰淇℃伅" forceRender className="basedata" key="basedata">
-                    {config ? <>
-                      <MenuForm
-                        config={config}
-                        MenuId={MenuId}
-                        adapters={adapters}
-                        updateConfig={(con) => {
-                          this.updateConfig(con)
-                          if (con.direction !== config.direction) {
-                            this.changeView(con.direction)
-                          }
-                        }}
-                      />
-                      <UrlFieldComponent config={config} updateConfig={this.updateConfig}/>
-                      {/* 琛ㄥ悕娣诲姞 */}
-                      <TableComponent config={config} updatetable={this.updateConfig}/>
-                      <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>鑿滃崟ID</Paragraph>
-                      <Paragraph style={{padding: '10px 0px 0px 18px'}} copyable={{ text:  `${window.GLOB.baseurl}mob/index.html#/index/${sessionStorage.getItem('kei_no')}/${sessionStorage.getItem('typename')}/${sessionStorage.getItem('lang')}/${MenuId}/@BID@` }}>鑿滃崟閾炬帴</Paragraph>
-                      <NormalCss config={config} updateConfig={this.updateConfig}/>
-                    </> : null}
-                  </Panel>
-                  {/* 缁勪欢娣诲姞 */}
-                  <Panel header="缁勪欢" className="component" key="component">
-                    <SourceWrap />
-                  </Panel>
-                  <Panel header="鍏冪礌" key="element">
-                    <Modulecell />
-                  </Panel>
-                  <Panel header="椤甸潰鏍峰紡" key="background">
-                    {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
-                  </Panel>
-                </Collapse>
-              </div>
+      <div className={'mk-mob-view ' + viewType} id="mk-mob-design-view">
+        <Header/>
+        {loading ? <Spin className="view-spin" size="large" /> : null}
+        <DndProvider backend={HTML5Backend}>
+          {view !== 'popview' ? <><div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
+            <div className="draw">
+              {settingshow ? <DoubleLeftOutlined onClick={() => {this.setState({settingshow: false})}} /> : null}
+              {!settingshow ? <DoubleRightOutlined onClick={() => {this.setState({settingshow: true})}} /> : null}
             </div>
-            <div className={'menu-control' + (!controlshow ? ' hidden' : '')}>
-              <div className="draw">
-                {controlshow ? <DoubleRightOutlined onClick={() => {this.setState({controlshow: false})}}/> : null}
-                {!controlshow ? <DoubleLeftOutlined onClick={() => {this.setState({controlshow: true})}}/> : null}
-              </div>
-              <div className="wrap">
-                <Button type="primary" className={needUpdate ? 'update-tip' : ''} onClick={this.submitConfig} id="save-config" loading={menuloading}>淇濆瓨</Button>
-                {config ? <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> : null}
-                <ArrowLeftOutlined title="鍚庨��" className="back-view" onClick={this.backView}/>
-                {config ? <Debug config={config}/> : null}
-                <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 缁勪欢鍚�</Button>
-                <CreateView resetmenu={this.getAppMenus} />
-                <PasteController insert={this.insert} />
-                <TableNodes config={config} />
-                <ViewNodes config={config} MenuId={MenuId}/>
-                <SysInterface config={config} updateConfig={this.updateConfig}/>
-                <PictureController/>
-                <Quotecomponent config={config} updateConfig={this.updateConfig}/>
-                <StyleCombControlButton menu={config} />
-                <Button className="mk-border-green set-home" onClick={this.setHomeView}><HomeOutlined /> 璁句负棣栭〉</Button>
-                <Button className="mk-border-purple set-login" onClick={this.setLoginView}><LoginOutlined /> 璁句负鐧诲綍椤�</Button>
-                <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
-                <Transfer MenuID={MenuId} />
-                {config ? <Versions MenuId={MenuId} Template="webPage" checklog={this.checklog} updateConfig={this.updateLogConfig}/> : null}
-                <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
-              </div>
+            <div className="pc-setting-tools">
+              <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
+                {/* 鍩烘湰淇℃伅 */}
+                <Panel header="鍩烘湰淇℃伅" forceRender className="basedata" key="basedata">
+                  {config ? <>
+                    <MenuForm
+                      config={config}
+                      MenuId={MenuId}
+                      adapters={adapters}
+                      updateConfig={(con) => {
+                        this.updateConfig(con)
+                        if (con.direction !== config.direction) {
+                          this.changeView(con.direction)
+                        }
+                      }}
+                    />
+                    <UrlFieldComponent config={config} updateConfig={this.updateConfig}/>
+                    {/* 琛ㄥ悕娣诲姞 */}
+                    <TableComponent config={config} updatetable={this.updateConfig}/>
+                    <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>鑿滃崟ID</Paragraph>
+                    <Paragraph style={{padding: '10px 0px 0px 18px'}} copyable={{ text:  `${window.GLOB.baseurl}mob/index.html#/index/${sessionStorage.getItem('kei_no')}/${sessionStorage.getItem('typename')}/${sessionStorage.getItem('lang')}/${MenuId}/@BID@` }}>鑿滃崟閾炬帴</Paragraph>
+                    <NormalCss config={config} updateConfig={this.updateConfig}/>
+                  </> : null}
+                </Panel>
+                {/* 缁勪欢娣诲姞 */}
+                <Panel header="缁勪欢" className="component" key="component">
+                  <SourceWrap />
+                </Panel>
+                <Panel header="鍏冪礌" key="element">
+                  <Modulecell />
+                </Panel>
+                <Panel header="椤甸潰鏍峰紡" key="background">
+                  {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
+                </Panel>
+              </Collapse>
             </div>
-            <div className={'menu-body menu-view' + (menuloading ? ' saving' : '') + (eyeopen ? ' eye-open' : '')}>
-              {config && !comloading ? <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}>
-                <MobShell menu={config} handleList={this.updateConfig} />
-              </div> : null}
-            </div></> : <PopView btn={this.state.popConfig} save={this.submitPopConfig} cancel={this.closePop}/>}
-          </DndProvider>
-          <StyleController />
-          <StyleCombController />
-          <ModalController />
-          <SearchController />
-        </div>
-      </ConfigProvider>
+          </div>
+          <div className={'menu-control' + (!controlshow ? ' hidden' : '')}>
+            <div className="draw">
+              {controlshow ? <DoubleRightOutlined onClick={() => {this.setState({controlshow: false})}}/> : null}
+              {!controlshow ? <DoubleLeftOutlined onClick={() => {this.setState({controlshow: true})}}/> : null}
+            </div>
+            <div className="wrap">
+              <Button type="primary" className={needUpdate ? 'update-tip' : ''} disabled={!config} onClick={this.submitConfig} id="save-config" loading={menuloading}>淇濆瓨</Button>
+              {config ? <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> : null}
+              <ArrowLeftOutlined title="鍚庨��" className="back-view" onClick={this.backView}/>
+              {config ? <Debug config={config}/> : null}
+              <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 缁勪欢鍚�</Button>
+              <CreateView resetmenu={this.getAppMenus} />
+              <PasteController insert={this.insert} />
+              <TableNodes config={config} />
+              <ViewNodes config={config} MenuId={MenuId}/>
+              <SysInterface config={config} updateConfig={this.updateConfig}/>
+              <PictureController/>
+              <Quotecomponent config={config} updateConfig={this.updateConfig}/>
+              <StyleCombControlButton menu={config} />
+              <Button className="mk-border-green set-home" disabled={MenuId === appHomeId} onClick={this.setHomeView}><HomeOutlined /> 璁句负棣栭〉</Button>
+              <Button className="mk-border-purple" disabled={MenuId === appLoginId} onClick={this.setLoginView}><LoginOutlined /> 璁句负鐧诲綍椤�</Button>
+              <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
+              <Transfer MenuID={MenuId} />
+              {config ? <Versions MenuId={MenuId} Template="webPage" checklog={this.checklog} updateConfig={this.updateLogConfig}/> : null}
+              <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
+            </div>
+          </div>
+          <div className={'menu-body menu-view' + (menuloading ? ' saving' : '') + (eyeopen ? ' eye-open' : '')}>
+            {config && !comloading ? <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}>
+              <MobShell menu={config} handleList={this.updateConfig} />
+            </div> : null}
+          </div></> : <PopView btn={this.state.popConfig} save={this.submitPopConfig} cancel={this.closePop}/>}
+        </DndProvider>
+        <StyleController />
+        <StyleCombController />
+        <ModalController />
+        <SearchController />
+      </div>
     )
   }
 }
diff --git a/src/views/mobdesign/index.scss b/src/views/mobdesign/index.scss
index 3753c8f..6d6d812 100644
--- a/src/views/mobdesign/index.scss
+++ b/src/views/mobdesign/index.scss
@@ -171,25 +171,25 @@
     background-size: 100% 100%;
     padding: 25px 13px 40px;
     border-radius: 30px;
-    .main-search-edit-list {
-      .page-card > div > .ant-form-item {
-        display: flex;
-        >.ant-form-item-label {
-          width: 70px;
-        }
-        >.ant-form-item-control-wrapper {
-          flex: 1;
-        }
-        .ant-form-item-label > label::after {
-          content: ' ';
+    // .main-search-edit-list {
+    //   .page-card > div > .ant-form-item {
+    //     display: flex;
+    //     >.ant-form-item-label {
+    //       width: 70px;
+    //     }
+    //     >.ant-form-item-control-wrapper {
+    //       flex: 1;
+    //     }
+    //     .ant-form-item-label > label::after {
+    //       content: ' ';
           
-        }
-      }
-      .page-card.date .ant-form-item, .page-card.datemonth .ant-form-item {
-        // box-shadow: 0px 1px 1px #f0f0f0;
-        border-bottom: 1px solid #f0f0f0;
-      }
-    }
+    //     }
+    //   }
+    //   .page-card.date .ant-form-item, .page-card.datemonth .ant-form-item {
+    //     // box-shadow: 0px 1px 1px #f0f0f0;
+    //     border-bottom: 1px solid #f0f0f0;
+    //   }
+    // }
   }
   .menu-control {
     position: fixed;
@@ -323,7 +323,7 @@
     }
   }
   .menu-control {
-    .quote-wrap, .set-home, .set-login {
+    .quote-wrap, .set-home {
       display: none!important;
     }
   }
@@ -332,7 +332,3 @@
 body {
   overflow-y: hidden;
 }
-
-.user-component-wrap {
-  display: none!important;
-}
\ No newline at end of file
diff --git a/src/views/mobdesign/menuform/index.jsx b/src/views/mobdesign/menuform/index.jsx
index 49d4013..00b8042 100644
--- a/src/views/mobdesign/menuform/index.jsx
+++ b/src/views/mobdesign/menuform/index.jsx
@@ -20,6 +20,14 @@
 
   state = {}
 
+  componentDidMount() {
+    const { config } = this.props
+
+    if (config.getLocation === 'true') {
+      window.GLOB.getLocation = true
+    }
+  }
+
   // 涓�浜岀骇鑿滃崟鍒囨崲
   selectChange = (key, value, hex) => {
     if (key === 'cacheTime' || key === 'localCacheTime') {
@@ -36,6 +44,8 @@
       } else {
         delete _config.statusBarHexColor
       }
+    } else if (key === 'getLocation') {
+      window.GLOB.getLocation = value === 'true'
     }
 
     this.props.updateConfig(_config)
@@ -279,6 +289,23 @@
               )}
             </Form.Item>
           </Col> : null}
+          <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="寮�鍚悗鏁版嵁婧愪腑灏嗘浛鎹� @mk_longitude@銆丂mk_latitude@锛屽湪灏忕▼搴忎腑灏嗚幏鍙栫敤鎴锋墍鍦ㄧ粡绾害銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                瀹氫綅
+              </Tooltip>
+            }>
+              {getFieldDecorator('getLocation', {
+                initialValue: config.getLocation || 'false'
+              })(
+                <Radio.Group onChange={(e) => {this.selectChange('getLocation', e.target.value)}}>
+                  <Radio value="true">寮�鍚�</Radio>
+                  <Radio value="false">涓嶅紑鍚�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
           {adapters.includes('weixin') || adapters.includes('wxmini') ? <Col span={24}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="浣跨敤榛樿鏃惰鍦ㄥ瓙搴旂敤璁剧疆鍒嗕韩淇℃伅锛屼娇鐢╱rl鍙傛暟浼氫娇鐢ㄤ笂椤靛弬鏁版浛鎹㈢浉搴斿瓧娈碉紙@field@锛夈�傛敞锛氫娇鐢ㄨ嚜瀹氫箟鎴杣rl鍙傛暟鏃朵細鍒嗕韩褰撳墠椤甸潰銆�">
diff --git a/src/views/pay/index.jsx b/src/views/pay/index.jsx
index 788a5c5..b01f691 100644
--- a/src/views/pay/index.jsx
+++ b/src/views/pay/index.jsx
@@ -17,54 +17,56 @@
   state = {
     orderId: '',
     orderNo: '',
-    appid: '',
-    logo: '',
-    name: '',
-    copyRight: '',
-    icp: '',
+    logo: window.GLOB.doclogo || '',
+    name: sessionStorage.getItem('Full_Name') || '',
+    copyRight: window.GLOB.copyRight || '',
+    icp: window.GLOB.ICP || '',
     total: '',
     unit: '',
     qrcode: '',
     second: 60,
     overdue: false,
-    overdone: false
+    overdone: false,
+    appId: '',
+    merchId: ''
   }
 
   UNSAFE_componentWillMount () {
-    let _urlparam = window.decodeURIComponent(window.atob(this.props.match.params.param))
-    let _params = {}
-    _urlparam.split('&').forEach(cell => {
-      let _cell = cell.split('=')
-      _params[_cell[0]] = _cell[1]
-    })
+    let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
 
-    if (!sessionStorage.getItem('LoginUID') && _params.LoginUID) {
-      sessionStorage.setItem('LoginUID', _params.LoginUID)
-    }
-    if (!sessionStorage.getItem('UserID') && _params.userid) {
-      sessionStorage.setItem('UserID', _params.userid)
-    }
+    let appId = param.appId || window.GLOB.WXAppID || window.GLOB.WXminiAppID || ''
+    let merchId = param.merchId || window.GLOB.WXMerchID || ''
 
     this.setState({
-      orderId: _params.ID,
-      logo: _params.logo,
-      name: _params.name,
-      copyRight: _params.copyRight,
-      icp: _params.icp
+      orderId: param.ID,
+      appId: appId,
+      merchId: merchId
     })
 
-    if (_params.ID) {
-      this.getOrder(_params.ID)
-    } else {
+    if (param.ID && appId && merchId) {
+      this.getOrder(param.ID, appId, merchId)
+    } else if (!param.ID) {
       notification.warning({
         top: 92,
         message: '鏈幏鍙栧埌璁㈠崟ID锛�',
         duration: 5
       })
+    } else if (!appId) {
+      notification.warning({
+        top: 92,
+        message: '鏈幏鍙栧埌搴旂敤ID锛�',
+        duration: 5
+      })
+    } else if (!merchId) {
+      notification.warning({
+        top: 92,
+        message: '鏈幏鍙栧埌鍟嗘埛鍙凤紒',
+        duration: 5
+      })
     }
   }
 
-  getOrder = (Id) => {
+  getOrder = (Id, appId, merchId) => {
     let param = {
       func: 's_get_weixin_pay_native',
       ID: Id
@@ -85,7 +87,6 @@
         }
 
         this.setState({
-          appid: res.appid,
           orderNo: res.out_trade_no,
           total: _total,
           unit: res.amount && res.amount.currency === 'CNY' ? '鍏�' : '鍏�',
@@ -114,19 +115,12 @@
             duration: 5
           })
           return
-        } else if (!res.appid) {
-          notification.warning({
-            top: 10,
-            message: '鏈幏鍙栧埌搴旂敤ID锛�',
-            duration: 5
-          })
-          return
         }
 
-        Api.getWxNativePay({ 'out_biz_no': res.out_trade_no, 'out_open_id': res.appid }).then(result => {
-          if (result.qrcode) {
+        Api.getWxNativePay({ 'out_biz_no': res.out_trade_no, app_id: appId, mchid: merchId }).then(result => {
+          if (result.status && result.code_url) {
             this.setState({
-              qrcode: result.qrcode
+              qrcode: result.code_url
             })
             setTimeout(this.resetSecond, 1000)
           } else {
@@ -135,7 +129,7 @@
             })
             notification.warning({
               top: 10,
-              message: result.msg || '鏈幏鍙栧埌鏀粯鐮侊紒',
+              message: result.message || '鏈幏鍙栧埌鏀粯鐮侊紒',
               duration: 5
             })
           }
@@ -198,7 +192,7 @@
   }
 
   resetQrcode = () => {
-    const { appid, orderNo } = this.state
+    const { orderNo, appId, merchId } = this.state
 
     if (!orderNo) {
       notification.warning({
@@ -207,12 +201,26 @@
         duration: 5
       })
       return
+    } else if (!appId) {
+      notification.warning({
+        top: 10,
+        message: '鏈幏鍙栧埌搴旂敤ID锛�',
+        duration: 5
+      })
+      return
+    } else if (!merchId) {
+      notification.warning({
+        top: 10,
+        message: '鏈幏鍙栧埌鍟嗘埛鍙凤紒',
+        duration: 5
+      })
+      return
     }
 
-    Api.getWxNativePay({ 'out_biz_no': orderNo, 'out_open_id': appid }).then(result => {
-      if (result.qrcode) {
+    Api.getWxNativePay({ 'out_biz_no': orderNo, app_id: appId, mchid: merchId }).then(result => {
+      if (result.status && result.code_url) {
         this.setState({
-          qrcode: result.qrcode,
+          qrcode: result.code_url,
           overdue: false,
           second: 60
         })
@@ -220,16 +228,16 @@
       } else {
         notification.warning({
           top: 10,
-          message: result.msg || '鏈幏鍙栧埌鏀粯鐮侊紒',
+          message: result.message || '鏈幏鍙栧埌鏀粯鐮侊紒',
           duration: 5
         })
       }
     })
   }
 
-  onChange = () => {
+  // onChange = () => {
 
-  }
+  // }
 
   render () {
     const { logo, name, orderNo, icp, copyRight, total, unit, qrcode, second, overdue, overdone } = this.state
@@ -251,17 +259,8 @@
                 {!overdone ? <div className="qrcode-box">
                   {!overdue ? <p>璺濈浜岀淮鐮佽繃鏈熻繕鍓�<span>{second}</span>绉掞紝杩囨湡鍚庤鍒锋柊椤甸潰閲嶆柊鑾峰彇浜岀淮鐮併��</p> : null}
                   {overdue ? <p className="overdue">浜岀淮鐮佸凡杩囨湡锛�<span onClick={this.resetQrcode}>鍒锋柊</span>椤甸潰閲嶆柊鑾峰彇浜岀淮鐮併��</p> : null}
-                  <QRCode
-                    value={qrcode}
-                    size={250}
-                    fgColor="#000000"
-                    // imageSettings={{
-                    //   src: '',
-                    //   height: 60,
-                    //   width: 60,
-                    //   excavate: true
-                    // }}
-                  />
+                  <QRCode value={qrcode} size={250} fgColor="#000000"/>
+                  {!overdue && !qrcode ? <div className="qr-mask"></div> : null}
                   {overdue ? <div className="overdue-mask"><p onClick={this.resetQrcode}>鑾峰彇澶辫触 鐐瑰嚮閲嶆柊鑾峰彇浜岀淮鐮�</p></div> : null}
                   <div className="qrcode-tip">
                     <img src={WeiXinScan} alt=""/>
diff --git a/src/views/pay/index.scss b/src/views/pay/index.scss
index b69ffac..e2fa10d 100644
--- a/src/views/pay/index.scss
+++ b/src/views/pay/index.scss
@@ -101,6 +101,14 @@
             cursor: pointer;
           }
         }
+        .qr-mask {
+          position: absolute;
+          width: 240px;
+          height: 240px;
+          top: 45px;
+          background: rgba(255, 255, 255, 0.95);
+          left: calc(50% - 120px);
+        }
         .qrcode-tip {
           background: #ff7674;
           width: 250px;
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index 63ef5fb..0638e83 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -3,15 +3,14 @@
 import { withRouter } from 'react-router'
 import { is, fromJS } from 'immutable'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
+import { notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import md5 from 'md5'
 
 import Api from '@/api'
-import Utils, { setGLOBFuncs } from '@/utils/utils.js'
-import { getTables, getFuncsAndInters } from '@/utils/utils-custom.js'
-import antdZhCN from 'antd/es/locale/zh_CN'
+import Utils from '@/utils/utils.js'
+import { getTables, getFuncsAndInters, getOutMessage, getLangTrans, getAllSqls } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import MenuUtils from '@/utils/utils-custom.js'
 import asyncComponent from '@/utils/asyncComponent'
@@ -69,7 +68,9 @@
     eyeopen: false,
     view: '',
     popConfig: null,
-    needUpdate: false
+    needUpdate: false,
+    appLoginId: '',
+    appHomeId: ''
   }
 
   UNSAFE_componentWillMount() {
@@ -100,17 +101,49 @@
     try {
       let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
 
+      if (param.lang) {
+        sessionStorage.setItem('lang', param.lang)
+      }
+
       if (param.type === 'app') {
         sessionStorage.setItem('appId', param.ID || '')
         sessionStorage.setItem('appName', param.remark || '')
-        sessionStorage.setItem('lang', param.lang || 'zh-CN')
         sessionStorage.setItem('kei_no', param.kei_no || '')
         sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
 
+        if (param.applangList) {
+          sessionStorage.setItem('applangList', param.applangList)
+        } else {
+          sessionStorage.removeItem('applangList')
+        }
+
+        if (param.wxAppId) {
+          sessionStorage.setItem('wxAppId', param.wxAppId)
+        }
+
         this.getAppMessage(param.MenuID)
       } else if (param.type === 'view') {
+        let appLoginId = ''
+        let appHomeId = ''
+        if (sessionStorage.getItem('appViewList')) {
+          try {
+            let appMenus = JSON.parse(sessionStorage.getItem('appViewList'))
+            appMenus.forEach(item => {
+              if (item.keys_type === 'login') {
+                appLoginId = item.keys_id
+              } else if (item.keys_type === 'index') {
+                appHomeId = item.keys_id
+              }
+            })
+          } catch (e) {
+
+          }
+        }
+
         this.setState({
-          MenuId: param.MenuID
+          MenuId: param.MenuID,
+          appLoginId: appLoginId,
+          appHomeId: appHomeId
         }, () => {
           this.getMenuParam(param)
         })
@@ -144,9 +177,13 @@
     MKEmitter.addListener('changeEditMenu', this.changeEditMenu)
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
 
+    if (sessionStorage.getItem('wxAppId')) {
+      window.GLOB.WXAppID = sessionStorage.getItem('wxAppId')
+    }
+
     setTimeout(() => {
       this.getRoleFields()
-      setGLOBFuncs()
+      // setGLOBFuncs()
     }, 1000)
 
     document.onkeydown = (event) => {
@@ -240,7 +277,8 @@
       MenuID: menu.MenuID,
       copyMenuId: menu.copyMenuId || '',
       clearMenu: menu.clearMenu !== 'false',
-      type: 'view'
+      type: 'view',
+      lang: sessionStorage.getItem('lang')
     }
 
     // param.MenuNo = menu.MenuNo || ''
@@ -316,12 +354,12 @@
             })
           } else {
             sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
-            this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'}))))
+            this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view', lang: sessionStorage.getItem('lang')}))))
           }
         })
       } else {
         sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
-        this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID || homeId, type: 'view'}))))
+        this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID || homeId, type: 'view', lang: sessionStorage.getItem('lang')}))))
       }
     })
   }
@@ -1140,6 +1178,20 @@
 
     if (!this.checkBase()) {
       return
+    } else if (this.checklog()) {
+      if (sessionStorage.getItem('applangList') && !config.trans) {
+
+      } else if (config.enabled && !config.allSqls) {
+        
+      } else {
+        notification.success({
+          top: 92,
+          message: '褰撳墠閰嶇疆鏈慨鏀癸紝鏃犻渶淇濆瓨銆�',
+          duration: 5
+        })
+        MKEmitter.emit('completeSave')
+        return
+      }
     }
 
     this.setState({
@@ -1155,6 +1207,52 @@
       } else if (!config.enabled && config.force && _pass) {
         config.enabled = true
         delete config.force
+      }
+
+      let long_data = ''
+      if (config.enabled) {
+        let sqls = getAllSqls(config)
+        let _t = moment().format('YYYYMMDDHHmmss')
+        let getguid = () => {
+          let uuid = ''
+          for (let i = 0; i < 18; i++) {
+            uuid += String.fromCharCode(Math.floor(Math.random() * 26) + 65)
+          }
+          uuid = uuid.replace(/minke/ig, 'MNKIE')
+          return uuid
+        }
+
+        long_data = []
+        let oriIds = {}
+        if (config.allSqls) {
+          config.allSqls.forEach(item => {
+            if (!item.md5) return
+            oriIds[item.uuid + item.md5] = item.v_id
+          })
+        }
+        
+        config.allSqls = sqls.map(item => {
+          let v_id = _t + getguid()
+
+          if (oriIds[item.uuid + item.md5]) {
+            v_id = oriIds[item.uuid + item.md5]
+          }
+          
+          long_data.push(`${md5(window.GLOB.appkey + v_id)},${item.uuid},${v_id},${window.btoa(window.encodeURIComponent(item.LText))}`)
+          
+          return {
+            uuid: item.uuid,
+            v_id: v_id,
+            type: item.type,
+            reps: item.reps,
+            md5: item.md5 || '',
+            luser: item.luser === true
+          }
+        })
+
+        long_data = long_data.join(';')
+      } else {
+        delete config.allSqls
       }
 
       if (config.cacheUseful !== 'true') {
@@ -1207,7 +1305,11 @@
       }
 
       let interfaces = getFuncsAndInters(config)
+      let msg = getOutMessage(config)
       roleParam.interfaces = interfaces
+      roleParam.msg = msg
+      roleParam.backend = 'level1'
+      let langSql = getLangTrans(config)
 
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
@@ -1221,15 +1323,20 @@
         TypeCharOne: sessionStorage.getItem('kei_no'),
         Typename: 'pc',
         MenuName: config.MenuName || '',
-        PageParam: JSON.stringify({Template: 'webPage', interfaces}),
+        PageParam: JSON.stringify({Template: 'webPage', interfaces, msg}),
         menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))),
         open_edition: config.open_edition,
-        LText: '',
-        LTexttb: '',
+        long_data: long_data,
+        // LText: '',
+        // LTexttb: '',
         menus_used_list,
         debug_md5: key,
         debug_url: url,
         debug_list: window.btoa(tbs)
+      }
+
+      if (langSql) {
+        param.lang_translation = window.btoa(window.encodeURIComponent(langSql))
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -1310,8 +1417,8 @@
               PageParam: JSON.stringify({Template: NavBar.type}),
               menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roles))),
               open_edition: NavBar.open_edition,
-              LText: '',
-              LTexttb: ''
+              // LText: '',
+              // LTexttb: ''
             }
 
             _param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(NavBar)))
@@ -1591,6 +1698,8 @@
     param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     param.secretkey = Utils.encrypt('', param.timestamp)
 
+    const that = this
+
     confirm({
       title: '纭畾璁剧疆鏈〉闈负棣栭〉鍚楋紵',
       content: '',
@@ -1604,6 +1713,10 @@
             })
           } else {
             sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
+
+            that.setState({
+              appHomeId: config.MenuID
+            })
           }
         })
       },
@@ -1651,6 +1764,7 @@
     param.secretkey = Utils.encrypt('', param.timestamp)
 
     let hasLogin = config.components.findIndex(item => item.type === 'login') > -1
+    const that = this
 
     confirm({
       title: '纭畾璁剧疆鏈〉闈负鐧诲綍椤靛悧锛�',
@@ -1665,6 +1779,10 @@
             })
           } else {
             sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
+
+            that.setState({
+              appLoginId: config.MenuID
+            })
           }
         })
       },
@@ -1693,10 +1811,10 @@
   }
 
   render () {
-    const { view, loading, comloading, activeKey, settingshow, controlshow, MenuId, config, menuloading, eyeopen, needUpdate } = this.state
+    const { view, loading, comloading, activeKey, settingshow, controlshow, MenuId, config, menuloading, eyeopen, needUpdate, appLoginId, appHomeId } = this.state
 
     return (
-      <ConfigProvider locale={antdZhCN}>
+      <>
         <DndProvider backend={HTML5Backend}>
           {view !== 'popview' ? <div className={'mk-pc-view '} id="mk-pc-design-view">
             {loading ? <Spin className="view-spin" size="large" /> : null}
@@ -1741,7 +1859,7 @@
                 {!controlshow ? <DoubleLeftOutlined onClick={() => {sessionStorage.setItem('controlshow', 'true'); this.setState({controlshow: true})}}/> : null}
               </div>
               <div className="wrap">
-                <Button type="primary" className={needUpdate ? 'update-tip' : ''} id="save-config" onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
+                <Button type="primary" className={needUpdate ? 'update-tip' : ''} disabled={!config} id="save-config" onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
                 {config ? <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                 <ArrowLeftOutlined title="鍚庨��" className="back-view" onClick={this.backView}/>
                 {config ? <Debug config={config}/> : null}
@@ -1754,8 +1872,8 @@
                 <PictureController/>
                 <Quotecomponent config={config} updateConfig={this.updateConfig}/>
                 <StyleCombControlButton menu={config} />
-                <Button className="mk-border-green" onClick={this.setHomeView}><HomeOutlined /> 璁句负棣栭〉</Button>
-                <Button className="mk-border-purple" onClick={this.setLoginView}><LoginOutlined/> 璁句负鐧诲綍椤�</Button>
+                <Button className="mk-border-green" disabled={MenuId === appHomeId} onClick={this.setHomeView}><HomeOutlined /> 璁句负棣栭〉</Button>
+                <Button className="mk-border-purple" disabled={MenuId === appLoginId} onClick={this.setLoginView}><LoginOutlined/> 璁句负鐧诲綍椤�</Button>
                 <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                 <Transfer MenuID={MenuId} />
                 {config ? <Versions MenuId={MenuId} Template="webPage" checklog={this.checklog} updateConfig={this.updateLogConfig}/> : null}
@@ -1773,7 +1891,7 @@
         <StyleController />
         <StyleCombController />
         <ModalController />
-      </ConfigProvider>
+      </>
     )
   }
 }
diff --git a/src/views/pcdesign/index.scss b/src/views/pcdesign/index.scss
index bb683f2..0d2b917 100644
--- a/src/views/pcdesign/index.scss
+++ b/src/views/pcdesign/index.scss
@@ -274,6 +274,3 @@
 body {
   overflow-y: hidden;
 }
-.user-component-wrap {
-  display: none!important;
-}
\ No newline at end of file
diff --git a/src/views/printTemplate/index.jsx b/src/views/printTemplate/index.jsx
index 8f72e0c..8374dff 100644
--- a/src/views/printTemplate/index.jsx
+++ b/src/views/printTemplate/index.jsx
@@ -20,6 +20,7 @@
   qrurl,
   imgurl
 } from './option.js'
+import { langs } from '@/store/options'
 import Utils from '@/utils/utils.js'
 import printCtrl from './print.js'
 import Api from '@/api'
@@ -35,7 +36,9 @@
 class PrintTemplate extends Component {
   state = {
     config: null,
+    oriConfig: null,
     ID: null,
+    langName: '',
     editItemId: '',
     editItemType: '',
     fields: [],
@@ -67,16 +70,24 @@
   }
 
   UNSAFE_componentWillMount () {
-    let _param = window.atob(this.props.match.params.param)
-    let _params = {}
-    _param.split('&').forEach(cell => {
-      let _cell = cell.split('=')
-      _params[_cell[0]] = _cell[1]
-    })
+    try {
+      let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
 
-    this.setState({
-      ID: _params.ID
-    })
+      if (param.lang) {
+        sessionStorage.setItem('lang', param.lang)
+      }
+
+      this.setState({
+        langName: sessionStorage.getItem('lang') !== 'zh-CN' && langs[sessionStorage.getItem('lang')] ? `锛�${langs[sessionStorage.getItem('lang')]}锛塦 : '',
+        ID: param.ID
+      })
+    } catch (e) {
+      notification.warning({
+        top: 92,
+        message: '妯℃澘淇℃伅瑙f瀽閿欒锛�',
+        duration: 5
+      })
+    }
   }
 
   componentDidMount () {
@@ -88,7 +99,7 @@
       let cy = position.cy
       let _selectItem = null
 
-      let _config = JSON.parse(JSON.stringify(this.state.config))
+      let _config = fromJS(this.state.config).toJS()
 
       _config.elements.forEach(element => {
         let x = +element.left
@@ -156,8 +167,8 @@
         return
       }
 
-      let _selectItem = JSON.parse(JSON.stringify(this.state.config.elements.filter(ele => ele.uuid === this.state.editItemId)[0]))
-      let _preItem = JSON.parse(JSON.stringify(_selectItem))
+      let _selectItem = fromJS(this.state.config.elements.filter(ele => ele.uuid === this.state.editItemId)[0]).toJS()
+      let _preItem = fromJS(_selectItem).toJS()
 
       let position = this.getclickpoint(e)
       let cx = position.cx
@@ -214,7 +225,7 @@
               let result = this.resetItem(_selectItem)
 
               if (!is(fromJS(result), fromJS(_preItem))) {
-                _preItem = JSON.parse(JSON.stringify(result))
+                _preItem = fromJS(result).toJS()
                 this.FormRef.resetForm(result)
 
                 config.elements = config.elements.map(item => {
@@ -261,7 +272,7 @@
               let result = this.resetItem(fromJS(_selectItem).toJS())
 
               if (!is(fromJS(result), fromJS(_preItem))) {
-                _preItem = JSON.parse(JSON.stringify(result))
+                _preItem = fromJS(result).toJS()
                 this.FormRef.resetForm(result)
 
                 config.elements = config.elements.map(item => {
@@ -407,6 +418,7 @@
       this.handleResize()
       this.setState({
         config: _config,
+        oriConfig: fromJS(_config).toJS(),
         editItemId: _config.uuid,
         editItemType: _config.type,
         formlist: getpageform(_config)
@@ -755,7 +767,7 @@
   }
 
   deleteItem = () => {
-    const _this = this
+    const that = this
     const { editItemId, config } = this.state
 
     confirm({
@@ -765,13 +777,13 @@
       onOk() {
         config.elements = config.elements.filter(item => item.uuid !== editItemId)
 
-        _this.setState({
+        that.setState({
           config: config,
           editItemId: config.uuid,
           editItemType: config.type,
           formlist: getpageform(config)
         }, () => {
-          _this.resetview()
+          that.resetview()
         })
       },
       onCancel() {}
@@ -779,9 +791,16 @@
   }
 
   submitConfig = () => {
-    const { config } = this.state
+    const { config, oriConfig } = this.state
 
-    if (config.height / config.width > 10 || config.width / config.height > 10) {
+    if (is(fromJS(config), fromJS(oriConfig))) {
+      notification.success({
+        top: 92,
+        message: '褰撳墠妯℃澘鏈慨鏀癸紝鏃犻渶淇濆瓨銆�',
+        duration: 5
+      })
+      return
+    } else if (config.height / config.width > 10 || config.width / config.height > 10) {
       notification.warning({
         top: 92,
         message: '绾稿紶绾垫í姣斾笉鍙秴杩�10!',
@@ -878,6 +897,7 @@
         })
       }
       this.setState({
+        oriConfig: fromJS(config).toJS(),
         saveloading: false
       })
     })
@@ -950,13 +970,13 @@
   }
 
   render () {
-    const { debug } = this.state
+    const { debug, langName } = this.state
     
     return (
       <div className="print-template">
         <DndProvider backend={HTML5Backend}>
           <header className="print-header-container ant-menu-dark">
-            妯℃澘鍒朵綔
+            妯℃澘鍒朵綔{langName}
             <div>蹇嵎閿細Delete锛堝垹闄ゅ厓绱狅級銆乧trl + q锛堝鍒跺厓绱狅級</div>
           </header>
           <aside className="tools">
diff --git a/src/views/rolemanage/index.jsx b/src/views/rolemanage/index.jsx
index cd23aaa..bb9d731 100644
--- a/src/views/rolemanage/index.jsx
+++ b/src/views/rolemanage/index.jsx
@@ -1,10 +1,9 @@
 import React, {Component} from 'react'
 import { fromJS } from 'immutable'
-import { Spin, notification, Button, Table, Modal, ConfigProvider, Tree, Input, Empty } from 'antd'
+import { Spin, notification, Button, Table, Modal, Tree, Input, Empty } from 'antd'
 import moment from 'moment'
 import md5 from 'md5'
-import zhCN from 'antd/es/locale/zh_CN'
-import { ApiOutlined } from '@ant-design/icons'
+import { ApiOutlined, SoundOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -27,12 +26,13 @@
     columns: [
       {
         title: '鑿滃崟鍚嶇О', dataIndex: 'MenuName', key: 'MenuName', align: 'center', render: (text, record) => {
-          if (record.extra) {
-            return <span style={{color: '#1890ff'}}>{text}</span>
-          } else if (record.interfaces === 'true') {
-            return <span><ApiOutlined style={{color: 'orange', marginRight: '5px'}} title="鑿滃崟涓娇鐢ㄤ簡澶栭儴鎺ュ彛" />{text}</span>
+          let className = window.backend && record.backend !== 'level1' ? 'unbackend' : ''
+          if (record.extra || this.state.appKeys.includes(record.MenuID)) {
+            return <span className={className} style={{color: '#1890ff'}}>{text}</span>
+          } else if (record.interfaces === 'true' || record.msg === 'true') {
+            return <span className={className}>{record.interfaces === 'true' ? <ApiOutlined style={{color: 'orange', marginRight: '5px'}} title="鑿滃崟涓娇鐢ㄤ簡澶栭儴鎺ュ彛" /> : null}{record.msg === 'true' ? <SoundOutlined style={{color: 'orange', marginRight: '5px'}} title="鑿滃崟涓彂閫佷簡娑堟伅" /> : null}{text}</span>
           }
-          return text
+          return <span className={className}>{text}</span>
         }
       },
       {
@@ -75,7 +75,8 @@
     trees: null,
     expandedKeys: [],
     searchkey: '',
-    appViewList: []
+    appViewList: [],
+    appKeys: []
   }
 
   oriTrees = null
@@ -83,6 +84,10 @@
   UNSAFE_componentWillMount() {
     document.body.className = ''
     let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
+
+    if (param.lang) {
+      sessionStorage.setItem('lang', param.lang)
+    }
 
     this.setState({app: param}, () => {
       this.getTreeList()
@@ -115,7 +120,9 @@
         })
         return
       }
-      this.setState({appViewList: result.data || []})
+
+      let data = result.data || []
+      this.setState({appViewList: data, appKeys: data.map(item => item.keys_id)})
     })
   }
 
@@ -151,9 +158,15 @@
               let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist)))
               item.nodes = pageParam
               item.interfaces = pageParam.interfaces || 'false'
+              item.msg = pageParam.msg || 'false'
+              item.backend = pageParam.backend || ''
               
               if (pageParam.type) {
                 item.type = pageParam.type
+              }
+
+              if (item.type === 'navbar' || item.type === 'im') {
+                item.backend = 'level1'
               }
 
               if (pageParam.version !== '1.0') {
@@ -183,10 +196,10 @@
         })
 
         if (!im) {
-          menus.push({nodes: '', type: 'none', extra: true, MenuID: app.instantMessage, MenuName: '鍗虫椂閫氫俊'})
+          menus.push({nodes: '', type: 'none', backend: 'level1', extra: true, MenuID: app.instantMessage, MenuName: '鍗虫椂閫氫俊'})
         }
         if (!ub) {
-          menus.push({nodes: '', type: 'none', extra: true, MenuID: app.userbind, MenuName: '鐢ㄦ埛缁戝畾'})
+          menus.push({nodes: '', type: 'none', backend: 'level1', extra: true, MenuID: app.userbind, MenuName: '鐢ㄦ埛缁戝畾'})
         }
 
         this.setState({
@@ -403,7 +416,7 @@
 
   deleteMenu = (record) => {
     const { app, appViewList } = this.state
-    const _this = this
+    const that = this
 
     let param = {
       func: 'sPC_MainMenu_Del',
@@ -444,7 +457,7 @@
                 message: '鎿嶄綔鎴愬姛锛�',
                 duration: 3
               })
-              _this.getMenuList(true)
+              that.getMenuList(true)
 
               if (_param) {
                 Api.getCloudConfig(_param).then(res => {
@@ -455,7 +468,7 @@
                       duration: 5
                     })
                   } else {
-                    _this.setState({appViewList: _appViewList})
+                    that.setState({appViewList: _appViewList})
                   }
                 })
               }
@@ -676,12 +689,12 @@
   }
 
   initTree = () => {
-    const _this = this
+    const that = this
     confirm({
       content: '鏉冮檺鏍戜細閲嶆柊鐢熸垚锛岀‘瀹氭墽琛屽悧锛�',
       onOk() {
         return new Promise(resolve => {
-          _this.getMenuList(true, resolve)
+          that.getMenuList(true, resolve)
         })
       },
       onCancel() {}
@@ -689,13 +702,13 @@
   }
 
   syncTree = () => {
-    const _this = this
+    const that = this
 
     confirm({
       content: '鍚屾浼氭牴鎹彍鍗曞垹闄ゆ垨鏂板鑺傜偣锛岀‘瀹氭墽琛屽悧锛�',
       onOk() {
         return new Promise(resolve => {
-          _this.syncMenutree(resolve)
+          that.syncMenutree(resolve)
         })
       },
       onCancel() {}
@@ -704,7 +717,7 @@
 
   saveTree = () => {
     // const { trees } = this.state
-    const _this = this
+    const that = this
 
     // if (!trees || trees.length === 0) {
     //   notification.warning({
@@ -719,7 +732,7 @@
       content: '纭畾鎵ц鍚楋紵',
       onOk() {
         return new Promise(resolve => {
-          _this.execSave(resolve)
+          that.execSave(resolve)
         })
       },
       onCancel() {}
@@ -916,61 +929,59 @@
 
     return (
       <div className="mk-role-manage">
-        <ConfigProvider locale={zhCN}>
-          <Header app={app} />
-          {loading ?
-            <div className="loading-mask">
-              <Spin size="large" />
-            </div> : null
-          }
-          <div className="view-wrap">
-            <div className="left-view">
-              <div className="app-table">
-                <div className="app-action">
-                  <Button className="mk-green" onClick={this.triggerThaw}>瑙e喕鑿滃崟</Button>
-                  <Search placeholder="缁煎悎鎼滅储" onSearch={value => this.setState({ searchkey: value })} enterButton />
-                </div>
-                <Table
-                  rowKey="MenuID"
-                  columns={columns}
-                  dataSource={_menulist}
-                  pagination={false}
-                  onChange={this.changeTable}
-                />
-              </div>
-            </div>
-            <div className="right-view">
+        <Header app={app} />
+        {loading ?
+          <div className="loading-mask">
+            <Spin size="large" />
+          </div> : null
+        }
+        <div className="view-wrap">
+          <div className="left-view">
+            <div className="app-table">
               <div className="app-action">
-                <Button className="mk-primary" onClick={this.initTree}>閲嶇疆</Button>
-                {/* <Button className="mk-purple" onClick={this.syncTree}>鍚屾</Button> */}
-                <Button className="mk-green save" onClick={this.saveTree}>淇濆瓨</Button>
+                <Button className="mk-green" onClick={this.triggerThaw}>瑙e喕鑿滃崟</Button>
+                <Search placeholder="缁煎悎鎼滅储" onSearch={value => this.setState({ searchkey: value })} enterButton />
               </div>
-              {trees && trees.length ? <Tree
-                className="draggable-tree"
-                defaultExpandedKeys={this.state.expandedKeys}
-                // showLine
-                draggable
-                blockNode
-                onDrop={this.onDrop}
-              >
-                {this.renderNode(trees)}
-              </Tree> : <div className="empty">
-                <Empty />
-              </div>}
+              <Table
+                rowKey="MenuID"
+                columns={columns}
+                dataSource={_menulist}
+                pagination={false}
+                onChange={this.changeTable}
+              />
             </div>
           </div>
-          <Modal
-            title="瑙i櫎鍐荤粨"
-            visible={this.state.visible}
-            width={600}
-            onOk={this.thawSubmit}
-            confirmLoading={this.state.confirmLoading}
-            onCancel={() => this.setState({visible: false, targetKeys: []})}
-            destroyOnClose
-          >
-            <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/>
-          </Modal>
-        </ConfigProvider>
+          <div className="right-view">
+            <div className="app-action">
+              <Button className="mk-primary" onClick={this.initTree}>閲嶇疆</Button>
+              {/* <Button className="mk-purple" onClick={this.syncTree}>鍚屾</Button> */}
+              <Button className="mk-green save" onClick={this.saveTree}>淇濆瓨</Button>
+            </div>
+            {trees && trees.length ? <Tree
+              className="draggable-tree"
+              defaultExpandedKeys={this.state.expandedKeys}
+              // showLine
+              draggable
+              blockNode
+              onDrop={this.onDrop}
+            >
+              {this.renderNode(trees)}
+            </Tree> : <div className="empty">
+              <Empty />
+            </div>}
+          </div>
+        </div>
+        <Modal
+          title="瑙i櫎鍐荤粨"
+          visible={this.state.visible}
+          width={600}
+          onOk={this.thawSubmit}
+          confirmLoading={this.state.confirmLoading}
+          onCancel={() => this.setState({visible: false, targetKeys: []})}
+          destroyOnClose
+        >
+          <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/>
+        </Modal>
       </div>
     )
   }
diff --git a/src/views/rolemanage/index.scss b/src/views/rolemanage/index.scss
index 41d5905..b1b6023 100644
--- a/src/views/rolemanage/index.scss
+++ b/src/views/rolemanage/index.scss
@@ -87,4 +87,18 @@
       margin-right: 0px;
     }
   }
+  .unbackend {
+    position: relative;
+  }
+  .unbackend::before {
+    content: '';
+    display: block;
+    position: absolute;
+    width: 4px;
+    height: 4px;
+    background-color: orange;
+    border-radius: 4px;
+    top: 0px;
+    left: -5px;
+  }
 }
diff --git a/src/views/sso/index.jsx b/src/views/sso/index.jsx
index 5b11539..007b51d 100644
--- a/src/views/sso/index.jsx
+++ b/src/views/sso/index.jsx
@@ -66,8 +66,6 @@
           res.menu_type = 'shutter'
         }
 
-        const _href = window.location.href.split('#')[0]
-        let _url = _href + 'system'
         let systemMsg = {
           favicon: res.titlelogo || '',
           platTitle: res.titleName || '',
@@ -103,12 +101,12 @@
           level = ''
         }
 
-        localStorage.setItem(_href + 'pwdlevel', level)
+        localStorage.setItem(window.GLOB.sysSign + 'pwdlevel', level)
 
         if (res.srcid) {
-          localStorage.setItem(_href + 'srcId', res.srcid)
+          localStorage.setItem(window.GLOB.sysSign + 'srcId', res.srcid)
         } else {
-          localStorage.removeItem(_href + 'srcId')
+          localStorage.removeItem(window.GLOB.sysSign + 'srcId')
         }
 
         sessionStorage.setItem('home_background', res.index_background_color || '')
@@ -123,9 +121,9 @@
         document.title = systemMsg.platTitle
 
         try {
-          localStorage.setItem(_url, window.btoa(window.encodeURIComponent(JSON.stringify(systemMsg))))
+          localStorage.setItem(window.GLOB.sysSign + 'system', window.btoa(window.encodeURIComponent(JSON.stringify(systemMsg))))
         } catch (e) {
-          localStorage.removeItem(_url)
+          localStorage.removeItem(window.GLOB.sysSign + 'system')
         }
 
         window.GLOB.mainlogo = systemMsg.mainlogo
diff --git a/src/views/systemfunc/index.jsx b/src/views/systemfunc/index.jsx
index 9c33163..179eb01 100644
--- a/src/views/systemfunc/index.jsx
+++ b/src/views/systemfunc/index.jsx
@@ -1,7 +1,5 @@
 import React, {Component} from 'react'
-import { ConfigProvider } from 'antd'
 import { withRouter } from 'react-router-dom'
-import zhCN from 'antd/es/locale/zh_CN'
 
 import asyncComponent from '@/utils/asyncComponent'
 import Header from './header'
@@ -59,11 +57,9 @@
   render () {
     return (
       <div className="mk-main-view">
-        <ConfigProvider locale={zhCN}>
-          <Sidemenu key="sidemenu"/>
-          <Tabview key="tabview"/>
-          <Header key="header"/>
-        </ConfigProvider>
+        <Sidemenu key="sidemenu"/>
+        <Tabview key="tabview"/>
+        <Header key="header"/>
         <ImgScale />
       </div>
     )
diff --git a/src/views/systemfunc/sidemenu/config.jsx b/src/views/systemfunc/sidemenu/config.jsx
index ce7475b..058481e 100644
--- a/src/views/systemfunc/sidemenu/config.jsx
+++ b/src/views/systemfunc/sidemenu/config.jsx
@@ -84,6 +84,14 @@
     MenuID: '15827879285193g85m3i2uprektpgmpf',
     MenuNo: 'bd_mes_techM',
     MenuName: '宸ヨ壓涓绘暟鎹�',
+  }, {
+    src: '',
+    systems: ['local'],
+    PageParam: {OpenType: 'newtab', Template: 'CustomPage'},
+    type: 'CustomPage',
+    MenuID: '17180925258436em38rhpqncckvohv0s',
+    MenuNo: 's_app_lang_translation_M',
+    MenuName: '璇█鍖�',
   }]
 }, {
   MenuID: 'systemManageViewInterface',
diff --git a/src/views/systemproc/index.jsx b/src/views/systemproc/index.jsx
index 9f1f68a..d6bf70e 100644
--- a/src/views/systemproc/index.jsx
+++ b/src/views/systemproc/index.jsx
@@ -1,7 +1,5 @@
 import React, {Component} from 'react'
-import { ConfigProvider } from 'antd'
 import { withRouter } from 'react-router-dom'
-import zhCN from 'antd/es/locale/zh_CN'
 
 import Header from '../systemfunc/header'
 import Proc from './proc'
@@ -20,10 +18,8 @@
 
     return (
       <div className="mk-proc-view">
-        <ConfigProvider locale={zhCN}>
-          <Header key="header"/>
-          <Proc func={func} />
-        </ConfigProvider>
+        <Header key="header"/>
+        <Proc func={func} />
       </div>
     )
   }
diff --git a/src/views/tabledesign/index.jsx b/src/views/tabledesign/index.jsx
index 3880a3d..80aa91e 100644
--- a/src/views/tabledesign/index.jsx
+++ b/src/views/tabledesign/index.jsx
@@ -4,15 +4,15 @@
 import { is, fromJS } from 'immutable'
 import moment from 'moment'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button, Typography } from 'antd'
+import { notification, Modal, Collapse, Card, Switch, Button, Typography } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined } from '@ant-design/icons'
 import md5 from 'md5'
 
 import Api from '@/api'
-import Utils, { setGLOBFuncs } from '@/utils/utils.js'
-import antdZhCN from 'antd/es/locale/zh_CN'
+import Utils from '@/utils/utils.js'
+import { langs } from '@/store/options'
 import MKEmitter from '@/utils/events.js'
-import { getTables, getFuncsAndInters } from '@/utils/utils-custom.js'
+import { getTables, getFuncsAndInters, getOutMessage, getLangTrans, getAllSqls } from '@/utils/utils-custom.js'
 import SourceElement from '@/templates/zshare/dragsource'
 import asyncComponent from '@/utils/asyncComponent'
 import Source from './source'
@@ -23,7 +23,6 @@
 const { Panel } = Collapse
 const { confirm } = Modal
 const { Paragraph } = Typography
-const _locale = antdZhCN
 
 const MenuForm = asyncComponent(() => import('./menuform'))
 const PopView = asyncComponent(() => import('./popview'))
@@ -59,6 +58,7 @@
     comloading: false,
     settingshow: sessionStorage.getItem('settingshow') !== 'false',
     view: null,
+    langName: '',
     popConfig: null
   }
 
@@ -88,11 +88,16 @@
     try {
       let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
 
+      if (param.lang) {
+        sessionStorage.setItem('lang', param.lang)
+      }
+      
       this.setState({
         MenuId: param.MenuID,
         ParentId: param.ParentId || '',
         MenuName: param.MenuName || '',
         MenuNo: param.MenuNo || '',
+        langName: sessionStorage.getItem('lang') !== 'zh-CN' && langs[sessionStorage.getItem('lang')] ? `锛�${langs[sessionStorage.getItem('lang')]}锛塦 : ''
       }, () => {
         this.getMenuParam()
       })
@@ -116,7 +121,7 @@
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
     setTimeout(() => {
       this.getRoleFields()
-      setGLOBFuncs()
+      // setGLOBFuncs()
     }, 1000)
 
     document.onkeydown = (event) => {
@@ -425,8 +430,8 @@
         window.GLOB.urlFields = config.urlFields || []
 
         this.setState({
-          oriConfig: config,
-          config: fromJS(config).toJS()
+          oriConfig: config.components[0].isNew ? {} : fromJS(config).toJS(),
+          config: config
         })
         window.GLOB.customMenu = config
       } else {
@@ -532,6 +537,20 @@
 
     if (!this.checkBase()) {
       return
+    } else if (this.checklog()) {
+      if (sessionStorage.getItem('langList') && !config.trans) {
+
+      } else if (config.enabled && !config.allSqls) {
+
+      } else {
+        notification.success({
+          top: 92,
+          message: '褰撳墠閰嶇疆鏈慨鏀癸紝鏃犻渶淇濆瓨銆�',
+          duration: 5
+        })
+        MKEmitter.emit('completeSave')
+        return
+      }
     }
 
     this.setState({
@@ -547,6 +566,52 @@
       } else if (!config.enabled && config.force && _pass) {
         config.enabled = true
         delete config.force
+      }
+
+      let long_data = ''
+      if (config.enabled) {
+        let sqls = getAllSqls(config)
+        let _t = moment().format('YYYYMMDDHHmmss')
+        let getguid = () => {
+          let uuid = ''
+          for (let i = 0; i < 18; i++) {
+            uuid += String.fromCharCode(Math.floor(Math.random() * 26) + 65)
+          }
+          uuid = uuid.replace(/minke/ig, 'MNKIE')
+          return uuid
+        }
+
+        long_data = []
+        let oriIds = {}
+        if (config.allSqls) {
+          config.allSqls.forEach(item => {
+            if (!item.md5) return
+            oriIds[item.uuid + item.md5] = item.v_id
+          })
+        }
+        
+        config.allSqls = sqls.map(item => {
+          let v_id = _t + getguid()
+
+          if (oriIds[item.uuid + item.md5]) {
+            v_id = oriIds[item.uuid + item.md5]
+          }
+          
+          long_data.push(`${md5(window.GLOB.appkey + v_id)},${item.uuid},${v_id},${window.btoa(window.encodeURIComponent(item.LText))}`)
+          
+          return {
+            uuid: item.uuid,
+            v_id: v_id,
+            type: item.type,
+            reps: item.reps,
+            md5: item.md5 || '',
+            luser: item.luser === true
+          }
+        })
+
+        long_data = long_data.join(';')
+      } else {
+        delete config.allSqls
       }
 
       let tbs = []
@@ -576,12 +641,16 @@
         let urlparam = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
         urlparam.type = 'admin'
         urlparam.MenuType = 'BaseTable'
+        urlparam.lang = sessionStorage.getItem('lang')
+
         url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
         config.tbkey = key
       }
 
       let interfaces = getFuncsAndInters(config)
+      let msg = getOutMessage(config)
       let urlFields = config.urlFields ? config.urlFields.join(',') : ''
+      let langSql = getLangTrans(config)
 
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
@@ -593,14 +662,17 @@
         EasyCode: config.easyCode || '',
         Template: 'BaseTable',
         MenuName: config.MenuName || '',
-        PageParam: JSON.stringify({Template: 'BaseTable', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false', menuColor: config.menuColor || '', interfaces, urlFields}),
+        PageParam: JSON.stringify({Template: 'BaseTable', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false', menuColor: config.menuColor || '', interfaces, msg, backend: 'level1', urlFields}),
         open_edition: config.open_edition,
-        LText: '',
-        LTexttb: '',
+        long_data: long_data,
         debug_md5: key,
         debug_url: url,
         debug_list: window.btoa(tbs),
         LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config)))
+      }
+
+      if (langSql) {
+        param.lang_translation = window.btoa(window.encodeURIComponent(langSql))
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -841,11 +913,11 @@
   }
 
   render () {
-    const { view, activeKey, comloading, MenuId, config, settingshow, ParentId, menuloading } = this.state
+    const { view, activeKey, comloading, MenuId, config, settingshow, ParentId, menuloading, langName } = this.state
 
     return (
-      <ConfigProvider locale={_locale}>
-        <Header menuName={config ? config.MenuName : ''}/>
+      <>
+        <Header menuName={config ? config.MenuName + langName : ''}/>
         <DndProvider backend={HTML5Backend}>
         {view !== 'popview' ? <div className="pc-table-view">
             <div className="menu-body">
@@ -909,8 +981,8 @@
                     <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                     <PasteBaseTable type="page" insert={this.insert}/>
                     {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>
+                    <Button type="primary" id="save-config" disabled={!config} onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
+                    <Button type="default" disabled={menuloading} onClick={this.closeView}>鍏抽棴</Button>
                   </div>
                 } style={{ width: '100%' }}>
                   {config && !comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
@@ -921,7 +993,7 @@
         </DndProvider>
         <StyleController />
         <ModalController />
-      </ConfigProvider>
+      </>
     )
   }
 }
diff --git a/src/views/tabledesign/index.scss b/src/views/tabledesign/index.scss
index a3be304..84954ae 100644
--- a/src/views/tabledesign/index.scss
+++ b/src/views/tabledesign/index.scss
@@ -138,7 +138,10 @@
       > .ant-card {
         >.ant-card-head {
           margin-bottom: 0px;
-          position: relative;
+          position: sticky;
+          top: 0px;
+          z-index: 10;
+          background: #ffffff;
           .ant-card-head-title {
             color: #1890ff;
             padding: 5px 0;
diff --git a/src/views/tabledesign/popview/index.jsx b/src/views/tabledesign/popview/index.jsx
index 05a7425..dbac3df 100644
--- a/src/views/tabledesign/popview/index.jsx
+++ b/src/views/tabledesign/popview/index.jsx
@@ -219,7 +219,7 @@
                 <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                 <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={config.enabled} onChange={this.onEnabledChange} />
                 <Button type="primary" id="save-pop-config" onClick={this.submitConfig} loading={menuloading}>淇濆瓨</Button>
-                <Button type="default" onClick={this.closeView}>杩斿洖</Button>
+                <Button type="default" disabled={menuloading} onClick={this.closeView}>杩斿洖</Button>
               </div>
             } style={{ width: '100%' }}>
               {!comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
diff --git a/src/views/tabledesign/popview/index.scss b/src/views/tabledesign/popview/index.scss
index 2ea36fa..02b8796 100644
--- a/src/views/tabledesign/popview/index.scss
+++ b/src/views/tabledesign/popview/index.scss
@@ -123,7 +123,10 @@
       > .ant-card {
         >.ant-card-head {
           margin-bottom: 0px;
-          position: relative;
+          position: sticky;
+          top: 0px;
+          z-index: 10;
+          background: #ffffff;
           .ant-card-head-title {
             color: #1890ff;
             padding: 5px 0;

--
Gitblit v1.8.0